summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorahaase2008-02-20 16:56:23 (EST)
committer ahaase2008-02-20 16:56:23 (EST)
commit4d740609071e0c995cc9cf5183aa9ce54a9fbc2e (patch)
tree85c38ac1d432e80d09b160d1b326608b392f7c21
parent2d81a241f4252fe74810b2f82d9f72e53079f665 (diff)
downloadorg.eclipse.xpand-4d740609071e0c995cc9cf5183aa9ce54a9fbc2e.zip
org.eclipse.xpand-4d740609071e0c995cc9cf5183aa9ce54a9fbc2e.tar.gz
org.eclipse.xpand-4d740609071e0c995cc9cf5183aa9ce54a9fbc2e.tar.bz2
added UmlTypesystem
-rw-r--r--plugins/org.eclipse.xtend.backend.uml2types/.classpath7
-rw-r--r--plugins/org.eclipse.xtend.backend.uml2types/.project28
-rw-r--r--plugins/org.eclipse.xtend.backend.uml2types/META-INF/MANIFEST.MF10
-rw-r--r--plugins/org.eclipse.xtend.backend.uml2types/build.properties4
-rw-r--r--plugins/org.eclipse.xtend.backend.uml2types/plugin.properties2
-rw-r--r--plugins/org.eclipse.xtend.backend.uml2types/src/org/eclipse/xtend/backend/types/uml2/UmlTypesystem.java199
-rw-r--r--plugins/org.eclipse.xtend.backend.uml2types/src/org/eclipse/xtend/backend/types/uml2/internal/EnumType.java91
-rw-r--r--plugins/org.eclipse.xtend.backend.uml2types/src/org/eclipse/xtend/backend/types/uml2/internal/MultipleStereotypeType.java69
-rw-r--r--plugins/org.eclipse.xtend.backend.uml2types/src/org/eclipse/xtend/backend/types/uml2/internal/StereotypeType.java201
-rw-r--r--plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/AbstractType.java24
10 files changed, 634 insertions, 1 deletions
diff --git a/plugins/org.eclipse.xtend.backend.uml2types/.classpath b/plugins/org.eclipse.xtend.backend.uml2types/.classpath
new file mode 100644
index 0000000..751c8f2
--- /dev/null
+++ b/plugins/org.eclipse.xtend.backend.uml2types/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/plugins/org.eclipse.xtend.backend.uml2types/.project b/plugins/org.eclipse.xtend.backend.uml2types/.project
new file mode 100644
index 0000000..6639a14
--- /dev/null
+++ b/plugins/org.eclipse.xtend.backend.uml2types/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.xtend.backend.uml2types</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/plugins/org.eclipse.xtend.backend.uml2types/META-INF/MANIFEST.MF b/plugins/org.eclipse.xtend.backend.uml2types/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..30f212c
--- /dev/null
+++ b/plugins/org.eclipse.xtend.backend.uml2types/META-INF/MANIFEST.MF
@@ -0,0 +1,10 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %Bundle-Name.0
+Bundle-SymbolicName: org.eclipse.xtend.backend.uml2types
+Bundle-Version: 1.0.0
+Require-Bundle: org.eclipse.xtend.backend,
+ org.eclipse.uml2.uml,
+ org.apache.commons.logging,
+ org.eclipse.xtend.backend.emftypes
+Bundle-Localization: plugin
diff --git a/plugins/org.eclipse.xtend.backend.uml2types/build.properties b/plugins/org.eclipse.xtend.backend.uml2types/build.properties
new file mode 100644
index 0000000..34d2e4d
--- /dev/null
+++ b/plugins/org.eclipse.xtend.backend.uml2types/build.properties
@@ -0,0 +1,4 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ .
diff --git a/plugins/org.eclipse.xtend.backend.uml2types/plugin.properties b/plugins/org.eclipse.xtend.backend.uml2types/plugin.properties
new file mode 100644
index 0000000..7a7369b
--- /dev/null
+++ b/plugins/org.eclipse.xtend.backend.uml2types/plugin.properties
@@ -0,0 +1,2 @@
+#Properties file for org.eclipse.xtend.backend.uml2types
+Bundle-Name.0 = Uml2types Plug-in \ No newline at end of file
diff --git a/plugins/org.eclipse.xtend.backend.uml2types/src/org/eclipse/xtend/backend/types/uml2/UmlTypesystem.java b/plugins/org.eclipse.xtend.backend.uml2types/src/org/eclipse/xtend/backend/types/uml2/UmlTypesystem.java
new file mode 100644
index 0000000..5a23e99
--- /dev/null
+++ b/plugins/org.eclipse.xtend.backend.uml2types/src/org/eclipse/xtend/backend/types/uml2/UmlTypesystem.java
@@ -0,0 +1,199 @@
+/*
+Copyright (c) 2008 Arno Haase.
+All rights reserved. This program and the accompanying materials
+are made available under the terms of the Eclipse Public License v1.0
+which accompanies this distribution, and is available at
+http://www.eclipse.org/legal/epl-v10.html
+
+Contributors:
+ Arno Haase - initial API and implementation
+ */
+package org.eclipse.xtend.backend.types.uml2;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.emf.ecore.EClassifier;
+import org.eclipse.uml2.uml.Element;
+import org.eclipse.uml2.uml.Enumeration;
+import org.eclipse.uml2.uml.EnumerationLiteral;
+import org.eclipse.uml2.uml.NamedElement;
+import org.eclipse.uml2.uml.Package;
+import org.eclipse.uml2.uml.Profile;
+import org.eclipse.uml2.uml.Stereotype;
+import org.eclipse.uml2.uml.Type;
+import org.eclipse.xtend.backend.common.BackendType;
+import org.eclipse.xtend.backend.common.BackendTypesystem;
+import org.eclipse.xtend.backend.types.builtin.BooleanType;
+import org.eclipse.xtend.backend.types.builtin.DoubleType;
+import org.eclipse.xtend.backend.types.builtin.LongType;
+import org.eclipse.xtend.backend.types.builtin.StringType;
+import org.eclipse.xtend.backend.types.emf.EmfTypesystem;
+import org.eclipse.xtend.backend.types.uml2.internal.EnumType;
+import org.eclipse.xtend.backend.types.uml2.internal.MultipleStereotypeType;
+import org.eclipse.xtend.backend.types.uml2.internal.StereotypeType;
+
+
+/**
+ * This typesystem implementation takes care of UML specifics, i.e. additional UML representations
+ * for primitive types and the mapping of UML stereotypes to backend types. It builds on top
+ * of the EmfTypesystem, which takes care of the "normal" mapping of UML elements to their
+ * corresponding types. <br>
+ *
+ * In other words, this typesystem implementation resolves all EMF types
+ * using the EmfTypesystem, so if you use UmlTypesystem, there is no need to use EmfTypesystem
+ * as well. But if you use both, make sure UmlTypesystem comes before EmfTypesystem.
+ *
+ * @author Arno Haase (http://www.haase-consulting.com)
+ */
+public final class UmlTypesystem implements BackendTypesystem {
+ private BackendTypesystem _rootTs;
+
+ private final EmfTypesystem _emfTypesystem = new EmfTypesystem ();
+
+ private final boolean _errorIfStereotypeIsMissing;
+ private static final Map<String, BackendType> _uml2Primitives = new HashMap<String, BackendType>();
+ private final Map<String, BackendType> _stereotypeTypes = new HashMap<String, BackendType> ();
+
+ static {
+ registerPrimitiveByName ("string", StringType.INSTANCE);
+
+ registerPrimitiveByName ("int", LongType.INSTANCE);
+ registerPrimitiveByName ("integer", LongType.INSTANCE);
+ registerPrimitiveByName ("unlimitedNatural", LongType.INSTANCE);
+
+ registerPrimitiveByName ("boolean", BooleanType.INSTANCE);
+
+ registerPrimitiveByName ("real", DoubleType.INSTANCE);
+ }
+
+ public UmlTypesystem (Collection<Profile> profiles, boolean errorIfStereotypeIsMissing) {
+ _errorIfStereotypeIsMissing = errorIfStereotypeIsMissing;
+ for (Profile p: profiles)
+ registerProfile (p);
+ }
+
+ public void registerProfile (Profile profile) {
+ fixName (profile);
+
+ for (Type t: getAllOwnedTypes(profile)) {
+ if (t instanceof Stereotype) {
+ final Stereotype st = (Stereotype) t;
+ fixName (st);
+ final String typeName = getFullName(st);
+ final BackendType bt = new StereotypeType (typeName, st, this);
+ _stereotypeTypes.put (typeName, bt);
+ }
+ else if (t instanceof Enumeration) {
+ final Enumeration en = (Enumeration) t;
+ fixName (en);
+ final String typeName = getFullName (en);
+ final BackendType bt = new EnumType (typeName, en);
+ _stereotypeTypes.put (typeName, bt);
+ }
+ }
+ }
+
+ private String getFullName (NamedElement ne) {
+ return ne.getQualifiedName();
+ }
+
+ /**
+ * recursively retrieves all UML types in a package and its children
+ */
+ private Collection<Type> getAllOwnedTypes (Package pkg) {
+ final Collection<Type> result = new ArrayList<Type> (pkg.getOwnedTypes());
+
+ for (Package child: pkg.getNestedPackages())
+ result.addAll (getAllOwnedTypes (child));
+
+ return result;
+ }
+
+ /**
+ * replace all whitespace in the element's name by underscore characters
+ */
+ public static void fixName (NamedElement elem) {
+ if (elem.getName() == null)
+ return;
+
+ elem.setName (elem.getName().replaceAll("\\s", "_"));
+ }
+
+
+ private static void registerPrimitiveByName (String name, BackendType type) {
+ _uml2Primitives.put (name.toLowerCase(), type);
+ }
+
+ public BackendType findType (Object o) {
+ if (! (o instanceof Type))
+ return _emfTypesystem.findType (o);
+
+ if (((Type) o).getName() != null) {
+ final BackendType umlPrimitive = _uml2Primitives.get (((Type) o).getName().toLowerCase());
+ if (umlPrimitive != null)
+ return umlPrimitive;
+ }
+
+ if (o instanceof EnumerationLiteral) {
+ final EnumerationLiteral el = (EnumerationLiteral) o;
+
+ // first, try to determine the literal's type by it's stereotype
+ BackendType result = getTypeByStereotype(el);
+ if (result != null)
+ return result;
+
+ // if that doesn't work, try to get the type of the containing enumeration
+ return _rootTs.findType (el.getEnumeration());
+ }
+ else if (o instanceof Element)
+ return getTypeByStereotype ((Element) o);
+
+ return null;
+ }
+
+ private BackendType getTypeByStereotype (Element element) {
+ final List<Stereotype> stereotypes = element.getAppliedStereotypes();
+
+ if (stereotypes.isEmpty()) {
+ //collection will be empty if the required profile is not loaded
+ if (_errorIfStereotypeIsMissing && !stereotypes.toString ().equals ("[]"))
+ throw new RuntimeException("Stereotype could not be loaded! Possible hint: '" + stereotypes);
+ else
+ return null;
+ }
+
+ final List<BackendType> stTypes = new ArrayList<BackendType>();
+ for (Stereotype st: stereotypes) {
+ BackendType stType = findType (st);
+ if (stType != null) {
+ stTypes.add (stType);
+ }
+ }
+ switch (stTypes.size()) {
+ case 0: return null;
+ case 1: return stTypes.get(0);
+ default: return new MultipleStereotypeType (stTypes);
+ }
+ }
+
+ public BackendType getTypeForEClassifier (EClassifier eClassifier) {
+ return _emfTypesystem.getTypeForEClassifier (eClassifier);
+ }
+
+ public BackendType findType (Class<?> cls) {
+ return _emfTypesystem.findType (cls);
+ }
+
+ public BackendTypesystem getRootTypesystem () {
+ return _rootTs;
+ }
+
+ public void setRootTypesystem (BackendTypesystem ts) {
+ _emfTypesystem.setRootTypesystem (ts);
+ _rootTs = ts;
+ }
+}
diff --git a/plugins/org.eclipse.xtend.backend.uml2types/src/org/eclipse/xtend/backend/types/uml2/internal/EnumType.java b/plugins/org.eclipse.xtend.backend.uml2types/src/org/eclipse/xtend/backend/types/uml2/internal/EnumType.java
new file mode 100644
index 0000000..004b835
--- /dev/null
+++ b/plugins/org.eclipse.xtend.backend.uml2types/src/org/eclipse/xtend/backend/types/uml2/internal/EnumType.java
@@ -0,0 +1,91 @@
+/*
+Copyright (c) 2008 Arno Haase.
+All rights reserved. This program and the accompanying materials
+are made available under the terms of the Eclipse Public License v1.0
+which accompanies this distribution, and is available at
+http://www.eclipse.org/legal/epl-v10.html
+
+Contributors:
+ Arno Haase - initial API and implementation
+ */
+package org.eclipse.xtend.backend.types.uml2.internal;
+
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.uml2.uml.Enumeration;
+import org.eclipse.uml2.uml.EnumerationLiteral;
+import org.eclipse.xtend.backend.common.BackendType;
+import org.eclipse.xtend.backend.common.ExecutionContext;
+import org.eclipse.xtend.backend.common.StaticProperty;
+import org.eclipse.xtend.backend.types.AbstractProperty;
+import org.eclipse.xtend.backend.types.AbstractType;
+import org.eclipse.xtend.backend.types.builtin.StringType;
+
+
+/**
+ *
+ * @author Arno Haase (http://www.haase-consulting.com)
+ */
+public final class EnumType extends AbstractType {
+ /** The Enumeration represented by this. */
+ private final Enumeration _enumeration;
+
+ public EnumType (String name, Enumeration en) {
+ super (name);
+ _enumeration = en;
+
+ for (final EnumerationLiteral el: en.getOwnedLiterals())
+ register (new StaticProperty() {
+ public Object get () {
+ return el;
+ }
+
+ public String getName () {
+ return el.getName();
+ }
+
+ public BackendType getOwner () {
+ return EnumType.this;
+ }
+
+ public BackendType getType () {
+ return EnumType.this;
+ }
+ });
+
+ register (new AbstractProperty (this, StringType.INSTANCE, "literal") {
+ @Override
+ public Object get (ExecutionContext ctx, Object o) {
+ if (o == null)
+ return null;
+
+ final EObject obj = (EObject) o;
+ return obj.eGet (obj.eClass ().getEStructuralFeature ("name"));
+ }
+ });
+ }
+
+ @Override
+ public int hashCode () {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((_enumeration == null) ? 0 : _enumeration.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals (Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ final EnumType other = (EnumType) obj;
+ if (_enumeration == null) {
+ if (other._enumeration != null)
+ return false;
+ } else if (!_enumeration.equals(other._enumeration))
+ return false;
+ return true;
+ }
+}
diff --git a/plugins/org.eclipse.xtend.backend.uml2types/src/org/eclipse/xtend/backend/types/uml2/internal/MultipleStereotypeType.java b/plugins/org.eclipse.xtend.backend.uml2types/src/org/eclipse/xtend/backend/types/uml2/internal/MultipleStereotypeType.java
new file mode 100644
index 0000000..815020c
--- /dev/null
+++ b/plugins/org.eclipse.xtend.backend.uml2types/src/org/eclipse/xtend/backend/types/uml2/internal/MultipleStereotypeType.java
@@ -0,0 +1,69 @@
+/*
+Copyright (c) 2008 Arno Haase.
+All rights reserved. This program and the accompanying materials
+are made available under the terms of the Eclipse Public License v1.0
+which accompanies this distribution, and is available at
+http://www.eclipse.org/legal/epl-v10.html
+
+Contributors:
+ Arno Haase - initial API and implementation
+ */
+package org.eclipse.xtend.backend.types.uml2.internal;
+
+import java.util.List;
+
+import org.eclipse.xtend.backend.common.BackendType;
+import org.eclipse.xtend.backend.types.AbstractType;
+
+/**
+ * This type is used to support assignment of multiple stereotypes to a
+ * model element. Methods from the superclass are overridden to evaluate
+ * them for each wrapped stereotype.
+ *
+ * @author Arno Haase (http://www.haase-consulting.com)
+ */
+
+public final class MultipleStereotypeType extends AbstractType {
+ private final List<BackendType> _stereotypeTypes;
+
+ public MultipleStereotypeType (List<BackendType> stereoTypeTypes) {
+ super (computeName (stereoTypeTypes), stereoTypeTypes.toArray (new BackendType[0]));
+
+ _stereotypeTypes = stereoTypeTypes;
+ }
+
+ /** Needed to be called within constructor */
+ private static String computeName (List<BackendType> stereotypes) {
+ final StringBuilder result = new StringBuilder (stereotypes.get(0).getName());
+
+ for (int i=1; i<stereotypes.size(); i++)
+ result.append ("," + stereotypes.get(i).getName());
+
+ return result.toString();
+ }
+
+ @Override
+ public int hashCode () {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((_stereotypeTypes == null) ? 0 : _stereotypeTypes.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals (Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ final MultipleStereotypeType other = (MultipleStereotypeType) obj;
+ if (_stereotypeTypes == null) {
+ if (other._stereotypeTypes != null)
+ return false;
+ } else if (!_stereotypeTypes.equals(other._stereotypeTypes))
+ return false;
+ return true;
+ }
+}
diff --git a/plugins/org.eclipse.xtend.backend.uml2types/src/org/eclipse/xtend/backend/types/uml2/internal/StereotypeType.java b/plugins/org.eclipse.xtend.backend.uml2types/src/org/eclipse/xtend/backend/types/uml2/internal/StereotypeType.java
new file mode 100644
index 0000000..4e8cfde
--- /dev/null
+++ b/plugins/org.eclipse.xtend.backend.uml2types/src/org/eclipse/xtend/backend/types/uml2/internal/StereotypeType.java
@@ -0,0 +1,201 @@
+/*
+Copyright (c) 2008 Arno Haase.
+All rights reserved. This program and the accompanying materials
+are made available under the terms of the Eclipse Public License v1.0
+which accompanies this distribution, and is available at
+http://www.eclipse.org/legal/epl-v10.html
+
+Contributors:
+ Arno Haase - initial API and implementation
+ */
+package org.eclipse.xtend.backend.types.uml2.internal;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+
+import org.apache.commons.logging.LogFactory;
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.InternalEObject;
+import org.eclipse.emf.ecore.util.EcoreUtil;
+import org.eclipse.uml2.uml.Classifier;
+import org.eclipse.uml2.uml.Element;
+import org.eclipse.uml2.uml.Generalization;
+import org.eclipse.uml2.uml.Property;
+import org.eclipse.uml2.uml.Stereotype;
+import org.eclipse.uml2.uml.Type;
+import org.eclipse.xtend.backend.common.BackendType;
+import org.eclipse.xtend.backend.common.ExecutionContext;
+import org.eclipse.xtend.backend.types.AbstractProperty;
+import org.eclipse.xtend.backend.types.AbstractType;
+import org.eclipse.xtend.backend.types.builtin.CollectionType;
+import org.eclipse.xtend.backend.types.uml2.UmlTypesystem;
+
+
+/**
+ *
+ * @author Arno Haase (http://www.haase-consulting.com)
+ */
+public final class StereotypeType extends AbstractType {
+ private final Stereotype _stereoType;
+
+ public StereotypeType (String name, Stereotype stereoType, UmlTypesystem umlTs) {
+ super (name, superTypes (umlTs, stereoType).toArray (new BackendType[0]));
+ _stereoType = stereoType;
+
+ for (StereotypeProperty stp: getProperties(this, stereoType, umlTs))
+ register (stp);
+ }
+
+
+ private Collection<StereotypeProperty> getProperties (BackendType owningType, Stereotype stereoType, UmlTypesystem umlTs) {
+ final Collection<StereotypeProperty> result = new HashSet<StereotypeProperty> ();
+
+ for (Property attrib: stereoType.getAttributes()) {
+ if (attrib.getName() == null)
+ continue;
+
+ UmlTypesystem.fixName (attrib);
+
+ final Type umlType = getTypeResolveProxy (attrib);
+ if (umlType.getQualifiedName() == null) {
+ LogFactory.getLog (owningType.getClass ()).error ("qualified name is null for element " + attrib.getQualifiedName());
+ continue;
+ }
+
+ final BackendType backendType = (attrib.isMultivalued()) ? CollectionType.INSTANCE : umlTs.findType (umlType);
+ result.add (new StereotypeProperty (backendType, attrib.getName ()));
+ }
+
+ return result;
+ }
+
+
+ private static Collection<BackendType> superTypes (UmlTypesystem umlTs, Stereotype stereoType) {
+ final List<Classifier> all = new ArrayList<Classifier> (stereoType.getExtendedMetaclasses());
+ all.addAll (stereoType.getSuperClasses());
+
+ final List<BackendType> result = new ArrayList<BackendType>();
+
+ for (Classifier classifier : all)
+ result.add (umlTs.getTypeForEClassifier (classifier.eClass()));
+
+ return result;
+ }
+
+
+ private Type getTypeResolveProxy (Property p) {
+ Type result = p.getType();
+
+ if (result.eIsProxy()) {
+ final InternalEObject proxy = (InternalEObject) result;
+ final URI uri = proxy.eProxyURI();
+
+ result = (Type) EcoreUtil.resolve (proxy, p);
+
+ if (result.eIsProxy())
+ throw new IllegalStateException ("Couldn't resolve proxy under " + uri);
+ }
+
+ return result;
+ }
+
+
+ @Override
+ public int hashCode () {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((_stereoType == null) ? 0 : _stereoType.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals (Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ final StereotypeType other = (StereotypeType) obj;
+ if (_stereoType == null) {
+ if (other._stereoType != null)
+ return false;
+ } else if (!_stereoType.equals(other._stereoType))
+ return false;
+ return true;
+ }
+
+
+ private final class StereotypeProperty extends AbstractProperty {
+ public StereotypeProperty (BackendType type, String name) {
+ super (StereotypeType.this, type, name);
+ }
+
+ @Override
+ public Object get (ExecutionContext ctx, Object target) {
+ if (target instanceof Element) {
+ final Element ele = (Element) target;
+
+ for (Stereotype st : ele.getAppliedStereotypes()) {
+ if (isStereoTypeAssignable (st, _stereoType)) {
+ final Object value = ele.getValue (st, getName());
+
+ // custom datatypes
+ // see Bug#185033
+ if (value instanceof EList) {
+ final EList<?> eList = (EList<?>) value;
+ final Collection<Object> values = new ArrayList<Object>();
+ for (Object dynObject: eList) {
+ final Object dynValue = getDynamicValue(dynObject);
+ if (dynValue != null)
+ values.add(dynValue);
+ }
+ if (!values.isEmpty ())
+ return values;
+ }
+ else if (value instanceof EObject) {
+ final Object dynValue = getDynamicValue(value);
+ if (dynValue != null)
+ return dynValue;
+ }
+
+ return value;
+ }
+ }
+ }
+ throw new IllegalArgumentException("uml2 Element expected but was " + target.getClass().getName());
+ }
+
+ private Object getDynamicValue(final Object value) {
+ if (value instanceof EObject) {
+ final EObject dynObject = (EObject) value;
+ final EClass dynClass = dynObject.eClass();
+ final EStructuralFeature baseClassFeature = dynClass.getEStructuralFeature("base_Class");
+
+ if(baseClassFeature != null){
+ return dynObject.eGet(baseClassFeature,true);
+ }
+ }
+ return null;
+ }
+
+ private boolean isStereoTypeAssignable(Stereotype st1, Stereotype st2) {
+ if (st1.getQualifiedName().equals(st2.getQualifiedName())) {
+ return true;
+ }
+ List<Generalization> gs = st1.getGeneralizations();
+ for (Generalization g : gs) {
+ if (g.getGeneral() instanceof Stereotype && isStereoTypeAssignable((Stereotype) g.getGeneral(), st2))
+ return true;
+ }
+ return false;
+ }
+ }
+
+}
diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/AbstractType.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/AbstractType.java
index 979d35f..a9b67e2 100644
--- a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/AbstractType.java
+++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/AbstractType.java
@@ -15,6 +15,7 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -25,6 +26,7 @@ import org.eclipse.xtend.backend.common.NamedFunction;
import org.eclipse.xtend.backend.common.Property;
import org.eclipse.xtend.backend.common.StaticProperty;
import org.eclipse.xtend.backend.types.builtin.ObjectType;
+import org.eclipse.xtend.backend.types.builtin.VoidType;
/**
@@ -38,7 +40,7 @@ public abstract class AbstractType implements BackendType {
private final Map<String, Property> _properties = new HashMap<String, Property> ();
private final Map<String, StaticProperty> _staticProperties = new HashMap<String, StaticProperty> ();
- private final List<NamedFunction> _builtinOperations = new ArrayList<NamedFunction> ();
+ private final Collection<NamedFunction> _builtinOperations = new HashSet<NamedFunction> ();
public AbstractType(String name, BackendType... superTypes) {
_name = name;
@@ -47,6 +49,12 @@ public abstract class AbstractType implements BackendType {
_superTypes = Collections.singletonList((BackendType) ObjectType.INSTANCE);
else
_superTypes = Arrays.asList(superTypes);
+
+ for (BackendType superType: superTypes) {
+ _builtinOperations.addAll (superType.getBuiltinOperations());
+ _properties.putAll (superType.getProperties());
+ _staticProperties.putAll (superType.getStaticProperties());
+ }
}
public AbstractType(String name, Collection<? extends BackendType> superTypes) {
@@ -114,6 +122,20 @@ public abstract class AbstractType implements BackendType {
public final Map<String, ? extends StaticProperty> getStaticProperties () {
return _staticProperties;
}
+
+ public boolean isAssignableFrom (BackendType other) {
+ if (other == VoidType.INSTANCE)
+ return true;
+
+ if (other.equals (this))
+ return true;
+
+ for (BackendType st: other.getSuperTypes())
+ if (isAssignableFrom (st))
+ return true;
+
+ return false;
+ }
@Override
public String toString () {