Notice: This Wiki is now read only and edits are no longer possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.
Difference between revisions of "Papyrus-RT/Developer/Design/0.9/UML-RT-Implementation"
(A word about Model Explorer integration) |
(→UML Extensions) |
||
Line 40: | Line 40: | ||
The extension elements are stored in a special resource maintained in the resource set, called the ''extension extent''. This resource, therefore, indirectly contains any "virtual elements" that are these implicit members or other model content. It also maintains an adapter on every element contained within it that, when some concrete change is made to it (thus effecting an incremental redefinition of some inherited element), ''reifies'' the object by moving it and any stereotype applications it may have into the user model (in the appropriate containment reference, of course). | The extension elements are stored in a special resource maintained in the resource set, called the ''extension extent''. This resource, therefore, indirectly contains any "virtual elements" that are these implicit members or other model content. It also maintains an adapter on every element contained within it that, when some concrete change is made to it (thus effecting an incremental redefinition of some inherited element), ''reifies'' the object by moving it and any stereotype applications it may have into the user model (in the appropriate containment reference, of course). | ||
+ | |||
+ | Extensions thus far are used only to define containment references for the distinct "shadow" elements representing the local view of an element inherited by some namespace. These typically are named <code>implicitXyz</code> (e.g., implicitPort) and are added to the <code>Namespace::ownedMember</code> superset as a non-standard subset, for access via the Eclipse UML2 UML API. They are in addition to queries such as <code>Namespace::inheritedMember()</code> and further supersets such as <code>Namespace::member</code> which account for inheritance by presenting the same definitions of elements in the supertype. | ||
+ | |||
+ | Extensions are not used for inheritable containment references such as <code>MultiplicityElement::lowerValue</code> and <code>Connector::end</code>. These are handled by customized setting/list implementations (<code>InheritableSetting</code> and <code>InheritableEList</code>, respectively) that take care of presenting "shadows" of inherited elements in the unset state and automatically reifying the contained elements when they are modified to effect redefinition. By implementing this inheritance in the unset state, the serialization of a model is assured never to contain an element in such a reference unless it is a redefinition. And, as these are not typically <code>RedefinableElement</code>s according to the UML metamodel, their traceability to the elements that they redefine is implied by the reference in which they are contained (e.g., lower or upper value of a multiplicity element) and position (in case of a reference collection). Furthermore, in the case of an inheritable reference collection such as <code>Connector::end</code> or <code>Operation::ownedParameter</code>, if any element is redefined and thus requires it to be persisted (making the containment reference "set" as compared to "unset"), then all elements in the collection are persisted and are, effectively, redefinitions of the inherited elements. This is unavoidable owing to the significance of ordering in these collections. | ||
== Façade API == | == Façade API == |
Revision as of 11:40, 2 January 2017
Contents
UML-RT Semantics in Eclipse UML
This document describes the implementation of UML-RT semantics in Papyrus as a customization of the Eclipse UML2 implementation of UML.
Most of the APIs and other code described herein are implemented in a new bundle org.eclipse.papyrusrt.umlrt.uml
. Critically, this bundle is designed (and required) to operate in a "pure Java" context, that is, without the Eclipse or any OSGi run-time running. Changes in other bundles are required to integrate these into Papyrus-RT; those will be called out in the text below.
Development of this feature is tracked in bug 467545, with attendant git branches, Gerrit patches, and blocking/related bugs. Builds of the feature branch are produced here. Use caution when trying these builds! Do not use them on models that you care about without adequate backup. There are bugs, particularly in undo/redo, which usually is intended to provide a safeguard.
Demonstrative videos are posted from time to time on YouTube:
- First prototype of incremental redefinition
- Brief addendum to the above
- First prototype of Capsule Structure Diagram inheritance
- Incremental refinement distinguishing view inheritance from semantic inheritance
- First prototype of exclusion of inherited elements in capsule structure diagrams
- Minor improvements in inheritance iconography
- Connector inheritance in the diagram
- Tweaks for inheritance in Model Explorer
- Selective tracking of corresponding views in superclass structure diagram
Incremental Redefinition
The key concept in UML-RT that distinguishes it, besides the profile, from UML is the notion of incremental redefinition. This recognizes that a redefining element can leave some of its attributes unset so that they shall be interpreted as being inherited from the redefined element. This is accomplished by means of subclasses of the UML2 implementation classes for the various redefinable elements. These implement an internal interface InternalUMLRTElement
that defines various operations for inheriting values of unset features from the redefined element, setting the redefined element, and more. The custom implementation classes use these common internal APIs to override the basic UML features inherited from Eclipse UML2.
These custom implementation classes also override the methods implementing standard UML well-formedness constraints to account for UML-RT requirements, especially for type compatibility in protocols, connector ends, etc.
Stand-alone Configuration
For configuration of a ResourceSet
to work with UML-RT models, a static utility class UMLRTResourcesUtil
is provided as an analogue to UMLResourcesUtil
from the UML2 API (the former actually uses the latter for core UML set-up). The init(ResourceSet)
API performs all of the registrations required to install the UML-RT support described in this document in a resource set.
UML Extensions
When a generalization relationship is established between capsules or protocols, or a redefinition relationship between state machines, then inheritance of elements is activated that is managed in part by extensions to the UML metamodel. These essentially are structural features of model elements that are stored in separate companion objects (extensions) made accessible through the elements, themselves. So, in a sense they are like features that may be added to metaclasses by package merge, only there is no actual merge; but in practice they are much more like stereotypes, except that they are more deeply integrated into the elements by way of the custom implementation classes.
The extensions are modelled as a metamodel umlext
with metaclasses that mirror the extended metaclasses in name and generalization relationships. One important use case for the extensions is to store implicit redefinitions of inherited elements for the cases where they are neither excluded nor configured differently in any attribute as compared to the inherited element. These implicit redefinitions are stored in extension attributes as depicted in the diagram below. The implementation classes, for example ClassImpl
, are instrumented to forward access to these features via Ecore reflection to the extension object. This makes it possible, for example, to extend the ownedMember
superset in the ClassImpl
to include the implicitAttribute
and implicitConnector
properties. This ripples to other derived unions such as ownedElement
.
The extension elements are stored in a special resource maintained in the resource set, called the extension extent. This resource, therefore, indirectly contains any "virtual elements" that are these implicit members or other model content. It also maintains an adapter on every element contained within it that, when some concrete change is made to it (thus effecting an incremental redefinition of some inherited element), reifies the object by moving it and any stereotype applications it may have into the user model (in the appropriate containment reference, of course).
Extensions thus far are used only to define containment references for the distinct "shadow" elements representing the local view of an element inherited by some namespace. These typically are named implicitXyz
(e.g., implicitPort) and are added to the Namespace::ownedMember
superset as a non-standard subset, for access via the Eclipse UML2 UML API. They are in addition to queries such as Namespace::inheritedMember()
and further supersets such as Namespace::member
which account for inheritance by presenting the same definitions of elements in the supertype.
Extensions are not used for inheritable containment references such as MultiplicityElement::lowerValue
and Connector::end
. These are handled by customized setting/list implementations (InheritableSetting
and InheritableEList
, respectively) that take care of presenting "shadows" of inherited elements in the unset state and automatically reifying the contained elements when they are modified to effect redefinition. By implementing this inheritance in the unset state, the serialization of a model is assured never to contain an element in such a reference unless it is a redefinition. And, as these are not typically RedefinableElement
s according to the UML metamodel, their traceability to the elements that they redefine is implied by the reference in which they are contained (e.g., lower or upper value of a multiplicity element) and position (in case of a reference collection). Furthermore, in the case of an inheritable reference collection such as Connector::end
or Operation::ownedParameter
, if any element is redefined and thus requires it to be persisted (making the containment reference "set" as compared to "unset"), then all elements in the collection are persisted and are, effectively, redefinitions of the inherited elements. This is unavoidable owing to the significance of ordering in these collections.
Façade API
The org.eclipse.papyrusrt.umlrt.uml
package contains a suite of classes that provide a façade API exposing the UML-RT model structure in a friendly way, primarily targeted to extenders but also used by the Papyrus-RT UI, especially the Properties View. Instances of the façade classes correspond one-to-one with the core element of the UML representation of each UML-RT concept; this association is maintained by means of an EMF Adapter
attached to the UML element.
This adapter provides the necessary coördination of the façade structure with the UML model as the latter changes with the user's edits and also maintains the UML extensions of model elements, including virtual redefinitions where necessary, amongst potentially other content.
The initial prototype of the façade API consists of these classes:
-
UMLRTModel
— corresponds to aResource
in the editor'sModelSet
-
UMLRTPackage
— corresponds to aPackage
, including the rootModel
, that is not a«protocolContainer»
package -
UMLRTCapsule
— corresponds to aClass
stereotyped as«capsule»
-
UMLRTPort
— corresponds to aPort
stereotyped as«rtPort»
-
UMLRTCapsulePart
— properties of a capsule stereotyped as«capsulePart»
-
UMLRTConnector
— aConnector
in a capsule that is stereotyped as«rtConnector»
-
UMLRTProtocol
— aCollaboration
stereotyped as«protocol»
. For each protocol façade there is a corresponding conjugate that follows the naming convention and presents its messages as being of the conjugate direction kind. The conjugate protocol façade is the type of a conjugate port façade -
UMLRTProtocolMessage
— anOperation
of in/out/inout direction as determined by the«rtMessageSet»
Interface
that defines it. The parameters of a message are exposed as the UML API because a façade would provide no significant value
The façades provide direct access to and modification of the most important properties of their UML-RT concepts. For example, names of elements, types of ports (as UMLRTProtocol
s), etc. The UMLRTCapsule
maintains a single list of UMLRTPort
s that synthesizes regular owned ports, redefining ports, virtual redefining ports (from the UML extension), and excluded ports. Other details can be obtained from the corresponding UML model element, which each façade object provides via a toUML()
operation. Notification of changes is not supported; this must be done at the UML level.
The UMLRT
prefix is applied to these façade class names to distinguish them clearly from the similarly named Java interfaces in the UML-RT Profile, e.g. Capsule
, Protocol
, CapsulePart
, RTPort
. Although it is not strictly necessary (the names are distinguished by their package namespace, anyways), it is convenient for readability of code to see at a glance that it is working in UML-RT terms, not UML terms, especially in sophisticated Papyrus-RT plug-ins and derived DSMLs that mix both APIs together.
Integration in Papyrus-RT
The UMLRTLanguage
class in the org.eclipse.papyrusrt.umlrt.core
bundle that plugs into the ILanguageService
uses the UMLRTResourcesUtil
to install the UML-RT implementation of the UML metamodel in place of the Eclipse UML2 UML implementation in the ModelSet
-local package registry. It also bootstraps the UML-RT façade API on the model with its listeners that react to structural changes to keep the UML-RT semantics up-to-date and hooks into the TransactionalEditingDomain
to ensure that undo/redo transactions do not interfere with the reification of virtual redefinition elements.
The org.eclipse.papyrusrt.umlrt.tooling.modelexplorer
bundle adds a new EMF Facet customization model, Structure.custom
, that enhances the Model Explorer presentation to show virtual redefinitions in the UML extension features of their namespaces. This is done by means of a generic GetExtensionFeatureQuery
facet-query that takes an extension feature (an EStructuralFeature
from the UML Extension metamodel) and retrieves its value from the context object, if that object is one from the UML-RT implementation that supports extension.
Capsule Structure Diagram Inheritance
For the visualization of inherited features in the Capsule Structure Diagrams, I have decided not to use the synchronization framework (org.eclipse.papyrus.infra.sync
) introduced in the Papyrus Mars release. Prototyping work with this framework showed that it is simply too unwieldy, prone to failure of undo/redo, and that it is in large part obviated by work done in bug 467545 on an implementation of UML-RT semantics in the UML metamodel. So, inheritance in the diagrams is implemented by means of a coördination of GEF edit policies:
- Canonical Edit Policy: the Papyrus-RT visual children strategy uses the UML-RT façade API to find and return inherited elements
- Inheritance Edit Policy: (NEW) manages three aspects of inherited elements:
- tracking of the visuals of the inherited elements from the capsule structure diagram in which they are defined
- transience (non-persistence) of the views of inherited elements
- reification of redefining elements when their presentation is customized in the inheriting diagram
- Applied Stereotype Comment Edit Policy: specialized in Papyrus-RT to omit the comment view for inherited elements
Properties View
The Papyrus-RT contributions to the Properties View are to a large extent built on the façade API, via JFace Data Bindings observable properties tailored to the façades. The org.eclipse.papyrusrt.umlrt.tooling.ui.databinding.facade
has a suite of factory classes providing IFacadeProperty
instances that are specialized implementations of observable data-binding properties for the façades:
-
CapsuleProperties
: observable list properties for ports, capsule-parts, and connectors -
ProtocolProperties
: observable list properties for each direction-kind of protocol messages -
NamedElementProperties
: observable value property for the name
The observable lists for containment references provided by these properties support the usual Papyrus UML observable list behaviours, with an extra for inherited elements:
- addition of new elements
- destruction of removed elements, if exclusion does not apply
- attempts to remove inherited or redefining elements are re-directed to exclusion, which preserves the element in the list but as an excluded element
These observables are used by a new FacadeModelElement
in the properties view context to provide appropriate UI bindings for a customized multiple reference editor, the InheritableMultipleReferenceEditor
. This adds buttons to the list controls for re-inheriting excluded or redefined elements and for filtering the presentation of excluded elements (by default, they are not shown). The FacadeModelElement
provides full support for protocol properties via the façade API, obviating the need for the delegation pattern of observables and other details to model-elements for the message-set interfaces in the UMLRTExtModelElement. This latter class is now simplified by the removal of capsule and protocol concerns.
The properties view context/XWT contributions for capsules and protocols are updated to use the FacadeModelElement
for their names, ports/parts (of capsules), and protocol messages. Likewise the creation dialog XWT descriptions for capsules and protocols that request only the name in certain UI workflows.
Model Explorer
Inherited elements in capsule (ports, parts, connectors) and protocols (messages) are presented via EMF Facets with reference queries implemented on the Façade API. By default, purely inherited elements are not shown (they are shown in the Properties View), but they can be enabled by an additional facet override in the customization dialog (the UML-RT Structure Inheritance customization). Excluded elements and redefinitions are always shown, with appropriate decorations.
The children of different dispositions are shown in a definite order:
- Capsule
- inherited RT ports — if shown, per above, either by redefinition/exclusion or customization to include inherited elements
- inherited capsule-parts
- inherited RT connectors
- locally-defined RT ports — root definitions initially defined by the capsule
- locally-defined capsule-parts
- locally-defined RT connectors
- other ports (non-RT, if applicable)
- other attributes (that are not capsule-parts)
- other connectors (non-RT, if applicable)
- Protocol
- inherited outgoing messages — if shown, per above, either by redefinition/exclusion or customization to include inherited elements. This ordering matches what was presented in the Properties View since the 0.7.x releases
- inherited incoming messages
- inherited in/out messages
- locally-defined outgoing messages — root definitions initially defined by the protocol
- locally-defined incoming messages
- locally-defined in/out messages
- (there is no provision in UML-RT for operations that are not protocol messages)