1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package com.finalist.mmbase.uml;
16
17 import java.util.Collection;
18 import java.util.HashMap;
19 import java.util.Iterator;
20 import java.util.LinkedHashMap;
21
22 import org.andromda.core.simpleuml.UMLAssociationEnd;
23 import org.andromda.core.simpleuml.UMLClassifier;
24 import org.andromda.core.simpleuml.UMLDependency;
25 import org.andromda.core.uml14.DirectionalAssociationEnd;
26 import org.omg.uml.foundation.core.AssociationEnd;
27 import org.omg.uml.foundation.core.Dependency;
28 import org.omg.uml.foundation.core.ModelElement;
29 import org.omg.uml.foundation.core.Classifier;
30 import com.finalist.mmbase.umlprofile.MMBaseUMLProfile;
31
32 /***
33 *
34 * Helper classes to get access to relation specific uml model elements.
35 *
36 * @author Kors van Beem - Finalist IT Group
37 * @version $Revision: 1.4 $, $Date: 2004/12/08 23:27:32 $
38 *
39 */
40 public class MMBaseRelationHelper {
41
42 private MMBaseHelper model = null;
43
44 /*** Default constructor. */
45 public MMBaseRelationHelper(MMBaseHelper model) {
46 this.model = model;
47 }
48
49 public MMBaseHelper getModel() {
50 return model;
51 }
52
53 /***
54 * Get a collection of MMBaseRelationVo's which contains information
55 * about the relations associated with the given object.
56 *
57 * @param object The ModelElement to find the relations of.
58 * @return A collection of MMBaseRelationVo's
59 */
60 public Collection getRelations(Object object) {
61 if ((object == null) || !(object instanceof ModelElement)) {
62 return null;
63 }
64
65 HashMap relations = new HashMap();
66
67 UMLClassifier umlClassifier = (UMLClassifier) object;
68 ModelElement sourceElement = (ModelElement) object;
69
70 Collection links = umlClassifier.getAssociationLinks();
71 for (Iterator iterator = links.iterator(); iterator.hasNext();) {
72 DirectionalAssociationEnd dirAssocEnd = model.getAssociationData(iterator.next());
73 UMLAssociationEnd umlTarget = (UMLAssociationEnd) dirAssocEnd.getTarget();
74 UMLAssociationEnd umlSource = (UMLAssociationEnd) dirAssocEnd.getSource();
75 String associationType = parseRelationName(dirAssocEnd.getName());
76
77 AssociationEnd source = dirAssocEnd.getSource();
78 AssociationEnd target = dirAssocEnd.getTarget();
79 String sourceName = getAssociationEndName(dirAssocEnd.getSource());
80 String targetName = getAssociationEndName(dirAssocEnd.getTarget());
81 String cardSourceLower = MMBaseAssociationHelper.getCardinalityLower(dirAssocEnd.getSource());
82 String cardSourceUpper = MMBaseAssociationHelper.getCardinalityUpper(dirAssocEnd.getSource());
83 String cardTargetLower = MMBaseAssociationHelper.getCardinalityLower(dirAssocEnd.getTarget());
84 String cardTargetUpper = MMBaseAssociationHelper.getCardinalityUpper(dirAssocEnd.getTarget());
85
86
87 String roleName = umlTarget.getRoleName();
88 if (roleName.equals(new String("The" + (umlTarget.getType()).getName()))) {
89 roleName = (umlTarget.getType()).getName();
90 }
91
92 String key = sourceName + ":" + targetName + ":" + associationType;
93 boolean addRelation = false;
94 if (!targetName.equals(sourceName) || (cardTargetUpper.equals("1") && cardSourceUpper.equals("1"))
95 || (cardTargetUpper.equals("-1") && cardSourceUpper.equals("-1"))) {
96
97 if (cardTargetUpper.equals("1") && cardSourceUpper.equals("1")) {
98 cardSourceLower = "0";
99 cardTargetLower = "0";
100 }
101
102 if (umlTarget.getNavigable().equals("true")) {
103 addRelation = true;
104 }
105 }
106 else {
107 cardSourceLower = "0";
108 cardTargetLower = "0";
109 associationType = "unidirectional" + associationType;
110
111 if (target.isNavigable() && !source.isNavigable()) {
112 addRelation = true;
113 }
114 else if (cardSourceUpper.equals("1") && (Integer.parseInt(cardTargetUpper) > 1 || cardTargetUpper.equals("-1"))) {
115 addRelation = true;
116 }
117 else if ((!"".equals(umlTarget.getRoleName()) && umlTarget.getRoleName() != null)
118 && ("".equals(umlSource.getRoleName()) || umlSource.getRoleName() == null)) {
119 addRelation = true;
120 }
121 else {
122 MMBaseRelationVo relDefVo = (MMBaseRelationVo) relations.get(key);
123 if (relDefVo == null) {
124
125 addRelation = true;
126 }
127 }
128 }
129
130
131
132 if (addRelation
133 && !MMBaseUMLProfile.STEREOTYPE_CLASS_OPTIONLIST.equalsIgnoreCase(model.getStereotype(umlTarget.getType()))
134 && !MMBaseUMLProfile.STEREOTYPE_CLASS_OPTIONLIST.equalsIgnoreCase(model.getStereotype(umlSource.getType()))) {
135
136 relations.remove(key);
137 relations.put(key, new MMBaseRelationVo(associationType, sourceName, targetName, cardSourceLower, cardSourceUpper,
138 cardTargetLower, cardTargetUpper, umlTarget.getNavigable(), roleName, umlTarget.getType()));
139 }
140 }
141 Collection deps = umlClassifier.getDependencies();
142 for (Iterator iterator = deps.iterator(); iterator.hasNext();) {
143 UMLDependency umlDependency = (UMLDependency) iterator.next();
144 Dependency dependency = (Dependency) umlDependency.getId();
145 String dependencyType = MMBaseUMLProfile.DEFAULT_RELATION_TYPE;
146 String depName = dependency.getName();
147 if (depName != null && !depName.equals("")) {
148 dependencyType = depName.toLowerCase();
149 }
150
151 Collection c = dependency.getStereotype();
152 String targetCardinalityLower = "0";
153 for (Iterator i = c.iterator(); i.hasNext();) {
154 ModelElement me = (ModelElement) i.next();
155 if (me.getName().equalsIgnoreCase("required")) {
156 targetCardinalityLower = "1";
157 }
158 }
159 ModelElement targetElement = umlDependency.getTargetType();
160
161 String key = sourceElement.getName() + ":" + targetElement.getName() + ":" + dependencyType;
162 relations.put(key, new MMBaseRelationVo(dependencyType, sourceElement.getName(), targetElement.getName(), "0",
163 "0", targetCardinalityLower, "-1", "true", targetElement.getName(), targetElement));
164 }
165 return model.sortValuesByKeys(relations);
166 }
167
168 /***
169 * Get name of the related relation for the specified object.
170 * The object should have the RelDef stereotype.
171 *
172 * @param object The ModelElement to find the relations of.
173 * @return String with the builder name for which a reldef has to be created.
174 */
175 public String getRelDef(Object object) {
176 if ((object == null) || !(object instanceof ModelElement)) {
177 return null;
178 }
179 String relDef = null;
180 UMLClassifier umlClassifier = (UMLClassifier) object;
181 ModelElement sourceElement = (ModelElement) object;
182 if ((model.getStereotype(object) == null) || !model.getStereotype(object).equalsIgnoreCase(MMBaseUMLProfile.STEREOTYPE_CLASS_RELDEF)) {
183
184 return null;
185 }
186 Collection deps = umlClassifier.getDependencies();
187 for (Iterator iterator = deps.iterator(); iterator.hasNext();) {
188 UMLDependency umlDependency = (UMLDependency) iterator.next();
189 ModelElement targetElement = umlDependency.getTargetType();
190 relDef = targetElement.getName();
191
192 break;
193 }
194 return relDef;
195 }
196
197 /***
198 * Add a relation name to the static hashmap.
199 *
200 * @param elements Collection of ModelElements.
201 * @return A collection of RelationVo's containing the information of relations.
202 */
203 public Collection getRelationReferences(Collection elements) {
204
205 LinkedHashMap relationReferences = new LinkedHashMap();
206 for (Iterator it = elements.iterator(); it.hasNext();) {
207 Object object = it.next();
208 if (object instanceof ModelElement) {
209 ModelElement modelElement = (ModelElement) object;
210 Collection stereoTypeNames = model.getStereotypeNames(modelElement);
211 if (stereoTypeNames.contains(MMBaseUMLProfile.STEREOTYPE_CLASS_MMBASE)) {
212 Collection c = getRelations(modelElement);
213 for (Iterator it2 = c.iterator(); it2.hasNext();) {
214 Object relationObject = it2.next();
215 if (relationObject instanceof MMBaseRelationVo) {
216 MMBaseRelationVo relationVo = (MMBaseRelationVo) relationObject;
217
218 String theSourceObject = relationVo.getSourceName();
219 String theTargetObject = relationVo.getTargetName();
220 String theRelationType = relationVo.getType();
221
222 if (relationReferences.get(theTargetObject + ":" + theSourceObject + ":" + theRelationType) == null) {
223 relationReferences.put(theSourceObject + ":" + theTargetObject + ":" + theRelationType, relationVo);
224 }
225 }
226 }
227 }
228 }
229 }
230 return model.sortValuesByKeys(relationReferences);
231 }
232
233 /***
234 * Return the static HashMap which contains all the relationDefinitions.
235 *
236 * @param elements The Collection of elements to check werther they are AssociationEnds.
237 * @return Collection of MMBaseRelationDefinitions.
238 */
239 public Collection getRelationDefinitions(Collection elements) {
240 HashMap relationDefinitions = new HashMap();
241 for (Iterator it = elements.iterator(); it.hasNext();) {
242 boolean classType = false;
243 Object object = it.next();
244
245 String relationType = MMBaseUMLProfile.DEFAULT_RELATION_TYPE;
246 String direction = MMBaseUMLProfile.DEFAULT_RELATION_DIRECTION;
247 String builder = MMBaseUMLProfile.DEFAULT_RELATION_BUILDER;
248
249 if (object instanceof AssociationEnd) {
250 AssociationEnd assocEnd = (AssociationEnd) object;
251 DirectionalAssociationEnd dirAssocEnd = model.getAssociationData(assocEnd);
252
253 relationType = parseRelationName(dirAssocEnd.getName());
254
255
256
257 String sourceName = getAssociationEndName(dirAssocEnd.getSource());
258 String targetName = getAssociationEndName(dirAssocEnd.getTarget());
259 String cardSourceUpper = MMBaseAssociationHelper.getCardinalityUpper(dirAssocEnd.getSource());
260 String cardTargetUpper = MMBaseAssociationHelper.getCardinalityUpper(dirAssocEnd.getTarget());
261
262 if (sourceName.equals(targetName) && !(cardSourceUpper.equals("1") && cardTargetUpper.equals("1"))) {
263 direction = "unidirectional";
264 relationType = "unidirectional" + relationType;
265 }
266 }
267 if (object instanceof Dependency) {
268 Dependency dep = (Dependency) object;
269 relationType = parseRelationName(dep.getName());
270 }
271
272 if (relationType.equals("posrel") || relationType.equals("unidirectionalposrel")) {
273 builder = "posrel";
274 }
275
276
277 if (object instanceof Classifier) {
278 String relationStereoType = model.getStereotype(object);
279 if (relationStereoType != null && MMBaseUMLProfile.STEREOTYPE_CLASS_RELATION.equals(relationStereoType)) {
280 relationType = model.getName(object);
281 builder = relationType;
282 classType = true;
283 System.out.println("Custom relation: " + builder);
284 }
285 if (relationStereoType != null && MMBaseUMLProfile.STEREOTYPE_CLASS_RELDEF.equals(relationStereoType)) {
286
287 relationType = model.getName(object);
288 builder = getRelDef(object);
289 classType = true;
290 }
291 }
292
293 String keyValue = relationType + ":" + direction;
294 MMBaseRelationDefinitionVo relDefVo = new MMBaseRelationDefinitionVo(relationType, direction, builder);
295 if (!relationDefinitions.containsKey(keyValue)) {
296 relationDefinitions.put(keyValue, relDefVo);
297 }
298 else if (classType) {
299
300 relationDefinitions.put(keyValue, relDefVo);
301 }
302
303 }
304 return model.sortValuesByKeys(relationDefinitions);
305 }
306
307 /***
308 * Function to determine the type of a relation. This type
309 * depends on the name of the relation.
310 *
311 * @return String containing the type of a relation.
312 */
313 private String parseRelationName(String relationName) {
314 String returnString = MMBaseUMLProfile.DEFAULT_RELATION_TYPE;
315 if (relationName == null) {
316 relationName = returnString;
317 }
318 if (!(relationName).startsWith("{") && !relationName.equals("") && !(relationName).endsWith("}")) {
319 returnString = relationName.toLowerCase();
320 }
321 return returnString;
322 }
323
324 /***
325 * Function to retrieve the name of a modelElement.
326 *
327 * @return String containing the name of the AssociationEnd.
328 */
329 private String getAssociationEndName(AssociationEnd assocEnd) {
330 String name = "";
331 if (assocEnd instanceof UMLAssociationEnd) {
332 UMLAssociationEnd umlAssocEnd = (UMLAssociationEnd) assocEnd;
333 name = umlAssocEnd.getType().getName();
334 }
335 return name;
336 }
337 }