Simply put I have the following EMF model:
Step
ForkStep
extends Step
Now there is a bi-directional reference between the successor
and its predecessor
- No problem so far.
The tricky part is: How to create a bi-directional reference from alternateSuccessor
to its super-class predecessor
?
Normally each step can only have one predecessor and one successor. But a fork may have two successors (successor
and alternateSuccessor
).
If I now go on and create a bi-directional reference, EMF generates a new attribute in the super class, which seems not quite right?
Your question can be understood in two ways:
You need a single class Step
where you introduce a property isForkStep
.
The value of this property will be derived using OCL as follows: successor->size() > 1
.
First, I created the meta-model (called the file My.ecore
) according to your example. I had to add a Scenario
class acting as a container for steps.
The meta-model looks as follows:
Then, I opened the My.ecore
file using "OCLinEcore editor" and added the OCL code to the isForkStep
property.
package test : test = 'test'
{
class Scenario {
property steps : Step[*] { ordered composes };
}
class Step {
attribute stepId : String { id };
attribute isForkStep : Boolean {
derivation: successor->size() > 1;
}
property predecessor#successor : Step[?];
property successor#predecessor : Step[*] { ordered };
}
}
Then, I tested my new meta-model by creating a "dynamic instance" from Scenario
where I created 4 steps. Here is a screenshot from that shows the Scenario
instance together with 4 steps. As you can see in the "Properties" view, Step 1
has the property "Is Fork Step" set to true
(by clicking to the other steps, you would see false
).
Here, I modeled the situation differently. I created an interface Step
and two implementation classes - DefaultStep
and ForkStep
.
Then, I added different OCL constraints to both classes.
successor->size() <= 1
successor->size() >= 2
Note: I might also use successor->size() >= 2 or successor->size() = 0
to allow ForkSteps without successors.
The meta-model looks like this:
There are many other ways how this can be implemented. For example, you can use Java instead of OCL, or you can model the situation differently.
Btw. a nice slideshow about OCL in EMF can be found here: http://www.slideshare.net/EdWillink/enriching-withocl