View Javadoc

1   /*
2    * Copyright (c) 2003-2008, by Henrik Arro and Contributors
3    *
4    * This file is part of JSeq, a tool to automatically create
5    * sequence diagrams by tracing program execution.
6    *
7    * See <http://jseq.sourceforge.net> for more information.
8    *
9    * JSeq is free software: you can redistribute it and/or modify
10   * it under the terms of the GNU Lesser General Public License as
11   * published by the Free Software Foundation, either version 3 of
12   * the License, or (at your option) any later version.
13   *
14   * JSeq is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17   * GNU Lesser General Public License for more details.
18   *
19   * You should have received a copy of the GNU Lesser General Public License
20   * along with JSeq. If not, see <http://www.gnu.org/licenses/>.
21   */
22  
23  package th.co.edge.jseq.argouml.util;
24  
25  import java.util.HashMap;
26  import java.util.Map;
27  
28  import javax.xml.parsers.ParserConfigurationException;
29  
30  import ru.novosoft.uml.MFactory;
31  import ru.novosoft.uml.behavior.collaborations.MCollaboration;
32  import ru.novosoft.uml.behavior.common_behavior.MCallAction;
33  import ru.novosoft.uml.behavior.common_behavior.MLink;
34  import ru.novosoft.uml.behavior.common_behavior.MLinkEnd;
35  import ru.novosoft.uml.behavior.common_behavior.MObject;
36  import ru.novosoft.uml.behavior.common_behavior.MStimulus;
37  import ru.novosoft.uml.foundation.core.MClass;
38  import ru.novosoft.uml.foundation.core.MNamespace;
39  import ru.novosoft.uml.foundation.data_types.MVisibilityKind;
40  import ru.novosoft.uml.model_management.MModel;
41  
42  import th.co.edge.jseq.Activation;
43  import th.co.edge.jseq.argouml.SequenceDiagram;
44  import th.co.edge.jseq.argouml.UUID;
45  
46  /**
47   * A utility class to work with <code>MModel</code> objects.
48   */
49  public class MModelUtil {
50      private static MFactory factory = MFactory.getDefaultFactory();
51  
52      /**
53       * This class only contains static methods, so we hide the constructor.
54       */
55      private MModelUtil() {
56      }
57  
58      /**
59       * Returns a new <code>MModel</code> object with the given name.
60       *
61       * @param name
62       *            the name of the model to create
63       *
64       * @return a new <code>MModel</code> object
65       */
66      public static MModel createMModel(String name) {
67          MModel model = factory.createModel();
68          model.setName(name);
69          model.setUUID(UUID.getID());
70          return model;
71      }
72  
73      /**
74       * Creates a new <code>SequenceDiagram</code> based on an
75       * <code>Activation</code> and adds it to the given <code>MModel</code>.
76       *
77       * @param model
78       *            the <code>MModel</code> to which to add the sequence diagram
79       * @param activation
80       *            the <code>Activation</code> on which to base the sequence
81       *            diagram
82       *
83       * @return the newly created <code>SequenceDiagram</code>
84       *
85       * @throws ParserConfigurationException
86       *             if there is some serious error in the XML configuration
87       *             (should normally not occur)
88       */
89      public static SequenceDiagram addSequenceDiagram(MModel model,
90              Activation activation) throws ParserConfigurationException {
91          MCollaboration collaboration = factory.createCollaboration();
92          model.addOwnedElement(collaboration);
93          collaboration.setName("newCollaboration");
94          collaboration.setUUID(UUID.getID());
95          model.addOwnedElement(collaboration);
96          SequenceDiagramBuilder builder =
97                  new SequenceDiagramBuilder(collaboration, activation);
98          return builder.getDiagram();
99      }
100 
101     private static class SequenceDiagramBuilder {
102         private MNamespace namespace;
103         private SequenceDiagram diagram;
104         private Map<String, MClass> addedClasses =
105                 new HashMap<String, MClass>();
106         private Map<String, MObject> addedObjects =
107                 new HashMap<String, MObject>();
108 
109         public SequenceDiagramBuilder(MNamespace namespace,
110                 Activation activation) throws ParserConfigurationException {
111             this.namespace = namespace;
112             this.diagram = new SequenceDiagram(namespace, activation);
113             fillSequenceDiagram(activation);
114         }
115 
116         public SequenceDiagram getDiagram() {
117             return diagram;
118         }
119 
120         private void fillSequenceDiagram(Activation activation) {
121             MObject receiver = addObject(activation.getClassName(), "");
122             Activation parent = activation.getParent();
123             if (parent != null) {
124                 MObject sender = addObject(parent.getClassName(), "");
125                 addCall(sender, receiver, activation.getMethod().name());
126             }
127             for (Activation nestedActivation : activation
128                     .getNestedActivations()) {
129                 fillSequenceDiagram(nestedActivation);
130             }
131             getDiagram().deactivate(receiver);
132         }
133 
134         private MObject addObject(String className, String name) {
135             MClass cls = createClass(className);
136             namespace.addOwnedElement(cls);
137             MObject object = createObject(cls, name);
138             namespace.addOwnedElement(object);
139             return object;
140         }
141 
142         private void addCall(MObject sender, MObject receiver, String name) {
143             MCallAction call = createCall(name);
144             namespace.addOwnedElement(call);
145 
146             MStimulus stimulus = createStimulus(sender, receiver, call);
147             namespace.addOwnedElement(stimulus);
148 
149             MLink link = createLink(sender, receiver, name, stimulus);
150             namespace.addOwnedElement(link);
151 
152             getDiagram().addCall(sender, receiver, link);
153         }
154 
155         private MClass createClass(String name) {
156             MClass cls;
157             if (addedClasses.containsKey(name)) {
158                 cls = addedClasses.get(name);
159             } else {
160                 cls = MModelUtil.factory.createClass();
161                 addedClasses.put(name, cls);
162                 if (name != null) {
163                     cls.setName(name);
164                 } else {
165                     cls.setName("");
166                 }
167                 cls.setUUID(UUID.getID());
168                 cls.setVisibility(MVisibilityKind.PUBLIC);
169             }
170             return cls;
171         }
172 
173         private MObject createObject(MClass cls, String name) {
174             MObject object;
175             String fullName = cls.getName() + "." + name;
176             if (addedObjects.containsKey(fullName)) {
177                 object = addedObjects.get(fullName);
178             } else {
179                 object = MModelUtil.factory.createObject();
180                 addedObjects.put(fullName, object);
181                 object.addClassifier(cls);
182                 if (name != null) {
183                     object.setName(name);
184                 } else {
185                     object.setName("");
186                 }
187                 object.setUUID(UUID.getID());
188                 getDiagram().addObject(object);
189             }
190             return object;
191         }
192 
193         private MLink createLink(MObject fromObject, MObject toObject,
194                 String name, MStimulus stimulus) {
195             MLink link = MModelUtil.factory.createLink();
196             link.setUUID(UUID.getID());
197             MLinkEnd linkFrom = MModelUtil.factory.createLinkEnd();
198             linkFrom.setInstance(fromObject);
199             linkFrom.setUUID(UUID.getID());
200             link.addConnection(linkFrom);
201             MLinkEnd linkTo = MModelUtil.factory.createLinkEnd();
202             linkTo.setInstance(toObject);
203             linkTo.setUUID(UUID.getID());
204             link.addConnection(linkTo);
205             link.addStimulus(stimulus);
206             return link;
207         }
208 
209         private MCallAction createCall(String name) {
210             MCallAction call = MModelUtil.factory.createCallAction();
211             if (name != null) {
212                 call.setName(name);
213             } else {
214                 call.setName("");
215             }
216             call.setUUID(UUID.getID());
217             return call;
218         }
219 
220         private MStimulus createStimulus(MObject fromObject, MObject toObject,
221                 MCallAction call) {
222             MStimulus stimulus = MModelUtil.factory.createStimulus();
223             stimulus.setName("");
224             stimulus.setSender(fromObject);
225             stimulus.setReceiver(toObject);
226             stimulus.setDispatchAction(call);
227             stimulus.setUUID(UUID.getID());
228             return stimulus;
229         }
230     }
231 }