<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 36, comments - 30, trackbacks - 0, articles - 3

    流程設計器開發一(模型部分)

    Posted on 2008-01-02 15:32 笑看人生 閱讀(3529) 評論(5)  編輯  收藏 所屬分類: Java插件開發
        我自從進入公司后,一直從事有關gef方面的開發工作,在這期間,走過不少彎路,僅僅是把GEF框架弄明白,就費了很大力氣,所以,現在想寫一點東西出來,供初學者閱讀。

        GEF(Graphical Editing Framework)是圖形化編輯器開發的工具,比較典型的應用就是IBM 的Rose,它是一個模型驅動的MVC框架,控制器(EditPart)作為模型的偵聽器,偵聽模型的變化,如果模型的屬性發生變化,它會通知控制器,控制器就會刷新模型對應的視圖(Figure)??梢钥闯瞿P秃鸵晥D之間沒有直接聯系,它們通過控制器而間接聯系,可見控制器在gef框架中有著很重要的重要。

        下面我們將從最基本的開始,介紹如何用GEF框架開發出一個流程設計器(開發工具Eclipse3.2.1包含插件包gef3.2.1和draw2d3.2.1)。

        我們首先從模型開始,流程設計器頂層模型是流程(WorkflowProcess),流程有活動和鏈接這些活動的轉移組成,其中活動又可以分為開始活動,普通活動,結束活動。理解了模型之間的組成關系,我們就可以設計模型對應的類了。由于上面提到,模型的屬性變化了,必須通知控制器,由它來刷新模型對應的視圖,所以控制器必須注冊為模型的偵聽器。由于每個模型都有相應的控制器偵聽器偵聽它屬性的變化,我們把這方面的功能都放在父類中,定義一個ModelElement父類,具體代碼如下:

     1package com.example.workflow.model;
     2 
     3import java.beans.PropertyChangeListener;
     4import java.beans.PropertyChangeSupport;
     5import java.io.IOException;
     6import java.io.ObjectInputStream;
     7import java.io.Serializable;
     8publicclass ModelElement implements Serializable{   
     9    privatestaticfinallongserialVersionUID = -5117340723140888394L;   
    10    privatetransient PropertyChangeSupport pcsDelegate = new PropertyChangeSupport(this);
    11       
    12    publicsynchronizedvoid addPropertyChangeListener(PropertyChangeListener l) {
    13       if (l == null{
    14           thrownew IllegalArgumentException();
    15       }

    16       pcsDelegate.addPropertyChangeListener(l);
    17    }

    18       
    19    protectedvoid firePropertyChange(String property, Object oldValue, Object newValue) {
    20       if (pcsDelegate.hasListeners(property)) {
    21           pcsDelegate.firePropertyChange(property, oldValue, newValue);
    22       }

    23    }

    24       
    25    privatevoid readObject(ObjectInputStream in) 
    26    throws IOException, ClassNotFoundException {
    27       in.defaultReadObject();
    28       pcsDelegate = new PropertyChangeSupport(this);
    29    }

    30    
    31    publicsynchronizedvoid removePropertyChangeListener(PropertyChangeListener l) {
    32       if (l != null{
    33           pcsDelegate.removePropertyChangeListener(l);
    34       }

    35    }

    36 
    37}

    38

    接下來我們定義流程,活動,轉移模型,讓這些模型都繼承這個父類ModelElement,我們注意到活動由開始活動,普通活動,結束活動組成,這三類活動由很多相同的屬性,例如活動的位置,名稱,大小等等,所以給這三類活動進行抽象,定義一個父類AbstractActivity,把這些公共屬性都放在這個父類中,父類的代碼如下:

      1package com.example.workflow.model;
      2 
      3import java.util.ArrayList;
      4import java.util.List;
      5 
      6import org.eclipse.draw2d.geometry.Dimension;
      7import org.eclipse.draw2d.geometry.Point;
      8 
      9/**
     10 * Abstract prototype of a Activity.
     11 * Has a size (width and height), a location (x and y position) and a list of incoming
     12 * and outgoing connections. Use subclasses to instantiate a specific Activity.
     13 * @see com.example.workflow.model.Activity
     14 * @see com.example.workflow.model.StartActivity
     15 * @see com.example.workflow.model.EndActivity
     16 */

     17public class AbstractActivity extends ModelElement{
     18    
     19    private static final long serialVersionUID = 3023802629976246906L
     20    /** Property ID to use when the location of this Activity is modified. */
     21    public static final String LOCATION_PROP = "Activity.Location";
     22    /** Property ID to use then the size of this Activity is modified. */
     23    public static final String SIZE_PROP = "Activity.Size";
     24    /** ID for the Name property value (used for by the corresponding property descriptor). */
     25    public static final String NAME_PROP = "Activity.Name";
     26    
     27    /** Property ID to use when the list of outgoing transitions is modified. */
     28    public static final String SOURCE_TRANSITIONS_PROP = "Activity.SourceTran";
     29    /** Property ID to use when the list of incoming transitions is modified. */
     30    public static final String TARGET_TRANSITIONS_PROP = "Activity.TargetTran";
     31    /** ID for the Width property value (used for by the corresponding property descriptor). */
     32    private static final String WIDTH_PROP = "Activity.Width";
     33    /** ID for the X property value (used for by the corresponding property descriptor). */
     34    private static final String XPOS_PROP = "Activity.xPos";
     35    /** ID for the Y property value (used for by the corresponding property descriptor). */
     36    private static final String YPOS_PROP = "Activity.yPos";
     37    
     38    
     39    /** Name of this Activity. */
     40    private String name = new String("");
     41    /** Location of this Activity. */
     42    private Point location = new Point(00);
     43    /** Size of this Activity. */
     44    private Dimension size = new Dimension(5050);
     45    /** List of outgoing Transitions. */
     46    private List sourceTransitions = new ArrayList();
     47    /** List of incoming Transitions. */
     48    private List targetTransitions = new ArrayList();
     49    
     50    /**
     51     * Add an incoming or outgoing connection to this Activity.
     52     * @param conn a non-null Transition instance
     53     * @throws IllegalArgumentException if the Transition is null or has not distinct endpoints
     54     */

     55    void addTransition(Transition tran) {
     56       if (tran == null || tran.getSource() == tran.getTarget()) {
     57           throw new IllegalArgumentException();
     58       }

     59       if (tran.getSource() == this{
     60           sourceTransitions.add(tran);
     61           firePropertyChange(SOURCE_TRANSITIONS_PROP, null, tran);
     62       }
     else if (tran.getTarget() == this{
     63           targetTransitions.add(tran);
     64           firePropertyChange(TARGET_TRANSITIONS_PROP, null, tran);
     65       }

     66    }

     67    
     68    /**
     69     * Return the Name of this Activity.
     70     * @return name
     71     */

     72    public String getName() {
     73       return name;
     74    }

     75    
     76    /**
     77     * Return the Location of this Activity.
     78     * @return a non-null location instance
     79     */

     80    public Point getLocation() {
     81       return location.getCopy();
     82    }
       
     83    
     84    /**
     85     * Return the Size of this Activity.
     86     * @return a non-null Dimension instance
     87     */

     88    public Dimension getSize() {
     89       return size.getCopy();
     90    }

     91 
     92    /**
     93     * Return a List of outgoing Transitions.
     94     */

     95    public List getSourceTransitions() {
     96       return new ArrayList(sourceTransitions);
     97    }

     98 
     99    /**
    100     * Return a List of incoming Transitions.
    101     */

    102    public List getTargetTransitions() {
    103       return new ArrayList(targetTransitions);
    104    }

    105    
    106    /**
    107     * Remove an incoming or outgoing Transition from this Activity.
    108     * @param conn a non-null Transition instance
    109     * @throws IllegalArgumentException if the parameter is null
    110     */

    111    void removeTransition(Transition tran) {
    112       if (tran == null{
    113           throw new IllegalArgumentException();
    114       }

    115       if (tran.getSource() == this{
    116           sourceTransitions.remove(tran);
    117           firePropertyChange(SOURCE_TRANSITIONS_PROP, null, tran);
    118       }
     else if (tran.getTarget() == this{
    119           targetTransitions.remove(tran);
    120           firePropertyChange(TARGET_TRANSITIONS_PROP, null, tran);
    121       }

    122    }

    123    
    124    /**
    125     * Set the Name of this Activity.
    126     * @param newName
    127     * @throws IllegalArgumentException if the parameter is null
    128     */

    129    public void setName(String newName) {
    130       if (newName == null{
    131           throw new IllegalArgumentException();
    132       }

    133       this.name = newName;
    134       firePropertyChange(LOCATION_PROP, null, name);
    135    }

    136 
    137    /**
    138     * Set the Location of this Activity.
    139     * @param newLocation a non-null Point instance
    140     * @throws IllegalArgumentException if the parameter is null
    141     */

    142    public void setLocation(Point newLocation) {
    143       if (newLocation == null{
    144           throw new IllegalArgumentException();
    145       }

    146       location.setLocation(newLocation);
    147       firePropertyChange(LOCATION_PROP, null, location);
    148    }

    149    
    150    /**
    151     * Set the Size of this Activity.
    152     * Will not modify the size if newSize is null.
    153     * @param newSize a non-null Dimension instance or null
    154     */

    155    public void setSize(Dimension newSize) {
    156       if (newSize != null{
    157           size.setSize(newSize);
    158           firePropertyChange(SIZE_PROP, null, size);
    159       }

    160    }

    161 
    162}

    163 

    在這個類中,我們定義兩個List對象,分別對應該活動的輸入轉移和輸出轉移,因為對于一個完整的流程來說,每個活動都會轉移的(或者有輸入轉移,或者有輸出轉移,或者兩者都有),在這個類中,我們還注意到,每個改變對象屬性的方法中,都會調用firePropertyChange方法,這個方面就是通知控制器,模型的屬性發生發生變化了,讓控制器根據相應的屬性來刷新視圖。
    定義了活動的父類之后,我們就可以分別來定義開始活動,普通活動,結束活動對應的類了,具體代碼如下:
    開始活動:

     1package com.example.workflow.model;
     2 
     3public class StartActivity extends AbstractActivity{
     4    
     5    private staticfinallongserialVersionUID = 4639994300421360712L;
     6    private staticfinal String STARTACTIVITY_NAME = "START";
     7    
     8    public String getName() {       
     9       returnSTARTACTIVITY_NAME;
    10    }

    11 
    12    public String toString() {
    13       return"StartActivity " + hashCode();
    14    }

    15}

    普通活動:

     1package com.example.workflow.model;
     2 
     3 
     4public class Activity extends AbstractActivity{
     5    
     6    private staticfinallongserialVersionUID = 3023802629976246906L
     7    private staticfinal String ACTIVITY_NAME = "ACTIVITY";
     8    
     9    public String getName() {       
    10       returnACTIVITY_NAME;
    11    }

    12    public String toString() {
    13       return"Activity " + hashCode();
    14    }

    15 
    16}

    17 

    結束活動:
     1package com.example.workflow.model;
     2 
     3public class EndActivity extends AbstractActivity{   
     4    
     5    private static final long serialVersionUID = 316984190041034535L
     6    privates tatic final String ENDACTIVITY_NAME = "END";
     7    
     8    public String getName() {       
     9       returnENDACTIVITY_NAME;
    10    }

    11 
    12    public String toString() {
    13       return"EndActivity " + hashCode();
    14    }

    15 
    16}

    定義完這些活動之后,我們來定義流程模型,由于流程中包含多個活動,所以里面應該有個列表來維護這些對象,同樣,流程中還包含多個轉移,由于在活動模型中,已經維護了轉移對象,所以這里就不維護這些轉移對象了,具體代碼如下:

     1package com.example.workflow.model;
     2 
     3import java.util.ArrayList;
     4import java.util.List;
     5 
     6/**
     7 * 流程模型,可以包含多個活動和轉移模型
     8 * @author Administrator
     9 *
    10 */

    11public class WorkflowProcess extends ModelElement{       
    12       
    13       private static final long serialVersionUID = -5478693636480758659L;
    14       /** Property ID to use when a child is added to this WorkflowProcess. */
    15       public static final String CHILD_ADDED_PROP = "WorkflowProcess.ChildAdded";
    16       /** Property ID to use when a child is removed from this WorkflowProcess. */
    17       public static final String CHILD_REMOVED_PROP = "WorkflowProcess.ChildRemoved";     
    18       private List activities = new ArrayList();
    19       
    20       /** 
    21        * Add a Activity to this WorkflowProcess.
    22        * @param s a non-null Activity instance
    23        * @return true, if the Activity was added, false otherwise
    24        */

    25       public boolean addChild(Activity a) {
    26              if (a != null && activities.add(a)) {
    27                     firePropertyChange(CHILD_ADDED_PROP, null, a);
    28                     return true;
    29              }

    30              return false;
    31       }

    32 
    33       /** Return a List of Activities in this WorkflowProcess. The returned List should not be modified. */
    34       public List getChildren() {
    35              return activities;
    36       }

    37       
    38       /**
    39        * Remove a Activity from this WorkflowProcess.
    40        * @param s a non-null Activity instance;
    41        * @return true, if the Activity was removed, false otherwise
    42        */

    43       public boolean removeChild(Activity a) {
    44              if (a != null && activities.remove(a)) {
    45                     firePropertyChange(CHILD_REMOVED_PROP, null, a);
    46                     return true;
    47              }

    48              return false;
    49       }

    50}

    最后我們來定義轉移模型,我們知道轉移模型是鏈接兩個活動的,所以在轉移模型中,應該有個轉移的源活動和目標活動,同時如果兩個活動之間已經有轉移連接時,就不能再在兩者之間建立轉移了,所以在兩個活動之間建立轉移時,必須先判斷兩者之間是否已經建立轉移,所以轉移模型具體代碼如下:

     1package com.example.workflow.model;
     2 
     3/**
     4 *ATransitionbetweentwodistinctactivities.
     5 */

     6public class Transition extends ModelElement{
     7    
     8    private static final long serialVersionUID = 516473924757575767L;
     9    /**True,ifthetransitionisattachedtoitsendpoints.*/
    10    private boolean isConnected;
    11    /**Transition'ssourceendpoint.*/
    12    private AbstractActivity source;
    13    /**Transition'stargetendpoint.*/
    14    private AbstractActivity target;
    15    
    16    /**
    17     *CreateaTransitionbetweentwodistinctactivities.
    18     *@paramsourceasourceendpointforthisTransition(nonnull)
    19     *@paramtargetatargetendpointforthisTransition(nonnull)
    20     *@throwsIllegalArgumentExceptionifanyoftheparametersarenullorsource==target
    21     *@see#setLineStyle(int)
    22     */

    23    public Transition(AbstractActivity source, AbstractActivity target) {
    24       reconnect(source, target);
    25    }

    26 
    27    /**
    28     *Disconnectthisconnectionfromtheactivitiesitisattachedto.
    29     */

    30    publicvoid disconnect() {
    31       if (isConnected) {
    32           source.removeTransition (this);
    33           target.removeTransition (this);
    34           isConnected = false;
    35       }

    36    }

    37    
    38    /**
    39     *ReturnsthesourceendpointofthisTransition.
    40     *@returnanon-nullActivityinstance
    41     */

    42    public AbstractActivity getSource() {
    43       returnsource;
    44    }

    45 
    46    /**
    47     *ReturnsthetargetendpointofthisTransition.
    48     *@returnanon-nullActivityinstance
    49     */

    50    public AbstractActivity getTarget() {
    51       returntarget;
    52    }

    53 
    54    /**
    55     *ReconnectthisTransition.
    56     *TheTransitionwillreconnectwiththeactivitiesitwaspreviouslyattachedto.
    57     */
     
    58    public void reconnect() {
    59       if (!isConnected) {
    60           source.addTransition (this);
    61           target.addTransition (this);
    62           isConnected = true;
    63       }

    64    }

    65 
    66    /**
    67     *Reconnecttoadifferentsourceand/ortargetActivity.
    68     *Theconnectionwilldisconnectfromitscurrentattachmentsandreconnectto
    69     *thenewsourceandtarget.
    70     *@paramnewSourceanewsourceendpointforthisTransition(nonnull)
    71     *@paramnewTargetanewtargetendpointforthisTransition(nonnull)
    72     *@throwsIllegalArgumentExceptionifanyoftheparamersarenullornewSource==newTarget
    73     */

    74    public void reconnect(AbstractActivity newSource, AbstractActivity newTarget) {
    75       if (newSource == null || newTarget == null || newSource == newTarget) {
    76           thrownew IllegalArgumentException();
    77       }

    78       disconnect();
    79       this.source = newSource;
    80       this.target = newTarget;
    81       reconnect();
    82    }

    83}

    到這兒,模型的定義已經全部完成,下一節我們將定義GEF框架中最重要的部分,也是最復雜的部分,控制器。

    Feedback

    # re: 流程設計器開發一(模型部分)  回復  更多評論   

    2008-01-03 09:35 by yuan1129
    寫的非常好,希望能夠提供源代碼下載,謝謝。

    # re: 流程設計器開發一(模型部分)  回復  更多評論   

    2008-01-03 09:51 by 玩轉Java
    在流程設計器三中可以下載代碼。

    # re: 流程設計器開發一(模型部分)  回復  更多評論   

    2008-07-29 17:08 by zhang li guo
    知道你是誰了。 :)

    還記得你剛進公司的第一天談話。那些天,做引擎的單元測試,感覺做的一般。
    后來就讓你全心做設計器了。 :)

    三年很快過完了。

    說句實話,我非常懷念那段開發產品的日子,充滿激情和夢想……
    也很有幸,后來我們臨別前在投標項目中又合作一把。

    最近我業余時間,在和一個老外合作一個eclipse插件,有空來看看
    http://code.google.com/p/camel-route-viewer/

    離你的eclipse水平差遠了。

    :)

    # re: 流程設計器開發一(模型部分)  回復  更多評論   

    2008-07-29 17:09 by zhang li guo
    MSN:catflame AT msn.com
    加我

    # re: 流程設計器開發一(模型部分)  回復  更多評論   

    2010-03-22 21:24 by 楊志斌
    很強大
    主站蜘蛛池模板: 亚洲综合另类小说色区| 免费A级毛片无码久久版| 好男人视频在线观看免费看片| 最近中文字幕无免费视频| 日本免费网站在线观看| 亚洲成AV人在线观看网址| 亚洲色自偷自拍另类小说| 久久91亚洲精品中文字幕| 亚洲伊人久久精品| 久久精品国产亚洲AV电影网| 一级毛片完整版免费播放一区| 免费av一区二区三区| jjizz全部免费看片| 免费jjzz在线播放国产| 久久亚洲一区二区| 亚洲AV成人影视在线观看| 添bbb免费观看高清视频| 成人影片一区免费观看| 18禁网站免费无遮挡无码中文| 国产免费av片在线无码免费看| 亚洲精品乱码久久久久久久久久久久| 亚洲高清不卡视频| 美女视频黄a视频全免费网站色| 成全视频免费观看在线看| 一本无码人妻在中文字幕免费| 亚洲国产人成精品| 亚洲视频网站在线观看| 国产精品亚洲专一区二区三区| 可以免费观看的国产视频| 成人免费在线观看网站| 久久久久亚洲AV无码专区桃色 | 久久精品a一国产成人免费网站| 免费在线视频一区| 亚洲资源在线观看| 成人亚洲国产精品久久| 七色永久性tv网站免费看| 四虎影院免费视频| 亚洲va在线va天堂va不卡下载 | 亚洲丰满熟女一区二区v| 九九久久精品国产免费看小说 | 女人18毛片水真多免费看|