blob: a384075588ec91e98da8ebf1f066029388b68281 [file] [log] [blame]
/*
* Copyright (c) 2005, 2010 Borland Software Corporation and others
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Artem Tikhomirov (Borland) - initial API and implementation
*/
@EmfaticAnnotationMap(
constraints="http://www.eclipse.org/gmf/2005/constraints",
constraintsMeta="http://www.eclipse.org/gmf/2005/constraints/meta")
@constraints("import"="http://www.eclipse.org/gmf/runtime/1.0.0/notation")
@namespace(uri="http://www.eclipse.org/gmf/2008/mappings", prefix="gmfmap")
package mappings;
import "platform:/resource/org.eclipse.gmf.graphdef/models/gmfgraph.ecore";
import "platform:/resource/org.eclipse.gmf.tooldef/models/tooldef.ecore";
@constraints(
ocl="nodes->forAll(n|n.containmentFeature.oclIsUndefined() and not n.child.domainMetaElement.oclIsUndefined() implies links->exists(let r:ecore::EReference= linkMetaFeature.oclAsType(ecore::EReference) in r.containment and r.eReferenceType.isSuperTypeOf(n.child.domainMetaElement)))",
description="Phantom nodes that are not targeted by a link mapping representing containment reference present in the model"
)
class Mapping {
!resolve val TopNodeReference[*] nodes;
!resolve val LinkMapping[*] links;
!resolve val CanvasMapping[1] diagram; // [1] ? 0..1?
val tooldef.StyleSelector[*] appearanceStyles;
val AuditContainer audits;
val MetricContainer metrics;
}
abstract class MappingEntry {
ref ecore.EClass[?] domainMetaElement;
// TODO inheriting getDomainContext from containmentFeature(as it was done) makes no sense for nodes provided containmentFeature is not part of MappingEntry. When node could be referenced from different parentNodes (with each having different containmentFeature) , it's just impossible to find out which containmentFeature is in use
@genmodel(documentation="This method simplifies OCL expressions (makes it easy to write for both Node and Link).")
op ecore.EClass getDomainContext();
@genmodel(documentation="Specializes further the domain meta element EClass associated with this mapping and should be evaluated in this EClass context")
@constraintsMeta(def="context", ocl="self.getDomainContext()")
@constraints(ocl="not domainSpecialization.oclIsUndefined() implies not domainMetaElement.oclIsUndefined()", description="Using 'Domain Specialization' requires 'Domain Meta Element' to be set")
val Constraint domainSpecialization;
@genmodel(documentation="Initializer for the domain model element associated with mapping")
@constraints(ocl="not domainInitializer.oclIsUndefined() implies not domainMetaElement.oclIsUndefined()", description="'Domain Element' must be set in mapping with 'Element Initializers'")
val ElementInitializer domainInitializer;
val LabelMapping[*]#mapEntry labelMappings;
@genmodel(documentation="Diagrams that may be associated with this diagram element. It's up to client application to define what this association means (e.g. open diagram)")
// @constaints(ocl="relatedDiagrams.domainMetaElement == self.domainMetaElement", description="If elements do not match, we can't generate code working properly right away", severity="warning")
ref CanvasMapping[*] relatedDiagrams;
// ref ecore.EClass drtClass; -> extract to interface NotationInstanceAspect, and use it in CanvasMapping
}
abstract interface NeedsContainment {
@constraints(
ocl="not containmentFeature.oclIsUndefined() implies containmentFeature.containment", description="Containment EReference expected"
)
ref ecore.EReference[?] containmentFeature;
}
// Not feasible for pure design nodes: @constraints(ocl="not (child.domainMetaElement.oclIsUndefined() and containmentFeature.oclIsUndefined())", description="Either 'domainMetaElement' or 'containmentFeature' must be specified")
@constraints(ocl="not containmentFeature.oclIsUndefined() implies containmentFeature.eReferenceType.isSuperTypeOf(child.domainMetaElement)", description="'Containment Feature' must reference the same class or super type of 'Domain Meta Element' of the referenced node")
abstract class NodeReference extends NeedsContainment {
// extends NeedsContainment OR ref ecore.EReference[?] containmentFeature;
@constraints(ocl="not childrenFeature.oclIsUndefined() implies childrenFeature.eReferenceType.isSuperTypeOf(child.domainMetaElement)", description="'Children Feature' must reference the same class or super type of 'Domain Meta Element' of the referenced node")
ref ecore.EReference[?] childrenFeature;
readonly unsettable derived volatile transient !resolve ref NodeMapping child;
}
@constraints(ocl="not (ownedChild.oclIsUndefined() and referencedChild.oclIsUndefined())", description="Either 'ownedChild' or 'referencedChild' NodeMapping must be set")
@constraints(ocl="not childrenFeature.oclIsUndefined() implies childrenFeature.eContainingClass.isSuperTypeOf(parentNode.domainMetaElement)", description="'Children Feature' must be owned by 'Domain Meta Element' or its super type of this reference parent Node Mapping")
@constraints(ocl="not containmentFeature.oclIsUndefined() implies containmentFeature.eContainingClass.isSuperTypeOf(parentNode.domainMetaElement)", description="'Containment Feature' must be owned by 'Domain Meta Element' or its super type of this reference parent Node Mapping")
@constraints(ocl="not child.getDomainContext().oclIsUndefined() implies not containmentFeature.oclIsUndefined()", description="ChildReference to NodeMapping with domainElement should define 'containmentFeature'")
@constraints(ocl="let child:NodeMapping=(if ownedChild.oclIsUndefined() then referencedChild else ownedChild endif) in (((child.labelMappings->size() = 1) and child.labelMappings->forAll( soleLabel: LabelMapping | soleLabel.diagramLabel = child.diagramNode)) implies (child.diagramNode.affixedParentSide = gmfgraph::Direction::NONE))", description="Side-affixed children can not be pure labels")
@constraints(ocl="let child:NodeMapping=(if ownedChild.oclIsUndefined() then referencedChild else ownedChild endif) in ((not compartment.oclIsUndefined()) implies (child.diagramNode.affixedParentSide = gmfgraph::Direction::NONE))", description="Side-affixed children can not be placed in compartments")
class ChildReference extends NodeReference {
ref NodeMapping[1]#children parentNode; // TODO readonly, no much sense to setParentNode
ref CompartmentMapping[?]#children compartment;
//ref gmfgraph.Node[?] overrideNode;
// either one of these two must me set
val NodeMapping[?] ownedChild;
ref NodeMapping[?] referencedChild;
}
class TopNodeReference extends NodeReference {
val NodeMapping[1] ownedChild;
}
@genmodel(documentation="Both top-level diagram node and any inner node")
class NodeMapping extends MappingEntry, MenuOwner, ToolOwner, AppearanceSteward {
ref gmfgraph.Node[1] diagramNode;
ordered val ChildReference[*]#parentNode children;
val CompartmentMapping[*]#parentNode compartments;
//FIXME no containment feature - persist in resource then. Was: @constraints(ocl="not containmentFeature.oclIsUndefined() ", description="The child node mapping containmentFeature must be set")
}
class CompartmentMapping {
ref gmfgraph.Compartment[1] compartment;
readonly !resolve ref NodeMapping[1]#compartments parentNode;
ref ChildReference[*]#compartment children;
}
@genmodel(documentation="Connection element")
@constraints(ocl="domainMetaElement.oclIsUndefined() implies containmentFeature.oclIsUndefined() and sourceMetaFeature.oclIsUndefined()", description="Link mapping without 'Domain Element' class does not use 'Containment Feature' and 'Source Feature'")
@constraints(ocl="not domainMetaElement.oclIsUndefined() implies containmentFeature.eReferenceType.isSuperTypeOf(domainMetaElement)", description="'Containment Feature' must reference the same class or super type of 'Domain Element' EClass")
class LinkMapping extends MappingEntry, NeedsContainment, MenuOwner, ToolOwner, AppearanceSteward {
ref gmfgraph.Connection[1] diagramLink;
@constraints(
ocl="not domainMetaElement.oclIsUndefined() implies sourceMetaFeature.oclIsUndefined() or sourceMetaFeature.eContainingClass.isSuperTypeOf(domainMetaElement)", description="'Source Feature' must be owned by the link 'Domain Element' or its super type"
)
ref ecore.EStructuralFeature[?] sourceMetaFeature;
// rename linkMetaFeature to linkTargetMetaReference;
@constraints(
ocl="not(domainMetaElement.oclIsUndefined() or linkMetaFeature.oclIsUndefined()) implies linkMetaFeature.eContainingClass.isSuperTypeOf(domainMetaElement)", description="'Target Feature' must be owned by the link 'Domain Element' or its super type"
)
ref ecore.EStructuralFeature[?] linkMetaFeature; // XXX EReference? Links only to classes, not to datatypes/enums (i.e. attributes)
// super.drtClass isSubtypeOf(diagramrt.DiagramLink)
@genmodel(documentation="Specifies additional restrictions on link creation")
val LinkConstraints#linkMapping creationConstraints;
}
class CanvasMapping {
ref gmfgraph.Canvas[1] diagramCanvas;
ref ecore.EPackage domainModel;
@constraints(
ocl="not domainMetaElement.oclIsUndefined() implies not(domainMetaElement.abstract or domainMetaElement.interface)",
description="Top-level diagram container must be concrete"
)
ref ecore.EClass domainMetaElement;
ref tooldef.Palette[?] palette;
ordered ref tooldef.MainMenu[*] menuContributions;
ordered ref tooldef.Toolbar[*] toolbarContributions;
// ref ecore.EPackage drtPackage;
// super.drtClass isSubtypeOf(diagramrt.DiagramCanvas)
}
@genmodel(documentation="Label definition; text is taken from the graph model; no editing support; user may contribute custom parser")
class LabelMapping {
ref gmfgraph.DiagramLabel[1] diagramLabel;
attr boolean readOnly;
readonly !resolve ref MappingEntry[1]#labelMappings mapEntry;
}
@genmodel(documentation="Label based on feature(s) from domain model")
class FeatureLabelMapping extends LabelMapping {
@constraints(ocl="features->forAll(f | f.eContainingClass.isSuperTypeOf(mapEntry.domainMetaElement))", description="Label attributes must be available in 'Domain Element' EClass of the labeled mapping entry")
ref ecore.EAttribute[1..*] features;
@constraints(ocl="editableFeatures->forAll(f | f.eContainingClass.isSuperTypeOf(mapEntry.domainMetaElement))", description="Label attributes must be available in 'Domain Element' EClass of the labeled mapping entry")
ref ecore.EAttribute[*] editableFeatures;
@genmodel(documentation="Pattern to produce label on diagram, depends on view method")
attr String viewPattern;
@genmodel(documentation="Pattern to produce text for inplace editor, depends on view method; if not specified then viewPattern should be used")
attr String editorPattern;
@genmodel(documentation="Pattern to extract values from input text, depends on edit method; if not specified then viewPattern should be used")
attr String editPattern;
attr LabelTextAccessMethod viewMethod;
attr LabelTextAccessMethod editMethod;
}
enum LabelTextAccessMethod {
MESSAGE_FORMAT; // java.text.MessageFormat
NATIVE; // EcoreUtil.convertToString(...) / EcoreUtil.createFromString(...)
REGEXP; // String.split(...)
PRINTF; // String.format(...)
}
@genmodel(documentation="Label based on DescriptionStyle from notation model")
class DesignLabelMapping extends LabelMapping {
}
@genmodel(documentation="Label based on a calculated value")
class ExpressionLabelMapping extends LabelMapping {
// In futute, we may want to add optional list of features, that are deemed as triggering label change
//ref ecore.EAttribute[*] features;
@genmodel(documentation="Expression to produce regular label value. Evaluated in the context of the owning mapEntry.domainMetaElement")
val ValueExpression[1] viewExpression;
@genmodel(documentation="Optional expression to produce editable string representation of the label. If not set, viewExpression is used.")
val ValueExpression[?] editExpression;
@genmodel(documentation="Boolean expression in a string context, which able to tell whether user-entered text is valid.")
val Constraint[?] validateExpression;
}
//////////////
// Constraints
//
@genmodel(documentation="Boolean type value expression which is to be evaluated in a context")
@constraintsMeta(def="Constraint")
class Constraint extends ValueExpression {
}
@genmodel(documentation="Groups constraints on the link source and target end")
@constraints(ocl="not (sourceEnd.oclIsUndefined() and targetEnd.oclIsUndefined())", description="Either 'sourceEnd' or 'targetEnd' constraint must be specified")
class LinkConstraints {
@genmodel(documentation="References the link mapping restricted by these constraints")
readonly !resolve ref LinkMapping[1]#creationConstraints linkMapping;
@genmodel(documentation="Restriction enforced by the the source end, may reference variable 'oppositeEnd' pointing to targetEnd domainMetaElement instance if available.")
@constraintsMeta(def="context", ocl="let lm:LinkMapping=linkMapping in if lm.sourceMetaFeature.oclIsUndefined() then (if lm.containmentFeature.oclIsUndefined() then lm.linkMetaFeature.eContainingClass else lm.containmentFeature.eContainingClass endif) else lm.sourceMetaFeature.oclAsType(ecore::EReference).eReferenceType endif")
@constraintsMeta(def="variable", name="oppositeEnd", type.ocl="linkMapping.linkMetaFeature.eType")
val Constraint sourceEnd;
@genmodel(documentation="Restriction enforced by the the target end, may reference variable 'oppositeEnd' pointing to sourceEnd domainMetaElement instance.")
@constraintsMeta(def="context", ocl="linkMapping.linkMetaFeature.eType.oclAsType(ecore::EClass)")
@constraintsMeta(def="variable", name="oppositeEnd", type.ocl="let lm:LinkMapping=linkMapping in if lm.sourceMetaFeature.oclIsUndefined() then (if lm.containmentFeature.oclIsUndefined() then lm.linkMetaFeature.eContainingClass else lm.containmentFeature.eContainingClass endif) else lm.sourceMetaFeature.oclAsType(ecore::EReference).eReferenceType endif")
val Constraint targetEnd;
}
@constraintsMeta(def="ValueSpec")
@genmodel(documentation="Expression as a textual statement which results in a value when evaluated in a context")
class ValueExpression {
@genmodel(documentation="The text of the expression")
@constraintsMeta(def="body")
attr String[1] body;
@genmodel(documentation="Specifies the language in which the expression is stated")
attr Language[1] language = "ocl";
@constraintsMeta(def="lang")
readonly volatile transient derived attr String langName;
}
@genmodel(documentation="Base class for initializers of domain model elements")
abstract interface ElementInitializer {
@genmodel(documentation="The 'MappingEntry' whose domain model element is to be intialized by this initializer")
readonly volatile transient ref MappingEntry[1] mappingEntry;
}
@genmodel(documentation="Feature sequence initializer to initialize a sequence of features")
class FeatureSeqInitializer extends ElementInitializer {
@genmodel(documentation="Value specifications as initializers for individual features which should be initialized in the order given by this list")
val FeatureInitializer[+]#featureSeqInitializer initializers;
@constraints(ocl="not creatingInitializer.feature.oclIsUndefined() implies creatingInitializer.feature.oclAsType(ecore::EReference).eReferenceType.isSuperTypeOf(elementClass)", description="'elementClass' must be the same as or sub-type of the containing 'GenReferenceNewElementSpec' reference type")
@constraints(ocl="not creatingInitializer.feature.oclIsUndefined() implies not (elementClass.interface or elementClass.abstract)", description="'elementClass' must be a concrete EClass which is the same or sub-type of the containing 'GenReferenceNewElementSpec' reference type")
ref ecore.EClass elementClass;
readonly !resolve ref ReferenceNewElementSpec#newElementInitializers creatingInitializer;
}
abstract class FeatureInitializer {
@GenModel(documentation="The feature for which is to be initialized by this initializer")
@constraints(ocl="feature <> null implies not featureSeqInitializer.initializers->exists(i| i <> self and i.feature = self.feature)", description="The feature is already initialized by another 'FeatureInitializer' in the sequence")
@constraints(ocl="feature <> null implies feature.eContainingClass.isSuperTypeOf(featureSeqInitializer.elementClass)", description="The 'feature' of 'FeatureInitializer' must be available in 'Meta Class' of the initialized element")
@constraints(ocl="feature <> null implies feature.changeable", description="The 'feature' of 'FeatureInitializer' must be changeable")
ref ecore.EStructuralFeature[1] feature;
readonly !resolve ref FeatureSeqInitializer[1]#initializers featureSeqInitializer;
}
@genmodel(documentation="Value specification associated with a specific feature")
class FeatureValueSpec extends FeatureInitializer {
@constraintsMeta(def="context", ocl="featureSeqInitializer.elementClass")
@constraintsMeta(def="type", ocl="feature")
val ValueExpression[1] value;
}
@constraints(ocl="feature.many = false implies not (newElementInitializers->size() > 1)", description="FeatureInitializer for single element EReference can't contain multiple element initializers")
@constraints(ocl="let r: ecore::EReference = feature.oclAsType(ecore::EReference) in feature <> null implies r.containment", description="'feature' of 'ReferenceNewElementSpec' must refer to containment ecore::EReference")
class ReferenceNewElementSpec extends FeatureInitializer {
val FeatureSeqInitializer[+]#creatingInitializer newElementInitializers;
}
/////////////////////////
// Tooling Aspects/Facets
//
abstract interface MenuOwner {
ref tooldef.ContextMenu contextMenu;
}
abstract interface ToolOwner {
// constraint: canvasMapping.palette contains this tool
@genmodel(documentation="Way to create this element")
ref tooldef.AbstractTool tool;
}
abstract interface AppearanceSteward {
ref tooldef.StyleSelector appearanceStyle;
}
/////////
// Audits
//
@genmodel(documentation="Container for audit rules representing a hierarchical organization of audits in the constraint category hierarchy of emft.validation framework")
class AuditContainer {
@genmodel(documentation="Identifier which is unique within the scope of its parent container.")
@constraints(ocl="not parentContainer.oclIsUndefined() implies parentContainer.childContainers->one(i | i.id = self.id)", description="Audit container with the same ID already exists")
attr String[1] ~id;
@genmodel(documentation="A human readable name for the category of audits organized in this container")
attr String name;
@genmodel(documentation="The detailed description of this audit container")
attr String description;
ref AuditContainer#childContainers parentContainer;
@genmodel(documentation="The audit rules organized in this container")
val AuditRule[*]#container audits;
val AuditContainer[*]#parentContainer childContainers;
}
@GenModel(documentation="Base class for rule like audit, metric rules...")
abstract interface RuleBase {
@GenModel(documentation="A human readable name of this rule")
attr String name;
@GenModel(documentation="The detailed description of this rule semantics")
attr String description;
}
class AuditRule extends RuleBase {
@genmodel(documentation="Unique identifier of this audit rule")
@constraints(ocl="not id.oclIsUndefined() implies container.audits->one(i | i.id = self.id)", description="Audit rule with the same ID already exists")
attr String[1] ~id;
@genmodel(documentation="A boolean type condition which if not satisfied indicates this audit rule violation. It is evaluated in the context of the target")
@constraintsMeta(def="context", "ref"="target")
val Constraint[1] rule;
@GenModel(documentation="The target representing the context this audit is evaluated in")
val Auditable[1]#rule target;
@genmodel(documentation="Describes the severity of this audit rule violation")
attr Severity severity = "ERROR";
@genmodel(documentation="Indicates if this audit should be evaluated also in Live mode. If 'false', only Batch mode is applicable")
attr boolean useInLiveMode = false;
@genmodel(documentation="The text message to be reported in case of this audit violation")
attr String message;
@genmodel(documentation="The containing audit container of this audit rule")
ref AuditContainer[1]#audits container;
}
@GenModel(documentation="Target for rules applied on domain model elements")
@constraintsMeta(def="context", ocl="element")
class DomainElementTarget extends Auditable, Measurable {
@GenModel(documentation="Targeted domain model element")
ref ecore.EClass[1] element;
}
@GenModel(documentation="Represents value based target, useful for audit rules expression not capable of ecore meta-model access")
@constraintsMeta(def="context", ocl="attribute.eType")
class DomainAttributeTarget extends Auditable {
@GenModel(documentation="The attribute the value of which is used as context in audit rule defining this target")
ref ecore.EAttribute[1] attribute;
@GenModel(documentation="Indicates whether null value of the attribute is reported as audit failure or success")
attr boolean nullAsError;
}
@GenModel(documentation="Target for rules applied on diagram notation model selectively, for specific visualized element")
@constraintsMeta(def="context", ocl="if element.oclIsKindOf(NodeMapping) then 'notation::Node' else 'notation::Edge' endif")
class DiagramElementTarget extends Auditable, Measurable {
@GenModel(documentation="Targeted visualized element")
ref MappingEntry[1] element;
}
@GenModel(documentation="Target for rules applied on diagram notation model elements")
@constraintsMeta(def="context", ocl="element")
class NotationElementTarget extends Auditable, Measurable {
@GenModel(documentation="Targeted diagram notation model element")
@constraints(ocl="element.eAllSuperTypes->including(element)->one(ePackage.name = 'notation' and name = 'View')", description="'notation::View' or its sub-class must be set to NotationElement target")
ref ecore.EClass[1] element;
}
class MetricContainer {
val MetricRule[+]#container metrics;
}
@constraints(ocl="not lowLimit.oclIsUndefined() and not highLimit.oclIsUndefined() implies lowLimit < highLimit", description="Metric value 'lowLimit' must be smaller then 'highLimit'")
class MetricRule extends RuleBase {
@GenModel(documentation="Unique key identifying this metric an abbreviation for this metric")
@constraints(ocl="not key.oclIsUndefined() implies container.metrics->one(i | i.key = self.key)", description="Metric rule with the same 'key' already exists")
attr String[1] key;
@GenModel(documentation="Expression that calculates the value of this metric which is of EDataType that encapsulates java.lang.Number subclasses or their primitives")
@constraintsMeta(def="context", "ref"="target")
@constraintsMeta(def="type", ocl="'ecore::EDoubleObject'")
val ValueExpression[1] rule;
@GenModel(documentation="The target representing the context this metric is evaluated in")
val Measurable[1] target;
@GenModel(documentation="The lowest acceptable value of the rule expression result")
attr Double lowLimit;
@GenModel(documentation="The highest acceptable value of the rule expression result")
attr Double highLimit;
@GenModel(documentation="The containing metric container of this metric rule")
ref MetricContainer[1]#metrics container;
}
@GenModel(documentation="Target metric which can be evaluated by audit rule. The target context here is the metric rule resulting type classifier")
@constraintsMeta(def="context", ocl="'ecore::EDoubleObject'")
class AuditedMetricTarget extends Auditable {
@GenModel(documentation="Metric which can be checked by audit")
ref MetricRule[1] metric;
}
@GenModel(documentation="Target suitable for auditing")
abstract interface Auditable {
}
@GenModel(documentation="Marker interface for anything that can be subject to metrics")
abstract interface Measurable {
}
enum Severity {
INFO = 0;
WARNING = 1;
ERROR = 2;
}
enum Language {
ocl = 0;
java = 1;
regexp = 2;
nregexp = 3;
literal = 4;
}