Repository navigation
XmiElementCache
XmiElementCache (interface IXmiElementCache, namespace uml4net) is the registry of every XmiElement that has been read, across all the documents of one read operation. It has one job: to let a reference — an xmi:idref, an href, an xmi:uuid pointer — be turned into the object it refers to. The Assembler is its main consumer; the generated readers are its main producer.
There is one cache per IXmiReader. It is created by the reader's dependency-injection scope (XmiReaderScope), handed to every generated IXmiElementReader and to the Assembler, and cleared when the reader is disposed.
Elements are stored under their FullyQualifiedIdentifier, {DocumentName}#{XmiId}:
| Element read from | Key |
|---|---|
Class with xmi:id="_c" in the file Model.xmi
|
Model.xmi#_c |
PrimitiveType Boolean reached through href="http://www.omg.org/spec/UML/20131001/PrimitiveTypes.xmi#Boolean"
|
http://www.omg.org/spec/UML/20131001/PrimitiveTypes.xmi#Boolean |
Class reached through href="../lib/types.xmi#T"
|
../lib/types.xmi#T |
The document part is the href as written in the referencing document, not the path the file was eventually loaded from. That is what makes the key of the element and the key derived from the reference identical, whatever LocalReferenceBasePath or the referencing document's location the ExternalReferenceResolver used to find the file.
xmi:id is optional (XMI 2.5.1 clause 7.6.1). An element without one cannot be referenced, but its own references, hrefs and extensions still have to be processed, so TryAdd stores it under a synthetic key {DocumentName}#<anonymous:n> that cannot clash with an xmi:id. It is enumerated and assembled like any other element.
TryAdd returns false when the key is already present; the element that was read first stays in the cache and is the one that references resolve to. The generated readers log an error with the element and line position in that case. It is deliberately not rejected, even in strict mode: the normative UML.xmi itself contains the xmi:id State-isConsistentWith twice.
TryGetValue(key, out element) looks the key up as-is. When that fails and the fragment of the key has the XPointer uuid form defined by XMI 2.5.1 clause 7.10.2,
Co.xmi#xpointer((//*[@xmi:uuid='DCE:emp-3'])[1])
the element is looked up in a secondary index by {DocumentName}#{XmiGuid}. TryAdd fills that index with the first element of a document that carries a given xmi:uuid, which is what the [1] of the XPointer selects. XmiElementCache.TryParseXPointerUuid exposes the parsing of the fragment (single or double quotes are accepted; other XPointer schemes, [2], or xmi:label are not).
An element without xmi:id but with an xmi:uuid is therefore still reachable — by uuid.
The cache is also enumerable (Keys, Values, Count, GetEnumerator), which the Assembler and the ExternalReferenceResolver use to walk every element that has been read.
AddExtender(xmiElement, extender) and TryGetExtenders(xmiElement, out extenders) associate arbitrary objects with an element. This is used by the extension mechanism: an xmi:Extension that a registered extender reader understands (for example the Enterprise Architect extension) produces objects that are attached to the extended element without becoming part of the UML model.
AddStereoTypeApplication(xmiElement, stereoTypeApplication) and TryGetStereoTypeApplications(xmiElement, out stereoTypeApplications) register the stereotype applications of a document with the element they extend, once they are resolved. The extension methods QueryStereoTypeApplications() and QueryStereoTypeApplication(name) on an element read them through its Cache; see Profiles and StereoTypes.
-
Generated readers call
TryAddfor every element as soon as its identity attributes are read, before its children — so that a child can refer back to its owner. -
ExternalReferenceResolverwalks the cache to collect every recordedhrefand load the documents they point to. - Assembler walks the cache to resolve every recorded identifier.
-
Derived-property emulation of
allInstances():Class::extensionandVertex::incoming/outgoingare defined in the metamodel over all instances of a metaclass; uml4net emulatesallInstances()over every element of the read: the elements in the cache, which holds the document and the external documents it references, together with the containment trees of those elements, so that elements created in code are included as well. -
XmiReaderResult: after reading, the elements of the document that was read and of the external documents are all in the cache;QueryRootElement<T>(xmiId)resolves through it.
- The cache is not thread-safe.
-
Clear()empties everything, including the uuid index and the extenders, and resets the anonymous-key counter.XmiReaderclears it when disposed; a reader instance is meant to be used for one read. - Building a model in code does not require a cache;
Cacheon such elements isnull, and the queries that emulateallInstances()fall back to walking the containment tree.
- XmiElement — the identity properties that make up the key
- Assembler — resolves references through the cache
-
uml4net.xmi project — external references and the
ExternalReferenceResolver
copyright @ Starion Group S.A.
- Home
- uml4net Tools
- Code Generation Tutorial
- Primitive Types Mapping
- Profiles and StereoTypes
- Code Generation Conventions
- UML Handlebars Helpers
- Generating uml4net
- Developers Experience
- SBOM
- Design Decisions