Persistence Tricks

From DaVinci

Below follows an email conversation with Peter & Lutz regarding persistence tricks and deep copy implementations

Peter & Lutz, The questions below are related to resources, object copying and persistence.

  • In a callback function for a plug-in you have a handle to an object of AObject(which is derived from EObject), which can be used to traverse the model and retrieve port information etc. I would like to make a copy of the entire model,leave the original as it is, work and make modifications on the copied model and ultimately either save it under a new file name or possibly replace (if so requested by the user) the original model. That way the user could compare the before and after models. Does this make sense?
  • I believe you sent out directions to use the 'EcoreUtil' functionality in order to perform a 'deep' copy of an model. As far as I understand, I don't see how one can easily make a deep copy of an model without manually makeing sure that the inter-object references are maintained in the new model, i.e. associate individual objects to each other. I see the EcoreUtil.Copier and EcoreUtil.ContentTreeIterator classes, but it seems that the actual copy and copyAll methods are working on either collections of EObjects or individual objects. Is there something I am missing? Is there a simple way of making an in-memory clone of a model given an AObject root reference?
  • Is there any way to retrieve the corresponding resource (file information or reference) to an AObject? I know that OsateResourceManager contains the resource set, but I was curious if it was possible to retrieve the resource in a callback method only getting in a AObject reference. If I get the file information for an object, I figured that I could use that to parse up another model into memory, which should be equivalent to the model passed into the osate plug-in callback function.Does this sound totally backwards?
  • After I have managed to clone a model and run some algorithms, I'd like to save it to file (aaxl and aadl). I think I know how to go about this, but just as a check; I'd need to save the new model to a resource and add it to the OsateResourceManager, right? Then the new model will be shown in the osate gui next to the original model, right?

Thanks, Harry

Hi Harry,

if I remember correctly the EcoreUtil copy operation maintains references as follws: referenes to objects being copied are to the copied objects. references to objects in part that are not copied are to the original. I vaguely remember that I had at some point a small problem with the copier doing the references right - you might want to do a test.

If you are trying to copy a model that is completely stored in a file you can do that through resources - as you indicate yourself. This is easy as well. Any Eobject has a method that returns the resource it is contained in (eResource). A quick and dirty way of getting a complete copy is to get a new resource for a different file name (OsateResoruceManager.getEmptyResource(newuri)); add the root object of your model to its content ( aobj.getRoot() and store it a res.getContents().add(root)). You then do a save OsateResourceManager.save(res). Finally, you do a reload of this resource which causes a separate copy of the model to be created in memory (OsateResoruceManager.reload(res)). An alternative is to change the the URI on the orginal resource, do a save, change the URI back to the original for this resource, and then do a OsateResoruceManager.getResource(newuri). Again we get a copy of the model.

Finally, if you do not want to clutter the OsateResourceSet that is used by the editors and analysis tools - it is maintained by OsateResoruceMaanger - you can create your own instance of that resource set and just do a getResource on that resourceset using the URI of the original resource aobj.eResource().getURI().

To get rid of the copy when doing it through the resource is to unload the resource as call on the resource itself). In case of your own resource set you then can delete the resoruce set; in the OSM case there is a removeResource function that does an unload and removes the resource object from the Osate maintained resoruce set.

Peter

Harry,

to create a deep copy you get the root object, which is of class AadlSpec, and call EcorUtil.copy(root). This will copy the object and, recursively, all objects that are contained. As a result you get a deep copy. References are handled as follows.

  • If the referenced object has been copied, the reference points to the copy.
  • If the referenced object has not been copied the reference will point to this object, unless it's a bidirectional reference. Bidirectional references will be dropped.

So the only place where you could run into trouble is with bidirectional references that are between objects in different resources. This can, for example, occur if you have a type in one package and implementations in other packages/specs. We also use bidirectional references in in connection with modes, but I don't know if the objects can be in different files. There may be other places where we use bidirectional references, I didn't check the complete metamodel.

The problem here is that it is non-obvious what it means to copy a model because a model can be split in multiple files. One could argue that a model consists of one AADL specification together with all directly and indirectly references packages. That means that you need to copy those packages also if the transformation changes them.

- Lutz