Previous | Table of Contents | Next |
This sub clause defines the semantic constraints that apply to the MOF Model. These are expressed as M2-level Constraints
and are formally part of the MOF Model (i.e., they are a required part of a representation of the MOF Model as MOF meta-objects
or in the MOF Model / XMI interchange format).
The sub clause also provides OCL semantic specifications for most M2-level Operations, derived Attributes, and derived Associations
in the MOF Model, and for a collection of “helper? functions used by them and the Constraints. These semantic specifications
need not be present in a representation of the MOF Model. Indeed, this document does not specify how they should be represented.
NOTE: The use of OCL in the MOF Model specification does not imply a requirement to use OCL evaluation as part of a MOF Model
server’s implementation. Furthermore, if that approach is used, it is anticipated that the implementor may rewrite the OCL
rules to make evaluation more efficient. For example, the Constraint OCL could be rewritten as pre-conditions on the appropriate
mapped update operations.
The M2-level Constraints on the MOF Model are described in the following notation:
[C-xxx] |
ConstraintName |
||||
evaluation policy: | immediate or deferred | ||||
description: | brief english description |
context SomeClassifierNameinv: ...
The meaning of the above is as follows:
• “[C-xxx]? is the cross reference tag for the Constraint used elsewhere in this document.
• “ConstraintName? is the name for the Constraint in the MOF Model. The IDL mapping uses this name to produce the MofError “kind? string for the Constraint. These strings appear in the generated IDL for the MOF Model, as described in 9.8.16, “Constraint Template,? on page 245.
• The “evaluation policy? states whether the Constaint should be checked on any relevant update operation, or whether checking should be deferred until full meta-model validation is triggered. It defines the Constraint’s “evaluationPolicy? value.
• The “description? is a brief non-normative synopsis of the Constraint. It could be used as the Constraint’s “annotation? value.
• The OCL for the Constraint is defined using the OCL syntax defined in UML 1.3.
The OCL for the Constraints start with a “context? clause that names a ModelElement in the MOF Model. This serves two purposes:
1. It defines the context in which the OCL constraint should be evaluated (i.e., the M3-level Class or DataType whose instances are constrained by the OCL).
2. It defines the “constrainedElements? and “container? for the Constraint.
While the OCL for the Constraints are mostly expressed as invariants, this should not be taken literally. Instead, the Constraint
OCL should be viewed as:
• a pre-condition on the relevant IDL operations for “immediate? Constraints, or
• a part of the specification of ModelElement’s “verify? Operation for “deferred? Constraints.
The Constraints in the MOF Model are expressed as restrictions on either Classes or DataTypes. Each one applies to (“Constrains?)
a single Classifier, and each one is defined to be contained by the Classifier that it applies. The “language? attribute of
each Constraint is either “MOF-OCL? (for those with complete OCL specifications) or “Other.? The “expression? attribute should
be the normative OCL defined here, even if different (but equivalent) OCL is used in a MOF Model server’s implementation.
The semantics of M2-level Operations, derived Attributes, and derived Associations on the MOF Model are described in the following
notation:
[O-xxx] |
ModelElementName |
||||
kind: | classification | ||||
description: | brief english description |
context ClassifierName::OperationName(...) : ...post: result = ...
or
context ClassName::AttributeName() : ...post: result = ...
or
context ClassName::ReferenceName() : ...post: result = ...
The meaning of the above is as follows:
• “[O-xxx]? is the cross reference tag for the semantic description that may be used elsewhere in this document.
• “ModelElementName? is the name of the Attribute, Operation, or Association in the MOF Model whose semantics is described.
• The “classification? describes the kind of the ModelElement (e.g., “readonly derived Attribute? or “query Operation?).
• The “description? is a brief non-normative synopsis of the semantics.
• The OCL is expressed using the OCL syntax defined in the UML 1.4 specification (http://www.omg.org/technology/ documents/formal/mof.htm). The “context? clause names an “abstract? operation or method on an M1 level interface whose semantics is specified. The name of the real operation(s) or method(s) will depend on the mapping. The semantics are expressed as post-conditions for these methods.
OCL Helper Functions are described in the following notation:
context ClassifierName::HelperName(...) : ...post: result = ...
The meaning of the above is as follows:
• “[S-xxx]? is the cross reference tag for the helper function that may be used elsewhere in this document.
• “HelperName? is the name of the Helper Function.
• The “description? is a brief non-normative synopsis of the Helper’s semantics.
• The OCL for the Helper is defined using the OCL syntax defined in UML 1.3. The “context? clause names a notional helper function on a ModelElement whose semantic is then specified. These notional functions are not intended to be callable by client code.
The OCL language was designed as a part of the UML specification. As such, the OCL semantics are specified in terms of UML
concepts and constructs. Some of these concepts do not match MOF concepts exactly. Accordingly, it is necessary to reinterpret
parts of the OCL specification so that it can be used in MOF Model’s Constraints and other semantics aspects of the MOF Model.
In the UML version of OCL, the dot (“.?) and arrow (“->?) operators are used to access Attribute values, and to navigate Associations.
Consider an OCL expression of the form:
<expr> “.? <identifier>
Assuming that “<expr>? evaluates to an object, the value of the expression is either the value of an Attribute named “<identifier>?
for the object or another object obtained by navigating a link in a binary Association which has “<identifier>? as an Association
End name.
In this context (i.e., the definition of the MOF Model), the “<identifier>? is interpreted differently. In the MOF Model,
the interfaces for navigating Associations are specified using References rather than AssociationEnds. Thus in the MOF version
of OCL, link navigation is expressed using the name of a Reference for the “<expr>? object as the “<identifier>.? However,
the overall meaning is analogous to the UML case.
In the UML version of OCL, object behavior is invoked by an expression of the form:
<expr> “.? <identifier> “(“ ... “)?
where “<identifier>? names a UML Operation or Method on the object obtained by evaluating “<expr>.?
In the MOF Model specification, the above expression invokes behavior defined by either a MOF Operation, or a helper function.
The distinction between conventional UML and its usage here is that helper functions have no defined connection with any internal
or external interfaces in a MOF Model server. Indeed, they need not exist at all as implementation artifacts.
Rules
[C-2] on page 105
,
[C-3] on page 106, and [C-4] on page 106 are intended to define post-conditions on all
operations on ModelElement objects. This is expressed in the MOF Model OCL by giving a Class rather than an Operation as the
“context? for the OCL rules. It is not clear that this is allowed by UML OCL.
The UML OCL specification does not define an evaluation order for OCL expressions in general, and for boolean operators in
particular. This is OK when OCL is used as an abstract specification language, as it is in the UML specification. However
it causes problems when OCL expressions may be directly evaluated. These problems arise in OCL that traverses cyclic graphs
(e.g.,
[O-1] on page 131
) or raises exceptions (e.g.,
[S-6] on page 127
).
The MOF Model semantic specification touches on some of these issues (e.g., when traversing a cyclical Imports graph). Therefore,
the MOF Model usage of OCL makes the following assumptions about OCL expression evaluation order:
• In general, a MOF OCL expression is assumed to be evaluated by evaluating its sub-expressions in order, starting with the leftmost sub-expression and ending with the rightmost. The sub-expressions are delimited according to the standard OCL operator precedence rules. If evaluation of one of the sub-expressions raises an exception, the remaining sub-expressions are not evaluated.
• The above does not apply to the boolean operators “and,? “or,? “implies,? and “if-then-else.? These are evaluated with short-circuiting as follows:
• In the expression “<expr1> and <expr2>,? “<expr2>? is only evaluated if “<expr1>? evaluates to true. • In the expression “<expr1> or <expr2>,? “<expr2>? is only evaluated if “<expr1>? evaluates to false. • In the expression “<expr1> implies <expr2>,? “<expr2>? is only evaluated if “<expr1>? evaluates to true. • In the expression “if <expr1> then <expr2> else <expr3> endif,? “<expr2>? is only evaluated if “<expr1>? evaluates to true, and “<expr3>? is only evaluated if “<expr1>? evaluates to false.
In UML OCL, the type.allInstances() is defined to return: “The set of all instances of type and all of its subtypes in existence
at the moment in time that the expression is evaluated.?
In the MOF Model OCL, this expression is used to refer to the set of all instances that exist within a given outermost
Package extent. (Any OCL expression that required the enumeration of all instances in existence “anywhere? would be
problematical, since a MOF repository does not exist in a closed world.)
The MOF Model OCL in rule Clause [C-4] assumes that the signature of OclType (as defined in the UML OCL specification) is
extended to include an operation called “references.? This is assumed to behave like the “attributes? operation, except that
it returns the names of an (M3-level) Classes’ References.
Some of the MOF Model OCL rules make use of types and operations that are not predefined in OCL, not defined as Operations
in the MOF Model, and not defined as Helper functions. Examples include:
• Rule [C-3] on page 106 makes uses of the CORBA Object::non_existent operation to assert that an object must continue to exist. This would be expressed differently in other contexts.
• Rules [C-2] on page 105 and [C-4] on page 106 use operations defined in the RefObject and RefBaseObject interfaces to access the meta-objects that represent the MOF Model. It should be understood that this is not intended to imply that a MOF Model server is required to make these objects available at runtime.
[C-1] MustBeContainedUnlessPackageformat1: MUST_BE_CONTAINED_UNLESS_PACKAGEformat2: must_be_contained_unless_packageevaluation policy deferreddescription: A ModelElement that is not a Package must have a container.
context ModelElementinv: not self.oclIsTypeOf(Package) impliesself.container -> size = 1
[C-2] FrozenAttributesCannotBeChangedformat1: FROZEN_ATTRIBUTES_CANNOT_BE_CHANGEDformat2: frozen_attributes_cannot_be_changedevaluation policy immediatedescription: The attribute values of a ModelElement that is frozen cannot be changed.
context ModelElementinv: self.isFrozen() implieslet myTypes = self.oclType() -> allSupertypes() ->includes(self.oclType()) inlet myAttrs : Set(Attribute) =
self.RefBaseObject::refMetaObject() ->asOclType(Class) ->findElementsByTypeExtended(Attribute) in
myAttrs -> forAll(a | self.RefObject::refValue@pre(a) =self.RefObject::refValue(a))
[C-3] | FrozenElementsCannotBeDeleted | ||||
format1: | FROZEN_ELEMENTS_CANNOT_BE_DELETED | ||||
format2: | frozen_elements_cannot_be_deleted | ||||
evaluation policy | immediate | ||||
description: | A frozen ModelElement that is in a frozen Namespace can only be deleted, by deleting the | ||||
Namespace. |
context ModelElementpost:
(self.isFrozen@pre() andself.container@pre -> notEmpty andself.container.isFrozen@pre()) implies
(self.container.Object::non_existent() or not self.Object::non_existent())
[C-4] | FrozenDependenciesCannotBeChanged | ||||
format1: | FROZEN_DEPENDENCIES_CANNOT_BE_CHANGED | ||||
format2: | frozen_dependencies_cannot_be_changed | ||||
evaluation policy | immediate | ||||
description: | The link sets that express dependencies of a frozen Element on other Elements cannot be | ||||
explicitly changed. |
context ModelElementpost: self.isFrozen() implieslet myClasses = self.oclType() -> allSupertypes() ->includes(self.oclType()) inlet myRefs = Set(Reference) =
self.RefBaseObject::refMetaObject() ->asOclType(Class) -> findElementsByTypeExtended(Reference) in
let myDepRefs = myRefs -> select(r |
Set{“contents?, “constraints?, “supertypes?,“type?, “referencedEnd?, “exceptions?,“importedNamespace?, “elements?} ->
includes(r.name)) inmyDepRefs ->forAll(r | self.RefObject::refValue@pre(r) = self.RefObject::refValue(r))
[C-5] | ContentNamesMustNotCollide | ||||
format1: | CONTENT_NAMES_MUST_NOT_COLLIDE | ||||
format2: | content_names_must_not_collide | ||||
evaluation policy | immediate | ||||
description: | The names of the contents of a Namespace must not collide. |
context Namespace
inv: self.contents.forAll(e1, e2 | e1.name = e2.name implies r1 = r2)
[C-6] SupertypeMustNotBeSelf format1: SUPERTYPE_MUST_NOT_BE_SELF format2: supertype_must_not_be_self evaluation policy immediate
description: A Generalizable Element cannot be its own direct or indirect supertype.
context GeneralizableElementinv: self.allSupertypes() -> forAll(s | s <> self)
[C-7] SupertypeKindMustBeSame format1: SUPERTYPE_KIND_MUST_BE_SAME format2: supertype_kind_must_be_same evaluation policy
immediate description: A supertypes of a Generalizable Element must be of the same kind as the
GeneralizableElement itself.
context GeneralizableElementinv: self.supertypes -> forAll(s | s.oclType() = self.oclType())
[C-8] | ContentsMustNotCollideWithSupertypes | ||||
format1: | CONTENTS_MUST_NOT_COLLIDE_WITH_SUPERTYPES | ||||
format2: | contents_must_not_collide_with_supertypes | ||||
evaluation policy | immediate | ||||
description: | The names of the contents of a GeneralizableElement should not collide with the names of | ||||
the contents of any direct or indirect supertype. |
context GeneralizableElementinv:let superContents = self.allSupertypes() -> collect(s | s.contents) inself.contents -> forAll(m1 |superContents -> forAll(m2 | m1.name = m2.name implies m1 = m2))
[C-9] | DiamondRuleMustBeObeyed | ||||
format1: | DIAMOND_RULE_MUST_BE_OBEYED | ||||
format2: | diamond_rule_must_be_obeyed | ||||
evaluation policy | immediate | ||||
description: | Multiple inheritance must obey the “Diamond Rule.? |
context GeneralizableElementinv:let superNamespaces = self.supertypes -> collect(s | s.extendedNamespace) insuperNamespaces -> asSet -> isUnique(s | s.name)
[C-10] NoSupertypesAllowedForRoot format1: NO_SUPERTYPES_ALLOWED_FOR_ROOT format2: no_supertypes_allowed_for_root evaluation
policy immediate description: If a Generalizable Element is marked as a “root,? it cannot have any supertypes.
context GeneralizableElementinv: self.isRoot implies self.supertypes -> isEmpty
[C-11] | SupertypesMustBeVisible | ||||
format1: | SUPERTYPES_MUST_BE_VISIBLE | ||||
format2: | supertypes_must_be_visible | ||||
evaluation policy | deferred | ||||
description: | A Generalizable Element’s immediate supertypes must all be visible to it. |
context GeneralizableElementinv: self.supertypes -> forAll(s | self.isVisible(s))
[C-12] NoSubtypesAllowedForLeaf format1: NO_SUBTYPES_ALLOWED_FOR_LEAF format2: no_subtypes_allowed_for_leaf evaluation policy
immediate description: A GeneralizableElement cannot inherit from a GeneralizableElement defined as a “leaf.?
context GeneralizableElementinv: self.supertypes -> forAll(s | not s.isLeaf)
[C-13] AssociationsCannotBeTypes format1: ASSOCIATIONS_CANNOT_BE_TYPES format2: associations_cannot_be_types evaluation policy
immediate description: An Association cannot be the type of a TypedElement.
context TypedElementinv: not self.type.oclIsKindOf(Association)
[C-14] | TypeMustBeVisible | ||||
format1: | TYPE_MUST_BE_VISIBLE | ||||
format2: | type_must_be_visible | ||||
evaluation policy | deferred | ||||
description: | A TypedElement and only have a type that is visible to it. |
context TypedElementinv: self.isVisible(self.type)
[C-15] ClassContainmentRules format1: CLASS_CONTAINMENT_RULES format2: class_containment_rules evaluation policy immediate
description: A Class may contain only Classes, DataTypes, Attributes, References, Operations,
Exceptions, Constants, Constraints, and Tags.
context Classinv: Set{Class, DataType, Attribute, Reference, Operation,Exception, Constant, Constraint, Tag} ->includesAll(self.contentTypes())
[C-16] | AbstractClassesCannotBeSingleton | ||||
format1: | ABSTRACT_CLASSES_CANNOT_BE_SINGLETON | ||||
format2: | abstract_classes_cannot_be_singleton | ||||
evaluation policy | deferred | ||||
description: | A Class that is marked as abstract cannot also be marked as singleton. |
context Classinv: self.isAbstract implies not self.isSingleton
[C-17] | DataTypeContainmentRules | ||||
format1: | DATA_TYPE_CONTAINMENT_RULES | ||||
format2: | data_type_containment_rules | ||||
evaluation policy | immediate | ||||
description: | A DataType may contain only TypeAliases, Constraints, Tags (or in the case of | ||||
StructureTypes) StructureFields. |
context DataType
inv: if self.oclIsOfType(StructureType)thenSet{TypeAlias, Constraint, Tag, StructureField} ->includesAll(self.contentTypes())elseSet{TypeAlias, Constraint, Tag} ->includesAll(self.contentTypes())
[C-18] <Placeholder for a deleted constraint>
[C-19] DataTypesHaveNoSupertypes format1: DATA_TYPES_HAVE_NO_SUPERTYPES format2: data_types_have_no_supertypes evaluation
policy immediate description: Inheritance / generalization is not applicable to DataTypes.
context DataTypeinv: self.supertypes -> isEmpty
[C-20] DataTypesCannotBeAbstractformat1: DATA_TYPES_CANNOT_BE_ABSTRACTformat2: data_types_cannot_be_abstractevaluation policy immediatedescription: A DataType cannot be abstract.
context DataTypeinv: not self.isAbstract
[C-21] | ReferenceMultiplicityMustMatchEnd | ||||
format1: | REFERENCE_MULTIPLICITY_MUST_MATCH_END | ||||
format2: | reference_multiplicity_must_match_end | ||||
evaluation policy | deferred | ||||
description: | The multiplicity for a Reference must be the same as the multiplicity for the referenced | ||||
AssociationEnd. |
context Referenceinv: self.multiplicity = self.referencedEnd.multiplicity
[C-22] | ReferenceMustBeInstanceScoped | ||||
format1: | REFERENCE_MUST_BE_INSTANCE_SCOPED | ||||
format2: | reference_must_be_instance_scoped | ||||
evaluation policy | immediate | ||||
description: | Classifier scoped References are not meaningful in the current M1 level computational | ||||
model. |
context Referenceinv: self.scope = #instance_level
[C-23] | ChangeableReferenceMustHaveChangeableEnd | ||||
format1: | CHANGEABLE_REFERENCE_MUST_HAVE_CHANGEABLE_END | ||||
format2: | changeable_reference_must_have_changeable_end | ||||
evaluation policy | deferred | ||||
description: | A Reference can be changeable only if the referenced AssociationEnd is also changeable. |
context Referenceinv: self.isChangeable = self.referencedEnd.isChangeable
[C-24] | ReferenceTypeMustMatchEndType | ||||
format1: | REFERENCE_TYPE_MUST_MATCH_END_TYPE | ||||
format2: | reference_type_must_match_end_type | ||||
evaluation policy | deferred | ||||
description: | The type attribute of a Reference and its referenced AssociationEnd must be the same. |
context Referenceinv: self.type = self.referencedEnd.type
[C-25] ReferencedEndMustBeNavigable format1: REFERENCED_END_MUST_BE_NAVIGABLE format2: referenced_end_must_be_navigable evaluation
policy deferred description: A Reference is only allowed for a navigable AssociationEnd.
context Referenceinv: self.referencedEnd.isNavigable
[C-26] ContainerMustMatchExposedType format1: CONTAINER_MUST_MATCH_EXPOSED_TYPE format2: container_must_match_exposed_type
evaluation policy deferred description: The containing Class for a Reference must be equal to or a subtype of the type of
the
Reference’s exposed AssociationEnd.
context Referenceinv:self.container.allSupertypes() -> including(self) ->includes(self.referencedEnd.otherEnd.type)
[C-27] | ReferencedEndMustBeVisible | ||||
format1: | REFERENCED_END_MUST_BE_VISIBLE | ||||
format2: | referenced_end_must_be_visible | ||||
evaluation policy | deferred | ||||
description: | The referenced AssociationEnd for a Reference must be visible from the Reference. |
context Referenceinv: self.isVisible(self.referencedEnd)
[C-28] OperationContainmentRules format1: OPERATION_CONTAINMENT_RULES format2: operation_containment_rules evaluation policy
immediate description: An Operation may only contain Parameters, Constraints, and Tags.
context Operationinv: Set{Parameter, Constraint, Tag} -> includesAll(self.contentTypes())
[C-29] | OperationsHaveAtMostOneReturn | ||||
format1: | OPERATIONS_HAVE_AT_MOST_ONE_RETURN | ||||
format2: | operations_have_at_most_one_return | ||||
evaluation policy | immediate | ||||
description: | An Operation may have at most one Parameter whose direction is “return.? |
context Operationinv:self.contents -> select(c | c.oclIsTypeOf(Parameter)) ->select(p : Parameter | p.direction = #return_dir) ->size < 2
[C-30] | OperationExceptionsMustBeVisible | ||||
format1: | OPERATION_EXCEPTIONS_MUST_BE_VISIBLE | ||||
format2: | operation_exceptions_must_be_visible | ||||
evaluation policy | deferred | ||||
description: | The Exceptions raised by an Operation must be visible to the Operation. |
context Operationinv: self.exceptions -> forAll(e | self.isVisible(e))
[C-31] ExceptionContainmentRules format1: EXCEPTION_CONTAINMENT_RULES format2: exception_containment_rules evaluation policy
immediate description: An Exception may only contain Parameters and Tags.
context Exceptioninv: Set{Parameter, Tag}) -> includesAll(self.contentTypes())
[C-32] ExceptionsHaveOnlyOutParameters format1: EXCEPTIONS_HAVE_ONLY_OUT_PARAMETERS format2: exceptions_have_only_out_parameters
evaluation policy immediate description: An Exception’s Parameters must all have the direction “out.?
context Exceptioninv:self.contents -> select(c | c.oclIsTypeOf(Parameter)) ->forAll(p : Parameter | p.direction = #out_dir)
[C-33] | AssociationContainmentRules | ||||
format1: | ASSOCIATIONS_CONTAINMENT_RULES | ||||
format2: | associations_containment_rules | ||||
evaluation policy | immediate | ||||
description: | An Association may only contain AssociationEnds, Constraints, and Tags. |
context Associationinv: Set{AssociationEnd, Constraint, Tag} ->includesAll(self.contentTypes())
[C-34] | AssociationsHaveNoSupertypes | ||||
format1: | ASSOCIATIONS_HAVE_NO_SUPERTYPES | ||||
format2: | associations_have_no_supertypes | ||||
evaluation policy | immediate | ||||
description: | Inheritance / generalization is not applicable to Associations. |
context Associationinv: self.supertypes -> isEmpty
[C-35] AssociationMustBeRootAndLeaf format1: ASSOCIATIONS_MUST_BE_ROOT_AND_LEAF format2: associations_must_be_root_and_leaf
evaluation policy immediate description: The values for “isLeaf? and “isRoot? on an Association must be true.
context Associationinv: self.isRoot and self.isLeaf
[C-36] | AssociationsCannotBeAbstract | ||||
format1: | ASSOCIATIONS_CANNOT_BE_ABSTRACT | ||||
format2: | associations_cannot_be_abstract | ||||
evaluation policy | immediate | ||||
description: | An Association cannot be abstract. |
context Associationinv: not self.isAbstract
[C-37] AssociationsMustBePublic format1: ASSOCIATIONS_MUST_BE_PUBLIC format2: associations_must_be_public evaluation policy
immediate description: Associations must have visibility of “public.?
context Associationinv: self.visibility = #public_vis
[C-38] AssociationsMustNotUnary format1: ASSOCIATIONS_MUST_NOT_BE_UNARY format2: associations_must_be_not_unary evaluation
policy immediate description: An Association must not be unary; that is, it must have at least two AssociationEnds.
context Associationinv: self.contents -> select(c | c.ocllstTypeOf(AssociationEnd)) -> size = 2
[C-39] EndTypeMustBeClass format1: END_TYPE_MUST_BE_CLASS
format2: | end_type_must_be_class | ||||
evaluation policy | immediate | ||||
description: | The type of an AssociationEnd must be Class. |
context AssociationEndinv: self.type.oclIsTypeOf(Class)
[C-40] | EndsMustBeUnique | ||||
format1: | ENDS_MUST_BE_UNIQUE | ||||
format2: | ends_must_be_unique | ||||
evaluation policy | immediate | ||||
description: | The “isUnique? flag in an AssociationEnd’s multiplicity must be true. |
context AssociationEndinv: (self.multiplicity.upper > 1 orself.multiplicity.upper = UNBOUNDED) impliesself.multiplicity.isUnique
[C-41] | CannotHaveTwoOrderedEnds | ||||
format1: | CANNOT_HAVE_TWO_ORDERED_ENDS | ||||
format2: | cannot_have_two_ordered_ends | ||||
evaluation policy | deferred | ||||
description: | An AssociationEnd cannot have two AssociationEnds marked as “ordered.? |
context AssociationEndinv:self.multiplicity.isOrdered impliesnot self.otherEnd.multiplicity.isOrdered
[C-42] CannotHaveTwoAggregateEnds format1: CANNOT_HAVE_TWO_AGGREGATE_ENDS
format2: | cannot_have_two_aggregate_ends | ||||
evaluation policy | deferred | ||||
description: | An AssociationEnd cannot have an aggregation semantic specified for both AssociationEnds. |
context AssociationEndinv: self.aggregation <> #none implies self.otherEnd = #none
[C-43] | PackageContainmentRules | ||||
format1: | PACKAGE_CONTAINMENT_RULES | ||||
format2: | package_containment_rules | ||||
evaluation policy | immediate | ||||
description: | A Package may only contain Packages, Classes, DataTypes, Associations, Exceptions, | ||||
Constants, Constraints, Imports, and Tags. |
context Packageinv:Set{Package, Class, DataType, Association, Exception, Constant, Constraint, Import, Tag}) ->includesAll(self.contentTypes)
[C-44] | PackagesCannotBeAbstract | ||||
format1: | PACKAGES_CANNOT_BE_ABSTRACT | ||||
format2: | packages_cannot_be_abstract | ||||
evaluation policy | immediate | ||||
description: | Packages cannot be declared as abstract. |
context Packageinv: not self.isAbstract
[C-45] ImportedNamespaceMustBeVisible format1: IMPORTED_NAMESPACE_MUST_BE_VISIBLE
format2: | imported_namespace_must_be_visible | ||||
evaluation policy | deferred | ||||
description: | The Namespace imported by an Import must be visible to the Import’s containing Package. |
context Importinv: self.container.isVisible(self.importedNamespace)
[C-46] | CanOnlyImportPackagesAndClasses | ||||
format1: | CAN_ONLY_IMPORT_PACKAGES_AND_CLASSES | ||||
format2: | can_only_import_packages_and_classes | ||||
evaluation policy | immediate | ||||
description: | It is only legal for a Package to import or cluster Packages or Classes. |
inv:self.imported.oclIsTypeOf(Class) orself.imported.oclIsTypeOf(Package)
[C-47] CannotImportSelf format1: CANNOT_IMPORT_SELF format2: cannot_import_self evaluation policy deferred description: Packages
cannot import or cluster themselves.
context Importinv: self.container <> self.imported
[C-48] CannotImportNestedComponents format1: CANNOT_IMPORT_NESTED_COMPONENTS
format2: | cannot_import_nested_components | ||||
evaluation policy | deferred | ||||
description: | Packages cannot import or cluster Packages or Classes that they contain. |
context Importinv: not self.container.allContents() -> includes(self.imported)
[C-49] | NestedPackagesCannotImport | ||||
format1: | NESTED_PACKAGES_CANNOT_IMPORT | ||||
format2: | nested_packages_cannot_import | ||||
evaluation policy | deferred | ||||
description: | Nested Packages cannot import or cluster other Packages or Classes. |
context Importinv:self.container -> notEmpty impliesself.container -> asSequence -> first -> container -> isEmpty
[C-50] | CannotConstrainThisElement | ||||
format1: | CANNOT_CONSTRAIN_THIS_ELEMENT | ||||
format2: | cannot_constrain_this_element | ||||
evaluation policy | immediate | ||||
description: | Constraints, Tags, Imports, and Constants cannot be constrained. |
context Constraintinv:self.constrainedElements ->forAll(c | not Set{Constraint, Tag, Imports, Constant} -> includes(c.oclType())
[C-51] | ConstraintsLimitedToContainer | ||||
format1: | CONSTRAINTS_LIMITED_TO_CONTAINER | ||||
format2: | constraints_limited_to_container | ||||
evaluation policy | deferred | ||||
description: | A Constraint can only constrain ModelElements that are defined by or inherited by its | ||||
immediate container. |
context Constraintinv:self.constrainedElements ->forAll(c | self.container.extendedNamespace() ->includes(c))
[C-52] ConstantsValueMustMatchType format1: CONSTANTS_VALUE_MUST_MATCH_TYPE format2: constants_value_must_match_type evaluation
policy deferred description: The type of a Constant and its value must be compatible.
context Constantinv: ...
[C-53] ConstantsTypeMustBePrimitive format1: CONSTANTS_TYPE_MUST_BE_PRIMITIVE format2: constants_type_must_be_primitive evaluation
policy immediate description: The type of a Constant must be a PrimitiveType.
context Constantinv: self.type.oclIsOfType(PrimitiveType)
[C-54] | LowerCannotBeNegativeOrUnbounded | ||||
format1: | LOWER_CANNOT_BE_NEGATIVE_OR_UNBOUNDED | ||||
format2: | lower_cannot_be_negative_or_unbounded | ||||
evaluation policy | immediate | ||||
description: | The “lower? bound of a MultiplicityType to be “Unbounded.? |
context MultiplicityTypeinv: self.lower >= 0 and self.lower <> Unbounded
[C-55] LowerCannotExceedUpper format1: LOWER_CANNOT_EXCEED_UPPER format2: lower_cannot_exceed_upper evaluation policy immediate
description: The “lower? bound of a MultiplicityType cannot exceed the “upper? bound.
context MultiplicityTypeinv: self.lower <= self.upper or self.upper = Unbounded
[C-56] UpperMustBePositive format1: UPPER_MUST_BE_POSITIVE format2: upper_must_be_positive evaluation policy immediate description:
The “upper? bound of a MultiplicityType cannot be less than 1.
context MultiplicityTypeinv: self.upper >= 1 or self.upper = Unbounded
[C-57] | MustBeUnorderedNonunique | ||||
format1: | MUST_BE_UNORDERED_NONUNIQUE | ||||
format2: | must_be_unordered_nonunique | ||||
evaluation policy | immediate | ||||
description: | If a MultiplicityType specifies bounds of [0..1] or [1..1]), the “is_ordered? and “is_unique? | ||||
values must be false. |
context MultiplicityTypeinv: self.upper = 1 implies(not self.isOrdered and not self.isUnique)
[C-58] StructuredFieldContainmentRules format1: STRUCTURE_FIELD_CONTAINMENT_RULES format2: structure_field_containment_rules
evaluation policy immediate description: A StructureField contains Constraints and Tags.
context StructureFieldinv: Set{ Constraint, Tag}) -> includesAll(self.contentTypes)
[C-59] MustHaveFields format1: MUST_HAVE_FIELDS format2: must_have_fields evaluation policy deferred description: A StructureType
must contain at least one StructureField.
context StructureTypeinv: self.contents -> exists(c | c.oclIsOfType(StructureField))
7.9.5 Semantic specifications for some Operations, derived Attributes and Derived Associations
[S-1] | allSupertypes | ||||
kind: | query Operation | ||||
description: | The value is the closure of the ‘Generalizes’ Association from the perspective of a subtype. | ||||
Note that the sequence of all supertypes has a well defined order. |
context GeneralizableElement::allSupertypes() :Sequence(GeneralizableElement)post: result = self.allSupertypes2(Set{})
[S-2] otherEnd kind: query Operation description: The value is the other AssociationEnd for this Association.
context AssociationEnd::otherEnd() : AssociationEnd post: result = self.container.contents ->select(c | c.oclIsKindOf(AssociationEnd) and c <> self)
[S-3] isVisible kind: query Operation description: Determines whether or not “otherElement? is visible for the definition
of this element. (Note:
As an interim measure, the OCL states that everything is visible!)
context ModelElement::isVisible(otherElement : ModelElement): booleanpost: result = true
[S-4] findRequiredElements kind: query Operation description: Selects a subset of a ModelElement’s immediate or recursive
dependents.
context ModelElement::isRequiredBecause(kinds : Sequence(DependencyKind),recursive : boolean) : Sequence(ModelElement)
post: result = if kinds -> includes(“all?) then
self.findRequiredElements(
Set{“constraint?, “container?, “constrained elements?,“specialization?, “import?, “contents?, “signature?,“tagged elements?, “type definition?, “referenced ends?})
else if recursivethen
self.recursiveFindDeps(kinds, Set{self})elsekinds -> collect(k : self.findDepsOfKind(k)) -> asSet()endifendif
[S-5] | findRequiredBecause | ||||
kind: | query Operation | ||||
description: | Returns the DependencyKind that describes the dependency between this element and | ||||
“other.? |
context ModelElement::findRequiredElements(other : ModelElement,reason : out DependencyKind) : boolean
post: -- NB, if there is more than one dependency between self -- and ‘other’, the selection of the ‘reason’ is defined -- to be non-deterministic ... not deterministic as a -- left to right evaluation of the OCL implies.
reason = (if self -> isDepOfKind(“constraint?, other)then
“constraint?
elseif self -> isDepOfKind(“container?, other)then
“container?
elseif self -> isDepOfKind(“constrained elements?, other)then
“constrained elements?
elseif self -> isDepOfKind(“specialization?, other)then
“specialization?
elseif self -> isDepOfKind(“import?, other)then
“import?
elseif self -> isDepOfKind(“contents?, other)then
“contents?
elseif self -> isDepOfKind(“signature?, other)then
“signature?
elseif self -> isDepOfKind(“tagged elements?, other)then
“tagged elements?
elseif self -> isDepOfKind(“type definition?, other)then
“type definition?
elseif self -> isDepOfKind(“referenced ends?, other)then
“referenced ends?
elseif self -> dependsOn() -> notEmpty()then
“indirect?
else
“?
endifendifendifendifendifendifendifendifendifendifendif) and result = (reason <> “?)
[S-6] | lookupElement | ||||
kind: | query Operation | ||||
description: | Returns the ModelElement in the Namespace whose name is equal to “name,? or raises an | ||||
exception. |
context Namespace::lookupElement(name : string) : ModelElement
post: result = let elems = self.contents -> select(m | m.name = name) inif elems -> size = 0then
-- Raise exception NameNotFound
elems -> first -- should only be one
endif
[S-7] | resolveQualifiedName | ||||
kind: | query Operation | ||||
description: | Returns the ModelElement that “qualifiedName? resolves to or raises an exception. |
context Namespace::resolveQualifiedName(
qualifiedName : Sequence(string)) : ModelElementpre: qualifiedName -> size >= 1post: result =
let elems = self.contents ->
select(m | m.name = qualifiedName -> first) inif elems -> size = 0then
-- Raise exception NameNotResolved ...
elseif qualifiedName -> size = 1then
elems -> first -- there should only be one
else if not elems -> first -> oclIsOfKind(Namespace)then
-- Raise exception NameNotResolved ...
elselet rest = qualifiedName -> subSequence(2, qualifiedName -> size) inelems -> first -> resolveQualifiedName(rest)
endifendifendif
[S-8] NameIsValid kind: query Operation description: Returns true if “proposedName? is a valid name that could be used for
a new
containedElement of this Namespace.
context Namespace::nameIsValid(proposedName : string) : booleanpost: result = self.extendedNamespace -> forAll(e | not e.name = proposedName)
[S-9] | findElementsByType | ||||
kind: | query Operation | ||||
description: | Returns a subset of the contained elements. If “includeSubtypes? is false, the result consists | ||||
of instances of “ofType.? If it is true, instances of subClasses are included. |
context Namespace::findElementsByType(ofType : Class,includeSubtypes : boolean) : Sequence(ModelElement)
post: result =if includeSubtypes then
self.contents -> select(m | m.oclIsOfKind(ofType))elseself.contents -> select(m | m.oclIsOfType(ofType))endif
[S-10] | lookupelementExtended | ||||
kind: | query Operation | ||||
description: | Returns the ModelElement whose name is equal to “name? in the extended namespace of this | ||||
GeneralizableElement, or raises an exception. |
context Namespace::lookupElementExtended(name : string) : ModelElementpost: result = let elems = self -> extendedNamespace ->
select(m | m.name = name) inif elems -> size = 0then
-- Raise exception NameNotFound
elems -> first -- should only be one
[S-11] | findElementsByTypeExtended | ||||
kind: | query Operation | ||||
description: | Returns a subset of the contained, inherited, or imported elements. If “includeSubtypes? is false, the result consists of instances of “ofType.? If it is true, instances of subClasses are included. |
context GeneralizeableElement::findElementsByTypeExtended(ofType : Class,includeSubtypes : boolean) : Sequence(ModelElement)
post: result =if includeSubtypes then
self.extendedNamespace -> select(m | m.oclIsOfKind(ofType))elseself.extendedNamespace -> select(m | m.oclIsOfType(ofType))endif
[S-12] qualifiedName kind: readonly derived Attribute description: The qualified name gives the sequence of names of the containers
of this ModelElement
starting with the outermost.
context ModelElement::qualifiedName() : Sequence(ModelElement)
post: result = if self.container -> notEmptythen
self.container.qualifiedName() -> append(self.name)elseself.nameendif
[S-13] Exposes kind: derived Association description: This association relates a Reference to the exposed AssociationEnd of
an Association that
corresponds to its referencedEnd.
context Referenceinv: AssociationEnd.allInstances ->
forAll(a |self.references = a implies self.exposes = a.otherEnd andnot self.references = a implies self.exposes <> a.otherEnd)
[S-14] | DependsOn | ||||
kind: | derived Association | ||||
description: | This association relates a ModelElement to the other ModelElements whose definition it | ||||
depends on. |
context ModelElementinv: self.findRequiredElements(“all?, true)
[O-1] allSupertypes2description: Helper function for the allSupertypes operation.
context GeneralizableElement::allSupertypes2(visited : Set(GeneralizableElement)) :Sequence(GeneralizableElement)
post: result =if (visited -> includes(self))then
Sequence{}
elselet mySupers : Sequence(GeneralizableElement) =self.supertypes ->collect(s | s.allSupertypes2(visited ->including(self))) inmySupers -> iterate(s2 : GeneralizableElement;
a : Sequence(GeneralizableElement) = Sequence{} |if a -> includes(s2) then
a
else
a -> append(s2)endif)
[O-2] | extendedNamespace | ||||
description: | The extendedNamespace of a Namespace is its contents, the contents of its supertypes, and | ||||
any Namespaces that it imports. |
context Namespace::extendedNamespace() : Set(ModelElement)post: result = self.contents
context GeneralizableElement::extendedNamespace : Set(ModelElement)post: result =self.contents -> union(self.allSupertypes() -> collect(s | s.contents))
context Package::extendedNamespace : Set(ModelElement)post: result =let ens = self.contents -> union(self.allSupertypes() -> collect(s | s.contents)) inlet imports = ens -> select(e | e.oclKindOf(Import)) -> collect(i : Import | i.imported) inens -> union(imports)
[O-3] contentTypesdescription: The set of OCL types for a Namespace’s contents.
context Namespace::contentTypes() : Set(OCLType)post: result = self.contents -> collect(m | m.oclType()) -> asSet
[O-4] format1Name
description: The simple name of the element converted to words and reassembled according to the “format1? rules; see “IDL
Identifier Format 1? on page 5-39.
context ModelElement::format1Name() : stringpost: result = ...
[O-5] repositoryIddescription: The qualified name of the element converted into a standard CORBA repositoryId string.
context ModelElement::repositoryId() : stringpost: result = ...
[O-6] recursiveFindDepsdescription: The set of ModelElements that recursively depend on this one.
context ModelElement::recursiveFindDeps(kinds : Sequence(string),seen : Set(ModelElement)) : Set(ModelElement)
post: result = let seen2 = seen -> collect(m | kinds ->
collect(k | m.findDepsOfKind(k)) -> asSet) inif seen2 = seen then
seen
else self.recursiveFindDeps(kinds, seen2)endif
[O-7] isDepOfKinddescription: Returns true if this element depends on ‘other’ with a dependency of ‘kind.’
context ModelElement::isDepOfKind(kind : string, other : ModelElement) : boolean
post: result = self -> findDepsOfKind(kind) -> includes(other)
[O-8] finalDepsOfKinddescription: The set of Modelelements that this one Depends on with “kind? dependency.
context ModelElement::findDepsOfKind(kind : string) : Sequence(ModelElement)
post: result =
if kind = “constraint?
then self.constraints()
else if kind = “container?
then self.container()
else if kind = “constrained elements? and
self -> isOclTypeOf(Constraint)
then self -> oclAsType(Constraint) -> constrainedElements()
else if kind = “specialization? and
self -> isOclKindOf(GeneralizableElement)
then self -> oclAsType(GeneralizableElement) -> supertypes()
else if kind = “import? and self -> isOclType(Import)
then self -> oclAsType(Import) -> importedNamespace()
else if kind = “contents? and self -> isOclKindOf(Namespace)
then self -> oclAsType(Namespace) -> contents()
else if kind = “signature? and self -> isOclTypeOf(Operation)
then self -> oclAsType(Operation) -> exceptions()
else if kind = “tagged elements? and
self -> isOclTypeOf(Tag)
then self -> oclAsType(Tag) -> elements()
else if kind = “type definition? and
self -> isOclKindOf(TypedElement)
then self -> oclAsType(TypedElement) -> type()
else if kind = “referenced ends? and
self -> isOclKindOf(Reference)
let ref = self -> asOclType(Reference) in
ref -> referencedEnd() -> union(ref -> exposedEnd())
Set{}
endif endif endif endif endif endif endif endif endif endif