001: package org.andromda.metafacades.uml14;
002:
003: import java.util.ArrayList;
004: import java.util.Collection;
005: import java.util.LinkedHashMap;
006: import java.util.Iterator;
007: import java.util.List;
008: import java.util.Map;
009:
010: import org.andromda.core.common.ExceptionUtils;
011: import org.andromda.core.metafacade.MetafacadeConstants;
012: import org.andromda.core.metafacade.MetafacadeFactory;
013: import org.andromda.metafacades.uml.ActivityGraphFacade;
014: import org.andromda.metafacades.uml.ClassifierFacade;
015: import org.andromda.metafacades.uml.EventFacade;
016: import org.andromda.metafacades.uml.ModelElementFacade;
017: import org.andromda.metafacades.uml.ParameterFacade;
018: import org.andromda.metafacades.uml.UMLProfile;
019: import org.andromda.metafacades.uml.UseCaseFacade;
020: import org.apache.commons.collections.CollectionUtils;
021: import org.apache.commons.collections.Predicate;
022: import org.apache.commons.lang.StringUtils;
023: import org.omg.uml.behavioralelements.activitygraphs.ActivityGraph;
024: import org.omg.uml.behavioralelements.statemachines.Event;
025: import org.omg.uml.behavioralelements.statemachines.FinalState;
026: import org.omg.uml.behavioralelements.usecases.UseCase;
027: import org.omg.uml.foundation.core.Attribute;
028: import org.omg.uml.foundation.core.Classifier;
029: import org.omg.uml.foundation.core.CorePackage;
030: import org.omg.uml.foundation.core.ModelElement;
031: import org.omg.uml.foundation.core.Parameter;
032: import org.omg.uml.foundation.core.Stereotype;
033: import org.omg.uml.foundation.core.TaggedValue;
034: import org.omg.uml.foundation.core.UmlClass;
035: import org.omg.uml.foundation.datatypes.VisibilityKind;
036: import org.omg.uml.foundation.datatypes.VisibilityKindEnum;
037: import org.omg.uml.modelmanagement.Model;
038: import org.omg.uml.modelmanagement.UmlPackage;
039:
040: /**
041: * Utilities for dealing with UML 1.4 metafacades
042: *
043: * @author Chad Brandon
044: */
045: public class UML14MetafacadeUtils {
046: /**
047: * Finds a given model element in the model having the specified
048: * <code>fullyQualifiedName</code>. If the model element can <strong>NOT
049: * </strong> be found, <code>null</code> will be returned instead.
050: *
051: * @param fullyQualifiedName the fully qualified name of the element to
052: * search for.
053: * @param separator the PSM separator used for qualifying the name (example
054: * ".").
055: * @param modelName a flag indicating whether or not a search shall be performed using
056: * the fully qualified model name or fully qualified PSM name.
057: * @return the found model element
058: */
059: static Object findByFullyQualifiedName(
060: final String fullyQualifiedName, final String separator,
061: final boolean modelName) {
062: Object modelElement;
063: Collection elements = ((org.omg.uml.UmlPackage) MetafacadeFactory
064: .getInstance().getModel().getModel()).getCore()
065: .getModelElement().refAllOfType();
066: modelElement = CollectionUtils.find(elements, new Predicate() {
067: public boolean evaluate(Object object) {
068: ModelElement element = (ModelElement) object;
069: StringBuffer fullName = new StringBuffer(
070: getPackageName(element, separator, modelName));
071: String name = element.getName();
072: if (StringUtils.isNotBlank(name)) {
073: String namespaceSeparator = MetafacadeConstants.NAMESPACE_SCOPE_OPERATOR;
074: if (!modelName) {
075: namespaceSeparator = separator;
076: }
077: fullName.append(namespaceSeparator);
078: fullName.append(name);
079: }
080: return fullName.toString().equals(fullyQualifiedName);
081: }
082: });
083: return modelElement;
084: }
085:
086: /**
087: * Constructs the package name for the given <code>metaObject</code>, seperating the package name by the given
088: * <code>separator</code>.
089: *
090: * @param metaObject the Model Element
091: * @param separator the PSM namespace separator
092: * @param modelName true/false on whether or not to get the model package name instead
093: * of the PSM package name.
094: * @return the package name.
095: */
096: static String getPackageName(ModelElement metaObject,
097: String separator, boolean modelName) {
098: String packageName = "";
099: for (ModelElement namespace = metaObject.getNamespace(); (namespace instanceof UmlPackage)
100: && !(namespace instanceof Model); namespace = namespace
101: .getNamespace()) {
102: packageName = packageName.equals("") ? namespace.getName()
103: : namespace.getName() + separator + packageName;
104: }
105: if (modelName && StringUtils.isNotBlank(packageName)) {
106: packageName = StringUtils.replace(packageName, separator,
107: MetafacadeConstants.NAMESPACE_SCOPE_OPERATOR);
108: }
109: return packageName;
110: }
111:
112: /**
113: * Basically just checks to make sure the <code>model</code> is of type <code>org.omg.uml.UmlPackage</code> and
114: * retrieves the <code>CorePackage</code> from it.
115: *
116: * @return the <code>model</code> as a <code>org.omg.uml.UmlPackage</code>
117: */
118: static CorePackage getCorePackage() {
119: return ((org.omg.uml.UmlPackage) MetafacadeFactory
120: .getInstance().getModel().getModel()).getCore();
121: }
122:
123: /**
124: * Finds and returns the first model element having the given <code>name</code> in the <code>modelPackage</code>,
125: * returns <code>null</code> if not found.
126: *
127: * @param name the name to find.
128: * @return the found model element.
129: */
130: static Object findByName(final String name) {
131: Object modelElement = null;
132: if (StringUtils.isNotBlank(name)) {
133: modelElement = CollectionUtils.find(getModel().getCore()
134: .getModelElement().refAllOfType(), new Predicate() {
135: public boolean evaluate(Object object) {
136: return StringUtils.trimToEmpty(
137: ((ModelElement) object).getName()).equals(
138: name);
139: }
140: });
141: }
142: return modelElement;
143: }
144:
145: /**
146: * Gets the root package in the model.
147: *
148: * @return the root package as a UmlPackage.
149: */
150: static UmlPackage getRootPackage() {
151: Object rootPackage = null;
152: Collection rootPackages = UML14MetafacadeUtils.getModel()
153: .getModelManagement().getModel().refAllOfType();
154: Iterator packageIt = rootPackages.iterator();
155: while (packageIt.hasNext()) {
156: rootPackage = packageIt.next();
157: // get the first package that's a ModelElement
158: // instance
159: if (rootPackage instanceof ModelElement) {
160: break;
161: }
162: }
163: return (UmlPackage) rootPackage;
164: }
165:
166: /**
167: * Returns the entire model.
168: *
169: * @return org.omg.uml.UmlPackage model instance.
170: */
171: static org.omg.uml.UmlPackage getModel() {
172: return (org.omg.uml.UmlPackage) MetafacadeFactory.getInstance()
173: .getModel().getModel();
174: }
175:
176: /**
177: * Gets the correct meta model visibility kind for the given <code>visibility</code> string.
178: *
179: * @param visibility the visibility to retrieve.
180: * @return the VisibilityKind
181: */
182: static VisibilityKind getVisibilityKind(String visibility) {
183: VisibilityKind visibilityKind = null;
184: visibility = StringUtils.trimToEmpty(visibility);
185: if (visibility.equals("public")) {
186: visibilityKind = VisibilityKindEnum.VK_PUBLIC;
187: } else if (visibility.equals("private")) {
188: visibilityKind = VisibilityKindEnum.VK_PRIVATE;
189: } else if (visibility.equals("")) {
190: visibilityKind = VisibilityKindEnum.VK_PACKAGE;
191: } else if (visibility.equals("protected")) {
192: visibilityKind = VisibilityKindEnum.VK_PROTECTED;
193: }
194: return visibilityKind;
195: }
196:
197: /**
198: * Creates an attribute having the give <code>name</code> and the type
199: * having the given <code>fullyQualifiedTypeName</code>, with the
200: * specified visibility, if no type can be found with the given name, no
201: * type is set.
202: *
203: * @param name the new name
204: * @param fullyQualifiedTypeName the name of the fully qualified type
205: * @param visibility the visibility name
206: * @param separator the separator used for qualifying the name.
207: * @return the new Attribute.
208: */
209: static Attribute createAttribute(String name,
210: String fullyQualifiedTypeName, String visibility,
211: String separator) {
212: Attribute attribute = UML14MetafacadeUtils.getCorePackage()
213: .getAttribute().createAttribute();
214: attribute.setName(name);
215: attribute.setVisibility(UML14MetafacadeUtils
216: .getVisibilityKind(visibility));
217: Object type = UML14MetafacadeUtils.findByFullyQualifiedName(
218: fullyQualifiedTypeName, separator, false);
219: if (type != null
220: && Classifier.class.isAssignableFrom(type.getClass())) {
221: attribute.setType((Classifier) type);
222: }
223: return attribute;
224: }
225:
226: /**
227: * Indicates whether or not the attribute exists on the given </code>classifier</code>.
228: *
229: * @param classifier the classifier to check
230: * @param name the name of the attribute
231: * @return true/false
232: */
233: static boolean attributeExists(Object classifier, String name) {
234: boolean exists = false;
235: if (Classifier.class.isAssignableFrom(classifier.getClass())) {
236: List features = ((Classifier) classifier).getFeature();
237: if (features != null && !features.isEmpty()) {
238: for (final Iterator featureIterator = features
239: .iterator(); featureIterator.hasNext();) {
240: Object feature = featureIterator.next();
241: if (feature != null
242: && Attribute.class.isAssignableFrom(feature
243: .getClass())) {
244: exists = StringUtils.trimToEmpty(
245: ((Attribute) feature).getName())
246: .equals(name);
247: }
248: }
249: }
250: }
251: return exists;
252: }
253:
254: /**
255: * Finds or creates a stereotype with the given name. If the stereotype isn't found, it will be created.
256: *
257: * @param name the name of the stereotype.
258: * @return the new Stereotype.
259: */
260: static Stereotype findOrCreateStereotype(String name) {
261: Object stereotype = UML14MetafacadeUtils.findByName(name);
262: if (stereotype == null
263: || !Stereotype.class.isAssignableFrom(stereotype
264: .getClass())) {
265: stereotype = UML14MetafacadeUtils.getCorePackage()
266: .getStereotype().createStereotype();
267: ((Stereotype) stereotype).setName(name);
268: }
269: return (Stereotype) stereotype;
270: }
271:
272: /**
273: * Returns the first use-case it can find with the given name.
274: */
275: static UseCase findFirstUseCaseWithName(String name) {
276: return findFirstUseCaseWithNameAndStereotype(name, null);
277: }
278:
279: /**
280: * Returns the first use-case it can find with the given name and stereotype, if the stereotype is not specified (it
281: * is null) it will be ignored and the returned use-case may have any arbitrary stereotype.
282: */
283: static UseCase findFirstUseCaseWithNameAndStereotype(String name,
284: String stereotypeName) {
285: UseCase useCaseWithNameAndStereotype = null;
286:
287: Collection useCases = getModel().getUseCases().getUseCase()
288: .refAllOfType();
289: for (final Iterator useCaseIterator = useCases.iterator(); useCaseIterator
290: .hasNext()
291: && useCaseWithNameAndStereotype == null;) {
292: UseCase useCase = (UseCase) useCaseIterator.next();
293: if (name.equals(useCase.getName())) {
294: if (stereotypeName == null
295: || isStereotypePresent(useCase, stereotypeName)) {
296: useCaseWithNameAndStereotype = useCase;
297: }
298: }
299: }
300:
301: return useCaseWithNameAndStereotype;
302: }
303:
304: /**
305: * Returns the first activity graph it can find with the given name.
306: */
307: static ActivityGraph findFirstActivityGraphWithName(String name) {
308: return findFirstActivityGraphWithNameAndStereotype(name, null);
309: }
310:
311: /**
312: * Returns the first activity graph it can find with the given name and stereotype, if the stereotype is not
313: * specified (it is null) it will be ignored and the returned activity graph may have any arbitrary stereotype.
314: */
315: static ActivityGraph findFirstActivityGraphWithNameAndStereotype(
316: String name, String stereotypeName) {
317: ActivityGraph graphWithNameAndStereotype = null;
318:
319: Collection graphs = getModel().getActivityGraphs()
320: .getActivityGraph().refAllOfType();
321: for (final Iterator graphIterator = graphs.iterator(); graphIterator
322: .hasNext()
323: && graphWithNameAndStereotype == null;) {
324: ActivityGraph graph = (ActivityGraph) graphIterator.next();
325: if (name.equals(graph.getName())) {
326: if (stereotypeName == null
327: || isStereotypePresent(graph, stereotypeName)) {
328: graphWithNameAndStereotype = graph;
329: }
330: }
331: }
332:
333: return graphWithNameAndStereotype;
334: }
335:
336: /**
337: * Returns true if the given model element has a tag with the given name and value, returns false otherwise.
338: */
339: static boolean isTagPresent(ModelElement element, String tag,
340: Object value) {
341: boolean tagPresent = false;
342:
343: Collection taggedValues = element.getTaggedValue();
344: for (final Iterator taggedValueIterator = taggedValues
345: .iterator(); taggedValueIterator.hasNext()
346: && !tagPresent;) {
347: TaggedValue taggedValue = (TaggedValue) taggedValueIterator
348: .next();
349: if (tag.equals(taggedValue.getName())) {
350: for (final Iterator valueIterator = taggedValue
351: .getDataValue().iterator(); valueIterator
352: .hasNext()
353: && !tagPresent;) {
354: Object dataValue = valueIterator.next();
355: if (value.equals(dataValue)) {
356: tagPresent = true;
357: }
358: }
359: for (final Iterator valueIterator = taggedValue
360: .getReferenceValue().iterator(); valueIterator
361: .hasNext()
362: && !tagPresent;) {
363: Object referenceValue = valueIterator.next();
364: if (value.equals(referenceValue)) {
365: tagPresent = true;
366: }
367: }
368: }
369: }
370: return tagPresent;
371: }
372:
373: /**
374: * Returns true if the given model element has a hyperlink with the given value, returns false otherwise.
375: */
376: static boolean isHyperlinkPresent(ModelElement element, Object value) {
377: return isTagPresent(element, "hyperlinkModel", value);
378: }
379:
380: static boolean isStereotypePresent(ModelElement element,
381: String stereotypeName) {
382: boolean stereotypePresent = false;
383:
384: Collection stereotypes = element.getStereotype();
385: for (final Iterator stereotypeIterator = stereotypes.iterator(); stereotypeIterator
386: .hasNext()
387: && !stereotypePresent;) {
388: Stereotype stereotype = (Stereotype) stereotypeIterator
389: .next();
390: if (stereotypeName.equals(stereotype.getName())) {
391: stereotypePresent = true;
392: }
393: }
394: return stereotypePresent;
395: }
396:
397: /**
398: * Returns the first use-case this method can find with the given tagged value or hyperlink. Both arguments are used
399: * to look for the tagged value but only <code>value</code> is used to search for the hyperlink.
400: */
401: static UseCase findUseCaseWithTaggedValueOrHyperlink(String tag,
402: String value) {
403: UseCase useCaseWithTaggedValue = null;
404:
405: Collection useCases = getModel().getUseCases().getUseCase()
406: .refAllOfType();
407: for (final Iterator useCaseIterator = useCases.iterator(); useCaseIterator
408: .hasNext()
409: && useCaseWithTaggedValue == null;) {
410: // loop over all use-cases
411: UseCase useCase = (UseCase) useCaseIterator.next();
412: if (isTagPresent(useCase, tag, value)
413: || isHyperlinkPresent(useCase, value)) {
414: useCaseWithTaggedValue = useCase;
415: }
416: }
417:
418: return useCaseWithTaggedValue;
419: }
420:
421: /**
422: * Returns the first class this method can find with the given tagged value or hyperlink. Both arguments are used to
423: * look for the tagged value but only <code>value</code> is used to search for the hyperlink.
424: */
425: static UmlClass findClassWithTaggedValueOrHyperlink(String tag,
426: String value) {
427: UmlClass classWithTaggedValue = null;
428:
429: Collection classes = getModel().getCore().getUmlClass()
430: .refAllOfType();
431: for (final Iterator classIterator = classes.iterator(); classIterator
432: .hasNext()
433: && classWithTaggedValue == null;) {
434: // loop over all classes
435: UmlClass clazz = (UmlClass) classIterator.next();
436: if (isTagPresent(clazz, tag, value)
437: || isHyperlinkPresent(clazz, value)) {
438: classWithTaggedValue = clazz;
439: }
440: }
441:
442: return classWithTaggedValue;
443: }
444:
445: static Collection findFinalStatesWithNameOrHyperlink(UseCase useCase) {
446: List finalStates = new ArrayList();
447:
448: if (useCase != null && useCase.getName() != null) {
449: String useCaseName = useCase.getName();
450: Collection allFinalStates = getModel().getStateMachines()
451: .getFinalState().refAllOfType();
452: for (final Iterator iterator = allFinalStates.iterator(); iterator
453: .hasNext();) {
454: FinalState finalState = (FinalState) iterator.next();
455: if (useCaseName != null) {
456: if (useCaseName.equals(finalState.getName())) {
457: finalStates.add(finalState);
458: } else {
459: if (isHyperlinkPresent(finalState, useCase)) {
460: finalStates.add(finalState);
461: }
462: }
463: } else {
464: if (isHyperlinkPresent(finalState, useCase)) {
465: finalStates.add(finalState);
466: }
467: }
468: }
469: }
470:
471: return finalStates;
472: }
473:
474: /**
475: * Finds the given metafacade class for the passed in <code>facade</code>.
476: *
477: * @param facade the model element facade for which to find the meta class.
478: * @return the meta model element
479: */
480: static ActivityGraph getMetaClass(ActivityGraphFacade facade) {
481: ActivityGraph activityGraph = null;
482:
483: if (facade != null) {
484: String id = facade.getId();
485: Collection graphs = getModel().getActivityGraphs()
486: .getActivityGraph().refAllOfType();
487: for (final Iterator iterator = graphs.iterator(); iterator
488: .hasNext()
489: && activityGraph == null;) {
490: ModelElement element = (ModelElement) iterator.next();
491: if (id.equals(element.refMofId())) {
492: activityGraph = (ActivityGraph) element;
493: }
494: }
495: }
496: return activityGraph;
497: }
498:
499: /**
500: * Finds the given metafacade class for the passed in <code>facade</code>.
501: *
502: * @param facade the model element facade for which to find the meta class.
503: * @return the meta model element
504: */
505: static UseCase getMetaClass(UseCaseFacade facade) {
506: UseCase useCase = null;
507:
508: if (facade != null) {
509: String id = facade.getId();
510: Collection useCases = getModel().getUseCases().getUseCase()
511: .refAllOfType();
512: for (final Iterator iterator = useCases.iterator(); iterator
513: .hasNext()
514: && useCase == null;) {
515: ModelElement element = (ModelElement) iterator.next();
516: if (id.equals(element.refMofId())) {
517: useCase = (UseCase) element;
518: }
519: }
520: }
521: return useCase;
522: }
523:
524: /**
525: * Finds the given metafacade class for the passed in <code>facade</code>.
526: *
527: * @param facade the model element facade for which to find the meta class.
528: * @return the meta model element
529: */
530: static Parameter getMetaClass(ParameterFacade facade) {
531: Parameter parameter = null;
532:
533: if (facade != null) {
534: String id = facade.getId();
535: Collection parameters = getModel().getCore().getParameter()
536: .refAllOfType();
537: for (final Iterator iterator = parameters.iterator(); iterator
538: .hasNext()
539: && parameter == null;) {
540: ModelElement element = (ModelElement) iterator.next();
541: if (id.equals(element.refMofId())) {
542: parameter = (Parameter) element;
543: }
544: }
545: }
546: return parameter;
547: }
548:
549: /**
550: * Finds the given metafacade class for the passed in <code>facade</code>.
551: *
552: * @param facade the model element facade for which to find the meta class.
553: * @return the meta model element
554: */
555: static Event getMetaClass(EventFacade facade) {
556: Event event = null;
557:
558: if (facade != null) {
559: String id = facade.getId();
560: Collection events = getModel().getStateMachines()
561: .getEvent().refAllOfType();
562: for (final Iterator iterator = events.iterator(); iterator
563: .hasNext()
564: && event == null;) {
565: ModelElement element = (ModelElement) iterator.next();
566: if (id.equals(element.refMofId())) {
567: event = (Event) element;
568: }
569: }
570: }
571: return event;
572: }
573:
574: /**
575: * Finds the given metafacade class for the passed in <code>facade</code>.
576: *
577: * @param facade the model element facade for which to find the meta class.
578: * @return the meta model element
579: */
580: static ModelElement getMetaClass(ModelElementFacade facade) {
581: ModelElement modelElement = null;
582:
583: if (facade != null) {
584: String id = facade.getId();
585: Collection modelElements = getModel().getCore()
586: .getModelElement().refAllOfType();
587: for (final Iterator iterator = modelElements.iterator(); iterator
588: .hasNext()
589: && modelElement == null;) {
590: ModelElement element = (ModelElement) iterator.next();
591: if (id.equals(element.refMofId())) {
592: modelElement = element;
593: }
594: }
595: }
596: return modelElement;
597: }
598:
599: /**
600: * Retrieves the serial version UID by reading the tagged value
601: * {@link UMLProfile#TAGGEDVALUE_SERIALVERSION_UID} of the
602: * <code>classifier</code>.
603: *
604: * @param classifier the classifier to be inspected.
605: * @return the serial version UID of the classifier. Returns
606: * <code>null</code> if the tagged value cannot be found.
607: */
608: static String getSerialVersionUID(ClassifierFacade classifier) {
609: ExceptionUtils.checkNull("classifer", classifier);
610: String serialVersionString = (String) classifier
611: .findTaggedValue(UMLProfile.TAGGEDVALUE_SERIALVERSION_UID);
612: return StringUtils.trimToNull(serialVersionString);
613: }
614:
615: /**
616: * This method removes all duplicates within the <code>elements</code> collection while at the same
617: * time copying tagged values from duplicates to the one remaining element with the given name.
618: *
619: * @param elements the elements to remove duplicates and copy tagged values to.
620: * @return the elements with duplicates removed.
621: */
622: public static List removeDuplicatesAndCopyTaggedValues(
623: final Collection elements) {
624: final Map map = new LinkedHashMap();
625: if (elements != null) {
626: for (final Iterator iterator = elements.iterator(); iterator
627: .hasNext();) {
628: ModelElementFacade element = (ModelElementFacade) iterator
629: .next();
630: final String name = element.getName();
631: final ModelElementFacade existingVariable = (ModelElementFacade) map
632: .get(name);
633: // - copy over any tagged values from the existing variable to the new one.
634: if (existingVariable != null) {
635: element.copyTaggedValues(existingVariable);
636: }
637: map.put(name, element);
638: }
639: }
640: return new ArrayList(map.values());
641: }
642: }
|