Previous Table of Contents Next


7.9 MOF Model Constraints

7.9.1 MOF Model Constraints and other M2 Level Semantics

   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.

7.9.2 Notational Conventions 7.9.2.1 Notation for MOF Model Constraints

   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:

   The OCL for the Constraints start with a “context? clause that names a ModelElement in the MOF Model. This serves two purposes:

   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:

   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.

7.9.2.2 Notation for Operations, derived Attributes and derived Association

   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:

7.9.2.3 Notation for Helper Functions

   OCL Helper Functions are described in the following notation:


   context ClassifierName::HelperName(...) : ...post: result = ...

   The meaning of the above is as follows:

7.9.3 OCL Usage in the MOF Model specification

   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.

7.9.3.1 UML AssociationEnds versus MOF References

   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.

7.9.3.2 Helper functions are not MOF Operations

   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.

7.9.3.3 Post-conditions on MOF Model objects

   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.

7.9.3.4 OCL evaluation order

   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:

7.9.3.5 “OclType::allInstances?

   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.)

7.9.3.6 “OclType::references?

   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.

7.9.3.7 Foreign types and operations

   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:

7.9.4 The MOF Model Constraints

   [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.

context Import

   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

else

   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

else

   elems -> first -- should only be one

endif
[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)

7.9.6 OCL Helper functions

   [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)

then

   let ref = self -> asOclType(Reference) in

   ref -> referencedEnd() -> union(ref -> exposedEnd())

else

   Set{}

   endif endif endif endif endif endif endif endif endif endif