UML2 is an EMF-based implementation of the Unified Modeling Language (UML) 2.x OMG metamodel for the Eclipse platform.
See CONTRIBUTING.md for details.
An EMF-based implementation of the UML 2.x metamodel for the Eclipse platform.
License: Eclipse Public License 2.0
UML2 is an EMF-based implementation of the Unified Modeling Language (UML) 2.x OMG metamodel for the Eclipse platform.
See CONTRIBUTING.md for details.
Hey,
I cannot get redefined operations to work and need some help.
What I have:
I have an UML (meta)model. It looks like this.
package Model
{
// isAbstract: true
class baseClass
{
// isAbstract: false
// isQuery: true
operation opA : String {
body: 'base'
}
}
// isAbstract: false
class secondClass : baseClass
{
// redefines: baseClass::opA
operation opA : String {
body: 'second'
}
}
}
After that, I create an Ecore genmodel based on that UML model. And generate the Model code. (all done in the latest release of Eclipse)
However, the "ModelPackage.java" contains errors due to duplicated code.
[...]
/**
* The operation id for the '<em>Op A</em>' operation.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
* @ordered
*/
int SECOND_CLASS___OP_A = ModelPackage.BASE_CLASS___OP_A;
/**
* The operation id for the '<em>Op A</em>' operation.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
* @ordered
*/
int SECOND_CLASS___OP_A = ModelPackage.BASE_CLASS_OPERATION_COUNT + 0;
[...]
Furthermore, with every code generation, the 2nd block is added over and over again.
Debugging lead me to 2 places:
I traced it to the following Jet template: org.eclipse.emf.codegen.ecore.templates.model.PackageClass.javajet
[...]
<%for (GenOperation genOperation : genClass.getAllGenOperations(false)) {%>
<%if (genClass.getOverrideGenOperation(genOperation) == null) {%>
/**
* The operation id for the '<em><%=genOperation.getFormattedName()%></em>' operation.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
* @ordered
*/
<%=publicStaticFinalFlag%>int <%=genClass.getOperationID(genOperation, false)%> = <%=genClass.getOperationValue(genOperation)%>;
<%}%>
<%}%>
[...]
Looking at the Jet template and debugging the code, method isOverrideOf of the GenOperation is important. It is called in org.eclipse.emf.codegen.ecore.genmodel.impl.GenClassImpl::getOverideGenOperation:
[...]
public GenOperation getOverrideGenOperation(GenOperation genOperation)
{
List<GenOperation> allGenOperations = getAllGenOperations(false);
int index = allGenOperations.indexOf(genOperation);
if (index != -1)
{
for (int i = allGenOperations.size() - 1; i > index; --i)
{
GenOperation otherGenOperation = allGenOperations.get(i);
if (otherGenOperation.isOverrideOf(this, genOperation))
{
return otherGenOperation;
}
}
}
return null;
}
[...]
GenOperation::isOverrideOf is where it becomes tricky. There are 2 implementations:
for 1, there is an actual implementation. It matches it by name, parameter count, parameter name and parameter type.
for 2, the method simply returns false. Always. No checks. Just false.
Issue seems to be: when a genmodel is based on an UML model, then the UML2 implementation of GenOperation is used.
This leads to always returning false in isOverrideOf.
This leads to always returning null in getOverrideGenOperation
This leads to the duplicated / not necessary code to generate in the Jet template, because baseClass:OpA as well as secondClass::OpA are both generated for secondClass.
Thus, redefined operations always create duplicated and non-compiling code in the xxxPackage.java file.
Also, in the actual class file, the OpA operation is not annotated with "override" at all. Just like it doesn't know it is overriding / redefining something...
... because it doesn't know when using the UML2 implementation.
Looking at the Ecore model the genmodel creates, the secondClass::OpA contains an "redefines" annotation with the correct baseClass:OpA target.
Am I missing something?
Is there an annotation or something I have to set for this to resolve?
Or is the implementation of isOverrideOf the culpit?
Some reference types are redefined with annotations in the UML2 metamodel.
This is the case, for instance, in the DurationConstraint concept for the specification reference we can find the duplicates annotation that gives us the actual expected type:
<eClassifiers xsi:type="ecore:EClass" name="DurationConstraint" eSuperTypes="#//IntervalConstraint">
<eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
<details key="documentation" value="A DurationConstraint is a Constraint that refers to a DurationInterval.
<p>From package UML::Values.</p>"/>
</eAnnotations>
<eAnnotations source="duplicates">
<eAnnotations source="specification">
<details key="eType" value="uml::DurationInterval"/>
</eAnnotations>
<contents xsi:type="ecore:EReference" name="specification" ordered="false" lowerBound="1"
eType="#//ValueSpecification" containment="true">
<eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
<details key="documentation" value="The DurationInterval constraining the duration.
<p>From package UML::Values.</p>"/>
</eAnnotations>
<eAnnotations source="redefines" references="#//IntervalConstraint/%duplicates%/specification #//Constraint/specification"/>
</contents>
</eAnnotations>
[...]
</eClassifiers>
As far as DestroyLinkAction is concerned the endData reference only accepts the LinkEndDestructionData instance but we cannot find the same pattern of annotation to specify this type redefinition:
<eClassifiers xsi:type="ecore:EClass" name="DestroyLinkAction" eSuperTypes="#//WriteLinkAction">
<eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
<details key="documentation" value="A DestroyLinkAction is a WriteLinkAction that destroys links (including link objects).
<p>From package UML::Actions.</p>"/>
</eAnnotations>
<eAnnotations source="duplicates">
<contents xsi:type="ecore:EReference" name="endData" ordered="false" lowerBound="2"
upperBound="-1" eType="#//LinkEndDestructionData" containment="true">
<eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
<details key="documentation" value="The LinkEndData that the values of the Association ends for the links to be destroyed.
<p>From package UML::Actions.</p>"/>
</eAnnotations>
<eAnnotations source="redefines" references="#//LinkAction/endData"/>
</contents>
</eAnnotations>
</eClassifiers>
We would expect to find an annotation such as inside DestroyLinkAction:
<eAnnotations source="endData">
<details key="eType" value="uml::LinkEndDestructionData"/>
</eAnnotations>
Is there a different way to express type redefinition or is the redefinition missing?
Thanks
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.