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:
Processing of UML models saved by commonly-available design tools
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.
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
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
|
|
|
|