I'm implementing a Composite design pattern to which a need to add OCL restriction. This is a snippet of a code I'm using.
public abstract class ComplexTerritory implements ITerritory {
private List<ITerritory> territories = new ArrayList<ITerritory>();
private Double surfaceArea;
private String name;
public ComplexTerritory(String name, Double surfaceArea) {
this.name = name;
this.surfaceArea = surfaceArea;
}
...
public Double getSurfaceArea() {
Double sArea = 0.0d;
for (ITerritory ter : territories) {
sArea += ter.getSurfaceArea();
}
return sArea;
}
}
public class City extends ComplexTerritory {
public City(String name, Double surfaceArea) {
super(name, surfaceArea);
}
}
The OCL restriction is regards to the total surface area. When you call getSurfaceArea()
the result of the calculation should match the value that is stored as surfaceArea
. How can I do this using OCL? This is what I have come up with, but I'm doubtful that I can use local variable from a method in OCL.
context ComplexTerritory::getSurfaceArea(): Real
post: self.surfaceArea = sArea
The other idea I had is, that maybe I can iterate over the List using the OCL, something like this:
context ComplexTerritory::getSurfaceArea(): Real
def: let area : Real = 0.0
self.territories -> iterate(ter: ITerritory | area = area + ter.getSurfaceArea())
pre: self.surfaceArea = area
Also, should OCL be used on my abstract class ComplexTerritory
or on City
class?
In the absence of a metamodel, what you ask is a bit crazy. Assuming you have a metamodel with a ComplexTerritory::surfaceArea property you could complement your Java model with the Complete OCL snippet:
context ComplexTerritory::getSurfaceArea(): Real
post: result = surfaceArea
But as already observed it is unclear why you use getSurfaceArea().
Your Java seems fairly free form so I suspect that your OCL will be no more than documentation. Even if you used OCLinEcore to auto-generate your Java code, you would still find that the postcondition was just documentation. (Eclipse OCL only checks the syntax of pre and postconditions).
If you coded
context ComplexTerritory::surfaceArea : Real
def: territories.surfaceArea->sum()
as an OCLinEcore property, the Java would be synthesized.