Coverage Report - org.argouml.model.euml.ExtensionMechanismsHelperEUMLImpl
 
Classes in this File Line Coverage Branch Coverage Complexity
ExtensionMechanismsHelperEUMLImpl
0%
0/248
0%
0/190
4.788
 
 1  
 // $Id: ExtensionMechanismsHelperEUMLImpl.java 19080 2011-02-28 09:54:08Z thn $
 2  
 /*******************************************************************************
 3  
  * Copyright (c) 2007,2010 Tom Morris and other contributors
 4  
  * All rights reserved. This program and the accompanying materials
 5  
  * are made available under the terms of the Eclipse Public License v1.0
 6  
  * which accompanies this distribution, and is available at
 7  
  * http://www.eclipse.org/legal/epl-v10.html
 8  
  *
 9  
  * Contributors:
 10  
  *    Tom Morris - initial framework 
 11  
  *    Thomas Neustupny
 12  
  *****************************************************************************/
 13  
 
 14  
 package org.argouml.model.euml;
 15  
 
 16  
 import java.util.ArrayList;
 17  
 import java.util.Collection;
 18  
 import java.util.Collections;
 19  
 import java.util.Iterator;
 20  
 import java.util.List;
 21  
 
 22  
 import org.argouml.model.ExtensionMechanismsHelper;
 23  
 import org.eclipse.emf.common.util.URI;
 24  
 import org.eclipse.emf.ecore.resource.Resource;
 25  
 import org.eclipse.emf.ecore.resource.ResourceSet;
 26  
 import org.eclipse.emf.ecore.util.EcoreUtil;
 27  
 import org.eclipse.uml2.uml.Association;
 28  
 import org.eclipse.uml2.uml.Class;
 29  
 import org.eclipse.uml2.uml.Element;
 30  
 import org.eclipse.uml2.uml.Extension;
 31  
 import org.eclipse.uml2.uml.LiteralUnlimitedNatural;
 32  
 import org.eclipse.uml2.uml.Model;
 33  
 import org.eclipse.uml2.uml.Package;
 34  
 import org.eclipse.uml2.uml.Profile;
 35  
 import org.eclipse.uml2.uml.Property;
 36  
 import org.eclipse.uml2.uml.Stereotype;
 37  
 import org.eclipse.uml2.uml.Type;
 38  
 import org.eclipse.uml2.uml.UMLPackage;
 39  
 import org.eclipse.uml2.uml.resource.UMLResource;
 40  
 
 41  
 /**
 42  
  * The implementation of the ExtensionMechanismsHelper for EUML2.
 43  
  */
 44  
 class ExtensionMechanismsHelperEUMLImpl implements ExtensionMechanismsHelper {
 45  
 
 46  
     // maybe UML2 has these as constants somewhere
 47  
     private static final String PTYPE_BOOLEAN_NAME = "Boolean";
 48  
     private static final String PTYPE_INTEGER_NAME = "Integer";
 49  
     private static final String PTYPE_STRING_NAME = "String";
 50  
     private static final String PTYPE_UNATURAL_NAME = "UnlimitedNatural";
 51  
 
 52  
     /**
 53  
      * The model implementation.
 54  
      */
 55  
     private EUMLModelImplementation modelImpl;
 56  
 
 57  
     /**
 58  
      * Lazily initialized collection of common tagged value types.
 59  
      */
 60  
     private Collection commonTaggedValueTypes;
 61  
 
 62  
     /**
 63  
      * Constructor.
 64  
      * 
 65  
      * @param implementation The ModelImplementation.
 66  
      */
 67  
     public ExtensionMechanismsHelperEUMLImpl(
 68  0
             EUMLModelImplementation implementation) {
 69  0
         modelImpl = implementation;
 70  0
     }
 71  
 
 72  
     public void addBaseClass(Object handle, Object baseClass) {
 73  0
         if (handle instanceof Stereotype) {
 74  0
             org.eclipse.uml2.uml.Class metaclass = getMetaclass(baseClass);
 75  0
             Profile profile = ((Stereotype) handle).getProfile();
 76  0
             if (metaclass != null && profile != null) {
 77  0
                 profile.createMetaclassReference(metaclass);
 78  0
                 ((Stereotype) handle).createExtension(metaclass, false);
 79  0
                 return;
 80  
             }
 81  
         }
 82  0
         throw new IllegalArgumentException(
 83  
                 "Not a Stereotype or illegal base class"); //$NON-NLS-1$
 84  
     }
 85  
 
 86  
     public void addCopyStereotype(Object modelElement, Object stereotype) {
 87  0
         modelImpl.getCoreHelper().addStereotype(modelElement, stereotype);
 88  0
     }
 89  
 
 90  
     public void addExtendedElement(Object handle, Object extendedElement) {
 91  
         // TODO: Auto-generated method stub
 92  
 
 93  0
     }
 94  
 
 95  
     public void addTaggedValue(Object handle, Object taggedValue) {
 96  0
         if (!(handle instanceof Element)) {
 97  0
             return;
 98  
         }
 99  0
         if (!(taggedValue instanceof Property)) {
 100  0
             return;
 101  
         }
 102  0
         Element elem = (Element) handle;
 103  0
         Property prop = (Property) taggedValue;
 104  0
         Stereotype stereotype = (Stereotype) prop.eContainer();
 105  0
         Object value = null;
 106  0
         if (prop.isMultivalued()) {
 107  0
             value = UMLUtil.getTaggedValue(elem, stereotype.getQualifiedName(),
 108  
                     prop.getName());
 109  0
             Collection newValue = new ArrayList();
 110  0
             if (value instanceof Collection) {
 111  0
                 newValue.addAll((Collection) value);
 112  0
             } else if (value != null) {
 113  0
                 newValue.add(value);
 114  
             }
 115  0
             newValue.add(getDefaultValueFor((Property) taggedValue));
 116  0
             value = newValue;
 117  0
         } else {
 118  0
             value = getDefaultValueFor((Property) taggedValue);
 119  
         }
 120  0
         setTaggedValue(elem, prop, value);
 121  0
     }
 122  
 
 123  
     public void applyProfile(Object handle, Object profile) {
 124  0
         if (profile instanceof Profile) {
 125  0
             if (((Profile) profile).isDefined()) {
 126  0
                 if (handle instanceof Model) {
 127  0
                     ((Model) handle).applyProfile((Profile) profile);
 128  0
                 } else if (handle instanceof Profile) {
 129  0
                     ((Profile) handle).applyProfile((Profile) profile);
 130  
                 }
 131  
             }
 132  
             // also apply subprofiles:
 133  0
             Iterator<Package> iter = ((Profile) profile).getNestedPackages()
 134  
                     .iterator();
 135  0
             while (iter.hasNext()) {
 136  0
                 Package p = iter.next();
 137  0
                 if (p instanceof Profile) {
 138  0
                     applyProfile(handle, p);
 139  
                 }
 140  0
             }
 141  
         }
 142  0
     }
 143  
 
 144  
     public Collection getAllPossibleStereotypes(Collection models,
 145  
             Object modelElement) {
 146  0
         List<Stereotype> ret = new ArrayList<Stereotype>();
 147  0
         if (modelElement instanceof Element) {
 148  0
             for (Stereotype stereo : getStereotypes(models)) {
 149  0
                 if (((Element) modelElement).isStereotypeApplicable(stereo)) {
 150  0
                     ret.add(stereo);
 151  
                 }
 152  
             }
 153  
         }
 154  0
         return ret;
 155  
     }
 156  
 
 157  
     @Deprecated
 158  
     public String getMetaModelName(Object m) {
 159  0
         if (m instanceof Element) {
 160  0
             return getMetaModelName(m.getClass());
 161  
         }
 162  0
         throw new IllegalArgumentException("Not an Element"); //$NON-NLS-1$
 163  
     }
 164  
 
 165  
     /**
 166  
      * @param clazz the UML class
 167  
      * @return the meta name of the UML class
 168  
      */
 169  
     protected String getMetaModelName(Class clazz) {
 170  0
         return modelImpl.getMetaTypes().getName(clazz);
 171  
     }
 172  
 
 173  
     public Object getStereotype(Object ns, Object stereo) {
 174  0
         if (!(ns instanceof Profile)) {
 175  0
             throw new IllegalArgumentException("profile"); //$NON-NLS-1$
 176  
         }
 177  0
         if (!(stereo instanceof Stereotype)) {
 178  0
             throw new IllegalArgumentException("stereotype"); //$NON-NLS-1$
 179  
         }
 180  0
         String name = ((Stereotype) stereo).getName();
 181  0
         Collection<Class> baseClasses = ((Stereotype) stereo)
 182  
                 .getAllExtendedMetaclasses();
 183  0
         if (name == null || baseClasses.size() != 1) {
 184  0
             return null;
 185  
         }
 186  0
         Class baseClass = baseClasses.iterator().next();
 187  
 
 188  0
         for (Stereotype o : getStereotypes(ns)) {
 189  0
             if (name.equals(o.getName())
 190  
                     && o.getAllExtendedMetaclasses().contains(baseClass)) {
 191  0
                 return o;
 192  
             }
 193  
         }
 194  0
         return null;
 195  
     }
 196  
 
 197  
     public Object getStereotype(Collection models, Object stereo) {
 198  0
         if (stereo == null) {
 199  0
             throw new IllegalArgumentException("null argument"); //$NON-NLS-1$
 200  
         }
 201  0
         if (!(stereo instanceof Stereotype)) {
 202  0
             throw new IllegalArgumentException("stereotype"); //$NON-NLS-1$
 203  
         }
 204  0
         String name = ((Stereotype) stereo).getName();
 205  0
         Collection<Class> baseClasses = ((Stereotype) stereo)
 206  
                 .getAllExtendedMetaclasses();
 207  0
         if (name == null || baseClasses.size() != 1) {
 208  0
             return null;
 209  
         }
 210  0
         Class baseClass = baseClasses.iterator().next();
 211  
 
 212  0
         for (Model model : ((Collection<Model>) models)) {
 213  
             // TODO: this should call the single namespace form
 214  
             // getStereotype(it2.next(); stereo);
 215  0
             for (Stereotype o : getStereotypes(model)) {
 216  0
                 if (name.equals(o.getName())
 217  
                         && o.getAllExtendedMetaclasses().contains(baseClass)) {
 218  0
                     return o;
 219  
                 }
 220  
             }
 221  
         }
 222  0
         return null;
 223  
     }
 224  
 
 225  
     public Collection<Stereotype> getStereotypes(Object ns) {
 226  0
         if (ns instanceof Profile) {
 227  0
             return new ArrayList<Stereotype>(((Profile) ns).getOwnedStereotypes());
 228  
         }
 229  0
         return Collections.emptySet();
 230  
     }
 231  
 
 232  
     public Collection<Stereotype> getStereotypes(Collection models) {
 233  0
         Collection<Stereotype> l = new ArrayList<Stereotype>();
 234  0
         if (models != null) {
 235  0
             for (Object ns : models) {
 236  0
                 if (ns instanceof Profile) {
 237  0
                     l.addAll(((Profile) ns).getOwnedStereotypes());
 238  
                     // TODO: Do we really want stereotypes from nested packages?
 239  0
                     Iterator<Package> iter = ((Profile) ns).getNestedPackages()
 240  
                             .iterator();
 241  0
                     while (iter.hasNext()) {
 242  0
                         Package p = iter.next();
 243  0
                         if (p instanceof Profile) {
 244  0
                             l.addAll(getAllStereotypesIn((Profile) p));
 245  
                         }
 246  0
                     }
 247  0
                 }
 248  
             }
 249  
         }
 250  0
         return l;
 251  
     }
 252  
 
 253  
     /*
 254  
      * @see org.argouml.model.ExtensionMechanismsHelper#getCommonTaggedValueTypes()
 255  
      */
 256  
     public Collection<Type> getCommonTaggedValueTypes() {
 257  
         // TODO: still not used, because in ArgoUML String is "hardwired"
 258  0
         if (commonTaggedValueTypes == null) {
 259  0
             commonTaggedValueTypes = new ArrayList<Type>();
 260  
             //commonTaggedValueTypes.add(org.eclipse.uml2.uml.resource.UMLResource.)
 261  0
             URI uri = URI.createURI(UMLResource.UML_PRIMITIVE_TYPES_LIBRARY_URI);
 262  0
             ResourceSet rs = modelImpl.getEditingDomain().getResourceSet();
 263  0
             Resource res = rs.getResource(uri, true);
 264  0
             Model m = (Model) (org.eclipse.uml2.uml.Package) EcoreUtil.getObjectByType(
 265  
                     res.getContents(), UMLPackage.Literals.MODEL);
 266  0
             commonTaggedValueTypes.add(m.getOwnedMember(PTYPE_BOOLEAN_NAME));
 267  0
             commonTaggedValueTypes.add(m.getOwnedMember(PTYPE_INTEGER_NAME));
 268  0
             commonTaggedValueTypes.add(m.getOwnedMember(PTYPE_STRING_NAME));
 269  0
             commonTaggedValueTypes.add(m.getOwnedMember(PTYPE_UNATURAL_NAME));
 270  
         }
 271  0
         return commonTaggedValueTypes;
 272  
     }
 273  
 
 274  
     public boolean hasStereotype(Object handle, String name) {
 275  0
         if (name == null || !(handle instanceof Element)) {
 276  0
             throw new IllegalArgumentException();
 277  
         }
 278  0
         Element element = (Element) handle;
 279  0
         if (element.getAppliedStereotype(name) != null) {
 280  0
             return true;
 281  
         }
 282  0
         return false;
 283  
     }
 284  
 
 285  
     public boolean isStereotype(Object object, String name, String base) {
 286  0
         if (!(object instanceof Stereotype)) {
 287  0
             return false;
 288  
         }
 289  0
         Stereotype st = (Stereotype) object;
 290  0
         if (name == null && st.getName() != null) {
 291  0
             return false;
 292  
         }
 293  0
         if (base == null && !(st.getAllExtendedMetaclasses().isEmpty())) {
 294  0
             return false;
 295  
         }
 296  0
         for (Class c : st.getAllExtendedMetaclasses()) {
 297  0
             if (c.getName().equals(base)) {
 298  0
                 return true;
 299  
             }
 300  
         }
 301  0
         return false;
 302  
     }
 303  
 
 304  
     public boolean isStereotypeInh(Object object, String name, String base) {
 305  0
         if (!(object instanceof Stereotype)) {
 306  0
             return false;
 307  
         }
 308  0
         if (isStereotype(object, name, base)) {
 309  0
             return true;
 310  
         }
 311  
         /*
 312  
          * TODO: mvw: do we really look into super-types of the stereotype, or
 313  
          * should we be looking into super-types of the baseclass?
 314  
          */
 315  0
         Iterator it = modelImpl.getCoreHelper().getSupertypes(object)
 316  
                 .iterator();
 317  0
         while (it.hasNext()) {
 318  0
             if (isStereotypeInh(it.next(), name, base)) {
 319  0
                 return true;
 320  
             }
 321  
         }
 322  0
         return false;
 323  
     }
 324  
 
 325  
     public boolean isValidStereotype(Object theModelElement,
 326  
             Object theStereotype) {
 327  0
         if (theModelElement instanceof Element
 328  
                 && theStereotype instanceof Stereotype) {
 329  0
             return ((Element) theModelElement)
 330  
                     .isStereotypeApplicable((Stereotype) theStereotype);
 331  
         }
 332  0
         return false;
 333  
     }
 334  
 
 335  
     public void removeBaseClass(Object handle, Object baseClass) {
 336  0
         if (handle instanceof Stereotype) {
 337  0
             org.eclipse.uml2.uml.Class metaclass = getMetaclass(baseClass);
 338  0
             Profile profile = ((Stereotype) handle).getProfile();
 339  0
             if (metaclass != null && profile != null) {
 340  0
                 Stereotype st = (Stereotype) handle;
 341  0
                 for (Extension ext : profile.getOwnedExtensions(false)) {
 342  0
                     if (ext.getMetaclass() == metaclass
 343  
                             && ext.getEndTypes().contains(st)) {
 344  0
                         for (Property p : st.getAttributes()) {
 345  0
                             Association assoc = p.getAssociation();
 346  0
                             if (assoc != null && assoc == ext) {
 347  
                                 // additional cleanup needed, because
 348  
                                 // this would not be removed by ext.destroy():
 349  0
                                 p.destroy();
 350  0
                                 break;
 351  
                             }
 352  0
                         }
 353  
                         // remove base class by destroying the extension
 354  0
                         ext.destroy();
 355  0
                         break;
 356  
                     }
 357  
                 }
 358  0
                 return;
 359  
             }
 360  
         }
 361  0
         throw new IllegalArgumentException(
 362  
                 "Not a Stereotype or illegal base class"); //$NON-NLS-1$
 363  
     }
 364  
 
 365  
     public void removeTaggedValue(Object handle, Object taggedValue) {
 366  
         // TODO: Auto-generated method stub
 367  0
     }
 368  
 
 369  
     public void setIcon(Object handle, Object icon) {
 370  
         // TODO: Auto-generated method stub
 371  0
     }
 372  
 
 373  
     public void setTaggedValue(Object handle, Collection taggedValues) {
 374  
         // This doesn't work in UML2: both owner and property needed!
 375  0
         throw new UnsupportedOperationException(); 
 376  
     }
 377  
 
 378  
     /*
 379  
      * Sets the value of an element#s property (tagged value). This method
 380  
      * makes sure that a Collection of values is set if and only if the
 381  
      * property is multivalued (upper multiplicity value greater 1), so passing
 382  
      * a collection is safe.
 383  
      * 
 384  
      * @see org.argouml.model.ExtensionMechanismsHelper#setValueOfTag(java.lang.Object, java.lang.Object, java.lang.Object)
 385  
      */
 386  
     public void setTaggedValue(Object handle, Object property, Object value) {
 387  0
         if (!(handle instanceof Element)) {
 388  0
             return;
 389  
         }
 390  0
         if (!(property instanceof Property)) {
 391  0
             return;
 392  
         }
 393  0
         Element elem = (Element) handle;
 394  0
         Property prop = (Property) property;
 395  
         // consider the property multiplicity
 396  0
         if (prop.isMultivalued() && !(value instanceof Collection)) {
 397  0
             Collection newValue = new ArrayList();
 398  0
             newValue.add(value);
 399  0
             value = newValue;
 400  0
         } else if (!prop.isMultivalued() && value instanceof Collection) {
 401  0
             Collection col = (Collection) value;
 402  0
             if (col.isEmpty()) {
 403  0
                 value = null; // or getDefaultValueFor(prop)?
 404  
             } else {
 405  
                 // too bad, we choose to take the first value
 406  0
                 value = col.iterator().next();
 407  
             }
 408  
         }
 409  
         // workaround for missing ability to parse "*"
 410  0
         if (value instanceof Collection) {
 411  0
             Collection newValue = new ArrayList();
 412  0
             for (Object v : ((Collection) value)) {
 413  0
                 newValue.add(postprocessPropertyValue(prop, v));
 414  
             }
 415  0
             value = newValue;
 416  0
         } else {
 417  0
             value = postprocessPropertyValue(prop, value);
 418  
         }
 419  
         // ready to set the value finally
 420  0
         Stereotype stereotype = (Stereotype) prop.eContainer();
 421  0
         UMLUtil.setTaggedValue(elem, stereotype, prop.getName(), value);
 422  0
     }
 423  
 
 424  
     private Object postprocessPropertyValue(Property prop, Object value) {
 425  
         // workaround for missing ability to parse "*"
 426  0
         if (prop.getType() != null
 427  
                 && "UnlimitedNatural".equals(prop.getType().getName())
 428  
                 && "*".equals(value)) {
 429  0
             value = LiteralUnlimitedNatural.UNLIMITED;
 430  
         }
 431  0
         return value;
 432  
     }
 433  
 
 434  
     public void setTagType(Object handle, String tagType) {
 435  
         // TODO: Auto-generated method stub
 436  0
     }
 437  
 
 438  
     public void setType(Object handle, Object type) {
 439  
         // in case of a tagged value, the type shouldn't be set here
 440  0
     }
 441  
 
 442  
     public void setValueOfTag(Object handle, String value) {
 443  
         // TODO: Auto-generated method stub
 444  0
     }
 445  
 
 446  
     public void setDataValues(Object handle, String[] value) {
 447  
         // not implementable in UML2, because property is missing
 448  0
     }
 449  
 
 450  
     public void unapplyProfile(Object handle, Object profile) {
 451  0
         if (profile instanceof Profile) {
 452  0
             if (handle instanceof Package) {
 453  0
                 ((Model) handle).unapplyProfile((Profile) profile);
 454  0
             } else if (handle instanceof Profile) {
 455  0
                 ((Profile) handle).unapplyProfile((Profile) profile);
 456  
             }
 457  
             // also unapply subprofiles:
 458  0
             Iterator<Package> iter = ((Profile) profile).getNestedPackages()
 459  
                     .iterator();
 460  0
             while (iter.hasNext()) {
 461  0
                 Package p = iter.next();
 462  0
                 if (p instanceof Profile) {
 463  0
                     unapplyProfile(handle, p);
 464  
                 }
 465  0
             }
 466  
         }
 467  0
     }
 468  
 
 469  
     public Object makeProfileApplicable(Object handle) {
 470  0
         Object result = null;
 471  0
         if (handle instanceof Profile) {
 472  0
             result = ((Profile) handle).define();
 473  
             // also define subprofiles:
 474  0
             Iterator<Package> iter = ((Profile) handle).getNestedPackages()
 475  
                     .iterator();
 476  0
             while (iter.hasNext()) {
 477  0
                 Package p = iter.next();
 478  0
                 if (p instanceof Profile) {
 479  0
                     makeProfileApplicable(p);
 480  
                 }
 481  0
             }
 482  
         }
 483  0
         return result;
 484  
     }
 485  
 
 486  
     private Collection<Stereotype> getAllStereotypesIn(Profile p) {
 487  0
         List<Stereotype> l = new ArrayList<Stereotype>();
 488  0
         Iterator<Element> iter = p.getOwnedElements().iterator();
 489  0
         while (iter.hasNext()) {
 490  0
             Element elem = iter.next();
 491  0
             if (elem instanceof Stereotype) {
 492  0
                 l.add((Stereotype) elem);
 493  0
             } else if (elem instanceof Profile) {
 494  0
                 l.addAll(getAllStereotypesIn((Profile) elem));
 495  
             }
 496  0
         }
 497  0
         return l;
 498  
     }
 499  
 
 500  
     private org.eclipse.uml2.uml.Class getMetaclass(Object baseClass) {
 501  0
         org.eclipse.uml2.uml.Class metaclass = null;
 502  0
         if (baseClass instanceof String) {
 503  0
             URI uri = URI.createURI(UMLResource.UML_METAMODEL_URI);
 504  0
             ResourceSet rs = modelImpl.getEditingDomain().getResourceSet();
 505  0
             Resource res = rs.getResource(uri, true);
 506  0
             Model m = (Model) EcoreUtil.getObjectByType(res.getContents(),
 507  
                     UMLPackage.Literals.PACKAGE);
 508  0
             metaclass = (org.eclipse.uml2.uml.Class) m
 509  
                     .getOwnedType((String) baseClass);
 510  0
         } else if (baseClass instanceof org.eclipse.uml2.uml.Class) {
 511  0
             metaclass = (org.eclipse.uml2.uml.Class) baseClass;
 512  
         }
 513  0
         return metaclass;
 514  
     }
 515  
 
 516  
     private Object getDefaultValueFor(Property property) {
 517  0
         Object value = null;
 518  0
         Type type = property.getType();
 519  0
         if (type != null) {
 520  0
             String tname = type.getName();
 521  0
             if (PTYPE_BOOLEAN_NAME.equals(tname)) {
 522  0
                 value = Boolean.FALSE;
 523  0
             } else if (PTYPE_INTEGER_NAME.equals(tname)) {
 524  0
                 value = new Integer(0);
 525  0
             } else if (PTYPE_STRING_NAME.equals(tname)) {
 526  0
                 value = new String();
 527  0
             } else if (PTYPE_UNATURAL_NAME.equals(tname)) {
 528  0
                 value = new Integer(0);
 529  
             }
 530  
         }
 531  0
         return value;
 532  
     }
 533  
 }