Friday, 22 March 2013

A visitor pattern for EMF model instances


When working with model instances the visitor pattern is a convenient way to separate operations from the object structure. Not only once did I implement my own visitor implementation, before I learned what EMF has already in store. Combining the generated model switch with EMF’s TreeIterator is a powerful tool to navigate through your model and perform operations upon it. Let’s look at a simple example:

CarModelSwitch<Object> carVisitor = new CarModelSwitch<Object>() { 
   public Object caseCar(Car car) {
     System.out.println("Visiting car: " + car.getBrand());
  }
   public Object caseBody(Body body) {
     repair(body);
     return Boolean.TRUE;
   }
   public Object caseEngine(Engine engine) {
     repair(engine);
     return Boolean.TRUE;
   }

   public Object caseWheel(Wheel wheel) {
     checkTirePreasure(wheel);
     return Boolean.TRUE;
   }
};

The visitor is implemented as an anonymous CarModelSwitch class. The generated model switch class provides case methods for each type defined in our car model. The base implementations of the case methods do nothing but to return a null value. Our carVisitor now selectivley overrides case methods for all car elements and performs element specific operations upon them. Note that all case methods return Boolean.TRUE to prevent the switch from steping up the inheritance hierachy of each element. Let’s assume our car elements would all extend CarElement the corresponding case method caseCarElement would only be called for Body, Engine and Car types if previously case invocations return null.

Now we could call carVisitor.doSwitch(carelementOrCar) to perform specific case operation. To navigate through the whole content of a car model a TreeIterator can be used. The following code snippet retrieves the all content of a car model through EcoreUtil’s method getAllContent and calls for each model element the doSwitch method of the above visitor implementation.
for(TreeIterator<EObject> iterator = EcoreUtil.getAllContents(carModel);  iterator.hasNext();) {
     EObject modelElement = iterator.next();
     carvisitor.doSwitch(modelElement);
}

1 comment:

  1. Respect and that i have a neat proposal: Whole House Reno hgtv home remodel

    ReplyDelete