Popular Posts
Wrong text encoding while Jsoup parse document While page encoding is different with content type encoding declaration. Jsoup will get wrong text decode content. To avoid this problem, As... JSON Foramter <html> <head>     <title>JSON Formater</title>     <style type="text/css">     body{         margin:... SwiXml SwiX ml , is a small GUI generating engine for Java applications and applets. Graphical User Interfaces are described in XML documents that ...
Blog Archive
Stats
ADD ... THEN ... UNTIL ...
data: begin of SERIES,
         N1 type I value 10,
         N2 type I value 20,
         N3 type I value 30,
         N4 type I value 40,
         N5 type I value 50,
         N6 type I value 60,
      end of SERIES.
data SUM type I.
add SERIES-N1 then SERIES-N2 until SERIES-N5 giving SUM.
write SUM.
add SERIES-N2 then SERIES-N3 until SERIES-N6 to SUM.
write / SUM.
output:
       150
       350
Horizontal, vertical line and space
* Horizontal line
write sy-uline.
write '------'.
uline.

* Vertical line
write sy-vline.
write '|'.

* space
skip 3.
skip to line 10.
WRITE: format option
通用格式化選項
選項 用途選項
LEFT-JUSTIFIED 輸出對左對齊
CENTERED 輸出置中對齊
RIGHT-JUSTIFIED 輸出對右對齊
UNDER <g> 輸出至<g>下方
NO-GAP 忽略輸出後方的間格空格
USING EDIT MASK <m> 指定輸出格式
USING NO EDIT MASK 取消abap dictionary中定義的輸出格式
NO-ZERO 取消前導的'0'以空格替代

數值格式化選項
選項 用途選項
NO-SIGN 取消前置符號
DECIMALS <d> 定義小數位數
EXPONENT <e> 定義資料類型F中的冪數
ROUND <r> 四拾五入至指定位數
CURRENCY <c> 以TCURX表中定義的貨幣格式化
UNIT <u> 按表格T006中為類型P欄位所指定的單位<u>固定小數位數

日期格式化選項
選項 用途選項
DD/MM/YY 以系統設定的分隔符號格式化
MM/DD/YY 以系統設定的分隔符號格式化
DD/MM/YYYY 以系統設定的分隔符號格式化
MM/DD/YYYY 以系統設定的分隔符號格式化
DDMMYY 無分隔符號格式化
MMDDYY 無分隔符號格式化
YYMMDD 無分隔符號格式化
Data type
資料類型 預設大小 大小 初始值 輸出長度 輸出定位 說明
C 1 1-65535 SPACE 字串長度 LEFT-JUSTIFIED 字元,字串
D 8 8 '00000000' 8 LEFT-JUSTIFIED 日期
F 8 8 0 24 RIGHT-JUSTIFIED 浮點數
I 4 4 0 11 RIGHT-JUSTIFIED 整數
N 1 1-65535 '000...0' 字串長度 LEFT-JUSTIFIED 數值字串
P 8 1-16 0 2*字串長度+1 RIGHT-JUSTIFIED 壓縮號
T 6 6 '000000' 6 LEFT-JUSTIFIED 時間
X 1 1-65536 X'00' 2*字串長度 LEFT-JUSTIFIED 16進制
abap naming rule
命名規則
  • 報表程式(以列表格式輸出資料分析):Yaxxxxxx或Zaxxxxxx。用應用程式區的分類字母替換a。
    任何有效字元替換x。注意SAP報表程式遵守相似的命名約定:Raxxxxxx。
  • 任何其他ABAP/4程式(培訓程式或事務程式):SAPMYxxx或SAPMZxxx。用有效字元替換x。
    注意標準SAPABAP/4程式遵守相似的命名約定:SAPMaxxx,其中a代表某應用程式區。
for xml usage
SELECT
p.[product_name],
p.[product_imgstyle],
p.[product_color],
p.[product_size],
p.[product_weight],
p.[product_desc],
(
 SELECT l.[purchase_url], s.[store_name], s.[display_order]
 FROM [Product_StoreLink] l, [Store] s
 WHERE l.[store_id] = s.[store_id] AND l.[product_id] = p.[product_id]
 FOR XML RAW
) store
FROM Product p
Tab control using url hash variant
Default.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebApplication1._Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>anchor test with tab design</title>
    <style type="text/css">
        ul.tab
        {
            margin: 1px 0px;
            padding: 0px;
        }
        ul.tab li
        {
            display: inline;
        }
        ul.tab li a
        {
            padding: 3px;
            margin-right: 2px;
            background-color: #eee;
            border: 1px outset gray;
            font-size: small;
            color: Blue;
        }
        ul.tab li a:hover
        {
            background-color: gold;
        }
        ul.tab li a.active_tab
        {
            background-color: Orange;
        }
        
        div.tab_container
        {
            border: 1px solid gray;
            padding: 10px;
        }
        
        a
        {
            text-decoration: none;
        }
        a:hover
        {
            text-decoration: underline;
        }
    </style>
    <script src="Scripts/jquery-1.6.2.min.js" type="text/javascript"></script>
    <script type="text/javascript">
        function tab_change() {
            // 頁籤序號
            var index = location.hash.substring(1);
            if (!index) index = '0';
            index = parseInt(index);

            // 變更頁籤css
            $('ul.tab li a').removeClass('active_tab').eq(index).addClass('active_tab');

            // postback, 以觸發update panel更新
            //$('<%=hdnTabIndex.ClientID%>').val(index);
            __doPostBack('hdnTabIndex', index);
        }
        $(function () {
            // 頁籤變更觸發
            $(window).bind('hashchange', tab_change);
            // 載入頁面時更新
            tab_change();
        });
        
    </script>
</head>
<body>
    <form id="form1" runat="server">
    <asp:ScriptManager ID="smPage" runat="server">
    </asp:ScriptManager>
    <ul class="tab">
        <li><a href="#0" class="active_tab">第一頁</a></li>
        <li><a href="#1">第二頁</a></li>
        <li><a href="#2">第三頁</a></li>
        <li><a href="#3">第四頁</a></li>
        <li><a href="#4">第五頁</a></li>
    </ul>
    <div class="tab_container">
        <asp:UpdatePanel ID="upTabContainer" runat="server" UpdateMode="Conditional" RenderMode="Block">
            <ContentTemplate>
                <asp:HiddenField ID="hdnTabIndex" runat="server" />
                <asp:Panel ID="plTabContainer0" runat="server" Visible="false">
                    第一頁內容
                </asp:Panel>
                <asp:Panel ID="plTabContainer1" runat="server" Visible="false">
                    第二頁內容
                </asp:Panel>
                <asp:Panel ID="plTabContainer2" runat="server" Visible="false">
                    第三頁內容
                </asp:Panel>
                <asp:Panel ID="plTabContainer3" runat="server" Visible="false">
                    第四頁內容
                </asp:Panel>
                <asp:Panel ID="plTabContainer4" runat="server" Visible="false">
                    第五頁內容
                </asp:Panel>
            </ContentTemplate>
        </asp:UpdatePanel>
    </div>
    </form>
</body>
</html>
Default.aspx.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace WebApplication1
{
    public partial class _Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            Tab_Load();
        }

        protected void Tab_Load()
        {
            // postback參數
            string _index = Request.Form["__EVENTARGUMENT"];
            if (string.IsNullOrEmpty(_index)) _index = "0";

            plTabContainer0.Visible = false;
            plTabContainer1.Visible = false;
            plTabContainer2.Visible = false;
            plTabContainer3.Visible = false;
            plTabContainer4.Visible = false;
            upTabContainer.FindControl("plTabContainer" + _index).Visible = true;
        }
    }
}
Speed up VisualStudio using RAMDisk
STEP:
  1. Install RAMDisk and create a ramdisk r:
  2. Create a batch file and setting temp variant:
    @echo off
    set tmp=r:\
    set temp=r:\
    call "C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE\devenv.exe"
  3. edit web.config
    <compilation debug="true" tempDirectory="r:\">
String.replaceAll()
String.prototype.replaceAll = function(oldValue, newValue) {
    return this.split(oldValue).join(newValue);
}
Register User Controls and Custom Controls in Web.config
<system.web>
    <pages>
        <controls>
            <add tagPrefix="scottgu" src="~/Controls/Header.ascx" tagName="header"/>
            <add tagPrefix="scottgu" src="~/Controls/Footer.ascx" tagName="footer"/>
            <add tagPrefix="ControlVendor" assembly="ControlVendorAssembly"/>
        </controls>
    </pages>
</system.web>
Parse query string
Uri url = new Uri("http://www.google.com.tw/search?sourceid=chrome&ie=UTF-8&q=uri");

System.Collections.Specialized.NameValueCollection queryString
    = System.Web.HttpUtility.ParseQueryString(url.Query);

Console.WriteLine(queryString.Get("sourceid"));
Console.WriteLine(queryString.Get("ie"));
script path in master page
use script manager (script will appear in body section)
<asp:ScriptManager ID="ScriptManager1" runat="server">
    <Scripts>
        <asp:ScriptReference Path="~/jquery.js" />
    </Scripts>
</asp:ScriptManager>
use ResolveClientUrl method
<script type="text/javascript" src="<%= Page.ResolveClientUrl("~/jquery.js") %>"></script>
asp.net form validate
// 確認更新
function confirmUpdate(
    confirmMessage, /* 確認訊息 */
    validateGroup, /* validate group*/
    fn /* 自訂欄位檢查function */
) {
    if ('undefined' != typeof (tinyMCE)) tinyMCE.triggerSave(); // 觸發tinyMCE儲存值
    if ('undefined' != typeof (validateGroup)) validateGroup = null;
    if ('function' != typeof (fn)) fn = function () { return true; }  // 自訂驗證的function, 若無則回傳true
    if ('function' != typeof (Page_ClientValidate)) var Page_ClientValidate = function (group) { return true; } // validate control驗證
    if ($(document.forms[0]).valid2() && Page_ClientValidate(validateGroup)) {
        return fn() && confirm(confirmMessage);
    } else {
        return false;
    }
}
Retire value from tinyMCE when jQuery validate valid() invoked
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm2.aspx.cs" Inherits="superspace.usercontrols.WebForm2" ValidateRequest="false" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>tinyMCE + jQuery validate</title>
    <!-- jQuery -->
    <script src="<%=VirtualPathUtility.ToAbsolute("~/")%>js/jquery-1.6.2.min.js" type="text/javascript"></script>
    <!-- jQuery validate + metadata -->
    <script src="<%=VirtualPathUtility.ToAbsolute("~/")%>js/jquery.validate/jquery.metadata.min.js" type="text/javascript"></script>
    <script src="<%=VirtualPathUtility.ToAbsolute("~/")%>js/jquery.validate/jquery.validate.min.js" type="text/javascript"></script>
    <script src="<%=VirtualPathUtility.ToAbsolute("~/")%>js/jquery.validate/jquery.validate.ext.min.js" type="text/javascript"></script>
    <!-- tinyMCE Editor -->
    <script src="<%=VirtualPathUtility.ToAbsolute("~/")%>js/tiny_mce/tiny_mce.js" type="text/javascript"></script>
    <script src="<%=VirtualPathUtility.ToAbsolute("~/")%>js/tiny_mce/jquery.tinymce.js" type="text/javascript"></script>
    <style type="text/css">
        body
        {
            font-size: smaller;
        }
    </style>
    <script type="text/javascript">
        $(function () {
            $('.txtContent').tinymce({
                theme: "advanced",
                language: "zh",
                theme_advanced_toolbar_location: "top",
                theme_advanced_toolbar_align: "left",
                theme_advanced_statusbar_location: "bottom",
                theme_advanced_resizing: true
            });
            $(document.forms).validate();
        });
        function confirmUpdate() {
            if (typeof (tinyMCE) != 'undefined') tinyMCE.triggerSave();
            if (!$(document.forms).valid()) return false;
            return true;
        }
    </script>
</head>
<body>
    <form id="form1" runat="server">
    <h3>
        Force tinyMCE editor to save content to control, avoid validate error when valid() has been invoked;</h3>
    <table border="0">
        <tr>
            <td>
                <b style="color: Red;">*</b>標題
            </td>
            <td>
                <asp:TextBox ID="txtTitle" runat="server" CssClass="{required:true,messages:{required:'請填寫標題!'}}" />
            </td>
        </tr>
        <tr>
            <td valign="top">
                <b style="color: Red;">*</b>內容
            </td>
            <td>
                <asp:TextBox ID="txtContent" runat="server" TextMode="MultiLine" Width="100%" Rows="15" CssClass="txtContent {required:true,messages:{required:'請填寫內容!'}}" />
            </td>
        </tr>
        <tr>
            <td align="center" colspan="2">
                <asp:Button ID="btnSubmit" runat="server" Text="儲存" OnClientClick="return confirmUpdate();" />
            </td>
        </tr>
    </table>
    </form>
</body>
</html>
jQuery validator: focus invalid field when calling valid()
/*
 * 在validate呼叫valid()驗證方法式, 加上focusInValid的動件
 */
(function($) {
    $.extend($.fn, {
        valid2 : function() {
            var valid = true;
            var validator;
            if ($(this[0]).is('form')) {
                validator = this.validate();
                valid = this.validate().form();
            } else {
                validator = $(this[0].form).validate();
                this.each(function() {
                    valid &= validator.element(this);
                });
            }
            if (!valid)
                validator.focusInvalid();
            return valid;
        }
    });

    // 新增一個 regex 的驗證方式
    $.validator.methods.regex = function(value, element, param) {
        return this.optional(element) || ((typeof(param) == 'function' && typeof(param.test) == 'function') ? param.test(value) : new RegExp(param).test(value));
    };
    $.validator.messages.regex = 'Please enter a valid value.';
})(jQuery);
Add a event to Outlook calendar dymatically
protected void btnAddEventToOutlook_Click(object sender, EventArgs e)
{
    Response.Clear();
    Response.AddHeader("content-disposition", string.Format("attachment;filename={0}.ics", HttpUtility.UrlEncode(EventName, Response.HeaderEncoding)));

    Response.Write(string.Format(@"BEGIN:VCALENDAR
METHOD:PUBLISH
PRODID:-//{0}//NONSGML iCalcreator 2.6//ZH_TW
VERSION:2.0
X-WR-CALNAME;LANGUAGE=zh_tw:有 {1} 筆相關活動
BEGIN:VEVENT
UID:{2}
DTSTAMP:{3:yyyyMMddTHHmmss}Z
DESCRIPTION;LANGUAGE=zh_tw:{4}
DTSTART;TZID=TAIWAN:{5:yyyyMMddTHHmmss}
DTEND;TZID=TAIWAN:{6:yyyyMMddTHHmmss}
LOCATION;LANGUAGE=zh_tw:{7}
SUMMARY;LANGUAGE=zh_tw:{8}
URL;VALUE=URI:{9}
END:VEVENT
END:VCALENDAR",
        Request.Url.Host,
        PlaceCount,
        Request.QueryString["oid"],
        DateTime.Now,
        Description,
        Convert.ToDateTime(FromDate),
        Convert.ToDateTime(ToDate),
        Location,
        EventName,
        Request.Url));
    Response.End();
}
about ics file
Add a event to Google Calendar dynamically
hlGoogle.NavigateUrl = string.Format(
    "https://www.google.com/calendar/render?action=TEMPLATE&text={0}&dates={1:yyyyMMddTHHmmss}/{2:yyyyMMddTHHmmss}&sprop=website:{3}&location={4}&details={5}",
    EventName,
    Convert.ToDateTime(FromDate),
    Convert.ToDateTime(ToDate),
    Request.Url.Host,
    Location,
    Details
);
ObjectDataSource
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="ObjectDataSourceSample.aspx.cs"
    Inherits="superspace.control.info.ObjectDataSourceSample" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:HiddenField ID="hdnContentId" runat="server" />
        <asp:ObjectDataSource ID="ObjectDataSource1" runat="server"
            DeleteMethod="Delete"
            InsertMethod="Insert"
            SelectMethod="Select"
            UpdateMethod="Update"
            OldValuesParameterFormatString="{0}"
            TypeName="SuperspaceLib.VoteOption">
            <DeleteParameters>
                <asp:Parameter Name="ContentId" Type="String" />
                <asp:Parameter Name="OptionID" Type="String" />
            </DeleteParameters>
            <InsertParameters>
                <asp:Parameter Name="ContentId" Type="String" />
                <asp:Parameter Name="OptionID" Type="String" />
                <asp:Parameter Name="OptionName" Type="String" />
            </InsertParameters>
            <SelectParameters>
                <asp:ControlParameter ControlID="hdnContentId" Name="ContentId" PropertyName="Value"
                    Type="String" />
            </SelectParameters>
            <UpdateParameters>
                <asp:Parameter Name="ContentId" Type="String" />
                <asp:Parameter Name="OptionID" Type="String" />
                <asp:Parameter Name="OptionName" Type="String" />
            </UpdateParameters>
        </asp:ObjectDataSource>
        <asp:TextBox ID="txtVoteOption" runat="server" MaxLength="50" Style="width: 100%;" />
        <asp:Button ID="btnAddOption" runat="server" Text="新增" OnClick="btnAddOption_Click" />
        <asp:GridView ID="gvOptions" runat="server" AutoGenerateColumns="False" GridLines="None"
            ShowHeader="False" DataKeyNames="ContentId,OptionID" EnableModelValidation="True"
            DataSourceID="ObjectDataSource1">
            <Columns>
                <asp:BoundField DataField="OptionName" HeaderText="OptionName" SortExpression="OptionName" />
                <asp:TemplateField ShowHeader="False">
                    <ItemTemplate>
                        <asp:LinkButton ID="LinkButton1" runat="server" CausesValidation="False" CommandName="Edit"
                            Text="編輯"></asp:LinkButton>
                        &nbsp;<asp:LinkButton ID="LinkButton2" runat="server" CausesValidation="False" CommandName="Delete"
                            Text="刪除"></asp:LinkButton>
                    </ItemTemplate>
                    <EditItemTemplate>
                        <asp:LinkButton ID="LinkButton1" runat="server" CausesValidation="True" CommandName="Update"
                            Text="更新"></asp:LinkButton>
                        &nbsp;<asp:LinkButton ID="LinkButton2" runat="server" CausesValidation="False" CommandName="Cancel"
                            Text="取消"></asp:LinkButton>
                    </EditItemTemplate>
                </asp:TemplateField>
            </Columns>
        </asp:GridView>
    </div>
    </form>
</body>
</html>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Data;
using System.Web;

namespace SuperspaceLib
{
    [DataObject(true)]
    public class VoteOption
    {
        [DataObjectMethod(DataObjectMethodType.Select)]
        public DataTable Select(string ContentId)
        {
            DataTable dtOption = null;
            if (HttpContext.Current.Session[ContentId] == null)
            {
                dtOption = new DataTable("VoteOption");
                dtOption.Columns.Add("ContentId");
                dtOption.Columns.Add("OptionID");
                dtOption.Columns.Add("OptionName");
            }
            else
            {
                dtOption = HttpContext.Current.Session[ContentId] as DataTable;
            }
            return dtOption;
        }

        [DataObjectMethod(DataObjectMethodType.Update)]
        public int Update(string ContentId, string OptionID, string OptionName)
        {
            DataTable dtOption = null;
            if (HttpContext.Current.Session[ContentId] == null)
            {
                dtOption = new DataTable("VoteOption");
                dtOption.Columns.Add("ContentId");
                dtOption.Columns.Add("OptionID");
                dtOption.Columns.Add("OptionName");
            }
            else
            {
                dtOption = HttpContext.Current.Session[ContentId] as DataTable;
            }

            int afftected = 0;
            foreach (DataRow row in dtOption.Rows)
            {
                if (row["ContentId"].Equals(ContentId) && row["OptionID"].Equals(OptionID))
                {
                    row["OptionName"] = OptionName;
                    afftected++;
                }
            }
            HttpContext.Current.Session[ContentId] = dtOption;

            return afftected;
        }

        [DataObjectMethod(DataObjectMethodType.Insert)]
        public int Insert(string ContentId, string OptionID, string OptionName)
        {
            DataTable dtOption = null;
            if (HttpContext.Current.Session[ContentId] == null)
            {
                dtOption = new DataTable("VoteOption");
                dtOption.Columns.Add("ContentId");
                dtOption.Columns.Add("OptionID");
                dtOption.Columns.Add("OptionName");
            }
            else
            {
                dtOption = HttpContext.Current.Session[ContentId] as DataTable;
            }

            DataRow row = dtOption.Rows.Add(ContentId, OptionID, OptionName);
            HttpContext.Current.Session[ContentId] = dtOption;

            return 1;
        }

        [DataObjectMethod(DataObjectMethodType.Delete)]
        public int Delete(string ContentId, string OptionID)
        {
            DataTable dtOption = null;
            if (HttpContext.Current.Session[ContentId] == null)
            {
                dtOption = new DataTable("VoteOption");
                dtOption.Columns.Add("ContentId");
                dtOption.Columns.Add("OptionID");
                dtOption.Columns.Add("OptionName");
            }
            else
            {
                dtOption = HttpContext.Current.Session[ContentId] as DataTable;
            }

            int afftected = 0;
            for (int i = dtOption.Rows.Count - 1; i >= 0; i--)
            {
                DataRow row = dtOption.Rows[i];
                if (row["ContentId"].Equals(ContentId) && row["OptionID"].Equals(OptionID))
                {
                    dtOption.Rows.Remove(row);
                    afftected++;
                }
            }
            HttpContext.Current.Session[ContentId] = dtOption;

            return afftected;
        }
    }
}
HINT:
  • OldValuesParameterFormatString="{0}" means parameter will take value of old value by this name format
  • Parameter name must compeletly match the param of method
UpdatePanel in Formview occurs duplicate component id error
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="InnerUpdatePanel.aspx.cs"
    Inherits="superspace.control.info.InnerUpdatePanel" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:FormView ID="fvVote" runat="server" DefaultMode="Insert">
            <InsertItemTemplate>
                <asp:TextBox ID="txtVoteName" runat="server" />
                <asp:UpdatePanel ID="upOption" runat="server" UpdateMode="Conditional">
                    <ContentTemplate>
                        <table border="0" width="100%">
                            <tr>
                                <td>
                                    <asp:TextBox ID="txtOption" runat="server" />
                                </td>
                                <td>
                                    <asp:Button ID="btnAddOption" runat="server" Text="新增選項" />
                                </td>
                            </tr>
                        </table>
                    </ContentTemplate>
                </asp:UpdatePanel>
            </InsertItemTemplate>
            <EditItemTemplate>
                <asp:TextBox ID="txtVoteName" runat="server" />
                <asp:UpdatePanel ID="upOption" runat="server" UpdateMode="Conditional">
                    <ContentTemplate>
                        <table border="0" width="100%">
                            <tr>
                                <td>
                                    <asp:TextBox ID="txtOption" runat="server" />
                                </td>
                                <td>
                                    <asp:Button ID="btnAddOption" runat="server" Text="新增選項" />
                                </td>
                            </tr>
                        </table>
                    </ContentTemplate>
                </asp:UpdatePanel>
            </EditItemTemplate>
        </asp:FormView>
    </div>
    </form>
</body>
</html>
Solutions:
  1. Remove update panel
  2. Create a user control wrapping update panel
Test mail sender
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

import bruce.lib.swing.SwingWrench;
import bruce.lib.util.DateTime;
import bruce.lib.util.PostCenter;

public class PostMan extends JFrame {

    JTextField txtIP;
    JTextField txtPort;
    JTextField txtAccount;
    JPasswordField txtPassword;

    JTextField txtSenderMail;
    JTextField txtSednerName;
    JTextField txtReceiverMail;

    JCheckBox cbIsHtml;
    JTextField txtSubject;
    JTextArea txtBody;

    JButton btnSubmit;

    JTextArea txtConsole;

    public PostMan() {
        setLayout(new GridBagLayout());
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setTitle("發信測試");

        JPanel control = new JPanel(new GridBagLayout());
        control.setMinimumSize(new Dimension(350, 100));

        control.add(new JLabel("主機ip"), new GridBagConstraints(1, 1, 1, 1, 0, 0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(3, 3, 3, 3), 1, 1));
        control.add(txtIP = new JTextField("ms2.ccic.com.tw", 10), new GridBagConstraints(2, 1, 1, 1, 0.3, 0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(3, 3, 3, 3), 1, 1));
        control.add(new JLabel("通訊埠"), new GridBagConstraints(3, 1, 1, 1, 0, 0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(3, 3, 3, 3), 1, 1));
        control.add(txtPort = new JTextField("25", 3), new GridBagConstraints(4, 1, 1, 1, 0.3, 0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(3, 3, 3, 3), 1, 1));

        control.add(new JLabel("帳號"), new GridBagConstraints(1, 2, 1, 1, 0, 0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(3, 3, 3, 3), 1, 1));
        control.add(txtAccount = new JTextField("gp_report", 10), new GridBagConstraints(2, 2, 1, 1, 0.3, 0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(3, 3, 3, 3), 1, 1));
        control.add(new JLabel("密碼"), new GridBagConstraints(3, 2, 1, 1, 0, 0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(3, 3, 3, 3), 1, 1));
        control.add(txtPassword = new JPasswordField("29952666", 10), new GridBagConstraints(4, 2, 1, 1, 0.3, 0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(3, 3, 3, 3), 1, 1));

        control.add(new JLabel("寄件人名稱"), new GridBagConstraints(1, 3, 1, 1, 0, 0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(3, 3, 3, 3), 1, 1));
        control.add(txtSednerName = new JTextField("MES系統訊息", 10), new GridBagConstraints(2, 3, 1, 1, 0.3, 0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(3, 3, 3, 3), 1, 1));
        control.add(new JLabel("寄件人mail"), new GridBagConstraints(3, 3, 1, 1, 0, 0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(3, 3, 3, 3), 1, 1));
        control.add(txtSenderMail = new JTextField("gp_report@ccic.com.tw", 10), new GridBagConstraints(4, 3, 1, 1, 0.3, 0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(3, 3, 3, 3), 1, 1));

        control.add(new JLabel("收件人"), new GridBagConstraints(1, 4, 1, 1, 0, 0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(3, 3, 3, 3), 1, 1));
        control.add(txtReceiverMail = new JTextField("", 10), new GridBagConstraints(2, 4, 3, 1, 0, 0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(3, 3, 3, 3), 1, 1));

        control.add(new JLabel("html格式"), new GridBagConstraints(1, 5, 1, 1, 0, 0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(3, 3, 3, 3), 1, 1));
        control.add(cbIsHtml = new JCheckBox(), new GridBagConstraints(2, 5, 3, 1, 0, 0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(3, 3, 3, 3), 1, 1));

        control.add(new JLabel("主旨"), new GridBagConstraints(1, 6, 1, 1, 0, 0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(3, 3, 3, 3), 1, 1));
        control.add(txtSubject = new JTextField("", 10), new GridBagConstraints(2, 6, 3, 1, 0, 0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(3, 3, 3, 3), 1, 1));
        control.add(new JScrollPane(txtBody = new JTextArea()), new GridBagConstraints(1, 7, 4, 1, 1, 1, GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(3, 3, 3, 3), 1, 1));

        add(control, new GridBagConstraints(1, 1, 1, 2, 0, 1, GridBagConstraints.EAST, GridBagConstraints.VERTICAL, new Insets(3, 3, 3, 3), 1, 1));

        add(new JLabel("LOG"), new GridBagConstraints(2, 1, 1, 1, 0, 0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(3, 3, 3, 3), 1, 1));
        add(btnSubmit = new JButton("發送"), new GridBagConstraints(3, 1, 1, 1, 0, 0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(3, 3, 3, 3), 1, 1));
        add(new JScrollPane(txtConsole = new JTextArea()), new GridBagConstraints(2, 2, 2, 1, 1, 1, GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(3, 3, 3, 3), 1, 1));

        btnSubmit.addActionListener(btnSubmit_Click);

        // redirect console
        System.setOut(new PrintStream(new OutputStream() {

            StringBuffer buffer = new StringBuffer();

            @Override
            public void write(int b) throws IOException {
                switch (b) {
                case '\n':
                    txtConsole.append(buffer.toString() + System.getProperty("line.separator"));
                    buffer.delete(0, buffer.length() - 1);
                    break;
                default:
                    buffer.append((char) b);
                    break;
                }
            }
        }));

        setSize(600, 400);
        SwingWrench.setLocationCenter(this);
    }

    private ActionListener btnSubmit_Click = new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {

            try {
                System.out.printf("==========Try sending mail at %s==========%n", DateTime.now().toString("yyyy-MM-dd HH:mm:ss"));

                PostCenter<PostCenter> pc = new PostCenter<PostCenter>();

                pc.init(txtIP.getText().trim(), Integer.parseInt(txtPort.getText().trim()), true, txtAccount.getText().trim(), txtPassword.getText().trim());
                pc.setDebug(true);
                pc.setDebugOut(System.out);
                pc.setEncoding("UTF-8");

                if (txtSednerName.getText().trim().length() == 0)
                    pc.setSender(txtSenderMail.getText().trim());
                else
                    pc.setSender(txtSenderMail.getText().trim(), txtSednerName.getText().trim());

                String[] receivers = txtReceiverMail.getText().replaceAll("\\s", "").replaceAll(",", ";").split(";");

                for (String s : receivers) {
                    pc.addReceiver(s);
                }

                pc.send(txtSubject.getText(), txtBody.getText(), cbIsHtml.isSelected());
            } catch (Exception ex) {
                ex.printStackTrace(System.out);
            }

            System.out.println();
            System.out.println();
            System.out.println();
        }
    };

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        new PostMan().setVisible(true);
    }

}
A good url validate regular expression
^(?#Protocol)(?:(?:ht|f)tp(?:s?)\:\/\/|~\/|\/)?(?#Username:Password)(?:\w+:\w+@)?(?#Subdomains)(?:(?:[-\w]+\.)+(?#TopLevel Domains)(?:com|org|net|gov|mil|biz|info|mobi|name|aero|jobs|museum|travel|[a-z]{2}))(?#Port)(?::[\d]{1,5})?(?#Directories)(?:(?:(?:\/(?:[-\w~!$+|.,=]|%[a-f\d]{2})+)+|\/)+|\?|#)?(?#Query)(?:(?:\?(?:[-\w~!$+|.,*:]|%[a-f\d{2}])+=?(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)(?:&(?:[-\w~!$+|.,*:]|%[a-f\d{2}])+=?(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)*)*(?#Anchor)(?:#(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)?$
GridView paging style design
<asp:GridView ID="GridView1" runat="server" AllowPaging="True"
    ...... >
    <Columns>
        <asp:BoundField DataField="Name" HeaderText="姓名" SortExpression="Name" />
        <asp:BoundField DataField="OrgID" HeaderText="單位編號" SortExpression="OrgID" />
        .............
    </Columns>
    <PagerTemplate>
        <div style="text-align:center;">
            <asp:LinkButton ID="btnFirstPage" runat="server" CommandArgument="First" CommandName="Page" Text="First"
                Visible='<%# (Container.NamingContainer as GridView).PageIndex > 0 %>' />
            <asp:LinkButton ID="btnPrevPage" runat="server" CommandArgument="Prev" CommandName="Page" Text="Pre"
                Visible='<%# (Container.NamingContainer as GridView).PageIndex > 0 %>' />
                
            <asp:LinkButton ID="btnP4" runat="server"
                Visible='<%# (Container.NamingContainer as GridView).PageIndex-3 > 0 %>'
                CommandArgument='<%# (Container.NamingContainer as GridView).PageIndex-3 %>'
                CommandName="Page" Text='<%# (Container.NamingContainer as GridView).PageIndex-3 %>' />
            <asp:LinkButton ID="btnP3" runat="server"
                Visible='<%# (Container.NamingContainer as GridView).PageIndex-2 > 0 %>'
                CommandArgument='<%# (Container.NamingContainer as GridView).PageIndex-2 %>'
                CommandName="Page" Text='<%# (Container.NamingContainer as GridView).PageIndex-2 %>' />
            <asp:LinkButton ID="btnP2" runat="server"
                Visible='<%# (Container.NamingContainer as GridView).PageIndex-1 > 0 %>'
                CommandArgument='<%# (Container.NamingContainer as GridView).PageIndex-1 %>'
                CommandName="Page" Text='<%# (Container.NamingContainer as GridView).PageIndex-1 %>' />
            <asp:LinkButton ID="btnP1" runat="server"
                Visible='<%# (Container.NamingContainer as GridView).PageIndex > 0 %>'
                CommandArgument='<%# (Container.NamingContainer as GridView).PageIndex %>'
                CommandName="Page" Text='<%# (Container.NamingContainer as GridView).PageIndex %>' />
                
            <asp:LinkButton ID="btnCurrent" runat="server"
                Enabled="false"
                CommandArgument='<%# (Container.NamingContainer as GridView).PageIndex %>'
                CommandName="Page" Text='<%# (Container.NamingContainer as GridView).PageIndex+1 %>' />
                
            <asp:LinkButton ID="btnN1" runat="server"
                Visible='<%# (Container.NamingContainer as GridView).PageIndex+1 < (Container.NamingContainer as GridView).PageCount %>'
                CommandArgument='<%# (Container.NamingContainer as GridView).PageIndex+2 %>'
                CommandName="Page" Text='<%# (Container.NamingContainer as GridView).PageIndex+2 %>' />
            <asp:LinkButton ID="btnN2" runat="server"
                Visible='<%# (Container.NamingContainer as GridView).PageIndex+2 < (Container.NamingContainer as GridView).PageCount %>'
                CommandArgument='<%# (Container.NamingContainer as GridView).PageIndex+3 %>'
                CommandName="Page" Text='<%# (Container.NamingContainer as GridView).PageIndex+3 %>' />
            <asp:LinkButton ID="btnN3" runat="server"
                Visible='<%# (Container.NamingContainer as GridView).PageIndex+3 < (Container.NamingContainer as GridView).PageCount %>'
                CommandArgument='<%# (Container.NamingContainer as GridView).PageIndex+4 %>'
                CommandName="Page" Text='<%# (Container.NamingContainer as GridView).PageIndex+4 %>' />
            <asp:LinkButton ID="btnN4" runat="server"
                Visible='<%# (Container.NamingContainer as GridView).PageIndex+4 < (Container.NamingContainer as GridView).PageCount %>'
                CommandArgument='<%# (Container.NamingContainer as GridView).PageIndex+5 %>'
                CommandName="Page" Text='<%# (Container.NamingContainer as GridView).PageIndex+5 %>' />
                
            <asp:LinkButton ID="btnNextPage" runat="server" CommandArgument="Next" CommandName="Page" Text="Next"
                Visible='<%# (Container.NamingContainer as GridView).PageIndex+1 < (Container.NamingContainer as GridView).PageCount %>' />
            <asp:LinkButton ID="btnLastPage" runat="server" CommandArgument="Last" CommandName="Page" Text="Last"
                Visible='<%# (Container.NamingContainer as GridView).PageIndex+1 < (Container.NamingContainer as GridView).PageCount %>' />
                
            ,共<%# (Container.NamingContainer as GridView).PageCount %>頁,
            到第<asp:TextBox ID="tbPageIndex" runat="server" Text='<%# (Container.NamingContainer as GridView).PageIndex+1 %>' Columns="3" />
            <asp:LinkButton ID="btnGotoPage" runat="server" Text="Go" OnClick="GotoPage_Click"
                OnClientClick="__doPostBack($(this).attr('id').split('_').join('$'),$(this).parent().find('input:text').val());return false;" />
        </div>
    </PagerTemplate>
</asp:GridView>
protected void GotoPage_Click(object sender, EventArgs e)
{
    GridView gv = (sender as LinkButton).NamingContainer.NamingContainer as GridView;

    try
    {
        // __doPostBack 參數
        int p = int.Parse(Request.Form["__EVENTARGUMENT"]);

        if (p < 1 || p > gv.PageCount)
        {
            ClientScript.RegisterClientScriptBlock(
                GetType(),
                "f",
                "alert('錯誤頁碼!');",
                true
            );
        }
        else
        {
            gv.PageIndex = p - 1;
            gv.DataBind();
        }
    }
    catch
    {
        ClientScript.RegisterClientScriptBlock(
            GetType(),
            "f",
            "alert('錯誤頁碼!');",
            true
        );
    }
}
IDES 4.7 Installation
  1. 電腦名稱不能使用特殊名稱(bin/etc/var ...)
  2. 網路卡-> File and Printer Sharing for Microsoft Networks ->網路應用程式的資料輸送量最大化
  3. 安裝jdk1.4 (不升級)
  4. 設置JAVA_HOME
  5. 調高虛擬記憶體
  6. 安裝oracle
  7. 清空暫存資料夾 (%USERPROFILE%\Local Settings\Temp, %SystemRoot%\TEMP)
  8. 時間修改為2029年避免過期, 過晚的時間會發生無法安裝
  9. 載入export data時, 會檢查exportXX的data資料夾, 將exportXX以網路磁碟機的方式顯示在根目錄
Clipboard Usage
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.ClipboardOwner;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;

public class ClipboardUsage implements ClipboardOwner {

    public void setClipboardContents(String aString) {
        StringSelection stringSelection = new StringSelection(aString);
        Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
        clipboard.setContents(stringSelection, this);
    }

    public String getClipboardContents() {
        String result = "";
        Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
        // odd: the Object param of getContents is not currently used
        Transferable contents = clipboard.getContents(null);
        boolean hasTransferableText = (contents != null) && contents.isDataFlavorSupported(DataFlavor.stringFlavor);
        if (hasTransferableText) {
            try {
                result = (String) contents.getTransferData(DataFlavor.stringFlavor);
            } catch (UnsupportedFlavorException ex) {
                // highly unlikely since we are using a standard DataFlavor
                System.out.println(ex);
                ex.printStackTrace();
            } catch (IOException ex) {
                System.out.println(ex);
                ex.printStackTrace();
            }
        }
        return result;
    }

    @Override
    public void lostOwnership(Clipboard clipboard, Transferable contents) {

    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        ClipboardUsage cu = new ClipboardUsage();
        System.out.printf("Clipboard : %s%n", cu.getClipboardContents());
        cu.setClipboardContents("clipboard test.");
        System.out.printf("Clipboard : %s%n", cu.getClipboardContents());
    }

}
Fill zero in front of number
SQL Server:
select replicate('0', (10-len('123')))+'123'
Oracle:
SELECT LPad('123',10,'0') FROM dual
DB2:
values char(repeat('0',10-length('123'))||'123',10)
DataList paging
//利用PageDataSource來做分頁功能
PagedDataSource pds = new PagedDataSource();
//將PageDataSource綁定SqlDataSource
pds.DataSource = SqlDataSource1.Select(DataSourceSelectArguments.Empty);
pds.AllowPaging = true;
// 分頁大小
pds.PageSize = 6;

int PageIndex;
//分頁參數
if (!string.IsNullOrEmpty(Request.QueryString["Page"]) && int.TryParse(Request.QueryString["Page"], out PageIndex))
{
    PageIndex = Convert.ToInt32(Request.QueryString["Page"]);
}
else
{
    PageIndex = 1;
}

pds.CurrentPageIndex = PageIndex - 1;

// 最後一頁
if (!pds.IsLastPage)
{
    hlNext.NavigateUrl = Request.CurrentExecutionFilePath + "?Page=" + Convert.ToString(PageIndex + 1);
    if (Request.QueryString["type"] != null) hlNext.NavigateUrl += "&type=" + Request.QueryString["type"];
}
else
{
    hlNext.Visible = false;
}


//將DataList綁定PageDataSource
this.DataList1.DataSource = pds;
this.DataList1.DataBind();
JTable : multi line cell
table.getColumnModel().getColumn(i).setCellRenderer(new DefaultTableCellRenderer() {
    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
        String v = (String) value;
        String[] vs = v.split("\n");

        JPanel p = new JPanel(new GridLayout(vs.length, 1)) {
            @Override
            public void setForeground(Color fg) {
                for (int i = 0; i < getComponentCount(); i++) {
                    getComponent(i).setForeground(fg);
                }
                super.setForeground(fg);
            }

            @Override
            public void setBackground(Color bg) {
                for (int i = 0; i < getComponentCount(); i++) {
                    getComponent(i).setBackground(bg);
                }
                super.setBackground(bg);
            }
        };

        // 內容
        for (String s : vs) {
            JLabel l = new JLabel(s, JLabel.LEFT);
            l.setOpaque(true);
            p.add(l);
        }
        // 列高
        table.setRowHeight(row, table.getRowHeight() * vs.length);

        // 顏色設定
        p.setOpaque(true);
        p.setBackground(Color.white);

        // 變更背景及字體 顏色同, 同時變更內部元件的顏色
        if (isSelected) {
            p.setBackground(UIManager.getColor("Table.selectionBackground"));
            p.setForeground(UIManager.getColor("Table.selectionForeground"));
        }

        if (hasFocus) {
            p.setBorder(UIManager.getBorder("Table.focusCellHighlightBorder"));

            if (table.isCellEditable(row, column)) {
                p.setForeground(UIManager.getColor("Table.focusCellForeground"));
                p.setBackground(UIManager.getColor("Table.focusCellBackground"));
            }
        } else {
            p.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
        }

        return p;
    }
});
focus on validating
function focusOnInvalidControl() {
    for (var i = 0; i < Page_Validators.length; i++) {
        if (!Page_Validators[i].isvalid) {
            document.getElementById(Page_Validators[i].controltovalidate).focus();
            return;
        }
    }
}
Programmingly end cell edit mode of jtable
// The following code saves the current value in the cell being edited
// and stops the editing process:
if (table.getCellEditor() != null) {
    table.getCellEditor().stopCellEditing();
}
// The following code discards any changes made by the user and stops
// the editing process:
if (table.getCellEditor() != null) {
    table.getCellEditor().cancelCellEditing();
}
Test polymorphism in reflection method invoke
package y11.m04;

import java.lang.reflect.Method;

public class d28t01 {

    /**
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
        // Test polymorphism in reflection
        Object invoker = new Invoker();
        Class clazz = invoker.getClass();

        Dialer p1 = new Phone("12345");
        Phone p2 = new Phone("234567");
        CellPhone p3 = new CellPhone("345678");

        // cause java.lang.NosuchMethodException
        try {
            Method m1 = clazz.getDeclaredMethod("use", p1.getClass());
            m1.invoke(invoker, p1);
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            Method m2 = clazz.getDeclaredMethod("use", p2.getClass());
            m2.invoke(invoker, p1);
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            Method m3 = clazz.getDeclaredMethod("use", p3.getClass());
            m3.invoke(invoker, p1);
        } catch (Exception e) {
            e.printStackTrace();
        }

        Method[] ms = clazz.getDeclaredMethods();
        for (Method m : ms) {
            if (m.getName().equals("use")) {
                Class[] paramTypes = m.getParameterTypes();
                if (paramTypes.length == 1 && paramTypes[0].isAssignableFrom(p1.getClass())) {
                    m.invoke(invoker, p1);
                }
            }

            if (m.getName().equals("use")) {
                Class[] paramTypes = m.getParameterTypes();
                if (paramTypes.length == 1 && paramTypes[0].isAssignableFrom(p2.getClass())) {
                    m.invoke(invoker, p2);
                }
            }

            if (m.getName().equals("use")) {
                Class[] paramTypes = m.getParameterTypes();
                if (paramTypes.length == 1 && paramTypes[0].isAssignableFrom(p3.getClass())) {
                    m.invoke(invoker, p3);
                }
            }
        }
    }
}

class Invoker {
    public void use(Dialer dialer) {
        if (dialer != null)
            dialer.call();
    }
}

interface Dialer {
    void call();
}

class Phone implements Dialer {
    public String number;

    public Phone(String number) {
        this.number = number;
    }

    public void call() {
        System.out.printf("Call %s%n", number);
    }
}

class CellPhone extends Phone {

    public CellPhone(String number) {
        super(number);
    }

    @Override
    public void call() {
        System.out.printf("Dial %s%n", number);
    }
}