fixed Bug#307281

Signed-off-by: Karsten Thoms <karsten.thoms@itemis.de>
diff --git a/plugins/org.eclipse.xtend.typesystem.uml2/src/org/eclipse/xtend/typesystem/uml2/profile/MultipleStereotypeType.java b/plugins/org.eclipse.xtend.typesystem.uml2/src/org/eclipse/xtend/typesystem/uml2/profile/MultipleStereotypeType.java
index a909bf7..ced31f0 100644
--- a/plugins/org.eclipse.xtend.typesystem.uml2/src/org/eclipse/xtend/typesystem/uml2/profile/MultipleStereotypeType.java
+++ b/plugins/org.eclipse.xtend.typesystem.uml2/src/org/eclipse/xtend/typesystem/uml2/profile/MultipleStereotypeType.java
@@ -30,8 +30,12 @@
 public final class MultipleStereotypeType extends StereotypeType {

 	List<StereotypeType> stereotypes;

 	

-	public MultipleStereotypeType(TypeSystem typeSystem, List<StereotypeType> stereotypes, boolean actualTypeAwareComparison) {

-		super(typeSystem, computeName(stereotypes), null, actualTypeAwareComparison);

+	public MultipleStereotypeType(TypeSystem typeSystem, List<StereotypeType> stereotypes) {

+		this(typeSystem, stereotypes, null);

+	}

+

+	public MultipleStereotypeType(TypeSystem typeSystem, List<StereotypeType> stereotypes, Type umlType) {

+		super(typeSystem, computeName(stereotypes), null, umlType);

 		this.stereotypes = stereotypes;

 	}

 

diff --git a/plugins/org.eclipse.xtend.typesystem.uml2/src/org/eclipse/xtend/typesystem/uml2/profile/ProfileMetaModel.java b/plugins/org.eclipse.xtend.typesystem.uml2/src/org/eclipse/xtend/typesystem/uml2/profile/ProfileMetaModel.java
index 2cd96a7..8126612 100644
--- a/plugins/org.eclipse.xtend.typesystem.uml2/src/org/eclipse/xtend/typesystem/uml2/profile/ProfileMetaModel.java
+++ b/plugins/org.eclipse.xtend.typesystem.uml2/src/org/eclipse/xtend/typesystem/uml2/profile/ProfileMetaModel.java
@@ -73,8 +73,6 @@
  */

 public class ProfileMetaModel implements MetaModel {

 

-	private boolean actualTypeAwareComparison = false;

-

 	public List<Profile> profiles = new ArrayList<Profile>(1);

 

 	private TypeSystem typeSystem;

@@ -160,7 +158,7 @@
 

 	private Map<String, Type> stereoTypes = null;

 

-	private Map<Pair<String, Type>, StereotypeType> stereoTypesWithActualType = null;

+	private Map<Pair<String, Type>, StereotypeType> stereoTypesWithUmlType = null;

 

 	/**

 	 * Initializes the metamodel. All stereotypes in the profile are mapped to

@@ -183,7 +181,7 @@
 			if (o instanceof Stereotype) {

 				final Stereotype st = (Stereotype) o;

 				final String typeName = getFullName(st);

-				final Type t = new StereotypeType(getTypeSystem(), typeName, st, actualTypeAwareComparison);

+				final Type t = new StereotypeType(getTypeSystem(), typeName, st);

 				stereoTypes.put(typeName, t);

 			}

 			else if (o instanceof Enumeration) {

@@ -255,8 +253,8 @@
 	 * 

 	 */

 	public Type getType(final Object obj) {

-		// Get actual type

-		Type actualType = internalProfileMetaModel.getType(obj);

+		// Get actual UML type

+		Type umlType = internalProfileMetaModel.getType(obj);

 		if (obj instanceof Element) {

 			if (obj instanceof EnumerationLiteral) {

 				EnumerationLiteral el = (EnumerationLiteral) obj;

@@ -277,7 +275,7 @@
 				if (errorIfStereotypeMissing && !stereotypes.toString().equals("[]"))

 					throw new RuntimeException("Stereotype could not be loaded! Possible hint: '" + stereotypes);

 				else

-					return actualType;

+					return umlType;

 			}

 

 			List<StereotypeType> types = new ArrayList<StereotypeType>(stereotypes.size());

@@ -289,20 +287,19 @@
 					StereotypeType stType = (StereotypeType) theType;

 					

 					// Find out whether the actual type is more specific than any of the StereotypeTypes superTypes

-					if(actualType != null && !actualType.isAssignableFrom(stType)) {

+					if(umlType != null && !umlType.isAssignableFrom(stType)) {

 						// Try to find a fitting combination in the cache

-						Pair<String, Type> key = new Pair<String, Type>(getFullName(st), actualType);

-						if(stereoTypesWithActualType == null) {

-							stereoTypesWithActualType = new HashMap<Pair<String, Type>, StereotypeType>();

+						Pair<String, Type> key = new Pair<String, Type>(getFullName(st), umlType);

+						if(stereoTypesWithUmlType == null) {

+							stereoTypesWithUmlType = new HashMap<Pair<String, Type>, StereotypeType>();

 						}

 						

-						stType = stereoTypesWithActualType.get(key);

+						stType = stereoTypesWithUmlType.get(key);

 						

 						// Create new StereotypeType and a reference to the actual type and put it into cache if not yet contained.

 						if(stType == null) {

-							stType = new StereotypeType(getTypeSystem(), getFullName(st), st, actualTypeAwareComparison);

-							stType.setActualType(actualType);

-							stereoTypesWithActualType.put(key, stType);

+							stType = new StereotypeType(getTypeSystem(), getFullName(st), st, umlType);

+							stereoTypesWithUmlType.put(key, stType);

 						}

 					}

 					types.add(stType);

@@ -310,17 +307,17 @@
 			}

 			switch (types.size()) {

 				case 0:

-					return actualType;

+					return umlType;

 				case 1:

 					return types.get(0);

 					// when more than one stereotype is applied we return a

 					// MultipleStereotypeType instance

 					// containing all applied stereotypes

 				default:

-					return new MultipleStereotypeType(getTypeSystem(), types, actualTypeAwareComparison);

+					return new MultipleStereotypeType(getTypeSystem(), types, umlType);

 			}

 		} else {

-			return actualType;

+			return umlType;

 		}

 	}

 

@@ -354,8 +351,4 @@
 		return namespaces;

 	}

 

-	public void setActualTypeAwareComparison(boolean actualTypeAwareComparison) {

-		this.actualTypeAwareComparison = actualTypeAwareComparison;

-	}

-

 }

diff --git a/plugins/org.eclipse.xtend.typesystem.uml2/src/org/eclipse/xtend/typesystem/uml2/profile/StereotypeType.java b/plugins/org.eclipse.xtend.typesystem.uml2/src/org/eclipse/xtend/typesystem/uml2/profile/StereotypeType.java
index ce313c3..3035b3e 100644
--- a/plugins/org.eclipse.xtend.typesystem.uml2/src/org/eclipse/xtend/typesystem/uml2/profile/StereotypeType.java
+++ b/plugins/org.eclipse.xtend.typesystem.uml2/src/org/eclipse/xtend/typesystem/uml2/profile/StereotypeType.java
@@ -32,7 +32,6 @@
 import org.eclipse.emf.ecore.util.EcoreUtil;

 import org.eclipse.internal.xtend.expression.parser.SyntaxConstants;

 import org.eclipse.internal.xtend.type.baseimpl.PropertyImpl;

-import org.eclipse.uml2.uml.Class;

 import org.eclipse.uml2.uml.Classifier;

 import org.eclipse.uml2.uml.Element;

 import org.eclipse.uml2.uml.Generalization;

@@ -50,31 +49,44 @@
 

     Stereotype stereoType;

 

-	private Type actualType;

+	/**

+	 * Represents the actual UML Type that the stereotype is applied to

+	 */

+	private Type umlType;

 

-	private final boolean actualTypeAwareComparison;

-

-    public StereotypeType(TypeSystem typeSystem, String name, Stereotype stereoType, boolean actualTypeAwareComparison) {

-        super(typeSystem, name);

-        this.stereoType = stereoType;

-		this.actualTypeAwareComparison = actualTypeAwareComparison;

+    public StereotypeType(TypeSystem typeSystem, String name, Stereotype stereoType) {

+        this(typeSystem, name, stereoType, null);

     }

 

-    @Override

+    public StereotypeType(TypeSystem typeSystem, String name, Stereotype stereoType, Type umlType) {

+    	super(typeSystem, name);

+    	this.stereoType = stereoType;

+		this.umlType = umlType;

+	}

+

+	@Override

 	public int hashCode() {

-		if (!actualTypeAwareComparison) {

+		// We need to distinguish between the situation where a Stereotype's

+		// base Class is more general than the actual UML Type in #equals() /

+		// #hashCode(), too - doing not, leads to issues with extension caching

+		// If a UML Type is present the cache should be aware of that

+		if (umlType == null) {

 			return super.hashCode();

 		}

 		final int prime = 31;

 		int result = super.hashCode();

 		result = prime * result

-				+ ((actualType == null) ? 0 : actualType.hashCode());

+				+ ((umlType == null) ? 0 : umlType.hashCode());

 		return result;

 	}

 

 	@Override

 	public boolean equals(Object obj) {

-		if (!actualTypeAwareComparison) {

+		// We need to distinguish between the situation where a Stereotype's

+		// base Class is more general than the actual UML Type in #equals() /

+		// #hashCode(), too - doing not, leads to issues with extension caching

+		// If a UML Type is present the cache should be aware of that

+		if (umlType == null) {

 			return super.equals(obj);

 		}

 		if (this == obj) {

@@ -87,11 +99,11 @@
 			return false;

 		}

 		StereotypeType other = (StereotypeType) obj;

-		if (actualType == null) {

-			if (other.actualType != null) {

+		if (umlType == null) {

+			if (other.umlType != null) {

 				return false;

 			}

-		} else if (!actualType.equals(other.actualType)) {

+		} else if (!umlType.equals(other.umlType)) {

 			return false;

 		}

 		return true;

@@ -253,13 +265,15 @@
         if (superTypes == null) {

             superTypes = new HashSet<Type>();

 

-            EList<Class> extendedMetaclasses = stereoType.getExtendedMetaclasses();

-			List<Classifier> all;

-			if(actualType != null) {

-				all = new ArrayList<Classifier>();

-			} else {

-				all = new ArrayList<Classifier>(extendedMetaclasses);

-			}

+            List<Classifier> all = new ArrayList<Classifier>();

+			// If an actual UML Type is present at this state, any of the

+			// metaclasses a Stereotype extends is more general than the actual

+			// type of the UML Object that this Stereotype has been created for.

+			// E.g. ProfileMetaModel.getType(Object) has been called for a

+			// Property, but the Stereotype extends the Element metaclass.

+            if(umlType == null) {

+            	all.addAll(stereoType.getExtendedMetaclasses());

+            }

             all.addAll(stereoType.getSuperClasses());

             for (Classifier classifier : all) {

                 String superTypeName = getFullName(classifier);

@@ -271,9 +285,10 @@
                 }

             }

 

-            // If an actual type has been set, add it to the list of superTypes in order to export its features

-            if(actualType != null && !superTypes.contains(actualType)) {

-            	superTypes.add(actualType);

+			// If an actual UML type has been set, add it to the list of superTypes

+			// in order to export its features

+            if(umlType != null && !superTypes.contains(umlType)) {

+            	superTypes.add(umlType);

             }

         }

         return Collections.unmodifiableSet(superTypes);

@@ -340,13 +355,9 @@
     	return result.toString();

     }

     

-    void setActualType(Type actualType) {

-		this.actualType = actualType;

-	}

-    

     @Override

     public String toString() {

-    	return (actualType != null ? MessageFormat.format("{0}[{1}]", super.toString(), actualType.getName()) : super.toString());

+    	return (umlType != null ? MessageFormat.format("{0}[{1}]", super.toString(), umlType.getName()) : super.toString());

     }

 

 }