KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > enhydra > jawe > WorkflowManager


1 /* WorkflowManager.java
2  *
3  * Authors:
4  * Stefanovic Nenad chupo@iis.ns.ac.yu
5  * Bojanic Sasa sasaboy@neobee.net
6  * Puskas Vladimir vpuskas@eunet.yu
7  * Pilipovic Goran zboniek@uns.ac.yu
8  * Harald Meister harald.meister@abacus.ch
9  *
10  */

11
12 package org.enhydra.jawe;
13
14 import org.enhydra.jawe.PackageEditor;
15 import org.enhydra.jawe.graph.*;
16 import org.enhydra.jawe.xml.*;
17 import org.enhydra.jawe.xml.elements.Activities;
18 import org.enhydra.jawe.xml.elements.ActivitySet;
19 import org.enhydra.jawe.xml.elements.ActivitySets;
20 import org.enhydra.jawe.xml.elements.Join;
21 import org.enhydra.jawe.xml.elements.Package;
22 import org.enhydra.jawe.xml.elements.Participants;
23 import org.enhydra.jawe.xml.elements.Performer;
24 import org.enhydra.jawe.xml.elements.Split;
25 import org.enhydra.jawe.xml.elements.Transitions;
26 import org.enhydra.jawe.xml.elements.WorkflowProcess;
27 import org.enhydra.jawe.xml.elements.WorkflowProcesses;
28
29 import org.jgraph.graph.*;
30 import org.jgraph.*;
31
32 import java.util.*;
33 import java.awt.*;
34 import java.awt.geom.Point2D JavaDoc;
35 import java.awt.geom.Rectangle2D JavaDoc;
36 import javax.swing.*;
37 import javax.swing.tree.*;
38
39 import java.io.*;
40
41 /**
42  * Class intended to serve as a control center for creation, removal,
43  * resizing and changing position of Participants as well as for
44  * doing the same things with Activity objects and Transitions. Class
45  * manages this actions in such a way that undoing of operations are
46  * possible. It incorporates multiple view and model changes into one
47  * by doing them virtually, and after all changes are done, in interaction
48  * with JaWEGraphModel class applies this changes so that undo is possible.
49  * Instance of this class is joined to to all objects of classes derived
50  * from AbstractGraph class (PackageGraph, ProcessGraph and BlockActivityGraph).
51  * <p> This class also handles the relationships between visual and logical
52  * representation of workflow graph.
53  * <p> When reading a package from an XML file, this class creates imported
54  * objects and establishes relationship between graph objects (classes within
55  * jawe and jawe.graph package) and 'graph logic' objects (
56  * classes within jawe.xml package).
57  */

58 public class WorkflowManager implements Serializable {
59
60    /** Graph reference */
61    private transient AbstractGraph graph;
62
63    /**
64     * Offset for drawing - no meaning (it was used in previous versions)
65     */

66    private int horizontalOffset=0;
67
68    // some default values for setting participants and activity sizes
69
/** Variable that holds width of process */
70    private static final int defProcessWidth=JaWEConfig.getInstance().getProcessWidth();
71    /** Variable that holds height of process */
72    private static final int defProcessHeight=JaWEConfig.getInstance().getProcessHeight();
73    /** Variable that holds minimum width for any participant */
74    private static final int minParWidth=JaWEConfig.getInstance().getMinParticipantWidth();
75    /** Variable that holds minimum height for any participant */
76    private static final int minParHeight=JaWEConfig.getInstance().getMinParticipantHeight();
77    /** Variable that holds the width for participant name section*/
78    private static final int defParNameWidth=JaWEConfig.getInstance().getParticipantNameWidth();
79    /** Variable that holds width of activities */
80    private static final int defActivityWidth=JaWEConfig.getInstance().getActivityWidth();
81    /** Variable that holds height of activities */
82    private static final int defActivityHeight=JaWEConfig.getInstance().getActivityHeight();
83
84    private boolean creatingGraph=false;
85
86    /**
87     * Creates new workflow manager for given graph.
88     * @param g The graph that manager manages.
89     */

90    public WorkflowManager (AbstractGraph g) {
91       this.graph=g;
92    }
93
94    /** Returns the graph which is managed. */
95    public AbstractGraph getGraph () {
96       return graph;
97    }
98
99    /**
100     * Returns the object representing the main element of XML file that
101     * defines the workflow model logic.
102     */

103    public Package JavaDoc getXMLPackage () {
104       return graph.getXMLPackage();
105    }
106
107    /**
108     * Returns the graph model - the model that represents the graph view.
109     * (See JGraph documentation).
110     */

111    public JaWEGraphModel graphModel () {
112       return (JaWEGraphModel)graph.getModel();
113    }
114
115    /**
116     * Creates graph representation of given workflow process. It creates a graph
117     * entities (participants, activities, transitions) and associates
118     * the workflow logic to it. The graph entities are inserted according
119     * to the data that <tt>wp</tt> object holds (the data from XML file).
120     * <p>This is used when reading a workflow definition from an XML file.
121     * @param wp Object that mapps the logic of WorkflowProcess element
122     * of XML - defines a particular Workflow process.
123     */

124    public void createWorkflowGraph (WorkflowProcess wp) {
125       creatingGraph=true;
126       // checks if it is graph made by JaWE
127
boolean isMine=true;
128       if (!getXMLPackage().isMadeByJaWE()) {
129          isMine=false;
130       }
131       //********* the creation other is very important and shouldn't be changed
132
//System.out.println("Creating graph for WP "+wp+" and VO="+getVisualOwner());
133

134       java.util.List JavaDoc entitiesToInsert=wp.getEntitiesToInsert(getVisualOwner());
135
136       //System.out.println("Entities to insert="+entitiesToInsert);
137
// show Participants
138
createGraphParticipants(wp,entitiesToInsert);
139
140       // showing Activities
141
createGraphActivitiesAndBlockActivities(wp,entitiesToInsert,isMine);
142
143       // show transitions
144
createGraphTransitions(wp,entitiesToInsert,isMine);
145
146       // show start
147
if (JaWEConfig.getInstance().getUseBubblesStatus()) {
148          createGraphStarts(wp,isMine,false);
149
150          // show ends
151
createGraphEnds(wp,isMine,false);
152       }
153
154       // if workflow model is not created by JaWE, perform some
155
// kind of layout, and create start and end objects
156
if (!isMine) {
157          layoutActivities();
158          ProcessEditor pe=(ProcessEditor)graph.getEditor();
159          Set startDescs=Utils.getStartDescriptions(pe);
160          Set endDescs=Utils.getEndDescriptions(pe);
161          XMLComplexElement vo=getVisualOwner();
162          if (vo instanceof WorkflowProcess) {
163             ((WorkflowProcess)vo).setStartDescriptions(startDescs);
164             ((WorkflowProcess)vo).setEndDescriptions(endDescs);
165          } else {
166             ((org.enhydra.jawe.xml.elements.Activity)vo).
167                setStartDescriptions(startDescs);
168             ((org.enhydra.jawe.xml.elements.Activity)vo).
169                setEndDescriptions(endDescs);
170          }
171       }
172       creatingGraph=false;
173       try {
174          Dimension prefSize=new Dimension(getRootParticipantWidth(null,null)+50,
175                                           getNewRootParYPos(null,null)+50);
176          graph.setPreferredSize(prefSize);
177       } catch (Exception JavaDoc ex) {}
178    }
179
180    /**
181     * Returns the object (part of mapped XML logic) that is represented by
182     * the graph managed by WorklowManager. That object can be instance
183     * of the Package, WorkflowProcess or ...xml.elements.BlockActivity class,
184     * and is held as a property of the manager's graph object.
185     * @return The object (representing XML logic) that is represented
186     * by this manager's graph.
187     */

188    public XMLComplexElement getVisualOwner () {
189       if (graph instanceof BlockActivityGraph) {
190          return (org.enhydra.jawe.xml.elements.Activity)
191             ((BlockActivityGraph)graph).getMyBlockActivity().getUserObject();
192       } else if (graph instanceof ProcessGraph) {
193          return (WorkflowProcess)graph.getPropertyObject();
194       } else {
195          return (Package JavaDoc)graph.getPropertyObject();
196       }
197    }
198
199    /**
200     * Returns the (XML logic) Activities object, that holds all
201     * (XML logic) Activity objects which graphical representation
202     * is managed by this workflow manager. That could be activites
203     * belonging directly to the WorkflowProcess, or activities
204     * belonging to the BlockActivity element. If this is a manager
205     * of Package graph, <tt>null</tt> is returned.
206     */

207    private Activities getActivitiesCollection () {
208       Activities acts;
209       XMLComplexElement myOwner=getVisualOwner();
210       if (myOwner instanceof WorkflowProcess) {
211          acts=(Activities)myOwner.get("Activities");
212       } else {
213          BlockActivity ba=((BlockActivityGraph)graph).getMyBlockActivity();
214          ActivitySet as=getBlockActivitySet(ba);
215          acts=(Activities)as.get("Activities");
216       }
217       return acts;
218    }
219
220    /**
221     * Returns the (XML logic) Transitions object, that holds all
222     * (XML logic) Transition objects which graphical representation
223     * is managed by this workflow manager. That could be transitions
224     * belonging directly to the WorkflowProcess, or transitions
225     * belonging to the BlockActivity element. If this is a manager
226     * of Package graph, <tt>null</tt> is returned.
227     */

228    public Transitions getTransitionsCollection () {
229       Transitions trans;
230       XMLComplexElement myOwner=getVisualOwner();
231       if (myOwner instanceof WorkflowProcess) {
232          trans=(Transitions)myOwner.get("Transitions");
233       } else {
234          BlockActivity ba=((BlockActivityGraph)graph).getMyBlockActivity();
235          ActivitySet as=getBlockActivitySet(ba);
236          trans=(Transitions)as.get("Transitions");
237       }
238       return trans;
239    }
240
241    /**
242     * Returns the (XML logic) ActivitySet object that is associated
243     * to the given graph's object logic.
244     */

245    private ActivitySet getBlockActivitySet (BlockActivity ba) {
246       try {
247          String JavaDoc ID=ba.getBlockID();
248          ActivitySet as=((ActivitySets)getWorkflowProcess().
249                             get("ActivitySets")).getActivitySet(ID);
250          return as;
251       } catch (Exception JavaDoc ex) {
252          return null;
253       }
254    }
255
256    /**
257     * Returns the (XML logic) WorkflowProcess object that is
258     * represented by the manager's graph, or (if the graph
259     * represents the (XML logic) BlockActivity content) the
260     * WorkflowProcess object that holds BlockActivity represented
261     * by manager's graph. If graph represents (XML logic) Package
262     * object, <tt>null</tt> is returned.
263     */

264    private WorkflowProcess getWorkflowProcess () {
265       if (graph.getPropertyObject() instanceof WorkflowProcess) {
266          return (WorkflowProcess)graph.getPropertyObject();
267       } else {
268          return null;
269       }
270    }
271
272    /**
273     * Inserts new process cell into (graph) model and creates
274     * new (XML logic) WorkflowProcess object. Depending on
275     * <tt>updateCollection</tt> parameter, it calls the method
276     * that updates the collection of existing WorkflowProcess
277     * objects (it is set to <tt>true</tt> when user inserts the
278     * new WorkflowProcess into the Package graph, and to <tt>false</tt>
279     * during importing from XML).
280     * @param p The position within the graph where
281     * the process cell should be inserted.
282     * @param updateCollection <tt>true</tt> if collection of
283     * WorkflowProcess objects should be
284     * updated (user inserts object), and
285     * <tt>false</tt> if not (XML file is
286     * importing, and objects are constructed
287     * depending on data held within the file).
288     * @return The created graph object.
289     */

290    public org.enhydra.jawe.graph.Process insertProcess (Point p,boolean updateCollection) {
291       Point realP=(Point)graph.fromScreen(new Point(p));//HM, JGraph3.4.1
292
int ulx=realP.x;
293       int uly=realP.y;
294       Rectangle bounds=new Rectangle(ulx,uly,defProcessWidth,defProcessHeight);
295
296       Map viewMap = new Hashtable();
297       Map map = GraphConstants.createMap();
298
299       org.enhydra.jawe.graph.Process pr =
300          new org.enhydra.jawe.graph.Process((PackageEditor)getGraph().getEditor());
301       WorkflowProcess wp=new WorkflowProcess((WorkflowProcesses)getXMLPackage().
302                                                 get("WorkflowProcesses"),getXMLPackage());
303       wp.get("Name").setValue(ResourceManager.getLanguageDependentString("ProcessKey"));
304       pr.setUserObject(wp);
305
306       GraphConstants.setBounds(map,bounds);
307       GraphConstants.setOpaque(map,true);
308       GraphConstants.setBorderColor(map,Color.darkGray);
309       GraphConstants.setFont(map,GraphConstants.defaultFont.deriveFont(JaWEConfig.getInstance().getFontSize()));
310
311       viewMap.put(pr,map);
312       Object JavaDoc[] insert = new Object JavaDoc[]{pr};
313       // makes all changes (if there was any) - to model and to view
314
String JavaDoc actionName=
315          ResourceManager.getLanguageDependentString("MessageInsertingProcessIntoPackage");
316       graphModel().insertAndEdit(insert,viewMap,null,null,null,actionName);
317
318       if (updateCollection) {
319          refreshCollections (insert,true);
320       }
321
322       return pr;
323    }
324
325    /**
326     * Inserts cells <b>insert</b> into model. First, the parent of cells is
327     * searched, and when found, put into ParentMap object (they are not
328     * inserted into model at ones). After that model's view is arranged
329     * (Participants are moved and translated along with it's children cells)
330     * to suite to the new model state - this is done "virtually" which
331     * means that changes are not directly applied to view until all
332     * changes are made. At the end, all changes are applied to model and view.
333     * Such procedure enables compound undo support.
334     * <BR> This method is called when pasting cells into model.
335     * @see #updateModelAndArrangeParticipants
336     */

337    public void insertCellsAndArrangeParticipants (Object JavaDoc[] insert,Map viewMap, ConnectionSet cs) {
338       if(JaWEGraphModel.getRootParticipants(graphModel()) != null) {
339          updateModelAndArrangeParticipants(insert,null,null,viewMap,
340                                            ResourceManager.getLanguageDependentString("MessageDuplicatingObject"),true,cs);
341       }
342       else {
343          JOptionPane.showMessageDialog(graph.getEditor().getWindow(),
344                                        ResourceManager.getLanguageDependentString(
345                                           "WarningCannotInsertObjectsOutsideParticipant"),
346                                        JaWE.getAppTitle(),JOptionPane.WARNING_MESSAGE);
347       }
348    }
349
350    /**
351     * Moves cells given in a <b>propertyMap</b> to new location (also
352     * given in <b>propertyMap</b>. First, the parent of cells is
353     * searched, and when found, put into ParentMap object (the model
354     * is not changed at ones). After that model's view is arranged
355     * (Participants are moved and translated along with it's children cells)
356     * to suite to the new model state - this is done "virtually" which
357     * means that changes are not directly applied to view until all
358     * changes are made. At the end, all changes are applied to model and view.
359     * Such procedure enables compound undo support.
360     * <BR> This method is called when moving cells along participants.
361     * @see #updateModelAndArrangeParticipants
362     */

363    public void moveCellsAndArrangeParticipants (Map propertyMap) {
364       updateModelAndArrangeParticipants(null,propertyMap,null,null,
365                                         ResourceManager.getLanguageDependentString("MessageMovingObjects"),false,null);
366    }
367
368    /**
369     * Inserts new Subflow cell at position <b>p</b> into model. First, the
370     * parent of new Subflow is searched, and when found, put into ParentMap
371     * object (it is not inserted into model at ones). After that model's view
372     * is arranged (Participants are moved and translated along with it's children
373     * cells) to suite to the new model state - this is done "virtually" which
374     * means that changes are not directly applied to view until all changes are
375     * made. At the end, all changes are applied to model and view.
376     * Such procedure enables compound undo support.
377     * <BR> This method is called when user inserts new Subflow into graph.
378     * @see #updateModelAndArrangeParticipants
379     */

380    public void insertSubflowAndArrangeParticipants (Point p) {
381       Set rootParticipants=JaWEGraphModel.getRootParticipants(graphModel());
382       if(rootParticipants != null && rootParticipants.size()>0) {
383          Map viewMap = new Hashtable();
384          Subflow sbf=createSubflow(p,viewMap);
385          //updateModelAndArrangeParticipants(new Object[] {sbf},viewMap,null,null,
386
updateModelAndArrangeParticipants(new Object JavaDoc[] {sbf},null,null,viewMap,
387                                            ResourceManager.getLanguageDependentString("MessageInsertingSubflowActivity"),
388                                            true,null);
389       }
390       else {
391          JOptionPane.showMessageDialog(graph.getEditor().getWindow(),
392                                        ResourceManager.getLanguageDependentString(
393                                           "WarningCannotInsertSubflowActivityOutsideParticipant"),
394                                        JaWE.getAppTitle(),JOptionPane.WARNING_MESSAGE);
395       }
396    }
397
398    /**
399     * Inserts new BlockActivity cell at position <b>p</b> into model. First, the
400     * parent of new BlockActivity is searched, and when found, put into ParentMap
401     * object (it is not inserted into model at ones). After that model's view
402     * is arranged (Participants are moved and translated along with it's children
403     * cells) to suite to the new model state - this is done "virtually" which
404     * means that changes are not directly applied to view until all changes are
405     * made. At the end, all changes are applied to model and view.
406     * Such procedure enables compound undo support.
407     * <BR> This method is called when user inserts new BlockActivity into graph.
408     * @see #updateModelAndArrangeParticipants
409     */

410    public void insertBlockActivityAndArrangeParticipants (Point p) {
411       Set rootParticipants=JaWEGraphModel.getRootParticipants(graphModel());
412       if(rootParticipants != null && rootParticipants.size()>0) {
413          Map viewMap = new Hashtable();
414          BlockActivity bla=createBlockActivity(p,viewMap);
415          //updateModelAndArrangeParticipants(new Object[] {bla},viewMap,null,null,
416
updateModelAndArrangeParticipants(new Object JavaDoc[] {bla},null,null,viewMap,
417                                            ResourceManager.getLanguageDependentString("MessageInsertingBlockActivity"),
418                                            true,null);
419       }
420       else {
421          JOptionPane.showMessageDialog(graph.getEditor().getWindow(),
422                                        ResourceManager.getLanguageDependentString(
423                                           "WarningCannotInsertBlockActivityOutsideParticipant"),
424                                        JaWE.getAppTitle(),JOptionPane.WARNING_MESSAGE);
425       }
426    }
427
428    /**
429     * Inserts new Start activity cell at position <b>p</b> into model. First,
430     * the parent of new Activity is searched, and when found, put into ParentMap
431     * object (it is not inserted into model at ones). After that model's view
432     * is arranged (Participants are moved and translated along with it's children
433     * cells) to suite to the new model state - this is done "virtually" which
434     * means that changes are not directly applied to view until all changes are
435     * made. At the end, all changes are applied to model and view.
436     * Such procedure enables compound undo support.
437     * <BR> This method is called when user inserts new Start into graph.
438     * @see #updateModelAndArrangeParticipants
439     */

440    public void insertStartAndArrangeParticipants (Point p) {
441       Set rootParticipants=JaWEGraphModel.getRootParticipants(graphModel());
442       if(rootParticipants != null && rootParticipants.size()>0) {
443          Map viewMap = new Hashtable();
444          Start s=createStart(p,viewMap);
445          //updateModelAndArrangeParticipants(new Object[] {s},viewMap,null,null,
446
updateModelAndArrangeParticipants(new Object JavaDoc[] {s},null,null,viewMap,
447                                            ResourceManager.getLanguageDependentString("MessageInsertingStart"),
448                                            true,null);
449       }
450       else {
451          String JavaDoc msg=ResourceManager.getLanguageDependentString(
452             "WarningCannotInsertStartOutsideParticipant");
453          JOptionPane.showMessageDialog(graph.getEditor().getWindow(),
454                                        msg,JaWE.getAppTitle(),JOptionPane.WARNING_MESSAGE);
455       }
456    }
457
458    /**
459     * Inserts new End activity cell at position <b>p</b> into model. First, the
460     * parent of new Activity is searched, and when found, put into ParentMap
461     * object (it is not inserted into model at ones). After that model's view
462     * is arranged (Participants are moved and translated along with it's children
463     * cells) to suite to the new model state - this is done "virtually" which
464     * means that changes are not directly applied to view until all changes are
465     * made. At the end, all changes are applied to model and view.
466     * Such procedure enables compound undo support.
467     * <BR> This method is called when user inserts new End into graph.
468     * @see #updateModelAndArrangeParticipants
469     */

470    public void insertEndAndArrangeParticipants (Point p) {
471       Set rootParticipants=JaWEGraphModel.getRootParticipants(graphModel());
472       if(rootParticipants != null && rootParticipants.size()>0) {
473          Map viewMap = new Hashtable();
474          Activity e=createEnd(p,viewMap);
475          //updateModelAndArrangeParticipants(new Object[] {e},viewMap,null,null,
476
updateModelAndArrangeParticipants(new Object JavaDoc[] {e},null,null,viewMap,
477                                            ResourceManager.getLanguageDependentString("MessageInsertingEnd"),
478                                            true,null);
479       }
480       else {
481          JOptionPane.showMessageDialog(graph.getEditor().getWindow(),
482                                        ResourceManager.getLanguageDependentString(
483                                           "WarningCannotInsertEndOutsideParticipant"),
484                                        JaWE.getAppTitle(),JOptionPane.WARNING_MESSAGE);
485       }
486    }
487
488    /**
489     * Inserts new Activity cell at position <b>p</b> into model. First, the
490     * parent of new Activity is searched, and when found, put into ParentMap
491     * object (it is not inserted into model at ones). After that model's view
492     * is arranged (Participants are moved and translated along with it's children
493     * cells) to suite to the new model state - this is done "virtually" which
494     * means that changes are not directly applied to view until all changes are
495     * made. At the end, all changes are applied to model and view.
496     * Such procedure enables compound undo support.
497     * <BR> This method is called when user inserts new generic activity into graph.
498     * @see #updateModelAndArrangeParticipants
499     */

500    public void insertActivityAndArrangeParticipants (Point p) {
501       Set rootParticipants=JaWEGraphModel.getRootParticipants(graphModel());
502       if(rootParticipants != null && rootParticipants.size()>0) {
503          Map viewMap = new Hashtable();
504          Activity act=createActivity(p,viewMap);
505          //updateModelAndArrangeParticipants(new Object[] {act},viewMap,null,null,
506
updateModelAndArrangeParticipants(new Object JavaDoc[] {act},null,null,viewMap,
507                                            ResourceManager.getLanguageDependentString("MessageInsertingGenericActivity"),
508                                            true,null);
509       }
510       else {
511          JOptionPane.showMessageDialog(graph.getEditor().getWindow(),
512                                        ResourceManager.getLanguageDependentString(
513                                           "WarningCannotInsertGenericActivityOutsideParticipant"),
514                                        JaWE.getAppTitle(),JOptionPane.WARNING_MESSAGE);
515       }
516    }
517
518    /**
519     * Inserts new Route activity cell at position <b>p</b> into model. First, the
520     * parent of new Activity is searched, and when found, put into ParentMap
521     * object (it is not inserted into model at ones). After that model's view
522     * is arranged (Participants are moved and translated along with it's children
523     * cells) to suite to the new model state - this is done "virtually" which
524     * means that changes are not directly applied to view until all changes are
525     * made. At the end, all changes are applied to model and view.
526     * Such procedure enables compound undo support.
527     * <BR> This method is called when user inserts new Route activity into graph.
528     * @see #updateModelAndArrangeParticipants
529     */

530    public void insertRouteAndArrangeParticipants (Point p) {
531       Set rootParticipants=JaWEGraphModel.getRootParticipants(graphModel());
532       if(rootParticipants != null && rootParticipants.size()>0) {
533          Map viewMap = new Hashtable();
534          Route r=createRoute(p,viewMap);
535          //updateModelAndArrangeParticipants(new Object[] {r},viewMap,null,null,
536
updateModelAndArrangeParticipants(new Object JavaDoc[] {r},null,null,viewMap,
537                                            ResourceManager.getLanguageDependentString("MessageInsertingRouteActivity"),
538                                            true,null);
539       }
540       else {
541          JOptionPane.showMessageDialog(graph.getEditor().getWindow(),
542                                        ResourceManager.getLanguageDependentString(
543                                           "WarningCannotInsertRouteActivityOutsideParticipant"),
544                                        JaWE.getAppTitle(),JOptionPane.WARNING_MESSAGE);
545       }
546    }
547
548    /**
549     * Inserts new Participant cell at position <b>p</b> into model. First, the
550     * parent of new Participant is searched, and if found, put into ParentMap
551     * (it is not inserted into model at ones). If parent participant isn't
552     * found -> root participant will be inserted. After that model's view
553     * is arranged (Participants are moved and translated along with it's children
554     * cells) to suite to the new model state - this is done "virtually" which
555     * means that changes are not directly applied to view until all changes are
556     * made. At the end, all changes are applied to model and view.
557     * Such procedure enables compound undo support.
558     * <BR> This method is called when inserting new Participant into model.
559     * <BR> If <tt>parUO</tt> is <tt>null</tt>, the new object is inserted
560     * into XML logic, and if not, the predefined XML object is used.
561     * @param p The position of participant within the graph.
562     * @param parUO The XML logic object that holds the data for participant
563     * to be inserted and that will be held as a property of
564     * the graph object.
565     */

566    public Participant insertParticipantAndArrangeParticipants (Point p,
567                                                                org.enhydra.jawe.xml.elements.Participant parUO) {
568
569       ToolTipManager.sharedInstance().setEnabled(false);
570
571       Participant par=null;
572
573       Map viewMap=new HashMap();
574       ParentMap parentMap=null;
575       Map propertyMap=null;
576
577       // get the topmost participant at the location where
578
// user want to insert participant
579
Object JavaDoc cell=((ProcessGraph)graph).
580          getFirstParticipantForLocation(p.x,p.y);
581
582       // if there is no cell at the mouse position,
583
// add new participant below existing ones
584
if (cell==null) {
585          par=createParticipant(
586             new Rectangle(horizontalOffset,getNewRootParYPos(null,null),
587                           getRootParticipantWidth(null,null),minParHeight),
588             viewMap);
589          propertyMap=new HashMap(viewMap);
590          // otherwise, display an warning message that
591
// participant can't be inserted here
592
} else {
593          JOptionPane.showMessageDialog(graph.getEditor().getWindow(),
594                                        ResourceManager.getLanguageDependentString(
595                                           "WarningParticipantCannotHaveParticipants"),
596                                        JaWE.getAppTitle(),JOptionPane.WARNING_MESSAGE);
597          return null;
598       }
599
600       Participants wfp =(Participants)getWorkflowProcess().get("Participants");
601       // if user inserts an existing (logical) participant into graph
602
if (parUO!=null) {
603          Object JavaDoc[] insert = new Object JavaDoc[]{par};
604          // graphModel().insertAndEdit(insert,null,propertyMap,parentMap,viewMap,
605
graphModel().insertAndEdit(insert,propertyMap,null,parentMap,null,
606                                     ResourceManager.getLanguageDependentString("MessageInsertingParticipant"));
607          par.setUserObject(parUO);
608          // notifies participants user object that one of it's graph
609
// presentation is added
610
// ADDED 19.02.03 - conditional graph reference adding, only
611
// if this is not external model graph
612
if (!getXMLPackage().isReadOnly()) {
613             parUO.graphReferenceAdded();
614          }
615          // if user creates new (logical) participant by selecting
616
// it from the toolbox toolbar
617
} else {
618          parUO=(org.enhydra.jawe.xml.elements.Participant)
619             wfp.generateNewElement();
620          // show dialog for entering initial participant data
621
Window w=graph.getEditor().getWindow();
622          XMLElementDialog de=new XMLElementDialog((JDialog)w,
623                                                   ResourceManager.getLanguageDependentString("DialogNewParticipant"));
624
625          de.editXMLElement(parUO.getPanel(),true,false);
626          // if cancel hasn't been pressed
627
if (!de.isCanceled()) {
628             Object JavaDoc[] insert = new Object JavaDoc[]{par};
629             //graphModel().insertAndEdit(insert,null,propertyMap,parentMap,viewMap,
630
graphModel().insertAndEdit(insert,propertyMap,null,parentMap,null,
631                                        ResourceManager.getLanguageDependentString("MessageInsertingParticipant"));
632             par.setUserObject(parUO);
633             // notifies participants user object that one of it's graph
634
// presentation is added
635
// ADDED 19.02.03 - conditional graph reference adding, only
636
// if this is not external model graph
637
if (!getXMLPackage().isReadOnly()) {
638                parUO.graphReferenceAdded();
639             }
640             // adds object to the collection
641
wfp.add(parUO);
642          }
643       }
644
645       if (JaWEConfig.getInstance().getTooltipStatus()) {
646          ToolTipManager.sharedInstance().setEnabled(true);
647       }
648
649       if (!creatingGraph) {
650          try {
651             Dimension prefSize=new Dimension(getRootParticipantWidth(propertyMap,parentMap)+50,
652                                              getNewRootParYPos(propertyMap,parentMap)+50);
653             graph.setPreferredSize(prefSize);
654          } catch (Exception JavaDoc ex) {}
655       }
656
657       return par;
658    }
659
660    /**
661     * Called when user wants to insert an existing (logical) participant
662     * into graph. Participant is inserted below all already inserted
663     * participants.
664     * @return <tt>true</tt> if participant is successfully inserted into
665     * graph, <tt>false</tt> otherwise.
666     */

667    public boolean showNode (org.enhydra.jawe.xml.elements.Participant parUO) {
668       if (parUO==null) return false;
669
670       Point ofInsert = new Point(10,Integer.MAX_VALUE);
671       Object JavaDoc graphObj = getGraphObjectForXMLParticipant(parUO);
672       // if participant is already inserted into graph, just return true
673
if (null != graphObj) {
674          return true;
675       }
676
677       Object JavaDoc ins=insertParticipantAndArrangeParticipants(ofInsert,parUO);
678
679       if (ins==null) {
680          return false;
681       } else {
682          return true;
683       }
684    }
685
686    /**
687     * Called when user wants to remove an existing (logical) participant
688     * from the graph. The participant can be removed only if there are
689     * no activities that it is responsible for (activity graph objects
690     * that lies inside the participant graph object).
691     */

692    public void hideNode(org.enhydra.jawe.xml.elements.Participant parUO) {
693       Participant p=getGraphObjectForXMLParticipant(parUO);
694       if (p!=null && !p.hasAnyActivity()) {
695          removeCellsAndArrangeParticipants(new Object JavaDoc[]{p});
696       }
697    }
698
699    /**
700     * Returns the graph object representing given (XML logic) Participant
701     * object.
702     * @param source The (XML logic) Participant object which graph
703     * object should be returned by this method.
704     * @return The graph object for given XML logic object if it is
705     * inserted into graph, <tt>null</tt> otherwise.
706     */

707    private Participant getGraphObjectForXMLParticipant(
708       org.enhydra.jawe.xml.elements.Participant source) {
709
710       Set graphParts=JaWEGraphModel.getAllParticipantsInModel(graphModel());
711       if (graphParts!=null) {
712          Participant graphPart;
713          Iterator it=graphParts.iterator();
714          while (it.hasNext()) {
715             graphPart=(Participant)it.next();
716             if (graphPart.getUserObject()==source) {
717                return graphPart;
718             }
719          }
720       }
721       return null;
722    }
723
724
725    /**
726     * Inserts new Transition cell, between points <b>start</b> and <b>end</b>,
727     * connected to the ports <b>source</b> and <b>target</b> into model.
728     * <BR> This method is called when inserting new Transition into graph.
729     * Depending on <tt>updateCollection</tt> parameter, it calls the method
730     * that updates the collection of existing Transition objects
731     * (it is set to <tt>true</tt> when user inserts the new Transition into
732     * the Process or BlockActivity graph, and to <tt>false</tt>
733     * during importing from XML).
734     * @param start The position of start point of transition
735     * within the graph.
736     * @param end The position of end point of transition
737     * within the graph.
738     * @param source The source port of transition's graph object.
739     * @param target The target port of transition's graph object.
740     * @param updateCollection <tt>true</tt> if collection of
741     * Transition objects should be
742     * updated (user inserts object), and
743     * <tt>false</tt> if not (XML file is
744     * importing, and objects are constructed
745     * depending on data held within the file).
746     * @return The created transition's graph object.
747     */

748    public Transition insertTransition (Point start,Point end,PortView source,
749                                        PortView target,boolean isRouting,boolean updateCollection) {
750
751       Point p = (Point)graph.fromScreen(new Point(start));//HM, JGraph3.4.1
752
Point p2 = (Point)graph.fromScreen(new Point(end));//HM, JGraph3.4.1
753
ArrayList list = new ArrayList();
754
755       // creating line style
756
Map map = GraphConstants.createMap();
757       if (source.equals(target)) {
758          GraphConstants.setLineStyle(map,GraphConstants.STYLE_BEZIER);
759          list.add(p);
760          if (updateCollection) {
761             list.add(new Point(p.x-50,p.y-75));
762             list.add(new Point(p.x+50,p.y-75));
763          }
764          list.add(p2);
765       } else {
766          list.add(p);
767          list.add(p2);
768       }
769       GraphConstants.setPoints(map,list);
770       if (isRouting) {
771          GraphConstants.setRouting(map, GraphConstants.ROUTING_SIMPLE);
772       }
773       //GraphConstants.setLineColor(map,Utils.getColor(JaWEConfig.getInstance().getTransitionColor()));
774
GraphConstants.setLineEnd(map,GraphConstants.ARROW_TECHNICAL);
775       GraphConstants.setEndFill(map,true);
776       GraphConstants.setEndSize(map,10);
777       GraphConstants.setFont(map,GraphConstants.defaultFont.deriveFont(JaWEConfig.getInstance().getFontSize()));
778
779       Map viewMap = new Hashtable();
780       Transition transition = new Transition();
781
782       viewMap.put(transition,map);
783
784       Object JavaDoc[] insert = new Object JavaDoc[]{transition};
785       ConnectionSet cs = new ConnectionSet();
786
787       cs.connect(transition,source.getCell(),target.getCell());
788
789       org.enhydra.jawe.xml.elements.Transition uo=null;
790       Transitions ts=getTransitionsCollection();
791       uo=new org.enhydra.jawe.xml.elements.Transition(ts);
792       //uo.get("Name").setValue(ResourceManager.getLanguageDependentString("TransitionKey"));
793
transition.setUserObject(uo);
794
795       //cs.connect(transition,source.getCell(),true);
796
//cs.connect(transition,target.getCell(),false);
797
String JavaDoc undoMsg=ResourceManager.getLanguageDependentString("MessageInsertingTransition");
798       // graphModel().insertAndEdit(insert,cs,null,null,viewMap,undoMsg);
799
graphModel().insertAndEdit(insert,viewMap,cs,null,null,undoMsg);
800       Activity s=null;
801       Activity t=null;
802       try {
803          s=transition.getSourceActivity();
804       } catch (Exception JavaDoc ex) {
805       }
806       try {
807          t=transition.getTargetActivity();
808       } catch (Exception JavaDoc ex) {
809       }
810
811       // must set source and target activity objects after inserting into model
812
org.enhydra.jawe.xml.elements.Activity sourceAct=null;
813       //System.out.println("s-"+s+", t="+t);
814
if (s!=null && t!=null && !(s instanceof Start) && !(t instanceof End)) {
815          try {
816             sourceAct=(org.enhydra.jawe.xml.elements.Activity)
817                s.getPropertyObject();
818             uo.setFrom(sourceAct);
819          } catch (Exception JavaDoc e) {}
820          try {
821             uo.setTo(t.getPropertyObject());
822          } catch (Exception JavaDoc e) {}
823       }
824
825       // refreshes collection of transitions within workflow process
826
if (updateCollection) {
827          refreshCollections (insert,true);
828       }
829
830       return transition;
831    }
832
833    /**
834     * Removes cells <b>cellsToDelete</b> from model. This means that given cells
835     * and all of their descendants as well as all transitions that connects given cells,
836     * will be removed from model. First, all remained participants are moved and
837     * resized according to participants that are beeing removed and ParentMap for
838     * all removed cells is created (all these things are made "virtually" - not
839     * applied to model and view). After that model's new view is arranged
840     * (Participants are moved and translated (along with it's children cells)
841     * according to the remained children - this is also done "virtually".
842     * At the end, all changes are applied to model and view.
843     * Such procedure enables compound undo support.
844     * <BR> This method is called when deleting or cutting cells from graph.
845     */

846    public void removeCellsAndArrangeParticipants (Object JavaDoc[] cellsToDelete) {
847       Set participantsToArrange=new HashSet();
848       Map propertyMap=new HashMap();
849       ParentMap parentMap=new JaWEParentMap();
850
851       Set ports=new HashSet();
852       // begining arrangement of parent of cells that will be deleted
853
if (cellsToDelete != null && cellsToDelete.length>0) {
854          for (int i=0; i<cellsToDelete.length; i++) {
855             if (cellsToDelete[i] instanceof Participant) {
856                Participant par=(Participant)cellsToDelete[i];
857
858                // getting bounds of rectangle
859
Rectangle2D JavaDoc r=getBounds(par,propertyMap);//HM, JGraph3.4.1
860
int yPos=r.getBounds().y+r.getBounds().height-1;//HM, JGraph3.4.1
861

862                // resize all parent participants (reduce their sizes) if needed, and
863
// also if needed, translate up all participants under yPos
864
Participant ppar=(Participant)par.getParent();
865                if (ppar != null) {
866                   // resizing and translating is needed only if "first" parent
867
// has other children except one that is beeing removed
868
// or if its height can be reduced
869
if (ppar.getChildCount()>1 ||
870                       getParticipantHeight(ppar,propertyMap)>minParHeight) {
871                      // gets all parents and resizes it
872
Object JavaDoc[] allParents=ppar.getPath();
873                      // calculates resize value
874
int resizeValue=r.getBounds().height;//HM, JGraph3.4.1
875
int pHeight=getParticipantHeight(ppar,propertyMap);
876                      // do not allow to resize participant under it's minimal height
877
if (pHeight-r.getBounds().height<minParHeight) {//HM, JGraph3.4.1
878
resizeValue=pHeight-minParHeight;
879                      }
880                      resize(allParents,propertyMap,0,-resizeValue);
881                      // translate up all participants under yPos
882
translateVertically(propertyMap,null,yPos,-resizeValue);
883                   }
884                }
885                   // if participant is root there is a need of translating participants under it
886
else {
887                   // translate up all participants under yPos
888
translateVertically(propertyMap,null,yPos,-r.getBounds().height);//HM, JGraph3.4.1
889
}
890                // if some port is originally set to be deleted it must be removed
891
} else if (cellsToDelete[i] instanceof Port) {
892                ports.add(cellsToDelete[i]);
893             }
894          }
895
896          // removing ports if they were somehow selected
897
Set ctd=new HashSet(Arrays.asList(cellsToDelete));
898          ctd.removeAll(ports);
899          if (ctd.size()==0) return;
900          cellsToDelete=ctd.toArray();
901
902          // after previous, participant's are transleted and resized to certain extent,
903
// now final resizing and translation takes place (translation and resizing
904
// that calculates minimal possible height and width of participants according
905
// to the activities that are contained within participant after deletion)
906

907          // All cells in model to be deleted
908
Set cellsToDel = JaWEGraphModel.getDescendants(graphModel(),cellsToDelete);
909          // getting transitions(edges) which are connected to the cellsForDel -> also has to be deleted
910
Set edges=graphModel().getEdges(graphModel(),cellsToDel.toArray());
911
912          // putting all items for deletation (edges and cells) together - thats ALL FOR DELETION
913
cellsToDel.addAll(edges);
914
915          // Separate cells and edges
916
Set allEdgesToDelete=new HashSet();
917          Set allCellsToDelete=new HashSet();
918          Iterator it=cellsToDel.iterator();
919          while (it.hasNext()) {
920             Object JavaDoc cell=it.next();
921             if (cell instanceof Edge) {
922                allEdgesToDelete.add(cell);
923             }
924             else if (!(cell instanceof Port)){
925                allCellsToDelete.add(cell);
926             }
927          }
928
929          // working resize and translation only with cells (edges doesn't count)
930
cellsToDelete=allCellsToDelete.toArray();
931
932          for (int i=0; i<cellsToDelete.length; i++) {
933             // adding parent of removing Activity cell (if there is one and if
934
// it is Participant) into array for arranging participants, and creating
935
// entry in parentMap -> this will be of use after basic resizing
936
// and translating operations
937
Object JavaDoc parent=((DefaultMutableTreeNode)cellsToDelete[i]).getParent();
938             if ((parent != null) && (parent instanceof Participant)) {
939                if (cellsToDelete[i] instanceof Activity) {
940                   participantsToArrange.add(parent);
941                }
942             }
943             parentMap.addEntry(cellsToDelete[i],null);
944          }
945
946          // resizing remained participants
947
resizeAllParticipantsHorizontally(propertyMap,parentMap);
948          arrangeParticipantsVertically(participantsToArrange.toArray(),propertyMap,parentMap);
949
950          // if this is deletion of process cell - arange other processes
951
if (cellsToDelete!=null && cellsToDelete.length==1 &&
952                 (cellsToDelete[0] instanceof org.enhydra.jawe.graph.Process)) {
953             org.enhydra.jawe.graph.Process pr=
954                (org.enhydra.jawe.graph.Process)cellsToDelete[0];
955             arrangeProcesses(propertyMap,GraphConstants.getBounds(pr.getAttributes()).getBounds());//HM, JGraph3.4.1
956
}
957
958          graphModel().removeAndEdit(cellsToDel.toArray(),propertyMap,
959                                     ResourceManager.getLanguageDependentString("MessageRemovingObjects"));
960
961          // refreshes the collection of XML objects
962
refreshCollections(cellsToDel.toArray(),false);
963       }
964
965       try {
966          Dimension prefSize=new Dimension(getRootParticipantWidth(propertyMap,parentMap)+50,
967                                           getNewRootParYPos(propertyMap,parentMap)+50);
968          graph.setPreferredSize(prefSize);
969       } catch (Exception JavaDoc ex) {}
970    }
971
972    /**
973     * Returns horizontal offset for inserting participants.
974     */

975    public int getHorizontalOffset () {
976       return horizontalOffset;
977    }
978
979    /**
980     * Returns the Id attribute of (XML logic) Participant object,
981     * which graph object visually holds given activity graph object.
982     */

983    public String JavaDoc getParticipantID (Activity a) {
984       if (a!=null) {
985          Participant par=(Participant)a.getParent();
986          if (par!=null) {
987             return par.get("Id").toString();
988          }
989       }
990       return "";
991    }
992
993    /**
994     * Returns the point within the graph where the upper-left corner
995     * of given graph activity is placed. The point origin is the
996     * upper-left corner of participant graph object that holds given
997     * activity.
998     */

999    public Point getOffset (Activity a) {
1000      if (a!=null && a instanceof Activity) {
1001         Participant par=(Participant)((Activity)a).getParent();
1002         if (par!=null) {
1003            Rectangle2D JavaDoc rpar=getBounds(par,null);//HM, JGraph3.4.1
1004
Rectangle2D JavaDoc ract=getBounds(a,null);//HM, JGraph3.4.1
1005
int yOff=ract.getBounds().y-rpar.getBounds().y;//HM, JGraph3.4.1
1006
int xOff=ract.getBounds().x-rpar.getBounds().x;//HM, JGraph3.4.1
1007
return new Point(xOff,yOff);
1008         }
1009      }
1010      return new Point(0,0);
1011   }
1012
1013   /**
1014    * Returns the set of BlockActivity graph objects contained within
1015    * the manager graph. If the graph of found BlockActivity graph objects
1016    * contains other BlockActivity graph objects, and the second parameter is
1017    * set to true, these are also returned, and so on - which means that
1018    * implementation is recursive.
1019    */

1020   public Set getBlockActivities(boolean recursivly) {
1021      Set allActs=JaWEGraphModel.getAllActivitiesInModel(graphModel());
1022      Set bas=new HashSet();
1023      if (allActs != null) {
1024         Iterator it=allActs.iterator();
1025         Object JavaDoc act;
1026         while (it.hasNext()) {
1027            act=it.next();
1028            if (act instanceof BlockActivity) {
1029               bas.add(act);
1030               if (!recursivly) continue;
1031               WorkflowManager wm=((BlockActivity)act).getWorkflowManager();
1032               if (wm!=null) {
1033                  bas.addAll(wm.getBlockActivities(true));
1034               }
1035            }
1036         }
1037      }
1038      return bas;
1039   }
1040
1041   /**
1042    * Creates new graph participant object.
1043    */

1044   protected Participant createParticipant(Rectangle bounds,Map viewMap) {
1045
1046      Map map;
1047
1048      Participant par = new Participant();
1049      map = GraphConstants.createMap();
1050      GraphConstants.setBounds(map,bounds);
1051      GraphConstants.setOpaque(map,false);
1052      GraphConstants.setBorderColor(map,Color.black);
1053      GraphConstants.setMoveable(map,false);
1054      GraphConstants.setFont(map,GraphConstants.defaultFont.deriveFont(JaWEConfig.getInstance().getFontSize()));
1055
1056      viewMap.put(par,map);
1057
1058      return par;
1059   }
1060
1061
1062   /**
1063    * Creates new graph subflow object and associates the new
1064    * XML logic activity object of SubFlow type to it.
1065    */

1066   protected Subflow createSubflow(Point p,Map viewMap) {
1067      Point realP=(Point)graph.fromScreen(new Point(p));//HM, JGraph3.4.1
1068
int ulx=realP.x;
1069      int uly=realP.y;
1070      Rectangle bounds=new Rectangle(ulx,uly,defActivityWidth,defActivityHeight);
1071
1072      Map map;
1073
1074      Subflow sbf = new Subflow();
1075
1076      WorkflowProcess wp=getWorkflowProcess();
1077      Activities acts=getActivitiesCollection();
1078
1079      org.enhydra.jawe.xml.elements.Activity ap=
1080         new org.enhydra.jawe.xml.elements.Activity(acts,wp,3);
1081      ap.set("Name",ResourceManager.getLanguageDependentString("SubFlowKey"));
1082      sbf.setUserObject(ap);
1083      map = GraphConstants.createMap();
1084      GraphConstants.setBounds(map, bounds);
1085      GraphConstants.setOpaque(map, true);
1086      GraphConstants.setBorderColor(map,new Color(15,0,115));
1087      GraphConstants.setFont(map,GraphConstants.defaultFont.deriveFont(JaWEConfig.getInstance().getFontSize()));
1088
1089      viewMap.put(sbf,map);
1090
1091      return sbf;
1092   }
1093
1094   /**
1095    * Creates new graph BlockActivity object and associates the new
1096    * XML logic activity object of BlockActivity type to it.
1097    */

1098   protected BlockActivity createBlockActivity(Point p,Map viewMap) {
1099      Point realP=(Point)graph.fromScreen(new Point(p));//HM, JGraph3.4.1
1100
int ulx=realP.x;
1101      int uly=realP.y;
1102      Rectangle bounds=new Rectangle(ulx,uly,defActivityWidth,defActivityHeight);
1103
1104      Map map;
1105
1106      BlockActivity bla = new BlockActivity((ProcessEditor)getGraph().getEditor());
1107
1108      org.enhydra.jawe.xml.elements.Activity ap=
1109         new org.enhydra.jawe.xml.elements.Activity(
1110         getActivitiesCollection(),getWorkflowProcess(),4);
1111      // set the ID of block
1112
ap.getBlockActivity().
1113         set("BlockId",((ActivitySets)getWorkflowProcess().
1114                           get("ActivitySets")).generateID());
1115      ap.set("Name",ResourceManager.getLanguageDependentString("BlockActivityKey"));
1116      bla.setUserObject(ap);
1117      map = GraphConstants.createMap();
1118      GraphConstants.setBounds(map, bounds);
1119      GraphConstants.setOpaque(map, true);
1120      GraphConstants.setBorderColor(map,new Color(15,0,115));
1121      GraphConstants.setFont(map,GraphConstants.defaultFont.deriveFont(JaWEConfig.getInstance().getFontSize()));
1122      viewMap.put(bla,map);
1123
1124      return bla;
1125   }
1126
1127
1128   /**
1129    * Creates start of graph object.
1130    */

1131   protected Start createStart(Point p,Map viewMap) {
1132      Point realP=(Point)graph.fromScreen(new Point(p));//HM, JGraph3.4.1
1133
int ulx=realP.x;
1134      int uly=realP.y;
1135      Rectangle bounds=new Rectangle(ulx,uly,defActivityHeight,defActivityHeight);
1136
1137      Map map;
1138
1139      Start s = new Start();
1140      map = GraphConstants.createMap();
1141      GraphConstants.setBounds(map,bounds);
1142      GraphConstants.setOpaque(map,true);
1143      GraphConstants.setBorderColor(map,Color.darkGray);
1144      GraphConstants.setFont(map,GraphConstants.defaultFont.deriveFont(JaWEConfig.getInstance().getFontSize()));
1145
1146      viewMap.put(s,map);
1147
1148      return s;
1149   }
1150
1151   /**
1152    * Creates end of graph object.
1153    */

1154   protected End createEnd(Point p,Map viewMap) {
1155      Point realP=(Point)graph.fromScreen(new Point(p));//HM, JGraph3.4.1
1156
int ulx=realP.x;
1157      int uly=realP.y;
1158      Rectangle bounds=new Rectangle(ulx,uly,defActivityHeight,defActivityHeight);
1159
1160      Map map;
1161
1162      End e=new End();
1163      map = GraphConstants.createMap();
1164      GraphConstants.setBounds(map,bounds);
1165      GraphConstants.setOpaque(map,true);
1166      GraphConstants.setBorderColor(map,Color.darkGray);
1167      GraphConstants.setFont(map,GraphConstants.defaultFont.deriveFont(JaWEConfig.getInstance().getFontSize()));
1168
1169      viewMap.put(e,map);
1170
1171      return e;
1172   }
1173
1174   /**
1175    * Creates new activity graph object, and associates the new
1176    * XML logic activity object of Tool type to it.
1177    */

1178   protected Activity createActivity(Point p,Map viewMap) {
1179      Point realP=(Point)graph.fromScreen(new Point(p));//HM, JGraph3.4.1
1180
int ulx=realP.x;
1181      int uly=realP.y;
1182
1183      Rectangle bounds=new Rectangle(ulx,uly,defActivityWidth,defActivityHeight);
1184
1185      Map map;
1186
1187      Activity act = new Activity();
1188
1189      WorkflowProcess wp=getWorkflowProcess();
1190      Activities acts=getActivitiesCollection();
1191      org.enhydra.jawe.xml.elements.Activity ap=
1192         new org.enhydra.jawe.xml.elements.Activity(acts,wp,2);
1193      ap.set("Name",ResourceManager.getLanguageDependentString("GenericKey"));
1194      act.setUserObject(ap);
1195      map = GraphConstants.createMap();
1196      GraphConstants.setBounds(map,bounds);
1197      GraphConstants.setOpaque(map,true);
1198      GraphConstants.setBorderColor(map,Color.darkGray);
1199      GraphConstants.setFont(map,GraphConstants.defaultFont.deriveFont(JaWEConfig.getInstance().getFontSize()));
1200      viewMap.put(act,map);
1201
1202      return act;
1203   }
1204
1205   /**
1206    * Creates new route activity graph object, and associates the new
1207    * XML logic activity object of Route type to it.
1208    */

1209   protected Route createRoute(Point p,Map viewMap) {
1210      Point realP=(Point)graph.fromScreen(new Point(p));//HM, JGraph3.4.1
1211
int ulx=realP.x;
1212      int uly=realP.y;
1213      Rectangle bounds=new Rectangle(ulx,uly,defActivityWidth,defActivityHeight);
1214
1215      Map map;
1216
1217      Route r = new Route();
1218
1219      WorkflowProcess wp=getWorkflowProcess();
1220      Activities acts=getActivitiesCollection();
1221      org.enhydra.jawe.xml.elements.Activity ap=
1222         new org.enhydra.jawe.xml.elements.Activity(acts,wp,0);
1223      ap.set("Name",ResourceManager.getLanguageDependentString("RouteKey"));
1224      r.setUserObject(ap);
1225      map = GraphConstants.createMap();
1226      GraphConstants.setBounds(map,bounds);
1227      GraphConstants.setOpaque(map,true);
1228      GraphConstants.setBorderColor(map,Color.darkGray);
1229      GraphConstants.setFont(map,GraphConstants.defaultFont.deriveFont(JaWEConfig.getInstance().getFontSize()));
1230      viewMap.put(r,map);
1231
1232      return r;
1233   }
1234
1235   /**
1236    * Inserts new activities into model, changes positions and sizes of
1237    * participants due to a insertion of new activities or due to a moving of
1238    * activities. Also, finds and changes parent's of inserted/changed-position
1239    * activities. This method is called when inserting new activities, when pasting
1240    * activities, and when moving activities. All changes to the model and to the
1241    * view are at first made virtually (to the parentMap and to the propertyMap)
1242    * and when all is done, method insertAndEdit of PEGraphModel class is called
1243    * to actually make changes. The updateCollection parameter is used when
1244    * some objects are inserted into model, to update collection of XML elements.
1245    */

1246   protected void updateModelAndArrangeParticipants (Object JavaDoc[] insert,
1247                                                     Map propertyMap,ParentMap parentMap,Map viewMap,String JavaDoc actionName,
1248                                                     boolean updateCollection, ConnectionSet cs) {
1249
1250      if (propertyMap==null && viewMap==null) return;
1251      if (propertyMap==null) {
1252         propertyMap=new HashMap(viewMap);
1253      }
1254      if (parentMap==null) {
1255         parentMap=new JaWEParentMap();
1256      }
1257
1258      arrangeParticipants(propertyMap,parentMap);
1259      // extracting viewMap elements out of propertyMap (if any), applying
1260
// change to viewMap element bounds (this must be done, because user
1261
// could press mouse when inserting or pasting activities at the
1262
// forbiden position so position of activity is changed during
1263
// updateActivityParent method) and applying change to model and view
1264
/*if (viewMap != null) {
1265       Iterator it = viewMap.keySet().iterator();
1266       while (it.hasNext()) {
1267       Object cell=it.next();
1268       // removing entry for cell that is contained within viewMap
1269       Map mapP=(Map)propertyMap.remove(cell);
1270       // apply position changes to corresponding viewMap element
1271       Map mapV=(Map)viewMap.get(cell);
1272       if (!(cell instanceof Port)) {
1273       Rectangle r=GraphConstants.getBounds(mapP);
1274       GraphConstants.setBounds(mapV,r);
1275       }
1276       }
1277       }*/

1278
1279      if (insert != null && ((JaWEParentMap)parentMap).entryCount() != insert.length) {
1280         //return; //HM: enable Transition-copy/paste
1281
}
1282
1283      Dimension prefSize=null;
1284      if (!creatingGraph) {
1285         try{
1286            prefSize=new Dimension(getRootParticipantWidth(propertyMap,parentMap)+50,
1287                                   getNewRootParYPos(propertyMap,parentMap)+50);
1288         } catch (Exception JavaDoc ex) {}
1289      }
1290
1291      // makes all changes (if there was any) - to model and to view
1292
//graphModel().insertAndEdit(insert,null,propertyMap,parentMap,viewMap,actionName);
1293
graphModel().insertAndEdit(insert,propertyMap,cs,parentMap,null,actionName);
1294
1295      if (updateCollection) {
1296         refreshCollections(insert,true);
1297      }
1298
1299      if (!creatingGraph && prefSize!=null) {
1300         try{
1301            graph.setPreferredSize(prefSize);
1302         } catch (Exception JavaDoc ex) {}
1303      }
1304   }
1305
1306   /**
1307    * Arranges participants according to the given property and parent maps.
1308    */

1309   protected void arrangeParticipants(Map propertyMap,ParentMap parentMap) {
1310      Set parsToArrangeVerticaly=new HashSet();
1311      // going through given propertyMap keys, and if key is
1312
// activity->updating it's parent if needed.
1313
// WARNING: must extract keys and put it in a array because
1314
// propertyMap changes -> ConcurrentModificationException
1315
// can happend
1316
Object JavaDoc[] cellsToManage=propertyMap.keySet().toArray();
1317      for (int i=0; i<cellsToManage.length; i++) {
1318         Object JavaDoc cell=cellsToManage[i];
1319         if (cell instanceof Activity) {
1320            Set oldAndNewParentPar=updateActivityParent((Activity)cell,
1321                                                        propertyMap,parentMap);
1322            parsToArrangeVerticaly.addAll(oldAndNewParentPar);
1323         }
1324      }
1325      // arrange participants vertically
1326
arrangeParticipantsVertically(parsToArrangeVerticaly.toArray(),propertyMap,parentMap);
1327      resizeAllParticipantsHorizontally(propertyMap,parentMap);
1328   }
1329
1330   /**
1331    * Determines old and new participant for activity, adjusts activities
1332    * position if needed and properly changes parent of activity (adds
1333    * entry into the parentMap).
1334    */

1335   protected Set updateActivityParent (Activity ac,Map propertyMap,
1336                                       ParentMap parentMap) {
1337      // must return old and new participant to the caller method
1338
Set oldAndNewPar=new HashSet();
1339      // old and new parent participant of given activity
1340
Participant oldPar=(Participant)ac.getParent();
1341
1342      // adds oldPar to the set to be returned
1343
if (oldPar!=null) {
1344         oldAndNewPar.add(oldPar);
1345      }
1346
1347      Participant newPar=null;
1348      // taking position elements of Activity
1349
// taking bounding rectangle
1350
Rectangle2D JavaDoc acRect=getBounds(ac,propertyMap);//HM, JGraph3.4.1
1351
// taking upper-left corner, this will be reference for moving activitys
1352
Point acUpperLeft=acRect.getBounds().getLocation();//HM, JGraph3.4.1
1353
Point newAcUpperLeft=new Point(acUpperLeft);
1354
1355      newPar=findParentActivityParticipantForLocation(newAcUpperLeft,propertyMap,parentMap);
1356
1357      // if previous method changed location of upper-left point,
1358
// move activity to new location
1359
if (!newAcUpperLeft.equals(acUpperLeft)) {
1360         Rectangle r=new Rectangle(acRect.getBounds());//HM, JGraph3.4.1
1361
r.setLocation(newAcUpperLeft);
1362         changeBounds(ac,propertyMap,r);
1363      }
1364
1365      if (newPar != null) {
1366         // adds newPar to the set to be returned
1367
oldAndNewPar.add(newPar);
1368
1369         // VERY IMPORTANT IS TO CHANGE THE PARENT
1370
// changing the parent participant of Activity cell if it has changed position
1371
if (!newPar.equals(oldPar)) {
1372            parentMap.addEntry(ac,newPar);
1373         }
1374         org.enhydra.jawe.xml.elements.Participant defaultP=
1375            org.enhydra.jawe.xml.elements.Participant.getFreeTextExpressionParticipant();
1376         // Setting the new performer for activity
1377
if (!(ac instanceof Route) && !(ac instanceof Start) &&
1378             !(ac instanceof End) && !(ac instanceof Subflow) &&
1379             !(ac instanceof BlockActivity) &&
1380             newPar.getUserObject()!=defaultP) {
1381            ac.set("Performer",newPar.getUserObject());
1382         }
1383         if (newPar!=oldPar && newPar.getUserObject()==defaultP) {
1384            ac.set("Performer","");
1385         }
1386
1387      }
1388
1389      return oldAndNewPar;
1390
1391   }
1392
1393   /**
1394    * Finds new participant for activity after it's position changes.
1395    * WARNING: this method changes it's argument loc if not appropriate.
1396    */

1397   protected Participant findParentActivityParticipantForLocation (Point loc,
1398                                                                   Map propertyMap,ParentMap parentMap) {
1399      Participant newPar=null;
1400      // if user put activity cell somewhere outside visible area, move it back
1401
if (loc.y <= 0) {
1402         loc.y=1;
1403      }
1404      if (loc.x <= 0) {
1405         loc.x=1;
1406      }
1407
1408      // determining the container for new position
1409
newPar=getLeafParticipantForYPos(loc.y,propertyMap,parentMap);
1410
1411      // if new container isn't found -> activity is placed under all participants
1412
// so it's new participant will be the leaf participant with the highest y-coord
1413
if (newPar == null) {
1414         newPar=getLeafParticipantForYPos(getNewRootParYPos(propertyMap,null)-10,
1415                                          propertyMap,parentMap);
1416      }
1417
1418      if (newPar!=null) {
1419         // Adjust activities x-pos if needed
1420
Rectangle newParRect=(Rectangle)getBounds(newPar,propertyMap);//HM, JGraph3.4.1
1421
// if x-position is not OK, set appropriate position
1422
if (newParRect.x+defParNameWidth>=loc.x) {
1423            loc.x=newParRect.x+defParNameWidth+1;
1424         }
1425      }
1426         // it is activity that belongs to an block activity
1427
else {
1428         // if x-position is not OK, set appropriate position
1429
if (horizontalOffset>=loc.x) {
1430            loc.x=horizontalOffset;
1431         }
1432      }
1433
1434      return newPar;
1435   }
1436
1437
1438   /**
1439    * Arranging heights and positions of given participants and positions of participants
1440    * that must be translated due to a change of given participants.
1441    */

1442   protected void arrangeParticipantsVertically(Object JavaDoc[] pars,Map propertyMap,
1443                                                ParentMap parentMap) {
1444      if ((pars == null) || (pars.length==0)) return;
1445
1446      for (int i=0; i<pars.length; i++) {
1447         // arrange participants vertically
1448
arrangeParticipantVertically(pars[i],propertyMap,parentMap);
1449      }
1450   }
1451
1452   /**
1453    * Resizing participant par and it's parents to appropriate height, and translating
1454    * other participants accordingly to changes of participant par. The size's and
1455    * positions are calculated considering propertyMap and parentMap - which means for
1456    * future children state, and for bounds that are constantly changed during other
1457    * calculations. If propertyMap and parentMap are null, size's and positions are
1458    * calculated for current state. Also, if par that is to be arranged has entry in
1459    * parentMap as removed participant, it will not be arranged.
1460    */

1461   protected void arrangeParticipantVertically(Object JavaDoc par,Map propertyMap,
1462                                               ParentMap parentMap) {
1463      // can't be null, must be instance of Participant,
1464
// and can't have other participants
1465
// also it can't be removed
1466
if (par == null) return;
1467      if (!(par instanceof Participant)) return;
1468      Participant p=(Participant)par;
1469      if (hasAnyParticipant(p,parentMap)) return;
1470      ArrayList removedPars=((JaWEParentMap)parentMap).getRemovedNodes();
1471      if (removedPars.contains(p)) return;
1472      // getting optimal and current height for participant
1473
int optHeight=optimalParticipantHeight(p,propertyMap,parentMap);
1474      int curHeight=getParticipantHeight(p,propertyMap);
1475      // calculating value for vertical resizing of new participant
1476
int dheight=optHeight-curHeight;
1477
1478      if (dheight != 0) {
1479         // translating verticaly participants under bottom edge
1480
// of participant for value of dheight
1481
translateVertically(propertyMap,
1482                             parentMap,getBounds(p,propertyMap).getBounds().y+curHeight-1,dheight);//HM, JGraph3.4.1
1483

1484         // gets all parents participant (and given participant) into array
1485
// and resizes them for value of dheight
1486
Object JavaDoc[] allParentsAndPar=p.getPath();
1487         resize(allParentsAndPar,propertyMap,0,dheight);
1488      }
1489
1490   }
1491
1492   /**
1493    * Method that resizes all participants horizontally to get there minimal
1494    * needed sizes. The size is calculated considering propertyMap and
1495    * parentMap - which means for future children state, and for bounds
1496    * that are constantly changed during other calculations. If propertyMap
1497    * and parentMap are null, size is calculated for current state.
1498    */

1499   protected void resizeAllParticipantsHorizontally (Map propertyMap,
1500                                                     ParentMap parentMap) {
1501      Set participants=JaWEGraphModel.getAllParticipantsInModel(graphModel());
1502      // removing ones which parent in a parentMap is null
1503
if (parentMap != null && participants != null) {
1504         participants.removeAll(((JaWEParentMap)parentMap).getRemovedNodes());
1505      }
1506      // if there is a need for resizing
1507
int optimalRDW=optimalRootParticipantWidth(participants,propertyMap,parentMap);
1508      int rootParWidth=getRootParticipantWidth(propertyMap,parentMap);
1509      if (optimalRDW != rootParWidth) {
1510         // resize all participants for needed increment
1511
int dw=optimalRDW-rootParWidth;
1512         if (participants != null) {
1513            resize(participants.toArray(),propertyMap,dw,0);
1514         }
1515      }
1516   }
1517
1518   /**
1519    * Calculates the minimal width of root participants. It depends
1520    * of minimal allowed width of leaf participants, which depends on
1521    * the position of Activity cells in them. The width is calculated
1522    * considering propertyMap and parentMap - which means for future
1523    * children state, and for bounds that are constantly changed
1524    * during other calculations. If propertyMap and parentMap
1525    * are null, size is calculated for current state.
1526    */

1527   protected int optimalRootParticipantWidth (Set participants,Map propertyMap,
1528                                              ParentMap parentMap) {
1529      // initial value for width stays the same
1530
int minWidth=minParWidth;
1531
1532      // exits if there are no participants created
1533
if (participants==null) return minWidth;
1534
1535      // finds the leaf participants
1536
Set leafParticipants=new HashSet();
1537
1538      Iterator it=participants.iterator();
1539      while (it.hasNext()) {
1540         Participant par=(Participant)it.next();
1541         // if participant doesn't have any other participants,
1542
// it is a leaf participant and should be added to collection
1543
if (!hasAnyParticipant(par,parentMap)) {
1544            leafParticipants.add(par);
1545         }
1546      }
1547
1548      // max. right edge position minus horizontalOffset (of all leafs) becomes minWidth
1549
it=leafParticipants.iterator();
1550      int maxRightEdgePosition=0;
1551
1552      while (it.hasNext()) {
1553         Participant lpar=(Participant)it.next();
1554         int minREdge;
1555         int minParREdge;
1556         int minChildrenREdge=0;
1557         // getting future participant bounds
1558
minParREdge=((Rectangle)getBounds(lpar,propertyMap)).x+minParWidth;//HM, JGraph3.4.1
1559
// getting the future child views bounding rectangle -> its right
1560
// edge plus some extra space is min. right edge for that participant
1561
Rectangle r=getBoundsOfParticipantFutureActivities(lpar,propertyMap,parentMap);
1562         if (r != null) {
1563            minChildrenREdge=r.x+r.width+defParNameWidth;
1564         }
1565
1566         minREdge=java.lang.Math.max(minParREdge,minChildrenREdge);
1567         // if entering first time, set the starting max.
1568
if (maxRightEdgePosition==0) {
1569            maxRightEdgePosition=minREdge;
1570         }
1571         else if (minREdge>maxRightEdgePosition) {
1572            maxRightEdgePosition=minREdge;
1573         }
1574      }
1575
1576      int minW=maxRightEdgePosition-horizontalOffset;
1577
1578      // can't allow that the minWidth<minParWidth
1579
if (minW>minParWidth) {
1580         minWidth=minW;
1581      }
1582
1583      return minWidth;
1584
1585   }
1586
1587   /**
1588    * Calculates minimal participant height, which depends of
1589    * position of all of its Activity cells. The height is calculated
1590    * considering propertyMap and parentMap - which means for future
1591    * children state, and for bounds that are constantly changed
1592    * during other calculations. If propertyMap and parentMap
1593    * are null, size is calculated for current state.
1594    */

1595   protected int optimalParticipantHeight (Participant par,Map propertyMap,
1596                                           ParentMap parentMap) {
1597      // initial value for height
1598
int optHeight=minParHeight;
1599
1600      // exits returning minParHeight if there are no activity cells within participant
1601
if (!hasAnyActivity(par,parentMap)) return optHeight;
1602
1603      // get bounds of par (either current or future)
1604
Rectangle rCurrent=(Rectangle)getBounds(par,propertyMap);//HM, JGraph3.4.1
1605
// get preffered bounding rectangle of participant (according to it's children)
1606
Rectangle rPreferred=getBoundsOfParticipantFutureActivities(par,propertyMap,parentMap);;
1607
1608      // difference of these rectangle's bottom positions plus current par height
1609
// plus some extra space is min. height for given participant
1610

1611      // calculate difference in bottom edges of these rectangles, and optimal height
1612
if (rPreferred!=null) {
1613         int dBottom=(rPreferred.y+rPreferred.height)-(rCurrent.y+rCurrent.height);
1614         int optH=rCurrent.height+dBottom+10;
1615
1616         // optimal height can't be less then minHeight
1617
if (optH>optHeight) {
1618            optHeight=optH;
1619         }
1620      } else {
1621         //System.err.println("OHINNNNNNNNNNNNNNNNNNNUUUUUUUUUUUUULLLLLLLLLL");
1622
}
1623
1624      return optHeight;
1625
1626   }
1627
1628   /**
1629    * Resizes given participants. The resizing is done to propertyMap
1630    * which will later (after all needed operation) be applied.
1631    */

1632   protected void resize(Object JavaDoc[] cells,Map propertyMap,int dw,int dh) {
1633      if (cells!=null && cells.length>0) {
1634         Map map;
1635         Rectangle r;
1636         for (int i = 0; i < cells.length; i++) {
1637            r=new Rectangle(getBounds(cells[i],propertyMap).getBounds());//HM, JGraph3.4.1
1638

1639            int newWidth=r.width+dw;
1640            int newHeight=r.height+dh;
1641
1642            if (newWidth<minParWidth || newHeight<minParHeight) {
1643               System.err.println("There was an error in calculating size of participant "+cells[i]+"!!!");
1644               System.err.println("New width="+newWidth+", new height="+newHeight);
1645            }
1646
1647            r.setSize(newWidth,newHeight);
1648            changeBounds(cells[i],propertyMap,r);
1649
1650         }
1651      }
1652   }
1653
1654   /**
1655    * Translates participants under given position yPos vertically for
1656    * a value of dv. The translating is done to propertyMap
1657    * which will later (after all needed operation) be applied.
1658    * @see #translateParticipants
1659    */

1660   protected void translateVertically (Map propertyMap,
1661                                       ParentMap parentMap,int yPos,int dv) {
1662      Participant[] pars=getParticipantsForYPos(yPos,0,propertyMap,parentMap);
1663      translateParticipants(pars,propertyMap,parentMap,0,dv);
1664   }
1665
1666   /**
1667    * Translates given participants using propertyMap for bounds checking
1668    * and parentMap for future children checking. The translating is
1669    * done to propertyMap which will later (after all needed operation) be applied.
1670    * @see #translateParticipant
1671    */

1672   protected void translateParticipants (Participant[] cells,Map propertyMap,
1673                                         ParentMap parentMap,int dx,int dy) {
1674      if (cells!=null && cells.length>0) {
1675         for (int i=0; i<cells.length; i++) {
1676            translateParticipant(cells[i],propertyMap,parentMap,dx,dy);
1677         }
1678      }
1679   }
1680
1681   /**
1682    * Translates single participant and its children.The method checks for bounds of
1683    * cells within propertyMap and uses parentMap to translate right children (the
1684    * children that will be it's after applying parentMap). The translating is done
1685    * to propertyMap which will later (after all needed operation) be applied.
1686    */

1687   protected void translateParticipant (Participant par,Map propertyMap,
1688                                        ParentMap parentMap,int dx,int dy) {
1689      Set participantAndItsFutureActivities = new HashSet();
1690      participantAndItsFutureActivities.add(par);
1691
1692      // Get future activities of participant
1693
Set futureActivities=getParticipantFutureActivities(par,parentMap);
1694
1695      participantAndItsFutureActivities.addAll(futureActivities);
1696
1697      // applying translations to the determined cells
1698
Map map;
1699      Rectangle r;
1700      Iterator it=participantAndItsFutureActivities.iterator();
1701      while (it.hasNext()) {
1702         Object JavaDoc cell=it.next();
1703         r=new Rectangle(getBounds(cell,propertyMap).getBounds());//HM, JGraph3.4.1
1704
r.translate(dx,dy);
1705         changeBounds(cell,propertyMap,r);
1706      }
1707   }
1708
1709   /**
1710    * Gets the bounding rectangle of future children activities of given Participant
1711    * par (that will be participants activities after parent map is applied). Bounding
1712    * rectangle is union of previous mentioned activities.
1713    */

1714   protected Rectangle getBoundsOfParticipantFutureActivities (Participant par,
1715                                                               Map propertyMap,ParentMap parentMap) {
1716      // simulate future state of children and get it's bounds
1717
Set futureActivities=getParticipantFutureActivities(par,parentMap);
1718      Set futureActivityBounds=new HashSet();
1719
1720      Iterator it=futureActivities.iterator();
1721      while (it.hasNext()) {
1722         Rectangle actBnd=(Rectangle)getBounds(it.next(),propertyMap);//HM, JGraph3.4.1
1723
futureActivityBounds.add(actBnd);
1724      }
1725
1726      Rectangle[] fab=new Rectangle[futureActivityBounds.size()];
1727      futureActivityBounds.toArray(fab);
1728      Rectangle unionBounds=getUnionBounds(fab);
1729
1730      return unionBounds;
1731   }
1732
1733   /**
1734    * Gets future children activities of given participant par (that will be
1735    * par's activities after parent map is applied).
1736    */

1737   protected Set getParticipantFutureActivities (Participant par,
1738                                                 ParentMap parentMap) {
1739      // if there is no parent map, or there is no entry for participant
1740
// in it, return current participants activities
1741
if (parentMap==null) {// || !parentMap.getChangedNodes().contains(par)) {
1742
return par.getChildActivities();
1743      }
1744      Set futureActivities=new HashSet();
1745      // getting participants which will be empty after applying parentMap
1746
ArrayList emptyPars=((JaWEParentMap)parentMap).emptyParentList();
1747      // returns empty set if there will be no activity cells within participant
1748
if (emptyPars.contains(par)) return futureActivities;
1749      // get changed nodes from parent map (nodes which parent changed and
1750
// nodes which children changed)
1751
Set changedNodes=parentMap.getChangedNodes();
1752      // get all (previous) participants activities and make the future look
1753
// of participant activities
1754
futureActivities=new HashSet(par.getChildActivities());
1755      Object JavaDoc[] previousActivities=futureActivities.toArray();
1756      // iterate through child activities and remove ones which are
1757
// contained in changed nodes of parent map - they will no longer
1758
// be the children of current participant
1759
for (int i=0; i<previousActivities.length; i++) {
1760         if (changedNodes.contains(previousActivities[i])) {
1761            futureActivities.remove(previousActivities[i]);
1762         }
1763      }
1764      // get new children of current participant from parent map
1765
// and add it to futureActivities set
1766
ArrayList nc=((JaWEParentMap)parentMap).getNewChildren(par);
1767      futureActivities.addAll(nc);
1768
1769      return futureActivities;
1770   }
1771
1772   /**
1773    * Returns leaf participant that bounds given y-coordinate. If
1774    * y-coordinate is at boundary of two participants, method
1775    * returns one that is above. The method checks for bounds of
1776    * cells within propertyMap.
1777    */

1778   protected Participant getLeafParticipantForYPos (int yPos,Map propertyMap,
1779                                                    ParentMap parentMap) {
1780      // getting all participants that contains yPos
1781
Participant[] pars=getParticipantsForYPos(yPos,2,propertyMap,parentMap);
1782
1783      // if there is no participants at this location, return null
1784
if (pars == null) return null;
1785
1786      // getting leaf participant(s)
1787
Set leafPars=new HashSet();
1788      for (int i=0; i<pars.length; i++) {
1789         if (!hasAnyParticipant(pars[i],parentMap)) {
1790            leafPars.add(pars[i]);
1791         }
1792      }
1793
1794      // if there is no leaf participant at this location (THIS SHOULD
1795
// NEVER HAPPEND, BUT ...) return null
1796
if (leafPars.size()==0) return null;
1797
1798      // taking first and making it the right one
1799
Iterator it=leafPars.iterator();
1800      Object JavaDoc rightPar=it.next();
1801
1802      // if there is more than one leaf participant, take the one that
1803
// has minimal y-coord of upper left corner
1804
if (leafPars.size()>1) {
1805         int upperLeftY;
1806         int minUpperLeftY;
1807         Rectangle parRect;
1808
1809         // taking bounding rectangle of first par
1810
parRect=getBounds(rightPar,propertyMap).getBounds();//HM, JGraph3.4.1
1811
// taking upper-left corner y-coord
1812
upperLeftY=parRect.getLocation().y;
1813         minUpperLeftY=upperLeftY;
1814
1815         // finding the participant with min. y-coord
1816
while (it.hasNext()) {
1817            Object JavaDoc curPar=it.next();
1818            parRect=getBounds(curPar,propertyMap).getBounds();//HM, JGraph3.4.1
1819
upperLeftY=parRect.getLocation().y;
1820            if (upperLeftY<minUpperLeftY) {
1821               minUpperLeftY=upperLeftY;
1822               rightPar=curPar;
1823            }
1824         }
1825      }
1826
1827      // return found participant
1828
return (Participant)rightPar;
1829
1830   }
1831
1832   /**
1833    * Returns participants that are under or above given yPos, or contains
1834    * that y-position: <BR> direction=0 -> under, <BR> direction=1 -> above,
1835    * <BR> direction=2 -> contains. The method checks for bounds of
1836    * cells within propertyMap. If some of model's participants is entered
1837    * in parentMap as removed participant, this method doesn't consider that
1838    * participant.
1839    */

1840   protected Participant[] getParticipantsForYPos (int yPos,int direction,
1841                                                   Map propertyMap,ParentMap parentMap) {
1842      // getting all participants that are in collection
1843
Set participants=JaWEGraphModel.getAllParticipantsInModel(graphModel());
1844
1845      // if there are no participants, return null
1846
if (participants == null) return null;
1847
1848      // removing ones which parent in a parentMap is null
1849
if (parentMap != null) {
1850         participants.removeAll(((JaWEParentMap)parentMap).getRemovedNodes());
1851      }
1852
1853      // making an array of participants
1854
Participant[] pars=new Participant[participants.size()];
1855      participants.toArray(pars);
1856
1857      // Set of participants that will satisfy needs
1858
Set yPosPars=new HashSet();
1859
1860      for (int i = 0; i < pars.length; i++) {
1861         Rectangle r=(Rectangle)getBounds(pars[i],propertyMap);//HM, JGraph3.4.1
1862
switch (direction) {
1863            case 0:
1864               if (r.y >=yPos) {
1865                  yPosPars.add(pars[i]);
1866               }
1867               break;
1868            case 1:
1869               if (r.y <yPos) {
1870                  yPosPars.add(pars[i]);
1871               }
1872               break;
1873            case 2:
1874               if ((r.y <= yPos) && (r.y+r.height >= yPos)) {
1875                  yPosPars.add(pars[i]);
1876               }
1877               break;
1878         }
1879      }
1880
1881      if (yPosPars.size()>0) {
1882         pars=new Participant[yPosPars.size()];
1883         yPosPars.toArray(pars);
1884         return pars;
1885      }
1886      else {
1887         return null;
1888      }
1889   }
1890
1891
1892   /**
1893    * Gets the insertation point (y-coordinate) of new root participant.
1894    */

1895   protected int getNewRootParYPos (Map propertyMap,ParentMap parentMap) {
1896      int newRootParYPos=0;
1897
1898      Set rootPars=JaWEGraphModel.getRootParticipants(graphModel());
1899
1900      // adding to rootPars set a root participants from propertyMap -> that is
1901
// done because of proper calculation of y-position of in/out ports when
1902
// new root participant is added to graph
1903

1904      if (propertyMap != null) {
1905         Iterator it=propertyMap.keySet().iterator();
1906         while (it.hasNext()) {
1907            Object JavaDoc rootPar=it.next();
1908            if ((rootPar instanceof Participant) &&
1909                   (((DefaultGraphCell)rootPar).getParent()==null)) {
1910               rootPars.add(rootPar);
1911            }
1912         }
1913      }
1914
1915      // removing from rootPars set a root participants from parentMap -> that is
1916
// done because of proper calculation of y-position of in/out ports when
1917
// root participant is removed from graph
1918

1919      if (parentMap != null) {
1920         rootPars.removeAll(((JaWEParentMap)parentMap).getRemovedNodes());
1921      }
1922
1923      // if there is no root participants, new Y-position is 0
1924
if (rootPars==null || rootPars.size()==0) return newRootParYPos;
1925
1926      newRootParYPos=minParHeight;
1927      // find the bottom of bottom most root participant
1928
Iterator it=rootPars.iterator();
1929      while(it.hasNext()) {
1930         Rectangle bounds=(Rectangle)getBounds(it.next(),propertyMap);//HM, JGraph3.4.1
1931
if (bounds.y+bounds.height>newRootParYPos) {
1932            newRootParYPos=bounds.y+bounds.height;
1933         }
1934      }
1935
1936      return newRootParYPos;
1937   }
1938
1939   /**
1940    * Gets the width of root participants. The method checks for bounds of
1941    * cells within propertyMap. If some of model's participants has entry
1942    * within propertyMap as removed, this participant doesn't count.
1943    */

1944   protected int getRootParticipantWidth (Map propertyMap,ParentMap parentMap) {
1945      int rootParWidth=minParWidth;
1946      Set rootPars=JaWEGraphModel.getRootParticipants(graphModel());
1947
1948      // if there is no root participants, width is equal to minParWidth
1949
if (rootPars==null) return rootParWidth;
1950
1951      // removing ones which parent in a parentMap is null (this means they
1952
// will be removed from a graph)
1953
if (parentMap != null) {
1954         rootPars.removeAll(((JaWEParentMap)parentMap).getRemovedNodes());
1955      }
1956
1957      // if there is no root participants, width is equal to minParWidth
1958
if (rootPars.size()==0) return rootParWidth;
1959
1960      // all root participants has same width, so take the first
1961
Iterator it=rootPars.iterator();
1962      Object JavaDoc firstPar=it.next();
1963      rootParWidth=getParticipantWidth(firstPar,propertyMap);
1964
1965      return rootParWidth;
1966   }
1967
1968   /**
1969    * Checks if given participant par has other participants. If parentMap is null,
1970    * or there is no entry for this this participant within a parentMap,
1971    * the current state is checked, elsewhere parentMap is checked-in other
1972    * words future state of participant participants (state after aplying parentMap)
1973    * is returned.
1974    * <p> This method has meaning in previous versions of JaWE, now it always
1975    * returns <tt>false</tt>.
1976    */

1977   protected boolean hasAnyParticipant (Participant par,ParentMap parentMap) {
1978      // if there is no parent map, or there is no entry for participant
1979
// in it, return original participant state
1980
if (parentMap==null || !parentMap.getChangedNodes().contains(par)) {
1981         return par.hasAnyParticipant();
1982      }
1983         // else, check if participant will be empty after applying parent map
1984
else {
1985         return ((JaWEParentMap)parentMap).hasAnyParticipant(par);
1986      }
1987   }
1988
1989   /**
1990    * Checks if given participant par has activities. If parentMap is null,
1991    * or there is no entry for this this participant within a parentMap,
1992    * the current state is checked, elsewhere parentMap is checked-in other
1993    * words future state of participant activities (state after aplying parentMap)
1994    * is returned.
1995    */

1996   protected boolean hasAnyActivity (Participant par,ParentMap parentMap) {
1997      // if there is no parent map, or there is no entry for participant
1998
// in it, return original participant state
1999
if (parentMap==null || !parentMap.getChangedNodes().contains(par)) {
2000         return par.hasAnyActivity();
2001      }
2002         // else, check if participant will be empty after applying parent map
2003
else {
2004         // getting participants which will be empty after applying parentMap
2005
ArrayList emptyPars=((JaWEParentMap)parentMap).emptyParentList();
2006         // returns empty set if there will be no activity cells within participant
2007
if (emptyPars.contains(par)) {
2008            return false;
2009         }
2010         else {
2011            return true;
2012         }
2013      }
2014   }
2015
2016   /**
2017    * Returns starts of process/block.
2018    */

2019   protected Set getStarts () {
2020      Set starts=new HashSet();
2021      Set allActivities=graphModel().getAllActivitiesInModel(graphModel());
2022
2023      if (allActivities!=null) {
2024         Iterator it=allActivities.iterator();
2025         while (it.hasNext()) {
2026            Object JavaDoc act=it.next();
2027            if (act instanceof Start) {
2028               starts.add(act);
2029            }
2030         }
2031      }
2032      return starts;
2033   }
2034
2035   /**
2036    * Returns set of ends of process/block.
2037    */

2038   protected Set getEnds () {
2039      Set ends=new HashSet();
2040      Set allActivities=graphModel().getAllActivitiesInModel(graphModel());
2041
2042      if (allActivities!=null) {
2043         Iterator it=allActivities.iterator();
2044         while (it.hasNext()) {
2045            Object JavaDoc act=it.next();
2046            if (act instanceof End) {
2047               ends.add(act);
2048            }
2049         }
2050      }
2051      return ends;
2052   }
2053
2054   /**
2055    * Gets view of given object.
2056    */

2057   public CellView getView (Object JavaDoc cell) {
2058      //return graph.getView().getMapping(cell,false);
2059
return graph.getGraphLayoutCache().getMapping(cell,false);
2060   }
2061
2062   /**
2063    * Gets width of given participant (from it's current view or
2064    * from propertyMap).
2065    */

2066   protected int getParticipantWidth (Object JavaDoc par,Map propertyMap) {
2067      return getBounds(par,propertyMap).getBounds().width;//HM, JGraph3.4.1
2068
}
2069
2070   /**
2071    * Gets height of given participant (from it's current view or
2072    * from propertyMap).
2073    */

2074   protected int getParticipantHeight (Object JavaDoc par,Map propertyMap) {
2075      return getBounds(par,propertyMap).getBounds().height;//HM, JGraph3.4.1
2076
}
2077
2078   /**
2079    * Replaces bounding rectangle of given cell in propertyMap object
2080    * with rectangle r if cell is contained within the propertyMap
2081    * object, otherwise adds new entry to the propertyMap that consists of
2082    * given cell and a map containing given rectangle r.
2083    */

2084   protected void changeBounds(Object JavaDoc cell,Map propertyMap,Rectangle r) {
2085      Map map;
2086      if (propertyMap==null || !propertyMap.containsKey(cell)) {
2087         map=GraphConstants.createMap();
2088         GraphConstants.setBounds(map,r);
2089         propertyMap.put(cell,map);
2090      }
2091      else {
2092         map=(Map)propertyMap.get(cell);
2093         GraphConstants.setBounds(map,r);
2094      }
2095   }
2096
2097   /**
2098    * Gets bounding rectangle of given cell. The rectangle is
2099    * either current rectangle of cellView either from propertyMap
2100    * where are held bounding rectangles of various cells during
2101    * multiple resizing and/or translating of cells.
2102    */

2103   public Rectangle2D JavaDoc getBounds (Object JavaDoc cell,Map propertyMap) {//HM, JGraph3.4.1
2104
if (propertyMap != null && propertyMap.containsKey(cell)) {
2105         Map map=(Map)propertyMap.get(cell);
2106         return GraphConstants.getBounds(map);
2107      }
2108      else {
2109         CellView view=getView(cell);
2110         return view.getBounds();
2111      }
2112   }
2113
2114   /**
2115    * Gets union of given rectangles.
2116    */

2117   protected Rectangle getUnionBounds (Rectangle[] rects) {
2118      if (rects != null && rects.length > 0) {
2119         Rectangle unionRect = null;
2120         for (int i=0; i<rects.length; i++) {
2121            if (unionRect == null) {
2122               unionRect = new Rectangle(rects[i]);
2123            }
2124            else {
2125               SwingUtilities.computeUnion(rects[i].x,rects[i].y,
2126                                           rects[i].width,rects[i].height,unionRect);
2127            }
2128         }
2129         return unionRect;
2130      }
2131      return null;
2132   }
2133
2134   /**
2135    * Used during import of an XML file to create graph participants for
2136    * given workflow process, and to associate the XML logic participant
2137    * objects to it.
2138    */

2139   private void createGraphParticipants (WorkflowProcess wp,java.util.List JavaDoc entitiesToInsert) {
2140      boolean participantInserted=false;
2141      Iterator it=entitiesToInsert.iterator();
2142      while (it.hasNext()) {
2143         Object JavaDoc p=it.next();
2144         if (p instanceof org.enhydra.jawe.xml.elements.Participant) {
2145            showNode((org.enhydra.jawe.xml.elements.Participant)p);
2146            participantInserted=true;
2147         }
2148      }
2149      if (!participantInserted) {
2150         Participants pcs=(Participants)wp.get("Participants");
2151         Activities acts=null;
2152         if (graph instanceof BlockActivityGraph) {
2153            ActivitySet as=getBlockActivitySet(
2154                                                 ((BlockActivityGraph)graph).getMyBlockActivity());
2155            if (as!=null) {
2156               acts=(Activities)as.get("Activities");
2157            }
2158         } else {
2159            acts=(Activities)wp.get("Activities");
2160         }
2161
2162         if (acts!=null && acts.size()>0) {
2163            showNode(org.enhydra.jawe.xml.elements.Participant.getFreeTextExpressionParticipant());
2164         }
2165      }
2166      //graph.repaint(0);
2167
}
2168
2169   /**
2170    * Used during import of an XML file to create graph activities for
2171    * the given process, and to associate the XML logic activity objects
2172    * to it.
2173    */

2174   private void createGraphActivitiesAndBlockActivities (WorkflowProcess wp,
2175                                                         java.util.List JavaDoc entitiesToInsert,boolean isMine) {
2176      //System.out.println("Workflow "+wp+", has to insert activities among "+entitiesToInsert.size()+" entities");
2177

2178      Iterator it=entitiesToInsert.iterator();
2179      while (it.hasNext()) {
2180         Object JavaDoc mayBeActivity=it.next();
2181         //System.out.println("Workflow "+wp+": entity "+aOrIb+" is next");
2182
if (mayBeActivity instanceof org.enhydra.jawe.xml.elements.Activity) {
2183            //System.out.println("Workflow "+wp+": entity "+aOrIb+" is next");
2184
insertActivity(
2185                             (org.enhydra.jawe.xml.elements.Activity)mayBeActivity,
2186               wp,isMine);
2187         }
2188      }
2189   }
2190
2191   /**
2192    * Used during import of an XML file to create graph activity object for
2193    * the given process, and to associate the given XML logic activity object
2194    * to it. It creates appropriate graph object depending on given logical
2195    * activity type (Route, Tool, Subflow or BlockActivity) and determines the
2196    * participant graph object to put it into.
2197    */

2198   private void insertActivity(
2199      org.enhydra.jawe.xml.elements.Activity a,
2200      WorkflowProcess wp,
2201      boolean isMine) {
2202
2203      //System.out.println("Must insert graph object for activity "+a);
2204
Participants pcs=(Participants)wp.get("Participants");
2205      Rectangle rPar;
2206      Point p=null;
2207      Activity act;
2208      Participant par;
2209      Map viewMap;
2210      Object JavaDoc performer;
2211      int actType;
2212
2213      // must save performer to set it later again (because of
2214
// movement during importing)
2215
performer=a.get("Performer").toValue();
2216
2217      String JavaDoc participantID="";
2218      if (isMine) {
2219         participantID=a.getParticipantID();
2220      }
2221      if (participantID.length()==0) {
2222         if (performer!=null && performer instanceof
2223             org.enhydra.jawe.xml.elements.Participant) {
2224            participantID=
2225               ((org.enhydra.jawe.xml.elements.Participant)
2226                   performer).getID();
2227         } else {
2228            participantID=performer.toString();
2229         }
2230      }
2231
2232      par=getGraphObjectForXMLParticipant(pcs.getParticipant(participantID));
2233      if (par==null) {
2234         par=getGraphObjectForXMLParticipant(org.enhydra.jawe.xml.elements.Participant.getFreeTextExpressionParticipant());
2235      }
2236      if (par!=null) {
2237         rPar=(Rectangle)getBounds(par,null);//HM, JGraph3.4.1
2238
p=new Point(rPar.getLocation());
2239         p.x+=10; p.y+=10;
2240      } else {
2241         rPar=null;
2242         p=new Point(10,10);
2243      }
2244
2245      viewMap = new Hashtable();
2246      actType=a.getType();
2247      switch (actType) {
2248         case 0:
2249            act=createRoute(p,viewMap);
2250            break;
2251         case 3:
2252            act=createSubflow(p,viewMap);
2253            break;
2254         case 4:
2255            act=createBlockActivity(p,viewMap);
2256            ((ActivitySets)wp.get("ActivitySets")).decrementID();
2257            break;
2258         default:
2259            act=createActivity(p,viewMap);
2260            break;
2261      }
2262      getActivitiesCollection().decrementID();
2263      act.setUserObject(a);
2264
2265      //System.out.println("Graph Activity object for "+act+" is created");
2266
updateModelAndArrangeParticipants(new Object JavaDoc[] {act},null,null,viewMap,"",
2267                                        false,null);
2268      int xOffset=0, yOffset=0;
2269      if (isMine) {
2270         xOffset=a.getXOffset();
2271         yOffset=a.getYOffset();
2272      }
2273      adjustActivityPosition(act,xOffset,yOffset,rPar);
2274      // setting back the activity performer
2275
a.set("Performer",performer);
2276      // if this is a block activity, create it's graph
2277
if (actType==4) {
2278         ((BlockActivity)act).
2279            createBlockActivityGraph(graph.getEditor().getWindow());
2280      }
2281   }
2282
2283   /**
2284    * Used during import of an XML file to create graph transitions for
2285    * the given process, and to associate the XML logic transition objects
2286    * to it.
2287    */

2288   private void createGraphTransitions (WorkflowProcess wp,
2289                                        java.util.List JavaDoc entitiesToInsert,boolean isMine) {
2290
2291      String JavaDoc IDFrom, IDTo;
2292      Activity source, target;
2293      org.enhydra.jawe.xml.elements.Transition trans;
2294      Transition t;
2295
2296      Iterator it=entitiesToInsert.iterator();
2297      while (it.hasNext()) {
2298         Object JavaDoc tr=it.next();
2299         if (tr instanceof org.enhydra.jawe.xml.elements.Transition) {
2300            trans=(org.enhydra.jawe.xml.elements.Transition)tr;
2301            IDFrom=trans.get("From").toValue().toString();
2302            IDTo=trans.get("To").toValue().toString();
2303            source=getActivity(IDFrom);
2304            target=getActivity(IDTo);
2305            String JavaDoc rt=trans.getRoutingType();
2306            boolean isRouting=(rt!=null && !rt.equals(trans.NO_ROUTING));
2307            t=connectActivities(source,target,isRouting);
2308            if (t!=null) {
2309               if (!isRouting) {
2310                  TransitionView tv=(TransitionView)getView(t);
2311                  Map ordNoToPoint=trans.getBreakPoints();
2312                  // now, inserting takes place - must be inserted in the right order
2313
for (int i=1; i<=ordNoToPoint.size(); i++) {
2314                     tv.addPointProgramatically((Point)ordNoToPoint.get(new Integer JavaDoc(i)),i);
2315                  }
2316               }
2317               t.setUserObject(trans);
2318            }
2319
2320            // to see changes
2321
//graph.paintImmediately(graph.getBounds());
2322
}
2323      }
2324   }
2325
2326   /** Used during import of an XML file to create graph start. */
2327   protected void createGraphStarts (WorkflowProcess wp,boolean isMine,boolean automaticCreation) {
2328      Activity source=null;
2329      Activity target=null;
2330
2331      Hashtable viewMap = new Hashtable();
2332      org.enhydra.jawe.xml.elements.Activity a=null;
2333
2334      // first, the case of package made by JaWE
2335
if (isMine && !automaticCreation) {
2336         Set startDescriptions=new HashSet();
2337         if (graph instanceof BlockActivityGraph) {
2338            a=(org.enhydra.jawe.xml.elements.Activity)
2339               getVisualOwner();
2340            startDescriptions=a.getStartDescriptions();
2341         } else {
2342            startDescriptions=wp.getStartDescriptions();
2343         }
2344
2345         if (startDescriptions.size()==0) return;
2346
2347         Participants pcs=(Participants)wp.get("Participants");
2348         String JavaDoc ID;
2349         Participant par;
2350         Rectangle rPar;
2351         Point p;
2352
2353         Iterator it=startDescriptions.iterator();
2354         String JavaDoc startDesc;
2355         String JavaDoc[] startD;
2356         while (it.hasNext()) {
2357            startDesc=(String JavaDoc)it.next();
2358            startD=Utils.tokenize(startDesc,";");
2359            ID="";
2360            try {
2361               ID=startD[0];
2362            } catch (Exception JavaDoc ex) {}
2363            par=getGraphObjectForXMLParticipant(pcs.getParticipant(ID));
2364
2365            if (par==null) {
2366               par=getGraphObjectForXMLParticipant(org.enhydra.jawe.xml.elements.Participant.getFreeTextExpressionParticipant());
2367            }
2368
2369            if (par!=null) {
2370               rPar=(Rectangle)getBounds(par,null);//HM, JGraph3.4.1
2371
p=new Point(rPar.getLocation());
2372               p.x+=10; p.y+=10;
2373            } else {
2374               rPar=null;
2375               p=new Point(10,10);
2376            }
2377            viewMap=new Hashtable();
2378            source=createStart(p,viewMap);
2379            updateModelAndArrangeParticipants(new Object JavaDoc[] {source},null,
2380                                              null,viewMap,"",false,null);
2381
2382            // adjusting activities position
2383
try {
2384               adjustActivityPosition(source,Integer.parseInt(startD[2]),
2385                                      Integer.parseInt(startD[3]),rPar);
2386            } catch (Exception JavaDoc ex) {}
2387
2388            try {
2389               target=getActivity(startD[1]);
2390            } catch (Exception JavaDoc ex) {}
2391
2392            boolean isTransitionRouted=false;
2393            try {
2394               String JavaDoc itr=startD[4];
2395               if (itr.equals(org.enhydra.jawe.xml.elements.Transition.NO_ROUTING)) {
2396                  isTransitionRouted=false;
2397               } else {
2398                  isTransitionRouted=true;
2399               }
2400            } catch (Exception JavaDoc ex) {
2401               isTransitionRouted=false;
2402            }
2403            if (source!=null && target!=null) {
2404               connectActivities(source,target,isTransitionRouted);
2405            }
2406         }
2407         // if the package is from other vendor
2408
} else {
2409         Set acs=JaWEGraphModel.getAllActivitiesInModel(graphModel());
2410         if (acs!=null) {
2411            int translY=10;
2412            Iterator it=acs.iterator();
2413            while (it.hasNext()) {
2414               Activity act=(Activity)it.next();
2415               if ((act instanceof Start) || (act instanceof End)) continue;
2416               if (Utils.isStartingActivity(act) && !Utils.hasConnectedStartBubble(act)) {
2417                  target=act;
2418                  viewMap = new Hashtable();
2419                  source=createStart(new Point(10,translY),viewMap);
2420                  translY+=30;
2421                  updateModelAndArrangeParticipants(new Object JavaDoc[] {source},
2422                                                    null,null,viewMap,"",false,null);
2423
2424                  if (source!=null && target!=null) {
2425                     connectActivities(source,target,false);
2426                  }
2427               }
2428            }
2429         }
2430      }
2431   }
2432
2433   /** Used during import of an XML file to create graph ends. */
2434   protected void createGraphEnds (WorkflowProcess wp,boolean isMine,boolean automaticCreation) {
2435      Activity source=null;
2436      Activity target=null;
2437
2438      Hashtable viewMap;
2439
2440      org.enhydra.jawe.xml.elements.Activity a=null;
2441      // first, the case of our package
2442
if (isMine && !automaticCreation) {
2443         Set endDescriptions=new HashSet();
2444         if (graph instanceof BlockActivityGraph) {
2445            a=(org.enhydra.jawe.xml.elements.Activity)
2446               getVisualOwner();
2447            endDescriptions=a.getEndDescriptions();
2448         } else {
2449            endDescriptions=wp.getEndDescriptions();
2450         }
2451
2452         if (endDescriptions.size()==0) return;
2453
2454         Participants pcs=(Participants)wp.get("Participants");
2455         String JavaDoc ID;
2456         Participant par;
2457         Rectangle rPar;
2458         Point p;
2459
2460         Iterator it=endDescriptions.iterator();
2461         String JavaDoc endDesc;
2462         String JavaDoc[] endD;
2463         while (it.hasNext()) {
2464            endDesc=(String JavaDoc)it.next();
2465            endD=Utils.tokenize(endDesc,";");
2466            ID="";
2467            try {
2468               ID=endD[0];
2469            } catch (Exception JavaDoc ex) {}
2470            par=getGraphObjectForXMLParticipant(pcs.getParticipant(ID));
2471            if (par==null) {
2472               par=getGraphObjectForXMLParticipant(org.enhydra.jawe.xml.elements.Participant.getFreeTextExpressionParticipant());
2473            }
2474            if (par!=null) {
2475               rPar=(Rectangle)getBounds(par,null);//HM, JGraph3.4.1
2476
p=new Point(rPar.getLocation());
2477               p.x+=10; p.y+=10;
2478            } else {
2479               rPar=null;
2480               p=new Point(10,10);
2481            }
2482            viewMap = new Hashtable();
2483            target=createEnd(p,viewMap);
2484            updateModelAndArrangeParticipants(new Object JavaDoc[] {target},null,null,
2485                                              viewMap,"",false,null);
2486            // adjusting activities position
2487
try {
2488               adjustActivityPosition(target,Integer.parseInt(endD[2]),
2489                                      Integer.parseInt(endD[3]),rPar);
2490            } catch (Exception JavaDoc ex) {}
2491            // connecting end of graph and last activity
2492
try {
2493               source=getActivity(endD[1]);
2494            } catch (Exception JavaDoc ex) {}
2495
2496            boolean isTransitionRouted=false;
2497            try {
2498               String JavaDoc itr=endD[4];
2499               if (itr.equals(org.enhydra.jawe.xml.elements.Transition.NO_ROUTING)) {
2500                  isTransitionRouted=false;
2501               } else {
2502                  isTransitionRouted=true;
2503               }
2504            } catch (Exception JavaDoc ex) {
2505               isTransitionRouted=false;
2506            }
2507
2508            if (source!=null && target!=null) {
2509               connectActivities(source,target,isTransitionRouted);
2510            }
2511         }
2512         // if the package is from other vendor
2513
} else {
2514         Set acs=JaWEGraphModel.getAllActivitiesInModel(graphModel());
2515         if (acs!=null) {
2516            int translY=10;
2517            Iterator it=acs.iterator();
2518            while (it.hasNext()) {
2519               Activity act=(Activity)it.next();
2520               if ((act instanceof Start) || (act instanceof End)) continue;
2521               if (Utils.isEndingActivity(act) && !Utils.hasConnectedEndBubble(act)) {
2522                  source=act;
2523                  viewMap = new Hashtable();
2524                  target=createEnd(new Point(600,translY),viewMap);
2525                  translY+=10;
2526                  updateModelAndArrangeParticipants(new Object JavaDoc[] {target},
2527                                                    null,null,viewMap,"",false,null);
2528
2529                  if (source!=null && target!=null) {
2530                     connectActivities(source,target,false);
2531                  }
2532               }
2533            }
2534         }
2535      }
2536   }
2537
2538   /** Used during import of an XML file to adjust position of activities. */
2539   private void adjustActivityPosition (Activity act,int xOff,int yOff,
2540                                        Rectangle rPar) {
2541      if (rPar==null || (xOff==0 && yOff==0)) return;
2542      int yPar=rPar.y; int xPar=rPar.x;
2543      Map attrib=GraphConstants.cloneMap(act.getAttributes());
2544      Map propertyMap=new Hashtable();
2545      ParentMap parentMap=new JaWEParentMap();
2546
2547      propertyMap.put(act,attrib);
2548
2549      Rectangle bounds=(Rectangle)GraphConstants.getBounds(attrib);//HM, JGraph3.4.1
2550

2551      int inc=rPar.height-5;
2552      int nextYOff=inc;
2553
2554      if (yOff<inc) {
2555         inc=yOff;
2556         nextYOff=yOff;
2557      }
2558
2559      bounds.setLocation(new Point(xPar+xOff,yPar+inc));
2560      arrangeParticipants(propertyMap,parentMap);
2561
2562      if (yOff>nextYOff) {
2563         inc=defActivityHeight;
2564         do {
2565            nextYOff+=inc;
2566            if (nextYOff>yOff) {
2567               nextYOff-=inc;
2568               inc=yOff-nextYOff;
2569               nextYOff+=inc;
2570            }
2571            bounds.translate(0,inc);
2572            arrangeParticipants(propertyMap,parentMap);
2573         } while (nextYOff<yOff);
2574      }
2575      // makes all changes (if there was any) - to model and to view
2576
//graphModel().edit(null,propertyMap,parentMap,null);
2577
graphModel().edit(propertyMap,null,parentMap,null);
2578      // to see changes
2579
graph.paintImmediately(graph.getBounds());
2580   }
2581
2582   /**
2583    * Creates and returns the graph Transition object that connects
2584    * given graph activities. If something goes wrong, returns null.
2585    */

2586   private Transition connectActivities (Activity source,Activity target,
2587                                         boolean isRouting) {
2588      // System.out.println("Connecting activities "+source+" and "+target);
2589
Point startP=getCenter(source);
2590      Point endP=getCenter(target);
2591      try {
2592         Transition t=insertTransition (startP,endP,(PortView)getView(source.getPort()),
2593                                           (PortView)getView(target.getPort()),isRouting,false);
2594         return t;
2595      } catch (Exception JavaDoc ex) {
2596         System.err.println("Error while connecting activities "+source+" and "+target+" !!!");
2597         return null;
2598      }
2599   }
2600
2601
2602   /**
2603    * Used during import of an XML file from other vendor to
2604    * layout graph activities.
2605    */

2606   private void layoutActivities () {
2607      Set participants=JaWEGraphModel.getAllParticipantsInModel(graphModel());
2608      if (participants != null) {
2609         Iterator it=participants.iterator();
2610         while (it.hasNext()) {
2611            Participant par=(Participant)it.next();
2612            Set activities=par.getChildActivities();
2613            Iterator itAct=activities.iterator();
2614
2615            int cnt=0;
2616            double chngDir=(int)Math.sqrt(activities.size());
2617
2618            int incX=2*defActivityWidth;
2619            int incY=defActivityHeight+5;
2620            int translateX=0;
2621            int translateY=0;
2622
2623            while (itAct.hasNext()) {
2624               Activity act=(Activity)itAct.next();
2625               if (!(act instanceof Start) && !(act instanceof End)) {
2626                  cnt++;
2627                  if ((cnt/chngDir)==((int)(cnt/chngDir))) {
2628                     //System.out.println("Changing dir, cnt="+cnt);
2629
incX=-incX;
2630                     translateY+=incY;
2631                  } else {
2632                     translateX+=incX;
2633                  }
2634
2635                  Map attrib=GraphConstants.cloneMap(act.getAttributes());
2636                  Map propertyMap=new Hashtable();
2637                  ParentMap parentMap=new JaWEParentMap();
2638
2639                  propertyMap.put(act,attrib);
2640                  Rectangle bounds=(Rectangle)GraphConstants.getBounds(attrib);//HM, JGraph3.4.1
2641

2642                  if (act instanceof End) {
2643                     bounds.translate(0,translateY);
2644                  } else {
2645                     bounds.translate(translateX,translateY);
2646                  }
2647
2648                  arrangeParticipants(propertyMap,parentMap);
2649                  // makes all changes
2650
//graphModel().edit(null,propertyMap,parentMap,null);
2651
graphModel().edit(propertyMap,null,parentMap,null);
2652                  // to see changes
2653
//graph.paintImmediately(graph.getBounds());
2654
}
2655            }
2656         }
2657      }
2658   }
2659
2660   /**
2661    * Returns graph Activity object which represents the logical
2662    * activity with given Id attribute.
2663    */

2664   public Activity getActivity (String JavaDoc ID) {
2665      Set allActs=JaWEGraphModel.getAllActivitiesInModel(graphModel());
2666      if (allActs != null) {
2667         Iterator it=allActs.iterator();
2668         Activity act;
2669         String JavaDoc curID;
2670         while (it.hasNext()) {
2671            act=(Activity)it.next();
2672            if (!(act instanceof Start) && !(act instanceof End)) {
2673               curID=act.get("Id").toValue().toString();
2674               if (curID!=null && curID.equals(ID)) {
2675                  return act;
2676               }
2677            }
2678         }
2679      }
2680      return null;
2681   }
2682
2683   /**
2684    * Returns graph Transition object which represents the logical
2685    * transition with given Id attribute.
2686    */

2687   public Transition getTransition (String JavaDoc ID) {
2688      Set allTrans=JaWEGraphModel.getAllTransitionsInModel(graphModel());
2689      if (allTrans != null) {
2690         Iterator it=allTrans.iterator();
2691         Transition tr;
2692         String JavaDoc curID;
2693         while (it.hasNext()) {
2694            tr=(Transition)it.next();
2695            org.enhydra.jawe.xml.elements.Transition xmlT=
2696               (org.enhydra.jawe.xml.elements.Transition)
2697               tr.getUserObject();
2698            if (xmlT.getFrom()!=null && xmlT.getTo()!=null) {
2699               curID=tr.get("Id").toValue().toString();
2700               if (curID!=null && curID.equals(ID)) {
2701                  return tr;
2702               }
2703            }
2704         }
2705      }
2706      return null;
2707   }
2708
2709   /**
2710    * Returns graph Participant object which represents the logical
2711    * participant with given Id attribute.
2712    */

2713   public Participant getParticipant (String JavaDoc ID) {
2714      Set allPartic=JaWEGraphModel.getAllParticipantsInModel(graphModel());
2715      if (allPartic != null) {
2716         Iterator it=allPartic.iterator();
2717         Participant p;
2718         String JavaDoc curID;
2719         while (it.hasNext()) {
2720            p=(Participant)it.next();
2721            if (p.get("Id").toString().equals(ID)) {
2722               return p;
2723            }
2724         }
2725      }
2726      return null;
2727   }
2728
2729   /**
2730    * Returns the central point of given graph object.
2731    */

2732   private Point getCenter (Object JavaDoc go) {
2733      if (go==null) return null;
2734      Rectangle r=(Rectangle)getBounds(go,null);//HM, JGraph3.4.1
2735
if (!(go instanceof Participant)) {
2736         return new Point(r.x+(int)(r.width / 2),r.y+(int)(r.height / 2));
2737      } else {
2738         return new Point(r.x+defParNameWidth/2,r.y+(int)(r.height / 2));
2739      }
2740   }
2741
2742   /**
2743    * Refreshes the collections (adds or removes it's elements) of
2744    * workflow logic objects (activities, transitions, workflow processes,
2745    * block activities) corresponding to the graph objects that are
2746    * beeing added to or removed from graph.
2747    * @param cellsToAddOrRemove The graph objects that are beeing added to
2748    * or removed from graph.
2749    * @param toAdd <tt>true</tt> if graph objects are beeing
2750    * added, <tt>false</tt> otherwise.
2751    */

2752   protected void refreshCollections (
2753      Object JavaDoc[] cellsToAddOrRemove,boolean toAdd) {
2754
2755      // the set of activities user objects to add or remove
2756
Set xmlaAR=new HashSet();
2757      // the set of transitions user objects to add or remove
2758
Set xmltAR=new HashSet();
2759      // the set of workflow processes user objects to add or remove
2760
Set xmlwAR=new HashSet();
2761
2762      // the set of block activities to add or remove
2763
Set baAR=new HashSet();
2764
2765      if (cellsToAddOrRemove!=null && cellsToAddOrRemove.length>0) {
2766         for (int i=0; i<cellsToAddOrRemove.length; i++) {
2767            Object JavaDoc cell=cellsToAddOrRemove[i];
2768            // managing the participant references if cell is
2769
// process, blockActivity or participant
2770
manageParticipantReferences(cell,toAdd);
2771            if (cell instanceof Transition) {
2772               Transition tr=(Transition)cell;
2773               boolean isValid=manageTransition(tr);
2774               if (toAdd) {
2775                  if (isValid) {
2776                     xmltAR.add(tr.getUserObject());
2777                  }
2778               } else {
2779                  xmltAR.add(tr.getUserObject());
2780               }
2781            } else if (cell instanceof org.enhydra.jawe.graph.Process) {
2782               org.enhydra.jawe.graph.Process proc=(org.enhydra.jawe.graph.Process)cell;
2783               WorkflowProcess wp=(WorkflowProcess)proc.getUserObject();
2784               xmlwAR.add(wp);
2785               // add or remove process to process graph mappings
2786
if (toAdd) {
2787                  JaWE.getInstance().getPackageEditor().putProcessObjectMapping(wp,proc);
2788               } else {
2789                  JaWE.getInstance().getPackageEditor().removeProcessObjectMapping(wp);
2790               }
2791
2792            } else if (cell instanceof BlockActivity) {
2793               xmlaAR.add(((Activity)cell).getUserObject());
2794               baAR.add(cell);
2795            } else if (cell instanceof Activity && !(cell instanceof Start)
2796                       && !(cell instanceof End)) {
2797               xmlaAR.add(((Activity)cell).getUserObject());
2798            }
2799         }
2800      }
2801      Package JavaDoc pkg=getXMLPackage();
2802      WorkflowProcesses wps=(WorkflowProcesses)pkg.get("WorkflowProcesses");
2803      wps.refreshCollection(xmlwAR,toAdd);
2804
2805      XMLElement el=graph.getPropertyObject();
2806      if (el instanceof WorkflowProcess) {
2807         WorkflowProcess wp=(WorkflowProcess)el;
2808         ActivitySets xmlactsts=(ActivitySets)wp.get("ActivitySets");
2809         Activities xmlacts=getActivitiesCollection();
2810         Transitions xmltrans=getTransitionsCollection();
2811
2812         xmlacts.refreshCollection(xmlaAR,toAdd);
2813         xmltrans.refreshCollection(xmltAR,toAdd);
2814
2815         // generating or removing activity set
2816
Iterator it=baAR.iterator();
2817         while (it.hasNext()) {
2818            BlockActivity ba=(BlockActivity)it.next();
2819            ActivitySet as=null;
2820            String JavaDoc ID=ba.getBlockID();
2821            if (toAdd) {
2822               as=new ActivitySet(xmlactsts,wp);
2823               as.set("Id",ID);
2824               as.setIDPrefixForCollections();
2825               xmlactsts.add(as);
2826            } else {
2827               as=xmlactsts.getActivitySet(ID);
2828               xmlactsts.remove(as);
2829            }
2830         }
2831      }
2832
2833      // updating statusbar
2834
if (cellsToAddOrRemove!=null && cellsToAddOrRemove.length>0) {
2835         getGraph().getEditor().getStatusBar().updateMessage();
2836      }
2837
2838   }
2839
2840   public boolean manageTransition (Transition tr) {
2841      org.enhydra.jawe.xml.elements.Transition xmlT=
2842         (org.enhydra.jawe.xml.elements.Transition)
2843         tr.getUserObject();
2844      Activity s=null;
2845      try {
2846         s=tr.getSourceActivity();
2847      } catch (Exception JavaDoc ex) {
2848         try {
2849            s=getActivity(xmlT.get("From").toString());
2850         } catch (Exception JavaDoc ex2) {
2851         }
2852      }
2853      Activity t=null;
2854      try {
2855         t=tr.getTargetActivity();
2856      } catch (Exception JavaDoc ex) {
2857         try {
2858            t=getActivity(xmlT.get("To").toString());
2859         } catch (Exception JavaDoc ex2) {
2860         }
2861      }
2862      if (s!=null) updateSplit(s);
2863      if (t!=null) updateJoin(t);
2864
2865      if (s!=null && !(s instanceof Start) && s.getUserObject() instanceof XMLElement
2866          && t!=null && !(s instanceof Start) && t.getUserObject() instanceof XMLElement) {
2867         return true;
2868      } else {
2869         return false;
2870      }
2871
2872   }
2873
2874   public void correctXMLTransition (Transition tr) {
2875      org.enhydra.jawe.xml.elements.Transition xmlT=
2876         (org.enhydra.jawe.xml.elements.Transition)
2877         tr.getUserObject();
2878      Activity s=tr.getSourceActivity();
2879      Activity t=tr.getTargetActivity();
2880      if (s!=null && s.getUserObject() instanceof XMLElement
2881          && t!=null && t.getUserObject() instanceof XMLElement) {
2882         xmlT.setFrom(s.getPropertyObject());
2883         xmlT.setTo(t.getPropertyObject());
2884      }
2885   }
2886
2887   public void updateSplit (Activity s) {
2888      // update split of source activity
2889
if (s!=null && s.getUserObject() instanceof XMLElement) {
2890         org.enhydra.jawe.xml.elements.Activity a=
2891            (org.enhydra.jawe.xml.elements.Activity)s.getUserObject();
2892         int noft=s.getOutgoingTransitions().size();
2893         String JavaDoc type=a.getSplit().get("Type").toString().trim();
2894         if (type.length()==0) {
2895            if (noft>1) {
2896               a.setSplitType(ResourceManager.getLanguageDependentString("XORKey"));
2897            }
2898         } else {
2899            if (noft<=1) {
2900               a.setSplitType("");
2901            }
2902         }
2903      }
2904   }
2905
2906   public void updateJoin (Activity t) {
2907      // update join of target activity
2908
if (t!=null && t.getUserObject() instanceof XMLElement) {
2909         org.enhydra.jawe.xml.elements.Activity a=
2910            (org.enhydra.jawe.xml.elements.Activity)t.getUserObject();
2911         int noft=t.getIncomingTransitions().size();
2912         String JavaDoc type=a.getJoin().get("Type").toString().trim();
2913         if (type.length()==0) {
2914            if (noft>1) {
2915               a.setJoinType(ResourceManager.getLanguageDependentString("XORKey"));
2916            }
2917         } else {
2918            if (noft<=1) {
2919               a.setJoinType("");
2920            }
2921         }
2922      }
2923   }
2924
2925   private void manageParticipantReferences (Set cellsToDelete,boolean toAdd) {
2926      Iterator it=cellsToDelete.iterator();
2927      while (it.hasNext()) {
2928         manageParticipantReferences(it.next(),toAdd);
2929      }
2930   }
2931
2932   private void manageParticipantReferences (Object JavaDoc cellToDelete,boolean toAdd) {
2933      if (cellToDelete instanceof org.enhydra.jawe.graph.Process) {
2934         org.enhydra.jawe.graph.Process pr=
2935            (org.enhydra.jawe.graph.Process)cellToDelete;
2936         try {
2937            Set s=JaWEGraphModel.getAllParticipantsInModel(pr.getImplementationEditor().getGraph().getModel());
2938            if (s!=null){
2939               Iterator iter = s.iterator();
2940               while (iter.hasNext()) {
2941                  // recursivly calling method but this time passing participant graph object
2942
manageParticipantReferences(iter.next(),toAdd);
2943               }
2944            }
2945            manageParticipantReferences(pr.getImplementationEditor().getGraph().
2946                                           getWorkflowManager().getBlockActivities(true),toAdd);
2947         } catch (Exception JavaDoc ex) {}
2948      } else if (cellToDelete instanceof BlockActivity) {
2949         BlockActivity b=(BlockActivity)cellToDelete;
2950         try {
2951            // add or remove all graph references of participants that are visible in a process
2952
Set s=JaWEGraphModel.getAllParticipantsInModel(b.getImplementationEditor().getGraph().getModel());
2953            if (s!=null){
2954               Iterator iter = s.iterator();
2955               while (iter.hasNext()) {
2956                  // recursivly calling method but this time passing participant graph object
2957
manageParticipantReferences(iter.next(),toAdd);
2958               }
2959            }
2960         } catch (Exception JavaDoc ex) {}
2961      } else if (cellToDelete instanceof Participant) {
2962         Participant par=(Participant)cellToDelete;
2963         try {
2964            org.enhydra.jawe.xml.elements.Participant puo=
2965               (org.enhydra.jawe.xml.elements.Participant)
2966               par.getUserObject();
2967            if (toAdd) {
2968               puo.graphReferenceAdded();
2969            } else {
2970               puo.graphReferenceRemoved();
2971            }
2972         } catch (Exception JavaDoc ex) {}
2973      }
2974   }
2975
2976   /**
2977    * Finds the nearest cell to the given cell in given direction.
2978    *
2979    * @param selectedCell first currently selected cell
2980    * @param direction 0-Up, 1-Down, 2-Left, 3-Right (if given some
2981    * other no, the Up is assumed)
2982    * @return The nearest cell to the given one in given direction, or
2983    * null if no such cell.
2984    */

2985   public Object JavaDoc findNearestCell (Object JavaDoc selectedCell,int direction) {
2986      // retrieve all cells from model
2987
Set cellSet=JaWEGraphModel.getAllCellsInModel(graphModel());
2988      //Set cellSet=PEGraphModel.getAllActivitiesInModel(graphModel());
2989
// if there is no any return null
2990
if (cellSet==null || cellSet.size()==0) return null;
2991
2992      Object JavaDoc[] cells=cellSet.toArray();
2993      // if current cell is null (nothing is selected), return
2994
// the first cell from array
2995
if (selectedCell==null) return cells[0];
2996
2997      // get the center point of currently selected cell
2998
Point centerOfSelectedCell=getCenter(selectedCell);
2999      // if something went wrong, return the first cell from array
3000
if (centerOfSelectedCell==null) return cells[0];
3001
3002      // initialy set the nearest cell to null, and min distance
3003
// to max. double value
3004
Object JavaDoc nearestCell=null;
3005      double minDistance=Double.MAX_VALUE;
3006
3007      // search for the nearest cell considering the wanted direction
3008
for (int i=0; i<cells.length; i++) {
3009         // skip the cell that we check for the nearest cell
3010
// and skip port cells
3011
if (cells[i]==selectedCell || cells[i] instanceof Port) continue;
3012
3013         // the center of the next cell
3014
Point centerOfCell=getCenter(cells[i]);
3015         Point ref=new Point(centerOfCell.x,centerOfSelectedCell.y);
3016         double dist=centerOfSelectedCell.distance(centerOfCell);
3017         double absOfTan=centerOfCell.distance(ref)/ref.distance(centerOfSelectedCell);
3018
3019         switch (direction) {
3020            case 1: //DOWN
3021
if (centerOfCell.y>=centerOfSelectedCell.y) {
3022                  if (dist<minDistance && absOfTan>=1) {
3023                     minDistance=dist;
3024                     nearestCell=cells[i];
3025                  }
3026               }
3027               break;
3028            case 2: //LEFT
3029
if (centerOfCell.x<=centerOfSelectedCell.x) {
3030                  if (dist<minDistance && absOfTan<=1) {
3031                     minDistance=dist;
3032                     nearestCell=cells[i];
3033                  }
3034               }
3035               break;
3036            case 3: //RIGHT
3037
if (centerOfCell.x>=centerOfSelectedCell.x) {
3038                  if (dist<minDistance && absOfTan<=1) {
3039                     minDistance=dist;
3040                     nearestCell=cells[i];
3041                  }
3042               }
3043               break;
3044            default: //UP
3045
if (centerOfCell.y<=centerOfSelectedCell.y) {
3046                  if (dist<minDistance && absOfTan>=1) {
3047                     minDistance=dist;
3048                     nearestCell=cells[i];
3049                  }
3050               }
3051               break;
3052         }
3053      }
3054      return nearestCell;
3055   }
3056
3057   public Object JavaDoc findCell (Point p,Map propertyMap) {
3058      // retrieve all cells from model
3059
Set cellSet=JaWEGraphModel.getAllCellsInModel(graphModel());
3060      //Set cellSet=PEGraphModel.getAllActivitiesInModel(graphModel());
3061
// if there is no any return null
3062
if (cellSet==null || cellSet.size()==0) return null;
3063
3064      Object JavaDoc[] cells=cellSet.toArray();
3065
3066      // search for the nearest cell considering the wanted direction
3067
for (int i=0; i<cells.length; i++) {
3068         // the center of the next cell
3069
Rectangle r=getBounds(cells[i],propertyMap).getBounds();//HM, JGraph3.4.1
3070
if (r.contains(p) && !(cells[i] instanceof Port)) {
3071            return cells[i];
3072         }
3073      }
3074      return null;
3075   }
3076
3077   /**
3078    * Arranges processes after deletion of one of them, and sets the new
3079    * insertion point for the processes that will be inserted next.
3080    */

3081   private void arrangeProcesses (Map propertyMap,Rectangle deletedProcessBounds) {
3082      int nextHowMany=JaWEGraphModel.getAllActivitiesInModel(graphModel()).size()-1;
3083      //System.out.println("There is "+nextHowMany+" prcs");
3084
int deletedOrdNoX=(int)Math.round((deletedProcessBounds.x-JaWEConstants.PROCESS_OFFSET)/
3085                                           (defProcessWidth*JaWEConstants.PROCESS_DISTANCE_COEFF));
3086      int deletedOrdNoY=(int)Math.round((deletedProcessBounds.y-JaWEConstants.PROCESS_OFFSET)/
3087                                           (defProcessHeight*JaWEConstants.PROCESS_DISTANCE_COEFF));
3088      int deletedOrdNo=(deletedOrdNoX+1)+deletedOrdNoY*
3089         JaWEConstants.HOW_MANY_PROCESSES_IN_ONE_ROW;
3090      //System.out.println("x="+deletedOrdNoX+",y="+deletedOrdNoY+", on="+deletedOrdNo);
3091
if (nextHowMany>=deletedOrdNo) {
3092         for (int i=deletedOrdNo+1; i<=nextHowMany+1; i++) {
3093            int xon=(i-1)%JaWEConstants.HOW_MANY_PROCESSES_IN_ONE_ROW;
3094            int yon=(i-1)/JaWEConstants.HOW_MANY_PROCESSES_IN_ONE_ROW;
3095            //System.out.println("xtp="+xon+", ytp="+yon);
3096
// find the cell for point corresponding to the current ordinal number
3097
Point p=new Point((int)(JaWEConstants.PROCESS_OFFSET+
3098                                       xon*JaWEConstants.PROCESS_DISTANCE_COEFF*defProcessWidth+defProcessWidth/2),
3099                                 (int)(JaWEConstants.PROCESS_OFFSET+
3100                                          yon*JaWEConstants.PROCESS_DISTANCE_COEFF*defProcessHeight+defProcessHeight/2));
3101            //System.out.println("FOC="+findCell(p,propertyMap).getClass().getName());
3102
org.enhydra.jawe.graph.Process pr=
3103               (org.enhydra.jawe.graph.Process)findCell(p,propertyMap);
3104            //System.out.println("Proc is "+pr);
3105
if (pr!=null) {
3106               // get old cell bounds
3107
int xo=getBounds(pr,propertyMap).getBounds().x;//HM, JGraph3.4.1
3108
int yo=getBounds(pr,propertyMap).getBounds().y;//HM, JGraph3.4.1
3109
// calculate new cell bounds
3110
int xn=(int)(JaWEConstants.PROCESS_OFFSET+
3111                               ((i-2)%JaWEConstants.HOW_MANY_PROCESSES_IN_ONE_ROW)*
3112                               JaWEConstants.PROCESS_DISTANCE_COEFF*defProcessWidth);
3113               int yn=(int)(JaWEConstants.PROCESS_OFFSET+
3114                               ((i-2)/JaWEConstants.HOW_MANY_PROCESSES_IN_ONE_ROW)*
3115                               JaWEConstants.PROCESS_DISTANCE_COEFF*defProcessHeight);
3116               // do translation of cell (virtually)
3117
Map attrib=GraphConstants.cloneMap(pr.getAttributes());
3118               Rectangle bounds=(Rectangle)GraphConstants.getBounds(attrib);//HM, JGraph3.4.1
3119
bounds.translate(xn-xo,yn-yo);
3120               propertyMap.put(pr,attrib);
3121            }
3122         }
3123      }
3124   }
3125
3126   //Harald Meister: method for moving participants in graph
3127
// direction=true for up, false for down
3128
//Note: the participants have to be correctly sorted so that moving of
3129
// multiple part's works
3130
public void moveParticipants (Object JavaDoc[] cellsToMove, boolean direction) {
3131      Map propertyMap=new HashMap();
3132      ParentMap parentMap=new JaWEParentMap();
3133
3134      if (cellsToMove != null && cellsToMove.length>0) {
3135         boolean updated=false;
3136         for (int i=0; i<cellsToMove.length; i++) {
3137            if (cellsToMove[i] instanceof Participant) {
3138               Participant parSource=(Participant)cellsToMove[i];
3139               Rectangle rSource=(Rectangle)getBounds(parSource,propertyMap);// getting bounds of rectangle//HM, JGraph3.4.1
3140

3141               Rectangle matching=new Rectangle(rSource); // added by SB
3142

3143               int yPos;
3144               Participant[] parts;
3145               if (direction){//move up
3146
yPos=rSource.y-1;
3147                  parts = getParticipantsForYPos(yPos,2,propertyMap,parentMap);
3148                  if (parts != null && parts.length>0){
3149                     Participant parTarget = parts[0];
3150                     Rectangle rTarget=(Rectangle)getBounds(parTarget,propertyMap);//HM, JGraph3.4.1
3151

3152                     translateParticipant(parSource,propertyMap,parentMap,0,-rTarget.height);//source part up
3153

3154                     translateParticipant(parTarget,propertyMap,parentMap,0,rSource.height);//target part down
3155
}
3156               }
3157               else{//move down
3158
yPos=rSource.y+rSource.height+1;
3159                  parts = getParticipantsForYPos(yPos,2,propertyMap,parentMap);
3160                  if (parts != null && parts.length>0){
3161                     Participant parTarget = parts[0];
3162                     Rectangle rTarget=(Rectangle)getBounds(parTarget,propertyMap);//HM, JGraph3.4.1
3163

3164                     translateParticipant(parSource,propertyMap,parentMap,0,rTarget.height);//source part down
3165

3166                     translateParticipant(parTarget,propertyMap,parentMap,0,-rSource.height);//target part up
3167
}
3168               }
3169
3170               Rectangle toMatch=(Rectangle)getBounds(parSource,propertyMap); // added by SB//HM, JGraph3.4.1
3171
arrangeParticipants(propertyMap,parentMap);
3172
3173               if (!toMatch.equals(matching)) {
3174                  updated=true;
3175               }
3176            }
3177         }
3178         // changed by Sasa Bojanic - so that undo/redo actions are compound
3179
// and that there is no action if position doesn't change
3180
if (updated) {
3181            graphModel().insertAndEdit(null,propertyMap,null,parentMap,null,"");
3182         }
3183      }
3184   }
3185   // Harald Meister
3186

3187   public Dimension getGraphsPreferredSize () {
3188      return new Dimension(getRootParticipantWidth(null,null)+50,
3189                           getNewRootParYPos(null,null)+50);
3190   }
3191
3192}
3193
3194/* End of WorkflowManager.java */
3195
3196
Popular Tags