javaoopocl

How can I add OCL restriction to the class variable?


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?


Solution

  • 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.