Table of Contents

Module: xmi ./src/peak/storage/xmi.py

Base classes for storing/retrieving model objects via XMI format

Because the XMI 1.x specs are incredibly confusing and self-contradictory, it's necessary for us to clarify our interpretations of the specs and what restrictions we are placing upon our implementation goals.

Our intended uses of XMI are as follows:

  1. Processing of UML models saved by commonly-available design tools

  2. Code generation from MOF metamodels for modelling languages such as UML and CWM, which are supplied in XMI format by the OMG and other standards bodies.

  3. Use as a metadata-driven persistence and import/export format for PEAK applications. (The idea being that a readable format that doesn't require custom coding would make it easy to experiment with domain model designs, and to create test suites and test data for domain logic verification before the "final" storage machinery is built.)

Usage 1 only requires reading of XMI 1.0 and 1.1 features needed by UML models, and is effectively complete now. Usage 2 requires support for reading XMI.any and CORBA typecodes. Usage 3 requires that we be able to write XMI files - and any version would suffice. However, if we support both 1.0 and 1.1 format for writing XMI, then we could support doing automated transforms of UML content, generation of UML or other constructs from code or database schemas, etc. So ideally, we should be able to write both 1.0 and 1.1.

XMI 2.0 looks very promising from the perspective of future tool support, but unfortunately it will not help us with any usage but #3. It may also need a somewhat differently structured implementation. So for now we will mostly ignore XMI 2.0. However, 2.0 introduces the idea of using tagged values on a metamodel to specify implementation details such as variations in tag or attribute names, etc., that would be useful to have for our intended applications. So, where applicable, we will represent these tagged values as PEAK configuration properties of the form org.omg.xmi.* corresponding to the official XMI tag names for those configuration options.

Within the XMI 1.x series, we will not support the XMI.TypeDefinitions block and its contents. Survey of existing XMI files suggests this is not used in practice, and it was removed as of the XMI 1.2 spec. Unfortunately, we do have to support the XMI.Corba* tags, as they are used by metamodels (such as UML and CWM) that are defined based on MOF 1.3 or earlier. (MOF 1.4 and up abandon Corba typecodes as a basis for metamodel definition; unfortunately, few systems of interest to us are presently based on the MOF 1.4 metametamodel.)

In any case, the XMI.TypeDefinitions block is only used when encoding datatypes that are not part of the metamodel for the data being encoded. For PEAK applications, all such type definitions should be part of the model, and this is true for common UML usage as well.

TODO

Write Algorithm
  • needs to know composition link direction (needs peak.model support)

  • Element state will contain a reference to pseudo-DOM node, if available. Elements are saved by modifying node in-place. Sub-elements are saved using their node, if the node's parent is the containing element's node. If the sub-element has no node, save the sub-element (creating a node), and point its node's parent to the current element's node.

  • If the sub-element's node's parent is not the current element's node, create an xmi.idref node linking to the sub-element node.

  • New elements, and non-persistent objects simply create a "fresh" node for use by the containing element. Elements keep a reference to this new node, so that potential containers can tell if they've seen it.

  • We only care about keeping XMI.Extension tags contained directly in an element, in the top-level object list (XMI.content), and in the XMI.Extensions block. If a node is modified, its extension tags may be moved to the end of the modified node's children.

  • Generate new ID's as UUIDs, and place in both UUID and ID fields; need to standardize on a __uuid__ or similar field in elements so that elements that need/want a UUID to map over to/from another data system can do so.

  • Format transforms can be supported via DM.thunk(); it should be possible to copy an entire model from one DM to another in this way, and thus switch between XMI 1.0 and 1.1 (or other) storage formats.

  • For thunking to be effective, XMI.extensions must be sharable, and therefore immutable -- so we need an XMI extension/text class.

  • XMIDocument should become persistent, and use a second-order DM to load/save it. Modifying XMINode instances should flag the XMIDocument as changed. We can then implement a transactional file-based DM that can load and save the XMIDocument itself.

  • XMIDocument needs to know its version or select a strategy object to handle node updates for a particular XMI version.

  • Need to research ignorableWhitespace et al to ensure that we can write cleanly indented files but with same semantics as originals.

XMI 1.2
XMI 1.2 is mostly a simplification and clarification of XMI 1.1:
  • Encoding of multi-valued attributes; note that it is not permissible to have a value for a feature both in an object tag's attribute and in the object's contained tags.

  • "Nested packages may result in name collision; a namespace prefix is required in this case." Need to review EBNF, and "Namespace Qualified XML Element Names". This may require metadata support on the writing side.

XMI 2.0
  • Requires full URI-based namespace handling; maybe we should go ahead and add this to current implementation? Note that this means all the xmi.* tag and attribute names are now xmi: instead.

  • Further note on namespace handling: it sounds as though XML attribute names for the target model are unqualified, and indeed that element names can be so as well.

  • Top-level element may not be the XMI tag; if a document represents a single object and doesn't want to include the XMI documentation, it can simply add an xmi:version attribute to the outermost tag representing the serialized object.

  • Compositions are less regular: instead of nesting object tags inside an attribute tag, the attribute and object tags can be combined. The tag name is the attribute name, and a new xmi:type attribute indicates the type of the object. If omitted, the type of the object is assumed to be the type specified by the composite reference.

  • Although xmi:id is the normal ID attribute, it can be specified via a tagged value as being different. It isn't clear how this would work if there were multiple ID attributes per XMI file.

Other
  • metamodel lookups

  • cross-reference between files could be supported by having document objects able to supply a relative or absolute reference to another document. But this requires HREF support. :( Note that cross-file HREF needs some way to cache the other documents and an associated DM, if it's to be dynamic.

Imported modules   
from peak.api import *
from peak.model.api import TCKind, SimpleTC, Boolean, TypeCode
from peak.persistence import Persistent
from peak.util import SOX
from types import StringTypes
from weakref import WeakValueDictionary
from xml.sax import saxutils
Functions   
fromFile
  fromFile 
fromFile (
        filename_or_stream,
        parentComponent,
        **kw,
        )

Classes   

DM

XMIDocument

XMINode


Table of Contents

This document was automatically generated on Mon Jan 23 01:11:05 2023 by HappyDoc version 2.1