View Javadoc

1   /*
2    WSMO Studio - a Semantic Web Service Editor
3    Copyright (c) 2004-2007, Ontotext Lab. / SIRMA Group
4   
5    This library is free software; you can redistribute it and/or modify it under
6    the terms of the GNU Lesser General Public License as published by the Free
7    Software Foundation; either version 2.1 of the License, or (at your option)
8    any later version.
9    This library is distributed in the hope that it will be useful, but WITHOUT
10   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11   FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12   details.
13   You should have received a copy of the GNU Lesser General Public License along
14   with this library; if not, write to the Free Software Foundation, Inc.,
15   59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16   */
17  
18  /***
19   * <p>Title: WSMO Studio</p>
20   * <p>Description: Semantic Web Service Editor</p>
21   * <p>Copyright:  Copyright (c) 2004-2007</p>
22   * <p>Company: Ontotext Lab. / SIRMA </p>
23   */
24  
25  package org.wsmostudio.bpmo.model.connectors;
26  
27  import java.beans.PropertyChangeListener;
28  import java.beans.PropertyChangeSupport;
29  import java.util.*;
30  
31  import org.eclipse.draw2d.Bendpoint;
32  import org.eclipse.draw2d.Graphics;
33  import org.eclipse.jface.dialogs.InputDialog;
34  import org.eclipse.jface.resource.JFaceResources;
35  import org.eclipse.jface.window.Window;
36  import org.eclipse.swt.widgets.Display;
37  import org.wsmo.common.IRI;
38  import org.wsmostudio.bpmo.model.*;
39  import org.wsmostudio.runtime.WSMORuntime;
40  import org.wsmostudio.runtime.WsmoImageRegistry;
41  import org.wsmostudio.ui.IdentifierInputDialog;
42  
43  public abstract class GraphConnector {
44  
45      public static final Integer SOLID_CONNECTION = new Integer(Graphics.LINE_SOLID);
46      public static final Integer DASHED_CONNECTION = new Integer(Graphics.LINE_DASHDOT);
47      public static final Integer DOT_CONNECTION = new Integer(Graphics.LINE_DOT);
48  
49      
50      /*** Property ID to use when the line style of this connection is modified. */
51      public static final String LINESTYLE_PROP = "LineStyle";
52      private static final long serialVersionUID = 1;
53  
54      private transient PropertyChangeSupport pcsDelegate = new PropertyChangeSupport(this);
55  
56      /*** True, if the connection is attached to its endpoints. */ 
57      private boolean isConnected;
58      /*** Line drawing style for this connection. */
59      private int lineStyle = Graphics.LINE_SOLID;
60  
61      private WorkflowEntityNode source;
62      private WorkflowEntityNode target;
63      
64  	protected WorkflowProperty nameProp = 
65  	    new WorkflowProperty(Consts.PROP_CONDITION, 
66  	            JFaceResources.getImage(WsmoImageRegistry.DATA_VALUE_ICON),
67  	            new String[] {Consts.ACTION_SET_LABEL}, false, 
68  	            WorkflowProperty.defaultValueEditOrRemovePolicies);
69  
70      protected WorkflowProperty identifierProp = new WorkflowProperty(Consts.PROP_ID, 
71              JFaceResources.getImage(WsmoImageRegistry.IRI_ICON),
72              new String[] {Consts.ACTION_CHANGE_ID}, false, 
73              new String[] {Consts.ACTION_CHANGE_ID});
74  
75      public String getLabel() {
76          return (String)this.nameProp.getSingleValue();
77      }
78      
79      public void setLabel(String lab) {
80          
81      	String oldLab = getLabel();
82      	this.nameProp.addValue(lab);
83          firePropertyChange("name", oldLab, lab);
84      }
85  
86      public IRI getIdentifier() {
87          return (IRI)this.identifierProp.getSingleValue();
88      }
89  
90      public void setIdentifier(IRI id) {
91          this.identifierProp.addValue(id);
92      }
93  
94  
95      protected String m_sourceTerminal = "";
96      protected String m_targetTerminal = "";
97  
98      public void setSourceTerminal(String s){
99          m_sourceTerminal = s;
100     }
101     public void setTargetTerminal(String s){
102         m_targetTerminal = s;
103     }
104     public String getSourceTerminal() {
105         return m_sourceTerminal;
106     }
107     public String getTargetTerminal() {
108         return m_targetTerminal;
109     }
110 
111     
112     /*** 
113      * Create a (solid) connection between two distinct shapes.
114      * @param source a source endpoint for this connection (non null)
115      * @param target a target endpoint for this connection (non null)
116      * @throws IllegalArgumentException if any of the parameters are null or source == target
117      * @see #setLineStyle(int) 
118      */
119     public GraphConnector(WorkflowEntityNode source, 
120                           String sourceTerminal,
121                           WorkflowEntityNode target,
122                           String targetTerminal) {
123         super();
124     	if (sourceTerminal != null) {
125             setSourceTerminal(sourceTerminal);
126         }
127         if (targetTerminal != null) {
128             setTargetTerminal(targetTerminal);
129         }
130         reconnect(source, target);
131     }
132 
133     /*** 
134      * Disconnect this connection from the shapes it is attached to.
135      */
136     public void disconnect() {
137         if (isConnected) {
138             source.removeOutConnection(this);
139             target.removeInConnection(this);
140             isConnected = false;
141             firePropertyChange("", null, null);
142         }
143     }
144 
145 
146     /*** 
147      * Attach a non-null PropertyChangeListener to this object.
148      * @param l a non-null PropertyChangeListener instance
149      * @throws IllegalArgumentException if the parameter is null
150      */
151     public synchronized void addPropertyChangeListener(PropertyChangeListener l) {
152         if (l == null) {
153             throw new IllegalArgumentException();
154         }
155         pcsDelegate.addPropertyChangeListener(l);
156     }
157 
158     /*** 
159      * Report a property change to registered listeners (for example edit parts).
160      * @param property the programmatic name of the property that changed
161      * @param oldValue the old value of this property
162      * @param newValue the new value of this property
163      */
164     protected void firePropertyChange(String property, Object oldValue, Object newValue) {
165         if (pcsDelegate.hasListeners(property)) {
166             pcsDelegate.firePropertyChange(property, oldValue, newValue);
167         }
168     }
169 
170     /*** 
171      * Remove a PropertyChangeListener from this component.
172      * @param l a PropertyChangeListener instance
173      */
174     public synchronized void removePropertyChangeListener(PropertyChangeListener l) {
175         if (l != null) {
176             pcsDelegate.removePropertyChangeListener(l);
177         }
178     }
179     
180     public void notifyContentChanged() {
181     	if (this.source != null) {
182     		this.source.notifyContentChanged();
183     	}
184     	else if (this.target != null) {
185     		this.target.notifyContentChanged();
186     	}
187     }
188 
189     public int getLineStyle() {
190         return lineStyle;
191     }
192     
193     public List<WorkflowProperty> listSupportedProperties() {
194         return new LinkedList<WorkflowProperty>();
195     }
196 
197 
198     public boolean handleAction(String actionID, WorkflowProperty prop, Object value) {
199         if (actionID.equals(Consts.ACTION_CHANGE_ID)) {
200             IdentifierInputDialog idDialog = new IdentifierInputDialog(
201                     Display.getCurrent().getActiveShell(),
202                     "Edit Identifier",
203                     "IRI",
204                     (getIdentifier() == null) ? "" : getIdentifier().toString(),
205                     getSource().getTopContainer().getNSHolder(),
206                     WSMORuntime.getRuntime().getWsmoFactory(),
207                     false);
208             if (idDialog.open() != Window.OK) {
209                 return false;
210             }
211             IRI newID = (IRI)idDialog.getIdentifier();
212             if (false == newID.equals(getIdentifier())) {
213                 setIdentifier(newID);
214                 return true;
215             }
216         }
217     	if (actionID.equals(Consts.ACTION_SET_LABEL)) {
218     		InputDialog dialog = new InputDialog(
219     				Display.getCurrent().getActiveShell(),
220                     "New Connection Condition",
221                     "Expression : ",
222                     this.getLabel(),
223                     null);
224             if (dialog.open() != Window.OK) {
225                 return false;
226             }
227             String newName = dialog.getValue();
228             if (newName == null 
229             		|| newName.trim().length() == 0) {
230             	if (this.getLabel() != null) {
231             		prop.removeValue(this.getLabel());
232                     firePropertyChange("name", null, newName);
233             	    return true;
234             	}
235             }
236             else {
237             	prop.addValue(newName);
238                 firePropertyChange("name", null, newName);
239         	    return true;
240             }
241         }
242         if (actionID.equals("Edit")) {
243             InputDialog dialog = new InputDialog(
244                     Display.getCurrent().getActiveShell(),
245                     "New Connection Condition",
246                     prop.toString() + " : ",
247                     (String)value,
248                     null);
249             if (dialog.open() != Window.OK) {
250                 return false;
251             }
252             String newValue = dialog.getValue();
253             if (newValue == null 
254             		|| newValue.trim().length() == 0) {
255             	    prop.removeValue(this.getLabel());
256                     firePropertyChange("name", null, newValue);
257             	    return true;
258             }
259             else {
260             	prop.addValue(newValue);
261                 firePropertyChange("name", null, newValue);
262         	    return true;
263             }
264         }
265         if (actionID.equals("Remove")) {
266         	prop.removeValue(value);
267             firePropertyChange("name", value, null);
268     	    return true;
269         }
270 
271 
272 	return false;
273     }
274 
275     /***
276      * Returns the source endpoint of this connection.
277      * @return a non-null Shape instance
278      */
279     public WorkflowEntityNode getSource() {
280         return source;
281     }
282 
283     /***
284      * Returns the target endpoint of this connection.
285      * @return a non-null Shape instance
286      */
287     public WorkflowEntityNode getTarget() {
288         return target;
289     }
290 
291     /*** 
292      * Reconnect this connection. 
293      * The connection will reconnect with the shapes it was previously attached to.
294      */  
295     public void reconnect() {
296         if (!isConnected) {
297             target.addInConnection(this);
298             source.addOutConnection(this);
299             isConnected = true;
300             firePropertyChange("", null, null);
301         }
302     }
303 
304     /***
305      * Reconnect to a different source and/or target shape.
306      * The connection will disconnect from its current attachments and reconnect to 
307      * the new source and target. 
308      * @param newSource a new source endpoint for this connection (non null)
309      * @param newTarget a new target endpoint for this connection (non null)
310      * @throws IllegalArgumentException if any of the paramers are null or newSource == newTarget
311      */
312     public void reconnect(WorkflowEntityNode newSource, WorkflowEntityNode newTarget) {
313         if (newSource == null || newTarget == null || newSource == newTarget) {
314             throw new IllegalArgumentException();
315         }
316         WorkflowEntityNode oldSource = this.source;
317         disconnect();
318         this.source = newSource;
319         this.target = newTarget;
320         if (this instanceof ControlflowArc 
321                 && false == newSource.equals(oldSource)
322                 && ((ControlflowArc)this).isDefaultBranch()) {
323             ((ControlflowArc)this).setDefaultBranch(false);
324         }
325         reconnect();
326     }
327 
328     /***
329      * Set the line drawing style of this connection.
330      * @param lineStyle one of following values: Graphics.LINE_DASH or Graphics.LINE_SOLID
331      * @see Graphics#LINE_DASH
332      * @see Graphics#LINE_SOLID
333      * @throws IllegalArgumentException if lineStyle does not have one of the above values
334      */
335     public void setLineStyle(int lineStyle) {
336         this.lineStyle = lineStyle;
337         firePropertyChange(LINESTYLE_PROP, null, new Integer(this.lineStyle));
338     }
339 
340 
341     /*** List of bendpoint model object associated with current connection model object. */
342     protected List<Bendpoint> bendpoints = new ArrayList<Bendpoint>();
343 
344     /*** Returns the list of bendpoints model objects. */
345     public List<Bendpoint> getBendpoints() {
346         return bendpoints;
347     }
348 
349     public void insertBendpoint(int index, Bendpoint point) {
350         getBendpoints().add(index, point);
351         firePropertyChange("bendpoint", null, null);
352     }
353 
354     /***
355      * Removes a bendpoint.
356      **/
357     public void removeBendpoint(int index) {
358         getBendpoints().remove(index);
359         firePropertyChange("bendpoint", null, null);
360     }
361 
362     /***
363      * Sets another location for an existing bendpoint.
364      **/
365     public void setBendpoint(int index, Bendpoint point)
366     {
367         getBendpoints().set(index, point);
368         firePropertyChange("bendpoint", null, null);
369     }
370     
371     public void cloneProperties(GraphConnector conn) {
372         conn.setSourceTerminal(getSourceTerminal());
373         conn.setTargetTerminal(getTargetTerminal());
374         conn.setLineStyle(getLineStyle());
375         if (getLabel() != null) {
376             conn.setLabel(getLabel());
377         }
378     }
379     
380     public String toString() {
381         return source + " => " + target;
382     }
383 
384 }
385 /*
386  * $Log$
387  * Revision 1.4  2007/09/17 13:10:23  alex_simov
388  * bpmo properties update
389  *
390  * Revision 1.3  2007/09/15 14:23:16  alex_simov
391  * general rework
392  *
393  * Revision 1.2  2007/08/21 15:29:18  alex_simov
394  * no message
395  *
396  * Revision 1.1  2007/08/17 14:39:05  alex_simov
397  * gui model update
398  *
399  * Revision 1.6  2007/08/01 15:47:23  alex_simov
400  * ui model refactoring: classnames are suffixed by "Node" to avoid name
401  * clashes with BPMO-API entities
402  *
403  * Revision 1.5  2007/04/11 08:48:04  alex_simov
404  * no message
405  *
406  * Revision 1.4  2007/04/06 16:36:50  alex_simov
407  * no message
408  *
409  * Revision 1.3  2007/04/03 17:38:36  alex_simov
410  * no message
411  *
412  * Revision 1.2  2007/03/20 12:42:22  alex_simov
413  * default deserialization fix
414  *
415  * Revision 1.1  2007/03/20 10:05:46  alex_simov
416  * SBP modeller initial version
417  *
418  */