Login | Register
My pages Projects Community openCollabNet

argouml
Wiki: DiagramPersistence

Edit this page | Links to this page | Page information | Attachments | Refresh page

 

Diagram Persistence

The save and load of diagrams and the !Figs that they contain can be difficult to figure out from the code because it uses Java's reflection API, hiding the dependencies among components.

See the ?PersistenceSubsystem page for an overview of the subsystem as a whole and the PGML page for a description of the file format used for diagrams.

Components

  • DiagramMemberFilePersister - Java class which controls the overall save/load process.

  • PGML.tee - Template for writing a PGML file. Processed by OclExpander.

  • PGML.dtd - DTD describing the PGML format. Probably unchanged since it was created by Adobe in 1998.
  • OclExpander - GEF class which takes a template (!PGML.tee in this case) and expands (evaluates) the embedded pseudo-OCL expressions. These expressions are typically of the form <ocl>self.fig</ocl> which will cause the getFig() method to be called for the current fig and the result place into the output in place of the expression.

  • !PGMLStackParser - The XML parser which parses a PGML file.

Saving a Diagram

DiagramMemberFilePersister passes the PGML.tee template file to OclExpander and starts it evaluating at the diagram which is being saved.

Loading a Diagram

?DiagramMemberFilePersister uses the ArgoUML-specific PGMLStackParser (which extends the GEF class of the same name) to parse a PGML file and the memory resident diagram and associated figs.

All diagrams and figs are created using Java's reflection API with the target classname stored directly in the PGML file. The one exception to this is a small translation table which is maintained for backward compatibility with classes that have been removed from ArgoUML. This translation table maps old class names to their replacements and must be updated any time a class name is changed (including moving it between packages).

Templates

The source should be checked for the definitive truth, but to help give some substance to the discussion here, some example templates are given.

Diagram Template

   1  <template class="org.tigris.gef.base.Diagram">
   2 
   3  <![CDATA[
   4  <?xml version="1.0" encoding="UTF-8" ?>
   5  <!DOCTYPE pgml SYSTEM "pgml.dtd">
   6 
   7  <pgml description="<ocl>self.classAndModelID</ocl>"
   8       name="<ocl>self.name</ocl>"
   9  >
  10   <private>ItemUID="<ocl ignoreNull>self.ItemUID</ocl>"</private>
  11   <ocl>self.layer.contents</ocl>
  12  </pgml>
  13 
  14  ]]>
  15 
  16  </template>

The template above represents the entire PGML document from XML declaration [line #4] to the closing </pgml> tag [line #12]. It will cause Diagram.getClassAndModelID() [7], Diagram.getName() [8] and Diagram.getItemUID [10] to be called and then it will use Diagram.getLayer().getContents() [11] to get the set of top-level Figs in the Diagram and will recursively process them in the same manner.

FigNodeModelElement Template

   1 <template class="org.argouml.uml.diagram.ui.FigNodeModelElement">
   2 
   3 <![CDATA[
   4 <group name="<ocl>org.argouml.persistence.PgmlUtility.getId(self)</ocl>"
   5      description="<ocl>self.classNameAndBounds</ocl>"
   6      href="<ocl ignoreNull>org.argouml.uml.UUIDHelper.getUUID(self)</ocl>"
   7      FILL_AND_STROKE
   8 >
   9 
  10   <private>
  11     ItemUID="<ocl ignoreNull>self.ItemUID</ocl>"
  12     enclosingFig="<ocl ignoreNull>org.argouml.persistence.PgmlUtility.getEnclosingId(self)</ocl>"
  13   </private>
  14 
  15   <ocl>self.figs</ocl>
  16 </group>
  17 ]]>
  18 
  19 </template>

DiagramPersistence (last edited 2008-12-29 21:11:22 -0800 by ?tfmorris)