Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Bergmayr2015-07-31 08:50:03 -0400
committerAlex Bergmayr2015-07-31 08:50:03 -0400
commit31245ca47c863216d15dcd3c86b83b0a5fc324ee (patch)
tree6de5d4de026908b799c381c5f75b7d2d6a4df7f6 /proprietary/bundles/org.eclipse.upr.platform.java.cm2up/src
parentd754246c1bc2dc9db9b392f1e00d69a6fb5ac42e (diff)
downloadupr-master.tar.gz
upr-master.tar.xz
upr-master.zip
Added initial JUMP contributionHEADmaster
Diffstat (limited to 'proprietary/bundles/org.eclipse.upr.platform.java.cm2up/src')
-rw-r--r--proprietary/bundles/org.eclipse.upr.platform.java.cm2up/src/org/eclipse/upr/platform/java/cm2up/.gitignore3
-rw-r--r--proprietary/bundles/org.eclipse.upr.platform.java.cm2up/src/org/eclipse/upr/platform/java/cm2up/CodeModel2UMLProfile.atl1205
-rw-r--r--proprietary/bundles/org.eclipse.upr.platform.java.cm2up/src/org/eclipse/upr/platform/java/cm2up/CodeModel2UMLProfile.java359
-rw-r--r--proprietary/bundles/org.eclipse.upr.platform.java.cm2up/src/org/eclipse/upr/platform/java/cm2up/CodeModel2UMLProfile.properties24
-rw-r--r--proprietary/bundles/org.eclipse.upr.platform.java.cm2up/src/org/eclipse/upr/platform/java/cm2up/CodeModel2UMLProfilePostProcessor.java394
-rw-r--r--proprietary/bundles/org.eclipse.upr.platform.java.cm2up/src/org/eclipse/upr/platform/java/cm2up/ResourceBasedCodeModel2UMLProfile.java257
-rw-r--r--proprietary/bundles/org.eclipse.upr.platform.java.cm2up/src/org/eclipse/upr/platform/java/cm2up/javaLibrary.atl329
-rw-r--r--proprietary/bundles/org.eclipse.upr.platform.java.cm2up/src/org/eclipse/upr/platform/java/cm2up/profileLibrary.atl51
-rw-r--r--proprietary/bundles/org.eclipse.upr.platform.java.cm2up/src/org/eclipse/upr/platform/java/cm2up/util/CodeModel2UMLProfileUtil.java27
9 files changed, 2649 insertions, 0 deletions
diff --git a/proprietary/bundles/org.eclipse.upr.platform.java.cm2up/src/org/eclipse/upr/platform/java/cm2up/.gitignore b/proprietary/bundles/org.eclipse.upr.platform.java.cm2up/src/org/eclipse/upr/platform/java/cm2up/.gitignore
new file mode 100644
index 0000000..e65a70e
--- /dev/null
+++ b/proprietary/bundles/org.eclipse.upr.platform.java.cm2up/src/org/eclipse/upr/platform/java/cm2up/.gitignore
@@ -0,0 +1,3 @@
+/CodeModel2UMLProfile.asm
+/javaLibrary.asm
+/profileLibrary.asm
diff --git a/proprietary/bundles/org.eclipse.upr.platform.java.cm2up/src/org/eclipse/upr/platform/java/cm2up/CodeModel2UMLProfile.atl b/proprietary/bundles/org.eclipse.upr.platform.java.cm2up/src/org/eclipse/upr/platform/java/cm2up/CodeModel2UMLProfile.atl
new file mode 100644
index 0000000..eacc8c7
--- /dev/null
+++ b/proprietary/bundles/org.eclipse.upr.platform.java.cm2up/src/org/eclipse/upr/platform/java/cm2up/CodeModel2UMLProfile.atl
@@ -0,0 +1,1205 @@
+--/*******************************************************************************
+-- * Copyright (c) 2015 Vienna University of Technology.
+-- * 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:
+-- * Alexander Bergmayr (TU Wien) - initial API and implementation
+-- * Manuel Wimmer (TU Wien) - initial API and implementation
+-- *
+-- * Initially developed in the context of ARTIST EU project www.artist-project.eu
+-- *******************************************************************************/
+
+-- @nsURI UMLMM=http://www.eclipse.org/uml2/4.0.0/UML
+-- @path JMM=http://www.eclipse.org/MoDisco/Java/0.2.incubation/java
+-- @path TMM=pathmap://METAMODEL/Trace.ecore
+-- @path CFGMM=/eu.artist.migration.mdt.jump.cm2up/metamodel/jump-configuration.ecore
+
+-- Discovers UML Profiles from Java application code, frameworks and libraries.
+
+module CodeModel2UMLProfile;-- creates UP the UML Profile and TM the Trace Model
+-- from CM the Code Model discovered from a Java application / library
+-- JP a Java-based UML Profile that provides Stereotypes for the parameterized types
+ -- and proxies
+-- JPT the Java Primitive Types library provided by the UML implementation
+-- MC the UML meta-classes in terms of a UML model
+-- UPT the UML Primitive Types library provided by the UML implementation
+create UP: UMLMM, TM: TMM from CM: JMM, JP: UMLMM, JPT: UMLMM, MC: UMLMM, UPT: UMLMM,
+ EPT: UMLMM, CFG : CFGMM;
+
+-- TODO: default value of Strings - default values need to be generally revised
+-- TODO: Code-generator: ID annotation nachziehen!
+
+
+-- helpers for Java-based processing
+uses javaLibrary;
+-- helpers for Stereotype application
+uses profileLibrary;
+
+helper def: getAnnotationTypeMemberDeclarations:
+ Sequence(JMM!AnnotationTypeMemberDeclaration) =
+ JMM!AnnotationTypeMemberDeclaration.allInstancesFrom('CM');
+
+helper def: repeatingStereotypesCfg:
+ OclAny =
+ CFGMM!ProfileConfigurationParameter.allInstancesFrom('CFG') -> first().repeatingStereotypes;
+
+helper def: getRepeatableAnnotations:
+ Sequence(JMM!Annotation) =
+ JMM!Annotation.allInstancesFrom('CM') -> select(e | e.type.type.name = 'Repeatable');
+
+-- check if the annotation type is repeatable
+helper context JMM!AnnotationTypeDeclaration def : isRepeatable : Boolean =
+ self.annotations -> exists(e | e.type.type.name = 'Repeatable');
+
+-- check if the annotation type is a container annotation
+helper context JMM!AnnotationTypeDeclaration def : isContainerAnnotation : Boolean =
+ thisModule.getRepeatableAnnotations -> collect(e | e.values) -> flatten() -> exists(e | e.value.type.type = self);
+
+helper context JMM!AnnotationTypeDeclaration def : requiresContainerAnnotation : Boolean =
+ -- thisModule.repeatingStereotypesCfg = 'native' -> we don't need a container stereotype
+ thisModule.repeatingStereotypesCfg = #composition or thisModule.repeatingStereotypesCfg = #emulation;
+
+helper def: getStereotypes: Sequence(UMLMM!Stereotype) =
+ UMLMM!Stereotype.allInstancesFrom('JP');
+
+helper def: profile: UMLMM!Profile =
+ OclUndefined;
+
+helper def: stereotype: UMLMM!Stereotype =
+ OclUndefined;
+
+helper def: proxyPackage: UMLMM!Package =
+ OclUndefined;
+
+helper def: trace: TMM!Trace =
+ OclUndefined;
+
+-- ensure that the trace model is generated
+entrypoint rule createTrace() {
+ to
+ tr: TMM!Trace (
+ )
+ do {
+ thisModule.trace <- tr;
+ }
+}
+
+-- init package for proxy elements
+lazy rule initProxyPackage {
+ from
+ s1: JMM!Type
+ to
+ t1: UMLMM!Package (
+ name <- 'proxy'
+ )
+ do {
+ thisModule.profile.packagedElement <- t1;
+ thisModule.proxyPackage <- t1;
+
+ t1.applyProfile(UMLMM!Profile.allInstancesFrom('JP').first());
+ }
+}
+
+-- create the profile
+rule Model2Profile {
+ from
+ s1: JMM!Model
+ to
+ t1: UMLMM!Profile (
+ -- packageImport <- Sequence{jpt, mc, upt},
+ packageImport <- Sequence{mc,
+ upt},
+ metamodelReference <- mc,
+ name <- s1.name,
+ packagedElement <- s1.ownedElements -> select(e | not e.proxy and e.
+ isAnnotationTypeContainer)
+ ),
+ -- java primitive types
+-- jpt : UMLMM!PackageImport(
+-- importedPackage <- UMLMM!Model.allInstancesFrom('JPT').first()
+-- ),
+ -- uml meta-classes
+ mc: UMLMM!PackageImport (
+ importedPackage <- UMLMM!Model.allInstancesFrom('MC').first()
+ ),
+ -- uml primitive types
+ upt: UMLMM!PackageImport (
+ importedPackage <- UMLMM!Model.allInstancesFrom('UPT').first()
+ ),
+ -- trace information
+ tl: TMM!TraceLink (
+ ruleName <- 'Model2Profile',
+ targetElements <- Sequence{t1}
+ )
+ do {
+ -- global access to the profile
+ thisModule.profile <- t1;
+ -- apply the profile for java generics / proxies
+ t1.applyProfile(UMLMM!Profile.allInstancesFrom('JP').first());
+ thisModule.stereotype <- UMLMM!Stereotype.allInstancesFrom('JP') -> any(e | e.name = 'JProfile');
+ t1.applyStereotype(thisModule.stereotype);
+
+ -- trace information
+ tl.refSetValue('sourceElements', Sequence{s1});
+ thisModule.trace.traceLinks <- tl;
+ }
+}
+
+rule Package2Package {
+ from
+ s1: JMM!Package (
+ not s1.proxy and s1.isAnnotationTypeContainer
+ )
+ to
+ t1: UMLMM!Package (
+ name <- s1.name,
+ packagedElement <- s1.ownedPackages -> select(e | not e.proxy and
+ e.isAnnotationTypeContainer) --,
+ -- instead of selecting all required elements here let's do it in the
+ -- corresponding rules
+ -- of ClassDeclaration, EnumDeclaration, InterfaceDeclaration,
+ -- AnnotationTypeDeclaration
+-- packagedElement <- s1.ownedElements
+
+ ),
+ -- trace information
+ tl: TMM!TraceLink (
+ ruleName <- 'Package2Package',
+ targetElements <- Sequence{t1}
+ )
+ do {
+ -- trace information
+ tl.refSetValue('sourceElements', Sequence{s1});
+ thisModule.trace.traceLinks <- tl;
+ }
+}
+
+-- but only enumerations that are required for the profile
+rule EnumDeclaration2Enumeration {
+ from
+ s1: JMM!EnumDeclaration (
+ s1.isEnumerationRelevant
+ )
+ to
+ t1: UMLMM!Enumeration (
+ name <- if (s1.refImmediateComposite().oclIsTypeOf(JMM!Package)) then
+ s1.name
+ else
+ s1.name.concat('From').concat(s1.refImmediateComposite().name)
+ endif,
+ ownedLiteral <- s1.enumConstants -> select(e | not e.proxy or e.
+ refImmediateComposite().isEnumerationRelevant),
+ -- TODO: new CHECK !!
+ ownedAttribute <- s1.bodyDeclarations -> select(e | e.
+ oclIsTypeOf(JMM!FieldDeclaration)),
+ -- with 'not e.proxy' we exclude the 'valueOf' method generated by the java
+ -- compiler
+ ownedOperation <- s1.bodyDeclarations -> select(e | e.
+ oclIsTypeOf(JMM!MethodDeclaration) and not e.proxy)
+ ),
+ -- trace information
+ tl: TMM!TraceLink (
+ ruleName <- 'EnumDeclaration2Enumeration',
+ targetElements <- Sequence{t1}
+ )
+ do {
+ -- if the required class declaration is a proxy then the proxy stereotype is
+ -- applied
+ if(s1.proxy = true) {
+ if(thisModule.proxyPackage.oclIsUndefined()) {
+ thisModule -> initProxyPackage(s1);
+ }
+ thisModule.proxyPackage.packagedElement <- t1;
+
+ -- apply the proxy stereotype
+ thisModule.stereotype <- thisModule.getStereotypes -> select(e | e.name =
+ 'JProxyType').first();
+ t1.applyStereotype(thisModule.stereotype);
+
+ -- set the namepace of the proxy element if available
+ if(s1.refImmediateComposite().oclIsTypeOf(JMM!Package)) {
+ t1.setValue(thisModule.stereotype, 'namespace', s1.
+ refImmediateComposite().getFullyQualifiedPackageName);
+ }
+ else {
+ t1.setValue(thisModule.stereotype, 'namespace', 'NOT_AVAILABLE');
+ }
+ }
+
+ -- elements are contained either by packages or classifiers (nested elements)
+ else {
+ if(not s1.package.oclIsUndefined()) {
+ thisModule.resolveTemp(s1.refImmediateComposite(), 't1').packagedElement
+ <- t1;
+ }
+ else {
+ -- so let's get the package of the owner and put the stereotype there
+ -- ... however
+ -- there is a problem when we generate code !!!!
+ thisModule.resolveTemp(s1.refImmediateComposite().getJavaPackage(), 't1').
+ packagedElement <- t1;
+ }
+ }
+
+ -- trace information
+ tl.refSetValue('sourceElements', Sequence{s1});
+ thisModule.trace.traceLinks <- tl;
+ }
+}
+
+rule FieldDeclaration2Property {
+ from
+ s1: JMM!FieldDeclaration (
+ not s1.proxy and s1.refImmediateComposite().oclIsTypeOf(JMM!EnumDeclaration)
+ and s1.refImmediateComposite().isEnumerationRelevant
+ )
+ to
+ t1: UMLMM!Property (
+ -- TODO: fragments is 0..* - check the exact behaviour!
+ name <- s1.fragments.first().name,
+ type <- s1.type.getType(),
+ isStatic <- s1.modifier.static
+ ),
+ -- trace information
+ tl: TMM!TraceLink (
+ ruleName <- 'FieldDeclaration2Property',
+ targetElements <- Sequence{t1}
+ )
+ do {
+ -- trace information
+ tl.refSetValue('sourceElements', Sequence{s1});
+ thisModule.trace.traceLinks <- tl;
+ }
+}
+
+rule MethodDeclaration2Operation {
+ from
+ s1: JMM!MethodDeclaration (
+ not s1.proxy and s1.refImmediateComposite().oclIsTypeOf(JMM!EnumDeclaration)
+ and s1.refImmediateComposite().isEnumerationRelevant
+ )
+ to
+ t1: UMLMM!Operation (
+ name <- s1.name,
+ ownedParameter <- s1.parameters -> collect(e | thisModule.createParameter(e))
+ ),
+ -- trace information
+ tl: TMM!TraceLink (
+ ruleName <- 'MethodDeclaration2Operation',
+ targetElements <- Sequence{t1}
+ )
+ do {
+ -- thisModule.applyStereotypes(s1, t1);
+
+ -- trace information
+ tl.refSetValue('sourceElements', Sequence{s1});
+ thisModule.trace.traceLinks <- tl;
+ }
+}
+
+lazy rule createParameter {
+ from
+ s1: JMM!SingleVariableDeclaration
+ to
+ t1: UMLMM!Parameter (
+ name <- s1.name,
+ type <- s1.type.getType(),
+ direction <- #"in"
+ ),
+ -- trace information
+ tl: TMM!TraceLink (
+ ruleName <- 'SingleVariableDeclaration2Paramter',
+ targetElements <- Sequence{t1}
+ )
+ do {
+
+ -- trace information
+ tl.refSetValue('sourceElements', Sequence{s1});
+ thisModule.trace.traceLinks <- tl;
+ }
+}
+
+rule EnumConstantDeclaration2EnumerationLiteral {
+ from
+ s1: JMM!EnumConstantDeclaration (
+ s1.refImmediateComposite().isEnumerationRelevant
+ )
+ to
+ t1: UMLMM!EnumerationLiteral (
+ name <- s1.name
+ ),
+ -- trace information
+ tl: TMM!TraceLink (
+ ruleName <- 'EnumConstantDeclaration2EnumerationLiteral',
+ targetElements <- Sequence{t1}
+ )
+ do {
+ -- trace information
+ tl.refSetValue('sourceElements', Sequence{s1});
+ thisModule.trace.traceLinks <- tl;
+ }
+}
+
+-- but only classes that are required for the profile. Such classes can only be
+-- bounded type parameters of java.lang.class
+rule ClassDeclaration2Class {
+ from
+ -- since java.lang.Class is mapped to UML class, we need to exclude it here as
+ -- well
+ s1: JMM!ClassDeclaration (
+ (s1.refImmediateComposite().getFullyQualifiedPackageName.concat('.').
+ concat(s1.name) <> 'java.lang.Class') and (thisModule.
+ getAnnotationTypeMemberDeclarations -> select(e | not e.type.
+ oclIsUndefined()) -> select(e | e.type.type.
+ oclIsTypeOf(JMM!ParameterizedType)) -> exists(f | f.type.type.
+ typeArguments -> exists(g | g.type = s1)))
+ )
+ to
+ t1: UMLMM!Class (
+ name <- if (s1.refImmediateComposite().oclIsTypeOf(JMM!Package)) then
+ s1.name
+ else
+ s1.name.concat('From').concat(s1.refImmediateComposite().name)
+ endif
+ ),
+ -- trace information
+ tl: TMM!TraceLink (
+ ruleName <- 'ClassDeclaration2Class',
+ targetElements <- Sequence{t1}
+ )
+ do {
+ -- if the required class declaration is a proxy then the proxy stereotype is
+ -- applied
+ if(s1.proxy = true) {
+ if(thisModule.proxyPackage.oclIsUndefined()) {
+ thisModule -> initProxyPackage(s1);
+ }
+ thisModule.proxyPackage.packagedElement <- t1;
+
+ -- apply the proxy stereotype
+ thisModule.stereotype <- UMLMM!Stereotype.allInstancesFrom('JP') ->
+ select(e | e.name = 'JProxyType').first();
+ t1.applyStereotype(thisModule.stereotype);
+
+ -- set the namepace of the proxy element if available
+ if(s1.refImmediateComposite().oclIsTypeOf(JMM!Package)) {
+ t1.setValue(thisModule.stereotype, 'namespace', s1.
+ refImmediateComposite().getFullyQualifiedPackageName);
+ }
+ else {
+ t1.setValue(thisModule.stereotype, 'namespace', 'NOT_AVAILABLE');
+ }
+ }
+
+ -- nested classifiers are contained by classifiers rather than packages ;)
+ else {
+ if(thisModule.resolveTemp(s1.refImmediateComposite(), 't1').
+ oclIsTypeOf(UMLMM!Package)) {
+ thisModule.resolveTemp(s1.refImmediateComposite(), 't1').packagedElement
+ <- t1;
+ }
+ else {
+ -- so let's get the package of the owner and put the stereotype there
+ -- ... however
+ -- there is a problem when we generate code !!!!
+ thisModule.resolveTemp(s1.refImmediateComposite().getJavaPackage(), 't1').
+ packagedElement <- t1;
+ }
+ }
+
+ -- trace information
+ tl.refSetValue('sourceElements', Sequence{s1});
+ thisModule.trace.traceLinks <- tl;
+ }
+}
+
+-- but only interfaces that are required for the profile. Such classes can only be
+-- bounded type parameters of java.lang.class
+rule InterfaceDeclaration2Interface {
+ from
+ s1: JMM!InterfaceDeclaration (
+ thisModule.getAnnotationTypeMemberDeclarations -> select(e | not e.type.
+ oclIsUndefined()) -> select(e | e.type.type.
+ oclIsTypeOf(JMM!ParameterizedType)) -> exists(f | f.type.type.
+ typeArguments -> exists(g | g.type = s1))
+ )
+ to
+ t1: UMLMM!Interface (
+ name <- if (s1.refImmediateComposite().oclIsTypeOf(JMM!Package)) then
+ s1.name
+ else
+ s1.name.concat('From').concat(s1.refImmediateComposite().name)
+ endif
+ ),
+ -- trace information
+ tl: TMM!TraceLink (
+ ruleName <- 'InterfaceDeclaration2Interface',
+ targetElements <- Sequence{t1}
+ )
+ do {
+ -- if the required class declaration is a proxy then the proxy stereotype is
+ -- applied
+ if(s1.proxy = true) {
+ if(thisModule.proxyPackage.oclIsUndefined()) {
+ thisModule.initProxyPackage(s1);
+ }
+ thisModule.proxyPackage.packagedElement <- t1;
+
+ -- apply the proxy stereotype
+ thisModule.stereotype <- UMLMM!Stereotype.allInstancesFrom('JP') -> select(e
+ | e.name = 'JProxyType').first();
+ t1.applyStereotype(thisModule.stereotype);
+
+ -- set the namepace of the proxy element if available
+ if(s1.refImmediateComposite().oclIsTypeOf(JMM!Package)) {
+ t1.setValue(thisModule.stereotype, 'namespace', s1.
+ refImmediateComposite().getFullyQualifiedPackageName);
+ }
+ else {
+ t1.setValue(thisModule.stereotype, 'namespace', 'NOT_AVAILABLE');
+ }
+ }
+
+ -- nested classifiers are contained by classifiers rather than packages ;)
+ else {
+ if(thisModule.resolveTemp(s1.refImmediateComposite(), 't1').
+ oclIsTypeOf(UMLMM!Package)) {
+ thisModule.resolveTemp(s1.refImmediateComposite(), 't1').packagedElement
+ <- t1;
+ }
+ else {
+ -- so let's get the package of the owner and put the stereotype there
+ -- ... however
+ -- there is a problem when we generate code !!!!
+ thisModule.resolveTemp(s1.refImmediateComposite().getJavaPackage(), 't1').
+ packagedElement <- t1;
+ }
+ }
+
+ -- trace information
+ tl.refSetValue('sourceElements', Sequence{s1});
+ thisModule.trace.traceLinks <- tl;
+ }
+}
+
+rule AnnotationTypeDeclaration2Stereotype {
+ from
+ -- only those AnnotationTypeDeclarations that are not proxies or return value of
+ -- a AnnotationTypeMemberDeclaration
+ s1: JMM!AnnotationTypeDeclaration (
+ -- isn't a proxy
+ not s1.proxy
+
+ -- is a container stereotype required
+ and ((s1.isContainerAnnotation and s1.requiresContainerAnnotation) or not s1.isContainerAnnotation)
+
+ -- TODO: document this case
+ or thisModule.getAnnotationTypeMemberDeclarations -> select(e | not e.type.oclIsUndefined()) ->
+ select(e | e.type.type.oclIsTypeOf(JMM!ParameterizedType)) -> exists(f | f.type.type.typeArguments ->
+ exists(g | g.type = s1))
+
+ -- we do have a proxy element that has been resolved. This happens if a
+ -- missing library has been added to the build path. If this
+ -- library is not added then an UnresolvedTypeDeclaration
+ -- is discovered by MoDisco.
+ or (s1.proxy and s1.isRelevantForAnnotationTypes)
+ )
+ to
+ t1: UMLMM!Stereotype (
+ name <- if (s1.refImmediateComposite().oclIsTypeOf(JMM!Package)) then
+ s1.name
+ else
+ s1.name.concat('From').concat(s1.refImmediateComposite().name)
+ endif,
+ -- can be set to public as no other visibility modifier is allowed for
+ -- annotation types
+ visibility <- #public,
+ -- should not be done since then the stereotype cannot be instantiated (Java
+ -- Feature or Bug ;) )
+ -- isAbstract <- if s1.modifier.inheritance.toString() = 'abstract' then true
+ -- else false endif,
+
+ -- TODO : According to JLS, an annotation type declaration can also contain
+ -- constant declarations
+ -- class declarations etc. ... even annotation type declarations -> inner
+ -- annotations
+ -- this means bodyDeclarations may also be of type JMM!FieldDeclaration
+
+ -- in findbugs haben wir den Fall einer ClassDeclaration innerhabl eienr
+ -- AnnotationTypeDeclaration,
+ -- see: edu.umd.cs.findbugs.internalAnnotations.SlashedClassName
+ ownedAttribute <- s1.bodyDeclarations -> select(e | e.
+ oclIsTypeOf(JMM!AnnotationTypeMemberDeclaration))
+ ),
+ -- trace information
+ tl: TMM!TraceLink (
+ ruleName <- 'AnnotationTypeDeclaration2Stereotype',
+ targetElements <- Sequence{t1}
+ )
+ do {
+ -- if the required class declaration is a proxy then the proxy stereotype is
+ -- applied
+ -- and the stereotype is added to a dedicated proxy package
+ if(s1.proxy) {
+ if(thisModule.proxyPackage.oclIsUndefined()) {
+ thisModule.initProxyPackage(s1);
+ }
+ thisModule.proxyPackage.packagedElement <- t1;
+
+ -- apply the proxy stereotype
+ thisModule.stereotype <- UMLMM!Stereotype.allInstancesFrom('JP') -> select(e
+ | e.name = 'JProxyType').first();
+ t1.applyStereotype(thisModule.stereotype);
+
+ -- set the namepace of the proxy element if available
+ if(s1.refImmediateComposite().oclIsTypeOf(JMM!Package)) {
+ t1.setValue(thisModule.stereotype, 'namespace', s1.
+ refImmediateComposite().getFullyQualifiedPackageName);
+ }
+ else {
+ t1.setValue(thisModule.stereotype, 'namespace', 'NOT_AVAILABLE');
+ }
+ }
+
+ -- TODO: nested classifiers are contained by classifiers rather than packages ;)
+ -- ... however nested
+ -- stereotypes are not actuall supported
+ else {
+ if(thisModule.resolveTemp(s1.refImmediateComposite(), 't1').
+ oclIsTypeOf(UMLMM!Package)) {
+ thisModule.resolveTemp(s1.refImmediateComposite(), 't1').packagedElement
+ <- t1;
+ }
+ else {
+ -- so let's get the package of the owner and put the stereotype there
+ -- ... however
+ -- there is a problem when we generate code !!!!
+ thisModule.resolveTemp(s1.refImmediateComposite().getJavaPackage(), 't1').
+ packagedElement <- t1;
+ }
+ }
+
+ -- if the target annotation is not set at all then we have to trigger a lazy rule
+ -- that produces extensions to
+ -- all possible candidates
+ if(not s1.proxy and not (s1.annotations -> exists(a | a.type.type.name =
+ 'Target'))) {
+ for(javaElementType in thisModule.umlTarget.getKeys()) {
+ for(umlElementType in thisModule.umlTarget.get(javaElementType)) {
+ thisModule.createExtension(s1, t1, umlElementType, javaElementType);
+ }
+ }
+ }
+
+ -- trace information
+ tl.refSetValue('sourceElements', Sequence{s1});
+ thisModule.trace.traceLinks <- tl;
+ }
+}
+
+rule createExtension(annotationType: JMM!AnnotationTypeDeclaration, stereotype:
+ UMLMM!Stereotype,
+ metaClass: UMLMM!Element, elementType: String) {
+ to
+ -- the extension relationship
+ t1: UMLMM!Extension (
+ name <- 'extension_'.concat(stereotype.name).concat('_').concat(metaClass.
+ name),
+ memberEnd <- Sequence{t2, t3},
+ ownedEnd <- t3
+ ),
+ -- the properties of the relationship (end points)
+ t2: UMLMM!Property (
+ name <- 'base_'.concat(metaClass.name),
+ type <- metaClass,
+ -- we set the lower bound to 0 because if the stereotype extends
+ -- several metaclasses then we would get validation errors with
+ -- a lower bound 1
+ lower <- 0,
+ upper <- 1
+ ),
+ t3: UMLMM!ExtensionEnd (
+ name <- 'extension_'.concat(metaClass.name),
+ aggregation <- #composite,
+ type <- stereotype,
+ lower <- 0,
+ upper <- if(annotationType.isRepeatable) then (0-1) else 1 endif
+ ),
+ -- trace information
+ tl: TMM!TraceLink (
+ ruleName <- 'createExtension',
+ targetElements <- Sequence{t1,
+ t2,
+ t3}
+ )
+ do {
+ -- refers to the ownedAttribute of the stereotype
+ stereotype.ownedAttribute <- t2;
+
+ -- refers to the profile that contains the stereotype
+ stereotype.refImmediateComposite().packagedElement <- t1;
+
+ -- if we create an extension of Type then we need a constraint as
+ -- UML:Type is more general then Java:Type
+
+ if(elementType = 'TYPE') {
+ thisModule.createTypeConstraint(stereotype);
+ }
+
+ else if(elementType = 'CONSTRUCTOR') {
+ thisModule.createConstructorConstraint(stereotype);
+ }
+
+ else if(elementType = 'METHOD') {
+ thisModule.createMethodConstraint(stereotype);
+ }
+
+ -- trace information
+ tl.refSetValue('sourceElements', Sequence{annotationType});
+ thisModule.trace.traceLinks <- tl;
+ }
+}
+
+rule SingleVariableAccessMultiValued2Extension {
+ from
+ s1: JMM!SingleVariableAccess (
+ s1.isMultiValuedAnnotationTarget
+ )
+ using {
+ s2: JMM!AnnotationTypeDeclaration = s1.refImmediateComposite().
+ refImmediateComposite().refImmediateComposite().refImmediateComposite();
+ }
+ to
+ -- the extension relationship
+ t1: UMLMM!Extension (
+ name <- 'extension_'.concat(thisModule.resolveTemp(s2, 't1').name).
+ concat('_').concat(thisModule.umlTarget.get(s1.variable.name).first().name),
+ memberEnd <- Sequence{t2,
+ t3},
+ ownedEnd <- t3
+ ),
+ -- the properties of the relationship (end points)
+ t2: UMLMM!Property (
+ name <- 'base_'.concat(thisModule.umlTarget.get(s1.variable.name).first().
+ name),
+ type <- thisModule.umlTarget.get(s1.variable.name).first(),
+ lower <- 0,
+ upper <- 1
+ ),
+ t3: UMLMM!ExtensionEnd (
+ name <- 'extension_'.concat(thisModule.umlTarget.get(s1.variable.name).
+ first().name),
+ aggregation <- #composite,
+ type <- thisModule.resolveTemp(s2, 't1')
+ ),
+ -- trace information
+ tl: TMM!TraceLink (
+ ruleName <- 'SingleVariableAccessMultiValued2Extension',
+ targetElements <- Sequence{t1,
+ t2,
+ t3}
+ )
+ do {
+ -- refers to the ownedAttribute of the stereotype
+ thisModule.resolveTemp(s2, 't1').ownedAttribute <- t2;
+
+ -- refers to the profile that contains the stereotype
+ thisModule.resolveTemp(s2.getPackage(), 't1').packagedElement <- t1;
+
+ -- if the target is of type FIELD, we do have to create an extension for
+ -- EnumDeclaration as well;
+ -- if we use Associatons, we may have to add another extension
+ if(s1.variable.name = 'FIELD') {
+ thisModule.createExtension(s2, thisModule.resolveTemp(s2, 't1'), thisModule.
+ umlTarget.get(s1.variable.name).at(2), s1.variable.name);
+ }
+
+ -- if the target is of type METHOD, we do have to create an extension for
+ -- Property as well as methods in annotationtypedeclrations are translated
+ -- to property
+ if(s1.variable.name = 'METHOD') {
+ thisModule.createExtension(s2, thisModule.resolveTemp(s2, 't1'), thisModule.
+ umlTarget.get(s1.variable.name).at(2), s1.variable.name);
+ }
+
+ -- in case of TYPE we do have to create the type constraint
+ if(s1.variable.name = 'TYPE') {
+ thisModule.createTypeConstraint(thisModule.resolveTemp(s2, 't1'));
+ }
+
+ -- in case of CONSTRUCTOR we do have to create the type constraint
+ else if(s1.variable.name = 'CONSTRUCTOR') {
+ thisModule.createConstructorConstraint(thisModule.resolveTemp(s2, 't1'));
+ }
+
+ -- trace information
+ tl.refSetValue('sourceElements', Sequence{s1});
+ thisModule.trace.traceLinks <- tl;
+ }
+}
+
+rule SingleVariableAccessSingleValued2Extension {
+ from
+ s1: JMM!SingleVariableAccess (
+ s1.isSingleValuedAnnotationTarget
+ )
+ using {
+ s2: JMM!AnnotationTypeDeclaration = s1.refImmediateComposite().
+ refImmediateComposite().refImmediateComposite();
+ }
+ to
+ -- the extension relationship
+ t1: UMLMM!Extension (
+ name <- 'extension_'.concat(thisModule.resolveTemp(s2, 't1').name).
+ concat('_').concat(thisModule.umlTarget.get(s1.variable.name).first().name),
+ memberEnd <- Sequence{t2,
+ t3},
+ ownedEnd <- t3
+ ),
+ -- the properties of the relationship (end points)
+ t2: UMLMM!Property (
+ name <- 'base_'.concat(thisModule.umlTarget.get(s1.variable.name).first().
+ name),
+ type <- thisModule.umlTarget.get(s1.variable.name).first(),
+ lower <- 0,
+ upper <- 1
+ ),
+ t3: UMLMM!ExtensionEnd (
+ name <- 'extension_'.concat(thisModule.umlTarget.get(s1.variable.name).
+ first().name),
+ aggregation <- #composite,
+ type <- thisModule.resolveTemp(s2, 't1')
+ ),
+ -- trace information
+ tl: TMM!TraceLink (
+ ruleName <- 'SingleVariableAccessSingleValued2Extension',
+ targetElements <- Sequence{t1,
+ t2,
+ t3}
+ )
+ do {
+ -- refers to the ownedAttribute of the stereotype
+ thisModule.resolveTemp(s2, 't1').ownedAttribute <- t2;
+
+ -- refers to the profile that contains the stereotype
+ thisModule.resolveTemp(s2.getPackage(), 't1').packagedElement <- t1;
+
+ -- if the target is of type FIELD, we do have to create an extension for
+ -- EnumDeclaration as well;
+ -- if we use Associatons, we may have to add another extension
+ if(s1.variable.name = 'FIELD') {
+ thisModule.createExtension(s2, thisModule.resolveTemp(s2, 't1'), thisModule.
+ umlTarget.get(s1.variable.name).at(2), s1.variable.name);
+ }
+
+ -- if the target is of type METHOD, we do have to create an extension for
+ -- Property as well as methods in annotationtypedeclrations are translated
+ -- to property
+ if(s1.variable.name = 'METHOD') {
+ thisModule.createExtension(s2, thisModule.resolveTemp(s2, 't1'), thisModule.
+ umlTarget.get(s1.variable.name).at(2), s1.variable.name);
+ }
+
+ -- in case of TYPE we do have to create the type constraint
+ if(s1.variable.name = 'TYPE') {
+ thisModule.createTypeConstraint(thisModule.resolveTemp(s2, 't1'));
+ }
+
+ -- in case of CONSTRUCTOR we do have to create the type constraint
+ else if(s1.variable.name = 'CONSTRUCTOR') {
+ thisModule.createConstructorConstraint(thisModule.resolveTemp(s2, 't1'));
+ }
+
+ -- trace information
+ tl.refSetValue('sourceElements', Sequence{s1});
+ thisModule.trace.traceLinks <- tl;
+ }
+}
+
+rule AnnotationTypeMemberDeclaration2Property {
+ from
+ s1: JMM!AnnotationTypeMemberDeclaration (
+ -- we need to exclude unresolved annotation type member declarations
+ if(s1.oclIsTypeOf(JMM!AnnotationTypeMemberDeclaration) and not s1.proxy) then
+
+ -- is a container stereotype required
+ ((s1.refImmediateComposite().isContainerAnnotation and s1.refImmediateComposite().requiresContainerAnnotation)
+ or not s1.refImmediateComposite().isContainerAnnotation)
+
+ or s1.refImmediateComposite().isRelevantForAnnotationTypes
+
+ else false
+ endif
+ )
+ to
+ t1: UMLMM!Property (
+ name <- s1.name,
+ -- can be set to public as no other visibility modifier is allowed for
+ -- annotation types
+ visibility <- #public,
+ -- the problem here is that we may have proxy member declaratios with no
+ -- further type information
+ type <- if (s1.type <> OclUndefined) then
+ s1.type.getType()
+ else
+ UMLMM!PrimitiveType.allInstancesFrom('EPT') -> select(e | e.name =
+ 'EJavaObject').first()
+ endif,
+ -- is done in post processing ;)
+ -- default <- if s1.default <> OclUndefined and
+ -- s1.default.oclIsTypeOf(JMM!NumberLiteral) then
+ -- s1.default.tokenValue else OclUndefined endif,
+ -- TODO: provide example for an undefined type
+ lower <- if s1.default <> OclUndefined then
+ 0
+ else
+ if s1.type <> OclUndefined then
+ if s1.type.type.oclIsTypeOf(JMM!ArrayType) then
+ 0
+ else
+ 1
+ endif
+ else
+ 1
+ endif
+ endif,
+ upper <- if s1.type <> OclUndefined then
+ if s1.type.type.oclIsTypeOf(JMM!ArrayType) then
+ -1
+ else
+ 1
+ endif
+ else
+ 1
+ endif,
+ -- if stereotypes are composed by other stereotypes
+ aggregation <- if s1.type <> OclUndefined
+ -- if the annotation member is of type Class then aggregation needs to be set to #none
+ then if(s1.type.isComplexType() and not s1.type.getType().oclIsTypeOf(UMLMM!Class)) then #composite else #none
+ endif
+ else #none
+ endif
+ ),
+ -- trace information
+ tl: TMM!TraceLink (
+ ruleName <- 'AnnotationTypeMemberDeclaration2Property',
+ targetElements <- Sequence{t1}
+ )
+ do {
+
+ -- TODO : Here we should also consider the discussion about OCL constraints for
+ -- the allowed types as specified by the binding Class<T>
+ -- same as above: the problem here is that we may have proxy member declaratios
+ -- with no further type information
+ if(s1.type <> OclUndefined) {
+ if (s1.type.type.oclIsTypeOf(JMM!ParameterizedType)) {
+ thisModule.stereotype <- thisModule.getStereotypes -> any(e | e.name =
+ 'JGenericType');
+ t1.applyStereotype(thisModule.stereotype);
+
+ t1.setValue(thisModule.stereotype, 'type', 'upperBounded');
+
+ -- set the type of the 'binding' ... unbounded (default), upperbounded,
+ -- lowerbounded, bounded;
+ if (s1.type.type.typeArguments.first().type.
+ oclIsTypeOf(JMM!WildCardType)) {
+
+ -- if the type parameterized type is unresolved then create a proxy
+ -- element
+ -- design decision: it seems to be rather hard to express this part
+ -- declaratively ;(
+
+ if(not s1.type.type.typeArguments.first().type.bound.
+ oclIsUndefined()) {
+ if(s1.type.type.typeArguments.first().type.bound.type.
+ oclIsTypeOf(JMM!UnresolvedTypeDeclaration)) {
+
+ -- s1.refImmediateComposite().name.debug();
+ -- s1.name.debug();
+ thisModule.UnresolvedTypeDeclaration2Type(s1.type.type.
+ typeArguments.first().type.bound.type);
+ }
+ }
+
+ -- upperBounded case
+ if (s1.type.type.typeArguments.first().type.name.startsWith('?' + ''
+ + ' extends')) {
+ thisModule.stereotype <- thisModule.getStereotypes -> any(e | e.
+ name = 'JGenericType');
+ t1.setValue(thisModule.stereotype, 'type', 'upperBounded');
+
+ --t1.setValue(thisModule.stereotype, 'type', 'upperBounded');
+ --t1.setValue(thisModule.stereotype, 'parameter',
+ -- thisModule.resolveTemp(s1.type.type.typeArguments.first().type.bound.typ
+ -- e
+ -- ,
+ -- 't1').debug());
+ }
+ -- lowerBounded case
+ else if (s1.type.type.typeArguments.first().type.name.toString().
+ startsWith('? super')) {
+ t1.setValue(thisModule.stereotype, 'type', 'lowerBounded');
+ -- t1.setValue(thisModule.stereotype, 'parameter',
+ -- thisModule.resolveTemp(s1.type.type.typeArguments.first().type.bound.typ
+ -- e
+ -- ,
+ -- 't1').debug());
+ }
+ }
+
+ -- bounded case
+ else if (not s1.type.type.typeArguments.first().type.oclIsUndefined()) {
+
+ -- s1.name.debug();
+ t1.setValue(thisModule.stereotype, 'type', 'bounded');
+ t1.setValue(thisModule.stereotype, 'parameter', thisModule.
+ resolveTemp(s1.type.type.typeArguments.first().type,
+ 't1'));
+ }
+ }
+
+ if (s1.type.isComplexType()) {
+ thisModule.AnnotationTypeMemberDeclaration2Association(s1);
+ }
+ }
+
+ -- trace information
+ tl.refSetValue('sourceElements', Sequence{s1});
+ thisModule.trace.traceLinks <- tl;
+ }
+}
+
+-- if we have UML properties with a complex type then we should create an UML association
+lazy rule AnnotationTypeMemberDeclaration2Association {
+ from
+ s1: JMM!AnnotationTypeMemberDeclaration
+ to
+ t1: UMLMM!Association (
+ name <- if (not s1.type.getType().name.oclIsUndefined()) then
+ s1.name.concat('_').concat(s1.refImmediateComposite().name).concat('_').concat(s1.type.getType().name)
+ else
+ s1.name.concat('_').concat(s1.refImmediateComposite().name).concat('_').concat(s1.type.type.name)
+ endif,
+ memberEnd <- s1,
+ memberEnd <- t2
+ ),
+ t2: UMLMM!Property (
+ -- the idea is to use the name of the Java field plus the classifier the
+ -- association points to
+ name <- s1.name.concat('_').concat(s1.refImmediateComposite().name),
+ -- can be set to public as no other visibility modifier is allowed for
+ -- annotation types
+ visibility <- #public,
+ -- TODO: Think about the multiplicity
+ lower <- 0,
+ upper <- 1,
+ type <- s1.refImmediateComposite()
+ ),
+ -- trace information
+ tl: TMM!TraceLink (
+ ruleName <- 'AnnotationTypeMemberDeclaration2Association',
+ targetElements <- Sequence{t1}
+ )
+ do {
+ thisModule.resolveTemp(s1.refImmediateComposite().getPackage(), 't1').
+ packagedElement <- t1;
+
+ -- case java.lang.Class / java.lang.Class[]: we do not want to change the
+ -- meta-class UML Class
+ -- so the produced property is contained by the association
+ if( (s1.type.type.oclIsTypeOf(JMM!ParameterizedType)) or
+ (s1.type.type.refImmediateComposite().getFullyQualifiedPackageName.toString().concat('.').concat(s1.type.type.name).toString()
+ = 'java.lang.Class') or ( -- in case the Array is parameterized the name
+ -- string also contains '<...>'
+ s1.type.type.name.toString().startsWith('java.lang.Class') and s1.type.
+ type.name.toString().endsWith('[]')) ) {
+
+ t1.ownedEnd <- t2;
+ }
+ -- we follow the standard procedure and put the produced property into the
+ -- associated element
+ else {
+ if(s1.type.type.oclIsTypeOf(JMM!ArrayType)) {
+
+ if(s1.type.type.elementType.type.
+ oclIsTypeOf(JMM!UnresolvedTypeDeclaration)) {
+ t1.ownedEnd <- t2;
+ }
+
+
+ thisModule.resolveTemp(s1.type.type.elementType.type, 't1').
+ ownedAttribute <- t2;
+ }
+ else {
+ thisModule.resolveTemp(s1.type.type, 't1').ownedAttribute <- t2;
+ }
+ }
+
+ -- trace information
+ tl.refSetValue('sourceElements', Sequence{s1});
+ thisModule.trace.traceLinks <- tl;
+
+ }
+}
+
+-- Refers to Types that cannot be resolved. This happens if a library references elements
+-- of another library for which we do not have access to the source. Then, we get only the
+-- type information and the type access but not further information.
+-- The idea is to transform those UnresolvedTypes that are used in the declaration of
+-- of annotations, i.e., AnnotationTypeMemberDeclarations. This seems to be essential
+-- to declare the AnnotationTypeMemberDeclaration.
+rule UnresolvedTypeDeclaration2Type {
+ from
+ s1: JMM!UnresolvedTypeDeclaration (
+ s1.usagesInTypeAccess -> exists(e | e.refImmediateComposite().
+ oclIsTypeOf(JMM!AnnotationTypeMemberDeclaration)) or
+ -- ArrayTypes need to be handled differently
+ s1.usagesInTypeAccess -> collect(e | e.refImmediateComposite()) ->
+ select(e | e.oclIsTypeOf(JMM!ArrayType)) -> exists(e | e.usagesInTypeAccess ->
+ exists(f | f.refImmediateComposite().oclIsTypeOf(JMM!AnnotationTypeMemberDeclaration)))
+ )
+ to
+ t1: UMLMM!Class (
+ name <- s1.name
+ ),
+ -- trace information
+ tl: TMM!TraceLink (
+ ruleName <- 'UnresolvedTypeDeclaration2Type',
+ targetElements <- Sequence{t1}
+ )
+ do {
+ if(thisModule.proxyPackage.oclIsUndefined()) {
+ thisModule -> initProxyPackage(s1);
+ }
+ thisModule.proxyPackage.packagedElement <- t1;
+
+ -- apply the proxy stereotype
+ thisModule.stereotype <- UMLMM!Stereotype.allInstancesFrom('JP') ->
+ select(e | e.name = 'JProxyType').first();
+ t1.applyStereotype(thisModule.stereotype);
+
+ -- trace information
+ tl.refSetValue('sourceElements', Sequence{s1});
+ thisModule.trace.traceLinks <- tl;
+ }
+}
+
+-- we do need a constraint for the Type extension as only Class, Interface, Enumeration
+-- and Stereotype
+-- should be targets for the produced Stereotype
+rule createTypeConstraint(stereotype: UMLMM!Stereotype) {
+ to
+ t1: UMLMM!Constraint (
+ name <- 'typeConstraint',
+ constrainedElement <- stereotype,
+ context <- stereotype,
+ specification <- t2
+ ),
+ t2: UMLMM!OpaqueExpression (
+ name <- 'typeConstraintExpression',
+ -- the type constraint
+-- body <- 'self.base_Type.oclIsUndefined() or
+-- (self.base_Type.oclIsTypeOf(uml::Class) or
+-- self.base_Type.oclIsTypeOf(uml::Interface) or
+-- self.base_Type.oclIsTypeOf(uml::Enumeration) or
+-- self.base_Type.oclIsTypeOf(uml::Stereotype))',
+ body <- 'not self.base_Type.oclIsUndefined() implies Set{uml::Stereotype,
+ uml::Class, uml::Enumeration, uml::Interface}
+ -> includes(self.base_Type.oclType())',
+ -- the language we use to express the constraint
+ language <- 'OCL'
+ )
+}
+
+-- furthermore, we do need a constraint for the Operation extension if the Java element
+-- type Constructor
+-- is used
+rule createConstructorConstraint(stereotype: UMLMM!Stereotype) {
+ to
+ t1: UMLMM!Constraint (
+ name <- 'constructorConstraint',
+ constrainedElement <- stereotype,
+ context <- stereotype,
+ specification <- t2
+ ),
+ t2: UMLMM!OpaqueExpression (
+ name <- 'constructorConstraintExpression',
+ -- the type constraint
+ -- body <- 'self.base_Operation.oclIsUndefined() or
+ -- self.base_Operation.name =
+ -- self.base_Operation.oclContainer().oclAsType(uml::Classifier).name'
+ -- ,
+ body <- 'not self.base_Operation.oclIsUndefined() implies
+ self.base_Operation.name =
+ self.base_Operation.oclContainer().oclAsType(uml::Classifier).name',
+ -- the language we use to express the constraint
+ language <- 'OCL'
+ )
+}
+
+-- since we translation methods of annotationtypedeclarations to properties, we do have
+-- to take care
+-- that such properties can be stereotyped if ElementType.Method is set
+rule createMethodConstraint(stereotype: UMLMM!Stereotype) {
+ to
+ t1: UMLMM!Constraint (
+ name <- 'methodConstraint',
+ constrainedElement <- stereotype,
+ context <- stereotype,
+ specification <- t2
+ ),
+ t2: UMLMM!OpaqueExpression (
+ name <- 'methodConstraintExpression',
+ -- the type constraint
+-- body <- 'self.base_Property.oclIsUndefined() or
+-- self.base_Property.oclContainer().oclIsTypeOf(uml::Stereotype)',
+ body <- 'not self.base_Property.oclIsUndefined() implies
+ self.base_Property.oclContainer().oclIsTypeOf(uml::Stereotype)',
+ -- the language we use to express the constraint
+ language <- 'OCL'
+ )
+}
+
+-- currently we do not use UML's support for templates and template binding!
+--rule ParameterizedType2Class {
+-- from
+-- s1 : JMM!ParameterizedType
+-- to
+-- t1 : UMLMM!Class (
+-- name <- s1.name,
+-- templateBinding <- s1.typeArguments
+-- )
+--}
+--
+--rule TypeAccessOfParameterizedType2TemplateBinding {
+-- from
+-- s1 : JMM!TypeAccess(
+-- if s1.refImmediateComposite().oclIsTypeOf(JMM!ParameterizedType)
+-- then s1.refImmediateComposite().typeArguments -> exists(e | e = s1)
+-- else false endif)
+-- to
+-- t1 : UMLMM!TemplateBinding (
+-- signature <-
+ -- s1.refImmediateComposite().getParameterizedClassFromJavaLibrary().ownedTemplateSignatur
+ -- e
+ -- ,
+ --
+-- parameterSubstitution <- t2
+-- ),
+--
+-- t2 : UMLMM!TemplateParameterSubstitution (
+-- -- TODO : the assumption here is that we have only one parameter
+-- formal <-
+ -- s1.refImmediateComposite().getParameterizedClassFromJavaLibrary().ownedTemplateSignature.ownedParameter.first(
+ -- )
+ -- ,
+ --
+-- actual <- if s1.type.oclIsTypeOf(JMM!AnnotationTypeDeclaration) then
+ -- s1.type else s1.getActualParameterFromModelLibrary() endif
+-- -- TODO : in RSA the property ownedActual is set as well ... but then the
+--- define step of UML2 plugin breaks!
+-- )
+--}
diff --git a/proprietary/bundles/org.eclipse.upr.platform.java.cm2up/src/org/eclipse/upr/platform/java/cm2up/CodeModel2UMLProfile.java b/proprietary/bundles/org.eclipse.upr.platform.java.cm2up/src/org/eclipse/upr/platform/java/cm2up/CodeModel2UMLProfile.java
new file mode 100644
index 0000000..595059f
--- /dev/null
+++ b/proprietary/bundles/org.eclipse.upr.platform.java.cm2up/src/org/eclipse/upr/platform/java/cm2up/CodeModel2UMLProfile.java
@@ -0,0 +1,359 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2012 Obeo.
+ * 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:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.upr.platform.java.cm2up;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Map.Entry;
+
+import org.eclipse.core.runtime.FileLocator;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.ecore.xmi.impl.EcoreResourceFactoryImpl;
+import org.eclipse.m2m.atl.common.ATLExecutionException;
+import org.eclipse.m2m.atl.core.ATLCoreException;
+import org.eclipse.m2m.atl.core.IExtractor;
+import org.eclipse.m2m.atl.core.IInjector;
+import org.eclipse.m2m.atl.core.IModel;
+import org.eclipse.m2m.atl.core.IReferenceModel;
+import org.eclipse.m2m.atl.core.ModelFactory;
+import org.eclipse.m2m.atl.core.emf.EMFExtractor;
+import org.eclipse.m2m.atl.core.emf.EMFInjector;
+import org.eclipse.m2m.atl.core.emf.EMFModelFactory;
+import org.eclipse.m2m.atl.core.launch.ILauncher;
+import org.eclipse.m2m.atl.engine.emfvm.launch.EMFVMLauncher;
+
+/**
+ * Entry point of the 'CodeModel2UMLProfile' transformation module.
+ */
+public class CodeModel2UMLProfile {
+
+ /**
+ * The property file. Stores module list, the metamodel and library locations.
+ * @generated
+ */
+ private Properties properties;
+
+ /**
+ * The CM model.
+ * @generated
+ */
+ protected IModel cmModel;
+
+ /**
+ * The JP model.
+ * @generated
+ */
+ protected IModel jpModel;
+
+ /**
+ * The JPT model.
+ * @generated
+ */
+ protected IModel jptModel;
+
+ /**
+ * The MC model.
+ * @generated
+ */
+ protected IModel mcModel;
+
+ /**
+ * The UPT model.
+ * @generated
+ */
+ protected IModel uptModel;
+
+ /**
+ * The EPT model.
+ * @generated
+ */
+ protected IModel eptModel;
+
+ /**
+ * The CFG model.
+ * @generated
+ */
+ protected IModel cfgModel;
+
+ /**
+ * The UP model.
+ * @generated
+ */
+ protected IModel upModel;
+
+ /**
+ * The TM model.
+ * @generated
+ */
+ protected IModel tmModel;
+
+ /**
+ * The main method.
+ *
+ * @param args
+ * are the arguments
+ * @generated
+ */
+ public static void main(String[] args) {
+ try {
+ if (args.length < 9) {
+ System.out.println("Arguments not valid : {CM_model_path, JP_model_path, JPT_model_path, MC_model_path, UPT_model_path, EPT_model_path, CFG_model_path, UP_model_path, TM_model_path}.");
+ } else {
+ CodeModel2UMLProfile runner = new CodeModel2UMLProfile();
+ runner.loadModels(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
+ runner.doCodeModel2UMLProfile(new NullProgressMonitor());
+ runner.saveModels(args[7], args[8]);
+ }
+ } catch (ATLCoreException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ } catch (ATLExecutionException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Constructor.
+ *
+ * @generated
+ */
+ public CodeModel2UMLProfile() throws IOException {
+ properties = new Properties();
+ properties.load(getFileURL("CodeModel2UMLProfile.properties").openStream());
+ EPackage.Registry.INSTANCE.put(getMetamodelUri("UMLMM"), org.eclipse.uml2.uml.UMLPackage.eINSTANCE);
+ Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap().put("ecore", new EcoreResourceFactoryImpl());
+ }
+
+ /**
+ * Load the input and input/output models, initialize output models.
+ *
+ * @param cmModelPath
+ * the CM model path
+ * @param jpModelPath
+ * the JP model path
+ * @param jptModelPath
+ * the JPT model path
+ * @param mcModelPath
+ * the MC model path
+ * @param uptModelPath
+ * the UPT model path
+ * @param eptModelPath
+ * the EPT model path
+ * @param cfgModelPath
+ * the CFG model path
+ * @throws ATLCoreException
+ * if a problem occurs while loading models
+ *
+ * @generated
+ */
+ public void loadModels(String cmModelPath, String jpModelPath, String jptModelPath, String mcModelPath, String uptModelPath, String eptModelPath, String cfgModelPath) throws ATLCoreException {
+ ModelFactory factory = new EMFModelFactory();
+ IInjector injector = new EMFInjector();
+ IReferenceModel umlmmMetamodel = factory.newReferenceModel();
+ injector.inject(umlmmMetamodel, getMetamodelUri("UMLMM"));
+ IReferenceModel cfgmmMetamodel = factory.newReferenceModel();
+ injector.inject(cfgmmMetamodel, getMetamodelUri("CFGMM"));
+ IReferenceModel tmmMetamodel = factory.newReferenceModel();
+ injector.inject(tmmMetamodel, getMetamodelUri("TMM"));
+ IReferenceModel jmmMetamodel = factory.newReferenceModel();
+ injector.inject(jmmMetamodel, getMetamodelUri("JMM"));
+ this.cmModel = factory.newModel(jmmMetamodel);
+ injector.inject(cmModel, cmModelPath);
+ this.jpModel = factory.newModel(umlmmMetamodel);
+ injector.inject(jpModel, jpModelPath);
+ this.jptModel = factory.newModel(umlmmMetamodel);
+ injector.inject(jptModel, jptModelPath);
+ this.mcModel = factory.newModel(umlmmMetamodel);
+ injector.inject(mcModel, mcModelPath);
+ this.uptModel = factory.newModel(umlmmMetamodel);
+ injector.inject(uptModel, uptModelPath);
+ this.eptModel = factory.newModel(umlmmMetamodel);
+ injector.inject(eptModel, eptModelPath);
+ this.cfgModel = factory.newModel(cfgmmMetamodel);
+ injector.inject(cfgModel, cfgModelPath);
+ this.upModel = factory.newModel(umlmmMetamodel);
+ this.tmModel = factory.newModel(tmmMetamodel);
+ }
+
+ /**
+ * Save the output and input/output models.
+ *
+ * @param upModelPath
+ * the UP model path
+ * @param tmModelPath
+ * the TM model path
+ * @throws ATLCoreException
+ * if a problem occurs while saving models
+ *
+ * @generated
+ */
+ public void saveModels(String upModelPath, String tmModelPath) throws ATLCoreException {
+ IExtractor extractor = new EMFExtractor();
+ extractor.extract(upModel, upModelPath);
+ extractor.extract(tmModel, tmModelPath);
+ }
+
+ /**
+ * Transform the models.
+ *
+ * @param monitor
+ * the progress monitor
+ * @throws ATLCoreException
+ * if an error occurs during models handling
+ * @throws IOException
+ * if a module cannot be read
+ * @throws ATLExecutionException
+ * if an error occurs during the execution
+ *
+ * @generated
+ */
+ public Object doCodeModel2UMLProfile(IProgressMonitor monitor) throws ATLCoreException, IOException, ATLExecutionException {
+ ILauncher launcher = new EMFVMLauncher();
+ Map<String, Object> launcherOptions = getOptions();
+ launcher.initialize(launcherOptions);
+ launcher.addInModel(cmModel, "CM", "JMM");
+ launcher.addInModel(jpModel, "JP", "UMLMM");
+ launcher.addInModel(jptModel, "JPT", "UMLMM");
+ launcher.addInModel(mcModel, "MC", "UMLMM");
+ launcher.addInModel(uptModel, "UPT", "UMLMM");
+ launcher.addInModel(eptModel, "EPT", "UMLMM");
+ launcher.addInModel(cfgModel, "CFG", "CFGMM");
+ launcher.addOutModel(upModel, "UP", "UMLMM");
+ launcher.addOutModel(tmModel, "TM", "TMM");
+ launcher.addLibrary("javaLibrary", getLibraryAsStream("javaLibrary"));
+ launcher.addLibrary("profileLibrary", getLibraryAsStream("profileLibrary"));
+ return launcher.launch("run", monitor, launcherOptions, (Object[]) getModulesList());
+ }
+
+ /**
+ * Returns an Array of the module input streams, parameterized by the
+ * property file.
+ *
+ * @return an Array of the module input streams
+ * @throws IOException
+ * if a module cannot be read
+ *
+ * @generated
+ */
+ protected InputStream[] getModulesList() throws IOException {
+ InputStream[] modules = null;
+ String modulesList = properties.getProperty("CodeModel2UMLProfile.modules");
+ if (modulesList != null) {
+ String[] moduleNames = modulesList.split(",");
+ modules = new InputStream[moduleNames.length];
+ for (int i = 0; i < moduleNames.length; i++) {
+ String asmModulePath = new Path(moduleNames[i].trim()).removeFileExtension().addFileExtension("asm").toString();
+ modules[i] = getFileURL(asmModulePath).openStream();
+ }
+ }
+ return modules;
+ }
+
+ /**
+ * Returns the URI of the given metamodel, parameterized from the property file.
+ *
+ * @param metamodelName
+ * the metamodel name
+ * @return the metamodel URI
+ *
+ * @generated
+ */
+ protected String getMetamodelUri(String metamodelName) {
+ return properties.getProperty("CodeModel2UMLProfile.metamodels." + metamodelName);
+ }
+
+ /**
+ * Returns the file name of the given library, parameterized from the property file.
+ *
+ * @param libraryName
+ * the library name
+ * @return the library file name
+ *
+ * @generated
+ */
+ protected InputStream getLibraryAsStream(String libraryName) throws IOException {
+ return getFileURL(properties.getProperty("CodeModel2UMLProfile.libraries." + libraryName)).openStream();
+ }
+
+ /**
+ * Returns the options map, parameterized from the property file.
+ *
+ * @return the options map
+ *
+ * @generated
+ */
+ protected Map<String, Object> getOptions() {
+ Map<String, Object> options = new HashMap<String, Object>();
+ for (Entry<Object, Object> entry : properties.entrySet()) {
+ if (entry.getKey().toString().startsWith("CodeModel2UMLProfile.options.")) {
+ options.put(entry.getKey().toString().replaceFirst("CodeModel2UMLProfile.options.", ""),
+ entry.getValue().toString());
+ }
+ }
+ return options;
+ }
+
+ /**
+ * Finds the file in the plug-in. Returns the file URL.
+ *
+ * @param fileName
+ * the file name
+ * @return the file URL
+ * @throws IOException
+ * if the file doesn't exist
+ *
+ * @generated
+ */
+ protected static URL getFileURL(String fileName) throws IOException {
+ final URL fileURL;
+ if (isEclipseRunning()) {
+ URL resourceURL = CodeModel2UMLProfile.class.getResource(fileName);
+ if (resourceURL != null) {
+ fileURL = FileLocator.toFileURL(resourceURL);
+ } else {
+ fileURL = null;
+ }
+ } else {
+ fileURL = CodeModel2UMLProfile.class.getResource(fileName);
+ }
+ if (fileURL == null) {
+ throw new IOException("'" + fileName + "' not found");
+ } else {
+ return fileURL;
+ }
+ }
+
+ /**
+ * Tests if eclipse is running.
+ *
+ * @return <code>true</code> if eclipse is running
+ *
+ * @generated
+ */
+ public static boolean isEclipseRunning() {
+ try {
+ return Platform.isRunning();
+ } catch (Throwable exception) {
+ // Assume that we aren't running.
+ }
+ return false;
+ }
+}
diff --git a/proprietary/bundles/org.eclipse.upr.platform.java.cm2up/src/org/eclipse/upr/platform/java/cm2up/CodeModel2UMLProfile.properties b/proprietary/bundles/org.eclipse.upr.platform.java.cm2up/src/org/eclipse/upr/platform/java/cm2up/CodeModel2UMLProfile.properties
new file mode 100644
index 0000000..381fa65
--- /dev/null
+++ b/proprietary/bundles/org.eclipse.upr.platform.java.cm2up/src/org/eclipse/upr/platform/java/cm2up/CodeModel2UMLProfile.properties
@@ -0,0 +1,24 @@
+# ==============================================================================
+# CodeModel2UMLProfile properties
+# ==============================================================================
+
+# ATL modules: if several, by order of superimposition (the latter ones overrides the former ones)
+CodeModel2UMLProfile.modules = CodeModel2UMLProfile.atl
+
+# Metamodels paths or nsUris
+CodeModel2UMLProfile.metamodels.UMLMM = http://www.eclipse.org/uml2/3.0.0/UML
+CodeModel2UMLProfile.metamodels.CFGMM = http://org.eclipse.upr.platform.java.configuration/0.9
+CodeModel2UMLProfile.metamodels.TMM = http://org.eclipse.upr.platform.trace/0.9
+CodeModel2UMLProfile.metamodels.JMM = http://www.eclipse.org/MoDisco/Java/0.2.incubation/java
+
+# Libraries paths
+CodeModel2UMLProfile.libraries.javaLibrary = javaLibrary.asm
+CodeModel2UMLProfile.libraries.profileLibrary = profileLibrary.asm
+
+# ATL Launching options
+CodeModel2UMLProfile.options.supportUML2Stereotypes = true
+CodeModel2UMLProfile.options.OPTION_CONTENT_TYPE = false
+CodeModel2UMLProfile.options.step = false
+CodeModel2UMLProfile.options.allowInterModelReferences = true
+CodeModel2UMLProfile.options.printExecutionTime = true
+
diff --git a/proprietary/bundles/org.eclipse.upr.platform.java.cm2up/src/org/eclipse/upr/platform/java/cm2up/CodeModel2UMLProfilePostProcessor.java b/proprietary/bundles/org.eclipse.upr.platform.java.cm2up/src/org/eclipse/upr/platform/java/cm2up/CodeModel2UMLProfilePostProcessor.java
new file mode 100644
index 0000000..0577d74
--- /dev/null
+++ b/proprietary/bundles/org.eclipse.upr.platform.java.cm2up/src/org/eclipse/upr/platform/java/cm2up/CodeModel2UMLProfilePostProcessor.java
@@ -0,0 +1,394 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Vienna University of Technology.
+ * 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:
+ * Alexander Bergmayr (Vienna University of Technology) - initial API and implementation
+ *
+ * Initially developed in the context of ARTIST EU project www.artist-project.eu
+ *******************************************************************************/
+package org.eclipse.upr.platform.java.cm2up;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.lang.StringUtils;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.gmt.modisco.java.AbstractTypeDeclaration;
+import org.eclipse.gmt.modisco.java.Annotation;
+import org.eclipse.gmt.modisco.java.AnnotationTypeDeclaration;
+import org.eclipse.gmt.modisco.java.AnnotationTypeMemberDeclaration;
+import org.eclipse.gmt.modisco.java.ArrayInitializer;
+import org.eclipse.gmt.modisco.java.BooleanLiteral;
+import org.eclipse.gmt.modisco.java.CharacterLiteral;
+import org.eclipse.gmt.modisco.java.Expression;
+import org.eclipse.gmt.modisco.java.NumberLiteral;
+import org.eclipse.gmt.modisco.java.PrefixExpression;
+import org.eclipse.gmt.modisco.java.SingleVariableAccess;
+import org.eclipse.gmt.modisco.java.StringLiteral;
+import org.eclipse.gmt.modisco.java.TypeDeclaration;
+import org.eclipse.gmt.modisco.java.TypeLiteral;
+import org.eclipse.gmt.modisco.java.emf.JavaPackage;
+import org.eclipse.m2m.atl.core.IModel;
+import org.eclipse.uml2.uml.Element;
+import org.eclipse.uml2.uml.Enumeration;
+import org.eclipse.uml2.uml.PrimitiveType;
+import org.eclipse.uml2.uml.Property;
+import org.eclipse.uml2.uml.Stereotype;
+import org.eclipse.uml2.uml.Type;
+import org.eclipse.uml2.uml.UMLPackage;
+import org.eclipse.upr.platform.trace.Trace;
+import org.eclipse.upr.platform.trace.TraceLink;
+import org.eclipse.upr.platform.trace.TracePackage;
+
+/**
+ * @author Alexander Bergmayr
+ *
+ */
+public class CodeModel2UMLProfilePostProcessor {
+
+ /**
+ *
+ */
+ private static Map<EObject, TraceLink> profileModel2CodeModeltraceMap = new HashMap<EObject, TraceLink>();
+
+ /**
+ *
+ */
+ private static Map<EObject, EObject> codeModel2ProfileModeltraceMap = new HashMap<EObject, EObject>();
+
+ /**
+ *
+ * @param codeModel
+ * @param profileModel
+ * @param traceModel
+ */
+ public static void runPostProcessing(IModel codeModel, IModel profileModel,
+ IModel traceModel) {
+ // init the trace map
+ initProfileModel2CodeModelTraceMap(traceModel);
+ initCodeModel2ProfileModelTraceMap(traceModel);
+
+ // set default values
+ setDefaultValues();
+
+ // helper collection to find property duplicates
+ Collection<String> properties = new ArrayList<String>();
+
+ // helper collection that stores the elements to destroy
+ Collection<Element> umlRemovals = new ArrayList<Element>();
+ Set<TraceLink> traceRemovals = new HashSet<TraceLink>();
+
+ // check the stereotypes for duplicates -> Property, Association,
+ // Operation
+ Set<? extends Object> stereotypes = profileModel
+ .getElementsByType(UMLPackage.eINSTANCE.getStereotype());
+
+ for (Object obj : stereotypes) {
+ Stereotype stereotype = (Stereotype) obj;
+
+ // TODO: maybe work with validators here !!
+ for (Property property : stereotype.getAllAttributes()) {
+ if (properties.contains(property.getName())) {
+
+ // the extension member ends of the Extension
+ for (Property extensionEnd : property.getAssociation()
+ .getMemberEnds()) {
+ umlRemovals.add(extensionEnd);
+
+ // if we remove an Operation extension, we should remove
+ // the constructor
+ // constraint as well
+ if (property.getType().getName().equalsIgnoreCase("Operation")) {
+ umlRemovals.add(stereotype.getOwnedRule("constructorConstraint"));
+ }
+
+ // if we remove a Property extension, we should remove
+ // the method
+ // constraint as well
+ if (property.getType().getName().equalsIgnoreCase("Property")) {
+ umlRemovals.add(stereotype.getOwnedRule("methodConstraint"));
+ }
+
+ traceRemovals.add(profileModel2CodeModeltraceMap.get(extensionEnd));
+ }
+
+ // the Extension
+ umlRemovals.add(property.getAssociation());
+ traceRemovals.add(profileModel2CodeModeltraceMap.get(property
+ .getAssociation()));
+
+ // TODO: we need to remove constraints regarding operations
+ // as well!
+ } else {
+ properties.add(property.getName());
+ }
+ }
+
+ // clear the collection of properties for the next stereotype
+ properties.clear();
+ }
+
+ // remove the trace links
+ for (TraceLink traceLink : traceRemovals) {
+ Trace trace = (Trace) traceLink.eContainer();
+ trace.getTraceLinks().remove(traceLink);
+ }
+
+ // remove the uml elements
+ for (Element element : umlRemovals) {
+ element.destroy();
+ }
+ }
+
+ private static void setDefaultValues() {
+ for (EObject eObj : codeModel2ProfileModeltraceMap.keySet()) {
+ if (eObj instanceof AnnotationTypeMemberDeclaration) {
+ AnnotationTypeMemberDeclaration member = (AnnotationTypeMemberDeclaration) eObj;
+
+ if (member.getDefault() != null) {
+ Object value = getValueFromExpression(member.getDefault());
+
+ if (value != null) {
+ EObject umlElement = codeModel2ProfileModeltraceMap.get(member);
+
+ if (umlElement != null) {
+ Property umlProperty = (Property) umlElement;
+
+ // TODO: We need to properly deal with "empty" values, e.g., {}
+ if(!(value.toString().equalsIgnoreCase("[]") ||
+ value.toString().equalsIgnoreCase("\"\""))) {
+
+ if(!isNumericPrimitiveType(umlProperty.getType()) ||
+ (isNumericPrimitiveType(umlProperty.getType()) && StringUtils.isNumeric(value.toString()))) {
+
+
+ if(umlProperty.getType() instanceof Enumeration && umlProperty.isMultivalued()) {
+ // remove brackets
+ value = value.toString().substring(1, value.toString().length() -1);
+ }
+ umlProperty.setDefault(value.toString());
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private static boolean isNumericPrimitiveType(Type type) {
+ boolean isNumeric = false;
+
+ if(type instanceof PrimitiveType) {
+ PrimitiveType primType = (PrimitiveType) type;
+
+ if(primType.getName().equalsIgnoreCase("long") || primType.getName().equalsIgnoreCase("int") ||
+ primType.getName().equalsIgnoreCase("double") || primType.getName().equalsIgnoreCase("float")) {
+ isNumeric = true;
+ }
+ }
+
+ return isNumeric;
+ }
+
+ /**
+ *
+ *
+ * @param umlElement
+ * @param valueExpression
+ * @return the UML value for a given Java expression.
+ */
+ private static Object getValueFromExpression(
+ /* Element umlElement, */Expression valueExpression) {
+ // TODO: their might still be cases that are not yet covered.
+ Object value = null;
+
+ // multi-valued expression
+ if (valueExpression.eClass().getClassifierID() == JavaPackage.ARRAY_INITIALIZER) {
+ ArrayInitializer arrayInitializer = (ArrayInitializer) valueExpression;
+ List<Object> values = new ArrayList<Object>();
+
+ for (Expression expression : arrayInitializer.getExpressions()) {
+
+ if (expression.eClass().getClassifierID() == JavaPackage.ANNOTATION) {
+ Annotation javaAnnotation = (Annotation) expression;
+
+ AnnotationTypeDeclaration annotationType = (AnnotationTypeDeclaration) javaAnnotation
+ .getType().getType();
+ value = annotationType.getName();
+ // Stereotype umlStereotype =
+ // this.getElementFromProfile(annotationType,
+ // Stereotype.class);
+ // if(umlStereotype != null && umlElement != null) {
+ //
+ // EClass stereotypeDefinition =
+ // this.getStereotypeDefinition(umlElement, umlStereotype);
+ // if(stereotypeDefinition != null) {
+ // EObject stereotypeInstance =
+ // EcoreUtil.create(stereotypeDefinition);
+ // this.setValues(javaAnnotation, umlElement,
+ // stereotypeInstance);
+ // values.add(stereotypeInstance);
+ //
+ // // stats
+ // this.reportStereotypeApplication(umlStereotype);
+ // notRecognizedAnnotationCounter--;
+ // }
+ // }
+ // else {
+ // System.out.println("... null value");
+ // }
+ }
+
+ if (expression.eClass().getClassifierID() == JavaPackage.SINGLE_VARIABLE_ACCESS) {
+ values
+ .add(getValueFromSingleVariableAccess((SingleVariableAccess) expression));
+ }
+
+ }
+ return values;
+ }
+
+ // EnumerationLiteral
+ else if (valueExpression.eClass().getClassifierID() == JavaPackage.SINGLE_VARIABLE_ACCESS) {
+ // SingleVariableAccess singleVariableAccess =
+ // (SingleVariableAccess) valueExpression;
+ value = getValueFromSingleVariableAccess((SingleVariableAccess) valueExpression);
+ }
+
+ else if (valueExpression.eClass().getClassifierID() == JavaPackage.TYPE_LITERAL) {
+ TypeLiteral typeLiteral = (TypeLiteral) valueExpression;
+
+ if (typeLiteral.getType().getType() instanceof TypeDeclaration) {
+ TypeDeclaration type = (TypeDeclaration) typeLiteral.getType()
+ .getType();
+ value = type.getName();
+ }
+
+ else if (typeLiteral.getType().getType() instanceof AnnotationTypeDeclaration) {
+ AnnotationTypeDeclaration annotationType = (AnnotationTypeDeclaration) typeLiteral
+ .getType().getType();
+ value = annotationType.getName();
+ } else if (typeLiteral.getType().getType().eClass().getClassifierID() == JavaPackage.PRIMITIVE_TYPE_VOID) {
+ value = "void.class";
+ }
+ }
+
+ else if (valueExpression.eClass().getClassifierID() == JavaPackage.ANNOTATION) {
+ Annotation javaAnnotation = (Annotation) valueExpression;
+
+ AbstractTypeDeclaration annotationType = (AbstractTypeDeclaration) javaAnnotation
+ .getType().getType();
+ value = annotationType.getName();
+ }
+
+ else if (valueExpression.eClass().getClassifierID() == JavaPackage.PREFIX_EXPRESSION) {
+ PrefixExpression prefix = (PrefixExpression) valueExpression;
+ value = prefix.getOperator().toString()
+ .concat(getValueFromExpression(prefix.getOperand()).toString());
+
+ }
+
+ // primitive literal
+ else {
+ if (valueExpression.eClass().getClassifierID() == JavaPackage.STRING_LITERAL) {
+ value = ((StringLiteral) valueExpression).getEscapedValue();
+ } else if (valueExpression.eClass().getClassifierID() == JavaPackage.CHARACTER_LITERAL) {
+ value = ((CharacterLiteral) valueExpression).getEscapedValue();
+ } else if (valueExpression.eClass().getClassifierID() == JavaPackage.BOOLEAN_LITERAL) {
+ value = ((BooleanLiteral) valueExpression).isValue();
+ } else if (valueExpression.eClass().getClassifierID() == JavaPackage.NUMBER_LITERAL) {
+ value = ((NumberLiteral) valueExpression).getTokenValue();
+ }
+ }
+
+ return value;
+ }
+
+ private static Object getValueFromSingleVariableAccess(
+ SingleVariableAccess valueExpression) {
+ if(valueExpression != null && valueExpression.getVariable() != null) {
+ return valueExpression.getVariable().getName();
+ }
+ else return "";
+
+ // Object value = null;
+ // // if the variable isn't a proxy, we should find it in the trace
+ // if(!valueExpression.getVariable().isProxy()) {
+ // //
+ // if(valueExpression.getVariable().eClass().getClassifierID() ==
+ // JavaPackage.VARIABLE_DECLARATION_FRAGMENT) {
+ // if(valueExpression.getVariable().getInitializer() != null) {
+ // value = getValueFromExpression(/*null,*/
+ // valueExpression.getVariable().getInitializer());
+ // }
+ // else {
+ // value = valueExpression.getVariable().getName();
+ // }
+ // }
+ //
+ // // else try to find the value in the trace map
+ // Object umlValue =
+ // codeModel2ProfileModeltraceMap.get(valueExpression.getVariable());
+ // value = umlValue;
+ // }
+ // else {
+ // // let's have a look in the profile
+ // // Element umlValue =
+ // this.getElementFromProfile(valueExpression.getVariable(),
+ // Element.class);
+ // // value = umlValue;
+ // value = valueExpression.getVariable().getName();
+ // }
+ //
+ // return value;
+ }
+
+ private static void initProfileModel2CodeModelTraceMap(IModel traceModel) {
+ // Trace t = (Trace) traceModel.getContents().get(0);
+ Set<? extends Object> traceLinks = traceModel
+ .getElementsByType(TracePackage.eINSTANCE.getTraceLink());
+ for (Object obj : traceLinks) {
+ TraceLink traceLink = (TraceLink) obj;
+
+ for (EObject eObj : traceLink.getTargetElements()) {
+ if (profileModel2CodeModeltraceMap.containsKey(eObj))
+ System.out.println("override!");
+ profileModel2CodeModeltraceMap.put(eObj, traceLink);
+ }
+ }
+ }
+
+ private static void initCodeModel2ProfileModelTraceMap(IModel traceModel) {
+ Set<? extends Object> traceLinks = traceModel
+ .getElementsByType(TracePackage.eINSTANCE.getTraceLink());
+ for (Object obj : traceLinks) {
+ TraceLink tl = (TraceLink) obj;
+
+ if (codeModel2ProfileModeltraceMap.containsKey(tl.getSourceElements()
+ .get(0))
+ && tl.getSourceElements().get(0).eClass().getClassifierID() == JavaPackage.ANNOTATION_TYPE_DECLARATION) {
+
+ if (tl.getTargetElements().get(0) instanceof Stereotype) {
+ codeModel2ProfileModeltraceMap.put(tl.getSourceElements().get(0), tl
+ .getTargetElements().get(0));
+ }
+ } else {
+ // TODO: we have to extend the trace map as we may get a list of
+ // targets in the future
+ codeModel2ProfileModeltraceMap.put(tl.getSourceElements().get(0), tl
+ .getTargetElements().get(0));
+ }
+ }
+ }
+
+}
diff --git a/proprietary/bundles/org.eclipse.upr.platform.java.cm2up/src/org/eclipse/upr/platform/java/cm2up/ResourceBasedCodeModel2UMLProfile.java b/proprietary/bundles/org.eclipse.upr.platform.java.cm2up/src/org/eclipse/upr/platform/java/cm2up/ResourceBasedCodeModel2UMLProfile.java
new file mode 100644
index 0000000..72c5417
--- /dev/null
+++ b/proprietary/bundles/org.eclipse.upr.platform.java.cm2up/src/org/eclipse/upr/platform/java/cm2up/ResourceBasedCodeModel2UMLProfile.java
@@ -0,0 +1,257 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Vienna University of Technology.
+ * 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:
+ * Alexander Bergmayr (Vienna University of Technology) - initial API and implementation
+ *
+ * Initially developed in the context of ARTIST EU project www.artist-project.eu
+ *******************************************************************************/
+package org.eclipse.upr.platform.java.cm2up;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.ecore.resource.ResourceSet;
+import org.eclipse.m2m.atl.common.ATLExecutionException;
+import org.eclipse.m2m.atl.core.ATLCoreException;
+import org.eclipse.m2m.atl.core.IExtractor;
+import org.eclipse.m2m.atl.core.IInjector;
+import org.eclipse.m2m.atl.core.IModel;
+import org.eclipse.m2m.atl.core.IReferenceModel;
+import org.eclipse.m2m.atl.core.ModelFactory;
+import org.eclipse.m2m.atl.core.emf.EMFExtractor;
+import org.eclipse.m2m.atl.core.emf.EMFInjector;
+import org.eclipse.m2m.atl.core.emf.EMFModel;
+import org.eclipse.m2m.atl.core.emf.EMFModelFactory;
+import org.eclipse.uml2.uml.Profile;
+import org.eclipse.uml2.uml.resources.util.UMLResourcesUtil;
+import org.eclipse.uml2.uml.util.UMLUtil;
+import org.eclipse.uml2.uml.util.UMLUtil.UML2EcoreConverter;
+import org.eclipse.upr.platform.java.jumpcfg.JConfigurationPackage;
+import org.eclipse.upr.platform.trace.TracePackage;
+
+/**
+ * @author Alexander Bergmayr
+ *
+ */
+public class ResourceBasedCodeModel2UMLProfile extends CodeModel2UMLProfile {
+
+ /**
+ *
+ */
+ private String umlProfilePath;
+
+ /**
+ *
+ */
+ private String traceModelPath;
+
+ /**
+ *
+ * @throws IOException
+ */
+ public ResourceBasedCodeModel2UMLProfile() throws IOException {
+ super();
+ // the Java metamodel needs to be registered because we directly inject
+ // a java resource produced by Modisco (Dynamic API vs. Metamodel API)
+ EPackage.Registry.INSTANCE.put(getMetamodelUri("JMM"), org.eclipse.gmt.modisco.java.emf.JavaPackage.eINSTANCE);
+ EPackage.Registry.INSTANCE.put(getMetamodelUri("TMM"), TracePackage.eINSTANCE);
+ EPackage.Registry.INSTANCE.put(getMetamodelUri("CFGMM"), JConfigurationPackage.eINSTANCE);
+ }
+
+ /**
+ * Loads the models required for the transformation. The <i>Code Model</i> is already
+ * a <code>Resource</code>, which means we can directly inject it.
+ *
+ * @param cmModelResource the <i>Code Model</i> of the Java application.
+ * @param jpModelPath the Java profile that contains UML steretypes for
+ * generic types and meta annotations.
+ * @param jptModelPath the UML model library for Java primitive types.
+ * @param mcModelPath the UML meta classes
+ * @param uptModelPath the UML model library for UML primitive types.
+ * @throws ATLCoreException
+ */
+ public void loadModels(Resource cmModelResource, Resource cfgModelResource, String jpModelPath, String jptModelPath, String mcModelPath,
+ String uptModelPath, String eptModelPath) throws ATLCoreException {
+ ModelFactory factory = new EMFModelFactory();
+
+
+ // metamodels
+ ResourceSet resourceSet = ((EMFModelFactory) factory).getResourceSet();
+ UMLResourcesUtil.init(resourceSet);
+
+ IInjector injector = new EMFInjector();
+ IReferenceModel jmmMetamodel = factory.newReferenceModel();
+ injector.inject(jmmMetamodel, getMetamodelUri("JMM"));
+ IReferenceModel umlmmMetamodel = factory.newReferenceModel();
+ injector.inject(umlmmMetamodel, getMetamodelUri("UMLMM"));
+ IReferenceModel tmmMetamodel = factory.newReferenceModel();
+ injector.inject(tmmMetamodel, getMetamodelUri("TMM"));
+ IReferenceModel cfgMetamodel = factory.newReferenceModel();
+ injector.inject(cfgMetamodel, getMetamodelUri("CFGMM"));
+
+ // in models
+ this.cmModel = factory.newModel(jmmMetamodel);
+ ((EMFInjector) injector).inject(cmModel, cmModelResource);
+ this.cfgModel = factory.newModel(cfgMetamodel);
+ ((EMFInjector) injector).inject(cfgModel, cfgModelResource);
+ this.jpModel = factory.newModel(umlmmMetamodel);
+ injector.inject(jpModel, jpModelPath);
+ this.jptModel = factory.newModel(umlmmMetamodel);
+ injector.inject(jptModel, jptModelPath);
+ this.mcModel = factory.newModel(umlmmMetamodel);
+ injector.inject(mcModel, mcModelPath);
+ this.uptModel = factory.newModel(umlmmMetamodel);
+ injector.inject(uptModel, uptModelPath);
+ this.eptModel = factory.newModel(umlmmMetamodel);
+ injector.inject(eptModel, eptModelPath);
+
+ // out models
+ this.upModel = factory.newModel(umlmmMetamodel);
+ this.tmModel = factory.newModel(tmmMetamodel);
+ }
+
+ /* (non-Javadoc)
+ * @see eu.artist.migration.mdt.umlprofilediscovery.codemodel2umlprofile.files.CodeModel2UMLProfile#saveModels(java.lang.String, java.lang.String)
+ */
+ @Override
+ public void saveModels(String upModelPath, String tmModelPath)
+ throws ATLCoreException {
+ // create the output models
+ super.saveModels(upModelPath, tmModelPath);
+ }
+
+ /**
+ *
+ * @throws ATLCoreException
+ */
+ public void saveModels() throws ATLCoreException {
+ saveModels(getUmlProfilePath(), getTraceModelPath());
+ }
+
+ /**
+ *
+ * @param upModelPath
+ * @throws ATLCoreException
+ */
+ public void saveUMLProfileModel(String upModelPath)
+ throws ATLCoreException {
+ IExtractor extractor = new EMFExtractor();
+ extractor.extract(upModel, upModelPath);
+
+ // add the profile to the local uml profile store
+ // UMLProfileStoreManager.INSTANCE.addProfile(((EMFModel) upModel).getResource());
+ }
+
+ /**
+ *
+ * @throws ATLCoreException
+ */
+ public void saveUMLProfileModel()
+ throws ATLCoreException {
+ IExtractor extractor = new EMFExtractor();
+ extractor.extract(upModel, getUmlProfilePath());
+ }
+
+ /**
+ *
+ * @param tmModelPath
+ * @throws ATLCoreException
+ */
+ public void saveTraceModel(String tmModelPath)
+ throws ATLCoreException {
+ IExtractor extractor = new EMFExtractor();
+ extractor.extract(tmModel, tmModelPath);
+ }
+
+ /**
+ *
+ * @throws ATLCoreException
+ */
+ public void saveTraceModel()
+ throws ATLCoreException {
+ IExtractor extractor = new EMFExtractor();
+ extractor.extract(tmModel, getTraceModelPath());
+ }
+
+ /* (non-Javadoc)
+ * @see eu.artist.migration.mdt.umlprofilediscovery.codemodel2umlprofile.files.CodeModel2UMLProfile#doCodeModel2UMLProfile(org.eclipse.core.runtime.IProgressMonitor)
+ */
+ @Override
+ public Object doCodeModel2UMLProfile(IProgressMonitor monitor)
+ throws ATLCoreException, IOException, ATLExecutionException {
+ Object result = super.doCodeModel2UMLProfile(monitor);
+
+ // create URIs for the generated models
+ URI umlProfileURI = URI.createURI(umlProfilePath);
+ URI traceModelURI = URI.createURI(traceModelPath);
+
+ // set URIs
+ ((EMFModel) upModel).getResource().setURI(umlProfileURI);
+ ((EMFModel) tmModel).getResource().setURI(traceModelURI);
+
+ // do post processing
+ CodeModel2UMLProfilePostProcessor.runPostProcessing(this.cmModel, this.upModel, this.tmModel);
+
+ // define profile
+ Profile profile = (Profile) ((EMFModel) upModel).getResource().getContents().get(0);
+
+ Map<String, String> options = new HashMap<String, String>();
+ options.put(UML2EcoreConverter.OPTION__INVARIANT_CONSTRAINTS, UMLUtil.OPTION__PROCESS);
+ profile.define(options, null, null);
+
+ return result;
+ }
+
+ /**
+ * @return the upModel
+ */
+ public IModel getUpModel() {
+ return this.upModel;
+ }
+
+ /**
+ * @return the tmModel
+ */
+ public IModel getTmModel() {
+ return this.tmModel;
+ }
+
+ /**
+ * @return the umlProfilePath
+ */
+ public String getUmlProfilePath() {
+ return umlProfilePath;
+ }
+
+ /**
+ * @param umlProfilePath the umlProfilePath to set
+ */
+ public void setUmlProfilePath(String umlProfilePath) {
+ this.umlProfilePath = umlProfilePath;
+ }
+
+ /**
+ * @return the traceModelPath
+ */
+ public String getTraceModelPath() {
+ return traceModelPath;
+ }
+
+ /**
+ * @param traceModelPath the traceModelPath to set
+ */
+ public void setTraceModelPath(String traceModelPath) {
+ this.traceModelPath = traceModelPath;
+ }
+
+}
diff --git a/proprietary/bundles/org.eclipse.upr.platform.java.cm2up/src/org/eclipse/upr/platform/java/cm2up/javaLibrary.atl b/proprietary/bundles/org.eclipse.upr.platform.java.cm2up/src/org/eclipse/upr/platform/java/cm2up/javaLibrary.atl
new file mode 100644
index 0000000..29e7a77
--- /dev/null
+++ b/proprietary/bundles/org.eclipse.upr.platform.java.cm2up/src/org/eclipse/upr/platform/java/cm2up/javaLibrary.atl
@@ -0,0 +1,329 @@
+--/*******************************************************************************
+-- * Copyright (c) 2015 Vienna University of Technology.
+-- * 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:
+-- * Alexander Bergmayr (TU Wien) - initial API and implementation
+-- * Manuel Wimmer (TU Wien) - initial API and implementation
+-- *
+-- * Initially developed in the context of ARTIST EU project www.artist-project.eu
+-- *******************************************************************************/
+
+-- @nsURI UMLMM=http://www.eclipse.org/uml2/3.0.0/UML
+-- @path JMM=pathmap://METAMODEL/java.ecore
+
+library javaLibrary;
+
+helper context JMM!TypeAccess def : getParameterizedType() : UMLMM!Type =
+ -- BUG: TODO : we need to deal with UnresolvedTypeDeclaration!
+-- if(self.oclIsTypeOf(JMM!UnresolvedTypeDeclaration)) then OclUndefined
+-- else
+ thisModule.resolveTemp(self.type, 't1');
+-- endif;
+
+--helper context JMM!TypeAccess def : containedByModelLibrary() : Boolean =
+-- UMLMM!Type.allInstancesFrom('ML') -> exists(e | e.name = self.type.name and e.refImmediateComposite().name = self.type.refImmediateComposite().name);
+
+-- checks if a type is complex
+helper context JMM!TypeAccess def : isComplexType() : Boolean =
+ if(self.isPrimitiveType() or self.type.oclIsTypeOf(JMM!EnumDeclaration)) then false
+ else
+ if(self.type.oclIsTypeOf(JMM!ArrayType)) then not self.type.isArrayWithNonComplexType
+ else
+ true
+ endif
+ endif;
+
+-- ckecks if a type is primitive ...
+helper context JMM!TypeAccess def : isPrimitiveType() : Boolean =
+ -- if we have a kind of PrimitiveType (int, float, bool, etc.)
+ if (self.type.oclIsKindOf(JMM!PrimitiveType)) then true
+ else
+ -- wrapped primitive types (e.g., ClassDeclaration of type String etc.)
+ if ((self.type.name = 'String') or (self.type.name = 'Integer')
+ or (self.type.name = 'Long') or (self.type.name = 'Short')
+ or (self.type.name = 'Float') or (self.type.name = 'Double')
+ or (self.type.name = 'Boolean') or (self.type.name = 'Number')) then true
+ else
+ -- finally, we have the case of Array's with primitive type
+ -- only in case it is an ArrayType, we check the type of the Array
+ if(not self.type.oclIsTypeOf(JMM!ArrayType)) then false
+ else
+ --if (self.type.elementType.isPrimitiveType() or self.type.elementType.type.oclIsTypeOf(JMM!EnumDeclaration)) then true
+ if(self.type.elementType.isPrimitiveType()) then true
+ else
+ false
+ endif
+ endif
+ endif
+ endif;
+
+helper context JMM!TypeAccess def : isParameterizedType : Boolean =
+ self.type.oclIsTypeOf(JMM!ParameterizedType) or self.type.isJavaLangClass();
+
+helper context OclAny def : isJavaLangClass : Boolean =
+ self.refImmediateComposite().getFullyQualifiedPackageName.toString().concat('.').concat(self.name).toString() = 'java.lang.Class' or
+ self.refImmediateComposite().getFullyQualifiedPackageName.toString().concat('.').concat(self.name).toString() = 'java.lang.Class[]';
+
+helper context JMM!ArrayType def : isArrayWithNonComplexType : Boolean =
+ if (self.elementType.isPrimitiveType() or self.elementType.type.oclIsTypeOf(JMM!EnumDeclaration)) then true
+ else false
+ endif;
+
+-- TODO: here we could also use a Map
+-- returns the type for a given type access; required to determine on the return type of
+-- a method in the annotation type declaration
+helper context JMM!TypeAccess def : getType() : UMLMM!Type =
+ -- PrimitiveType, String
+ if self.isPrimitiveType() then self.type.getTypeFromPrimitiveType
+ else
+ -- Class / Parameterized Class (can only be java.lang.Class)
+ if (self.type.oclIsTypeOf(JMM!ClassDeclaration) or self.type.oclIsTypeOf(JMM!ParameterizedType)) then self.type.getTypeFromTypeDeclaration
+ else
+ -- EnumType
+ if self.type.oclIsTypeOf(JMM!EnumDeclaration) then self.type.getTypeFromEnumDeclaration()
+ else
+ -- AnnotationType
+ if self.type.oclIsTypeOf(JMM!AnnotationTypeDeclaration) then self.type.getTypeFromAnnotationTypeDeclaration()
+ else
+ -- ArrayType
+ if self.type.oclIsTypeOf(JMM!ArrayType) then self.type.getTypeFromArrayType
+
+ -- UnresolvedType
+ else thisModule.resolveTemp(self.type, 't1')
+ endif
+ endif
+ endif
+ endif
+ endif;
+
+-- return for a given Java
+-- we should use here Java Primitive Types ... ????
+helper context JMM!Type def : getTypeFromPrimitiveType : UMLMM!Type =
+ thisModule.javaPrimitiveType.get(self.name.toString());
+
+-- can only be java.lang.Class
+helper context OclAny def : getTypeFromTypeDeclaration : UMLMM!Type =
+ UMLMM!Class.allInstancesFrom('MC') -> any(e | e.name = 'Class');
+
+-- return for a given Java parameterized Class the appropriate UML Class
+helper context JMM!ParameterizedType def : getTypeFromParameterizedType() : UMLMM!Class =
+ UMLMM!Class.allInstancesFrom('MC') -> any(e | e.name = 'Class');
+
+-- return for a given Java Enum Type the appropriate UML instance of this Enum Type
+helper context JMM!EnumDeclaration def : getTypeFromEnumDeclaration() : UMLMM!Enumeration =
+ thisModule.resolveTemp(self, 't1');
+
+-- return for a given Java Annotation Type the appropriate UML instance of this
+helper context JMM!AnnotationTypeDeclaration def : getTypeFromAnnotationTypeDeclaration() : UMLMM!Stereotype =
+ thisModule.resolveTemp(self, 't1');
+
+-- return for a given Java Annotation Type the appropriate UML instance of this
+helper context JMM!UnresolvedTypeDeclaration def : getTypeFromUnresolvedTypeDeclaration() : UMLMM!Class =
+ thisModule.resolveTemp(self, 't1');
+
+-- return for a given Java ArrayType the appropriate UML Type ... here deal only with
+-- complex types and enumerations
+helper context JMM!ArrayType def : getTypeFromArrayType : UMLMM!Type =
+ if(self.elementType.type.oclIsTypeOf(JMM!ClassDeclaration) or
+ self.elementType.type.oclIsTypeOf(JMM!InterfaceDeclaration)) then
+ self.elementType.type.getTypeFromTypeDeclaration
+ else
+ if(self.elementType.type.oclIsTypeOf(JMM!ParameterizedType)) then
+ self.elementType.type.getTypeFromParameterizedType()
+ else
+ if(self.elementType.type.oclIsTypeOf(JMM!EnumDeclaration)) then
+ self.elementType.type.getTypeFromEnumDeclaration()
+ else
+ if(self.elementType.type.oclIsTypeOf(JMM!AnnotationTypeDeclaration)) then
+ self.elementType.type.getTypeFromAnnotationTypeDeclaration()
+ else
+ if(self.elementType.type.oclIsTypeOf(JMM!UnresolvedTypeDeclaration)) then
+ self.elementType.type.getTypeFromUnresolvedTypeDeclaration()
+ else
+ -- TODO: check ... but should actually not happen ;)
+ OclUndefined
+ endif
+ endif
+ endif
+ endif
+ endif;
+
+-- decide if a class or interface is required for the annotation type declaration
+--helper context JMM!Type def : isRequiredForAnnotationTypes : Boolean =
+-- if (JMM!AnnotationTypeMemberDeclaration.allInstances() ->
+-- select(e | e.type.type.oclIsTypeOf(JMM!ParameterizedType)) -> exists(f | f.type.type.typeArguments -> exists(g | g.type.name = s1.name)) or
+--
+--
+-- )
+
+-- get fully qualified package name of a java type
+helper context OclAny def : getFullyQualifiedPackageName : String =
+ if(self.refImmediateComposite().oclIsTypeOf(JMM!Package)) then
+ self.refImmediateComposite().getFullyQualifiedPackageName.concat('.').concat(self.name)
+ else
+ self.name
+ endif;
+
+-- get Java package
+helper context OclAny def : getJavaPackage() : JMM!Package =
+ if(not self.package.oclIsUndefined()) then
+ self.package
+ else
+ self.refImmediateComposite().getPackage()
+ endif;
+
+-- get the package of a PackageableElement
+helper context UMLMM!PackageableElement def : getPackage() : UMLMM!Package =
+ if(self.refImmediateComposite().oclIsTypeOf(UMLMM!Package)) then
+ self.refImmediateComposite()
+ else
+ self.refImmediateComposite().getPackage()
+ endif;
+
+-- only those code elements that are relevant element types / return values of annotation type declarations
+helper context OclAny def : isRelevantForAnnotationTypes : Boolean =
+ -- maybe the name matching here can be dangerous ...
+ if(self.oclIsKindOf(JMM!Type)) then
+ if ((self.oclIsTypeOf(JMM!AnnotationTypeDeclaration) and self.proxy = false)) or
+
+ (thisModule.getAnnotationTypeMemberDeclarations -> select(e | not e.type.oclIsUndefined())
+ -> exists(e | e.type.type = self) or
+
+ (thisModule.getAnnotationTypeMemberDeclarations -> select(e | not e.type.oclIsUndefined())
+ -> select(e | e.type.type.oclIsTypeOf(JMM!ArrayType)))
+ -> exists(e | e.type.type.elementType.type = self) or
+
+ self.hasInnerAnnotationTypeDeclaration()
+
+ ) then true
+ else false endif
+ else false
+ endif;
+
+-- we want to have only packages that serve as container for annotation type declarations
+helper context JMM!Package def : isAnnotationTypeContainer : Boolean =
+ if self.ownedElements -> exists(e | e.isRelevantForAnnotationTypes) or
+ self.ownedPackages -> exists(e | e.isAnnotationTypeContainer) then true
+ else false
+ endif;
+
+helper context JMM!Type def : hasInnerAnnotationTypeDeclaration() : Boolean =
+ if(self.bodyDeclarations -> exists(e | e.oclIsTypeOf(JMM!AnnotationTypeDeclaration)) or
+ self.bodyDeclarations -> select(e | e.oclIsKindOf(JMM!Type)) -> exists(f | f.hasInnerAnnotationTypeDeclaration())
+ ) then true
+ else false
+ endif;
+
+helper context OclAny def : isEnumerationRelevant : Boolean =
+ -- must be an EnumerationType
+ if(not self.oclIsTypeOf(JMM!EnumDeclaration)) then false
+ else
+
+ -- the Enumeration is the type of an AnnotationTypeMemberDeclaration
+ thisModule.getAnnotationTypeMemberDeclarations -> select(e | not e.type.oclIsUndefined()) ->
+ exists(e | e.type.type = self) or
+
+ -- the Enumeration is the element type of an Array which is the type of an AnnotationTypeMemberDeclaration
+ thisModule.getAnnotationTypeMemberDeclarations -> select(e | not e.type.oclIsUndefined()) ->
+ select(e | e.type.type.oclIsTypeOf(JMM!ArrayType)) ->
+ exists(f | f.type.type.elementType.type = self) or
+
+ -- the Enumeration is the parameter of java.lang.Class which is the type of an AnnotationTypeMemberDeclaration
+ thisModule.getAnnotationTypeMemberDeclarations -> select(e | not e.type.oclIsUndefined()) ->
+ select(e | e.type.type.oclIsTypeOf(JMM!ParameterizedType)) ->
+ exists(f | f.type.type.typeArguments -> exists(g | g.type = self))
+
+ endif;
+
+-- required because the structure of the model differs depending on multi-valued vs. single-valued SingleVariableAccess elements
+helper context JMM!SingleVariableAccess def : isMultiValuedAnnotationTarget : Boolean =
+ if self.refImmediateComposite().refImmediateComposite().refImmediateComposite().oclIsTypeOf(JMM!Annotation) then
+ self.refImmediateComposite().refImmediateComposite().refImmediateComposite().type.type.name = 'Target'
+ else false
+ endif;
+
+-- required because the structure of the model differs depending on multi-valued vs. single-valued SingleVariableAccess elements
+helper context JMM!SingleVariableAccess def : isSingleValuedAnnotationTarget : Boolean =
+ if self.refImmediateComposite().refImmediateComposite().oclIsTypeOf(JMM!Annotation) then
+ self.refImmediateComposite().refImmediateComposite().type.type.name = 'Target'
+ else false
+ endif;
+
+-- mapping between java element type targets and UML targets, i.e., the extended UML element
+helper def : umlTarget : Map(String, Sequence(UMLMM!Element)) =
+ Map{
+ ('ANNOTATION_TYPE', Sequence{UMLMM!Type.allInstances() -> select(e | e.name = 'Stereotype').first()}),
+ -- TODO: add constraint
+ ('CONSTRUCTOR', Sequence{UMLMM!Type.allInstances() -> select(e | e.name = 'Operation').first()}),
+ -- maybe we could think also to annotate the association on a model level ... however
+ -- for this prototype we do not consider associations at all .. so it is sufficient to
+ -- have here Property only.
+ ('FIELD', Sequence{UMLMM!Type.allInstances() -> select(e | e.name = 'Property').first(),
+ UMLMM!Type.allInstances() -> select(e | e.name = 'EnumerationLiteral').first()--,
+-- UMLMM!Type.allInstances() -> select(e | e.name = 'Association').first()
+ }),
+ ('LOCAL_VARIABLE', Sequence{UMLMM!Type.allInstances() -> select(e | e.name = 'Property').first()--,
+ -- UMLMM!Type.allInstances() -> select(e | e.name = 'Association').first()
+ }),
+ ('METHOD', Sequence{UMLMM!Type.allInstances() -> select(e | e.name = 'Operation').first(),
+ UMLMM!Type.allInstances() -> select(e | e.name = 'Property').first()
+ }),
+ ('PACKAGE', Sequence{UMLMM!Type.allInstances() -> select(e | e.name = 'Package').first()}),
+ ('PARAMETER', Sequence{UMLMM!Type.allInstances() -> select(e | e.name = 'Parameter').first()}),
+ -- adaptation required ... Java Type --> Class, Interface, AnnotationType, Enumeration
+ -- TODO: add constraint!!
+ -- Idea: less explicit stereotypes in the profile
+ ('TYPE', Sequence{UMLMM!Type.allInstances() -> select(e | e.name = 'Type').first()})};
+
+-- ensure the use of java primitive types
+helper def : javaPrimitiveType : Map(String, UMLMM!Element) = Map{('boolean', UMLMM!Type.allInstancesFrom('JPT') -> select(e | e.name = 'boolean').first()),
+ ('byte', UMLMM!Type.allInstancesFrom('JPT') -> select(e | e.name = 'byte').first()),
+ ('char', UMLMM!Type.allInstancesFrom('JPT') -> select(e | e.name = 'char').first()),
+ ('double', UMLMM!Type.allInstancesFrom('JPT') -> select(e | e.name = 'double').first()),
+ ('float', UMLMM!Type.allInstancesFrom('JPT') -> select(e | e.name = 'float').first()),
+ ('int', UMLMM!Type.allInstancesFrom('JPT') -> select(e | e.name = 'int').first()),
+ ('integer', UMLMM!Type.allInstancesFrom('JPT') -> select(e | e.name = 'int').first()),
+ ('long', UMLMM!Type.allInstancesFrom('JPT') -> select(e | e.name = 'long').first()),
+ ('short', UMLMM!Type.allInstancesFrom('JPT') -> select(e | e.name = 'short').first()),
+ -- first letter is capital
+ ('Boolean', UMLMM!Type.allInstancesFrom('JPT') -> select(e | e.name = 'boolean').first()),
+ ('Byte', UMLMM!Type.allInstancesFrom('JPT') -> select(e | e.name = 'byte').first()),
+ ('Char', UMLMM!Type.allInstancesFrom('JPT') -> select(e | e.name = 'char').first()),
+ ('Double', UMLMM!Type.allInstancesFrom('JPT') -> select(e | e.name = 'double').first()),
+ ('Float', UMLMM!Type.allInstancesFrom('JPT') -> select(e | e.name = 'float').first()),
+ ('Int', UMLMM!Type.allInstancesFrom('JPT') -> select(e | e.name = 'int').first()),
+ ('Integer', UMLMM!Type.allInstancesFrom('JPT') -> select(e | e.name = 'int').first()),
+ ('Long', UMLMM!Type.allInstancesFrom('JPT') -> select(e | e.name = 'long').first()),
+ ('Short', UMLMM!Type.allInstancesFrom('JPT') -> select(e | e.name = 'short').first()),
+ -- TODO: maybe we should have here also a Java STRING
+ ('String', UMLMM!Type.allInstancesFrom('UPT') -> select(e | e.name = 'String').first()),
+ -- the array version ...
+ ('boolean[]', UMLMM!Type.allInstancesFrom('JPT') -> select(e | e.name = 'boolean').first()),
+ ('byte[]', UMLMM!Type.allInstancesFrom('JPT') -> select(e | e.name = 'byte').first()),
+ ('char[]', UMLMM!Type.allInstancesFrom('JPT') -> select(e | e.name = 'char').first()),
+ ('double[]', UMLMM!Type.allInstancesFrom('JPT') -> select(e | e.name = 'double').first()),
+ ('float[]', UMLMM!Type.allInstancesFrom('JPT') -> select(e | e.name = 'float').first()),
+ ('int[]', UMLMM!Type.allInstancesFrom('JPT') -> select(e | e.name = 'int').first()),
+ ('long[]', UMLMM!Type.allInstancesFrom('JPT') -> select(e | e.name = 'long').first()),
+ ('short[]', UMLMM!Type.allInstancesFrom('JPT') -> select(e | e.name = 'short').first()),
+ -- TODO: maybe we should have here also a Java STRING
+ ('java.lang.String[]', UMLMM!Type.allInstancesFrom('UPT') -> select(e | e.name = 'String').first())};
+
+-- get package even though types are declared inside types
+helper context JMM!AbstractTypeDeclaration def : getPackage() : JMM!Package =
+ if(not self.package.oclIsUndefined()) then self.package
+ -- assumption: the type is declared inside another type
+ else self.refImmediateComposite().getPackage()
+ endif;
+
+
+
+
+
+
+
+
diff --git a/proprietary/bundles/org.eclipse.upr.platform.java.cm2up/src/org/eclipse/upr/platform/java/cm2up/profileLibrary.atl b/proprietary/bundles/org.eclipse.upr.platform.java.cm2up/src/org/eclipse/upr/platform/java/cm2up/profileLibrary.atl
new file mode 100644
index 0000000..563101e
--- /dev/null
+++ b/proprietary/bundles/org.eclipse.upr.platform.java.cm2up/src/org/eclipse/upr/platform/java/cm2up/profileLibrary.atl
@@ -0,0 +1,51 @@
+--/*******************************************************************************
+-- * Copyright (c) 2015 Vienna University of Technology.
+-- * 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:
+-- * Alexander Bergmayr (Vienna University of Technology) - initial API and implementation
+-- * Manuel Wimmer (Vienna University of Technology) - initial API and implementation
+-- *
+-- * Initially developed in the context of ARTIST EU project www.artist-project.eu
+-- *******************************************************************************/
+
+-- @nsURI UMLMM=http://www.eclipse.org/uml2/3.0.0/UML
+
+library profileLibrary;
+
+helper context UMLMM!Element def: setTaggedValue(stereotype : OclAny, propertyName : String, newValue : OclAny ) : OclAny =
+if (not newValue.oclIsUndefined())
+ then
+ if (not thisModule.isMultiValued(newValue)) -- if single-valued
+ then
+ if (not thisModule.isComplexType(propertyName))
+ then
+ -- CASE 1: single-valued && simple
+ self.setValue(stereotype, propertyName, newValue)
+ else
+ -- CASE 2: single-valued && complex
+ self.setValue(stereotype, propertyName, thisModule.resolveTemp(newValue, 'y').getStereotypeApplications().asSequence().first())
+ endif
+ else -- if multi-valued
+ if (not thisModule.isComplexType(propertyName))
+ then
+ -- CASE 3: multi-valued && simple
+ self.setValue(stereotype, propertyName, newValue)
+ else
+ -- CASE 4: multi-valued && complex
+ self.setValue(stereotype, propertyName, newValue -> collect(c | thisModule.resolveTemp(c, 'y').getStereotypeApplications().asSequence().first()))
+ endif
+ endif
+ else OclUndefined
+endif;
+
+helper def : isMultiValued(attr : OclAny) : Boolean =
+ attr.oclIsKindOf(Collection(OclAny))
+;
+
+helper def : isComplexType(taggedValueName : String) : Boolean =
+ UMLMM!Property.allInstances() -> any(e|e.name = taggedValueName).type.oclIsTypeOf(UMLMM!Stereotype)
+;
diff --git a/proprietary/bundles/org.eclipse.upr.platform.java.cm2up/src/org/eclipse/upr/platform/java/cm2up/util/CodeModel2UMLProfileUtil.java b/proprietary/bundles/org.eclipse.upr.platform.java.cm2up/src/org/eclipse/upr/platform/java/cm2up/util/CodeModel2UMLProfileUtil.java
new file mode 100644
index 0000000..a9ee82d
--- /dev/null
+++ b/proprietary/bundles/org.eclipse.upr.platform.java.cm2up/src/org/eclipse/upr/platform/java/cm2up/util/CodeModel2UMLProfileUtil.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Vienna University of Technology.
+ * 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:
+ * Alexander Bergmayr (Vienna University of Technology) - initial API and implementation
+ *
+ * Initially developed in the context of ARTIST EU project www.artist-project.eu
+ *******************************************************************************/
+
+package org.eclipse.upr.platform.java.cm2up.util;
+
+public class CodeModel2UMLProfileUtil {
+
+ /** default input for the UML profile discovery transformation */
+ public static final String JP_Model_Path = "pathmap://JAVA_PROFILE/javaProfile.uml";
+ public static final String JPT_Model_Path = "pathmap://UML_LIBRARIES/JavaPrimitiveTypes.library.uml";
+ public static final String MC_Model_Path = "pathmap://UML_METAMODELS/UML.metamodel.uml";
+ public static final String UPT_Model_Path = "pathmap://UML_LIBRARIES/UMLPrimitiveTypes.library.uml";
+ public static final String EPT_Model_Path = "pathmap://UML_LIBRARIES/EcorePrimitiveTypes.library.uml";
+ public static final String UML_PROFILE_PATH_SEGMENT = "_profile.profile.uml";
+ public static final String TRACE_PATH_SEGMENT = "_profile.trace.xmi";
+
+}

Back to the top