The Types Package
OCL is a typed language. Each expression has a type which is either
explicitly declared or can be statically derived. Evaluation of
the expression yields a value of this type. Therefore, before we can
define expressions, we have to provide a model for the concept of
type. A metamodel for OCL types is shown in this section. Note that
instances of the classes in the metamodel are the types
themselves (e.g. Integer) not instances of the domain they represent
(e.g. -15, 0, 2, 3).
The model in Figure 5 shows the OCL types. The basic type is the UML
Classifier, which includes all subtypes of Classifier from the
UML infrastructure.
In the model the CollectionType and its subclasses and the TupleType
are special. One can never instantiate all collection types,
because there is an infinite number, especially when nested collections
are taken in account. Users will never instantiate these types
explicitly. Conceptually all these types do exist, but such a type
should be (lazily) instantiated by a tool, whenever it is needed
in an expression.
In comparison with UML 1.4 the type OclType has been removed from the
type hierarchy. This means that a Classifier is not a valid OCL
expression any more.

BagType
BagType is a collection type which describes a multiset of
elements where each element may occur multiple times in the bag.
The elements are unordered. Part of a BagType is the
declaration of the type of its elements.
CollectionType
CollectionType describes a list of elements of a particular
given type. CollectionType is an abstract class. Its
concrete subclasses are SetType, SequenceType and
BagType types. Part of every collection type is the declaration
of the type of its elements, i.e. a collection type is parameterized
with an element type. In the metamodel, this is shown as an
association from CollectionType to Classifier. Note
that there is no restriction on the element type of a collection type.
This means in particular that a collection type may be parameterized
with other collection types allowing collections to be nested
arbitrarily deep.
Associations
- elementType The type
of the elements in a collection. All elements in a collection must
conform to this type.
OclMessageType
OclMessageType describe ocl
messages. Like to the collection types, OclMessageType describes a set of
types in the standard library. Part of every OclMessageType is a reference to
the declaration of the type of its operation or signal, i.e. an ocl
message type is parameterized
with an operation or signal. In the metamodel, this is shown as an
association from OclMessageType
to Operation and to Signal. OclMessageType is part of the
abstract syntax of OCL, residing on M2 level. Its instances, called OclMessage, and subtypes of OclMessage, reside on M1 level.
Associations
- referredSignal
The Signal that is sent by the message.
- referredOperation The Operation that is
called by the message.
OclModelElementType
OclModelElementType represents the types of elements that
are ModelElements in the UML metamodel. It is used to be
able to refer to states and classifiers in e.g. oclInState(...)
and oclIsKindOf(...)
OrderedSetType
OrderedSetType is a collection type which describes a set of
elements where each distinct element occurs only once in the set.
The elements are ordered by their position in the sequence. Part of an OrderedSetType
is the declaration of the type of its elements.
SequenceType
SequenceType is a collection type which describes a list of
elements where each element may occur multiple times in the
sequence. The elements are ordered by their position in the sequence.
Part of a SequenceType is the declaration of the type of
its elements.
SetType
SetType is a collection type which describes a set of
elements where each distinct element occurs only once in the set.
The elements are not ordered. Part of a SetType is the
declaration of the type of its elements.
TupleType
TupleType (informaly known as record type or struct)
combines different types into a single aggregate type. The parts
of a TupleType are described by its attributes, each
having a name and a type. There is no restriction on the kind of
types that can be used as part of a tuple. In particular, a TupleType
may contain other tuple types and collection types. Each
attribute of a TupleType represents a single feature of a TupleType.
Each part is to uniquely identified by its name.
VoidType
VoidType represents a type that conforms to all types. The
only instance of VoidType is OclVoid, which is further
defined in the standard library. Furthermore OclVoid has
exactly one instance called OclUndefined.
Type Conformance
The type conformance rules are formally underpinned in the Semantics
section of the specification. To ensure that the rules are accessible
to UML modellers they are specified in this section using OCL. For
this, the additional operation conformsTo(c : Classifier) : Boolean
is defined on Classifier. It evaluates to true, if the self Classifier
conforms to the argument c. The following OCL statements define
type conformance for individual types.
BagType
- Different bag types conform to each other if their element
types
conform to each other.context BagType
inv: BagType.allInstances()->forAll(b |
self.elementType.conformsTo(b.elementType) implies
self.conformsTo(b))
Classifier
- Conformance is a transitive relationship.
context Classifier
inv Transitivity:
Classifier.allInstances()->forAll(x|Classifier.allInstances()
->forAll(y|
self.conformsTo(x) and
x.conformsTo(y)) implies self.conformsTo(y)))
- All classifiers except collections conform to OclAny.
context Classifier
inv: (not self.oclIsKindOf (CollectionType)) implies
Primitive.allInstances()->forAll(p | (p.name =
'OclAny') implies
self.conformsTo(p))
- Classes conform to superclasses and interfaces that they realize.
context Class
inv : self.generalization.parent->forAll (p |
(p.oclIsKindOf(Class) or p.oclIsKindOf(Interface))
implies
self.conformsTo(p.oclAsType(Classifier)))
- Interfaces conforms to super interfaces.
context Interface
inv : self.generalization.parent->forAll (p |
p.oclIsKindOf(Interface) implies
self.conformsTo(p.oclAsType(Interface)))
- The Conforms operation between Types is reflexive, a Classifier
always conform to itself.
context Classifier
inv: self.conformsTo(self)
- The Conforms operation between Types is anti-symmetric.
context Classifier
inv: Classifier.allInstances()->forAll(t1, t2 |
(t1.conformsTo(t2) and t2.conformsTo(t1)) implies t1
= t2)
CollectionType
- Specific collection types conform to collection type.
context CollectionType
inv: -- all instances of SetType, SequenceType, BagType conform to a
-- CollectionType if the elementTypes conform
CollectionType.allInstances()->forAll (c |
c.oclIsTypeOf(CollectionType) and
self.elementType.conformsTo(c.elementType) implies
self.conformsTo(c))
- Collections do not conform to any primitive type.
context CollectionType
inv: Primitive.allInstances()->forAll (p | not self.conformsTo(p))
- Collections of non-conforming types do not conform.
context CollectionType
inv: CollectionType.allInstances()->forAll (c |
(not self.elementType.conformsTo (c.elementType))
implies (not
self.conformsTo (c)))
OrderedSetType
- Different ordered set types conform to each other if their
element types conform to each other.
context OrderedSetType
inv: OrderedSetType.allInstances()->forAll(s |
self.elementType.conformsTo(s.elementType) implies
self.conformsTo(s))
Primitive
- Integer conforms to real.
context Primitive
inv: (self.name = 'Integer') implies
Primitive.allInstances()->forAll (p | (p.name =
'Real') implies
(self.conformsTo(p))))
SequenceType
- Different sequence types conform to each other if their element
types conform to each other.
context SequenceType
inv: SequenceType.allInstances()->forAll(s |
self.elementType.conformsTo(s.elementType) implies
self.conformsTo(s))
SetType
- Different set types conform to each other if their
element
types conform to each other.
context SetType
inv: SetType.allInstances()->forAll(s |
self.elementType.conformsTo(s.elementType) implies
self.conformsTo(s))
TupleType
- Tuple types conform to each other when their names and types
conform to each other. Note that allAttributes is an additional
operation in the UML 1.4.
context TupleType
inv: TupleType.allInstances()->forAll (t |
( t.allAttributes()->forAll (tp |
-- make sure at least one
tuplepart has the same name
-- (uniqueness of tuplepart names
will ensure that not two
-- tupleparts have the same name
within one tuple)
self.allAttributes()->exists(stp|stp.name = tp.name) and
-- make sure that all tupleparts
with the same name conforms.
self.allAttributes()->forAll(stp | (stp.name = tp.name) and
stp.type.conformsTo(tp.type))
)
implies
self.conformsTo(t)
) )
VoidType
- Void conforms to all other types.
context VoidType
inv: Classifier.allInstances()->forAll (c | self.conformsTo (c))
Well-formedness Rules for the Types Package
BagType
- The name of a bag type is "Bag" followed by the element type's
name in parentheses.
context BagType
inv: self.name = 'Bag(' + self.elementType.name + ')'
CollectionType
- The name of a collection type is "Collection"
followed by the
element type's name in parentheses.
context CollectionType
inv: self.name = 'Collection(' + self.elementType.name + ')'
Classifier
- For each classifier at most one of each of the different
collection types exist.\
context Classifier
inv: collectionTypes->select(oclIsTypeOf(CollectionType))->size()
<= 1
inv: collectionTypes->select(oclIsTypeOf(BagType ))->size() <=
1
inv: collectionTypes->select(oclIsTypeOf(SequenceType ))->size()
<= 1
inv: collectionTypes->select(oclIsTypeOf(SetType ))->size() <=
1
OclMessageType
- OclMessageType has either a link with a Signal or with an
operation, but not both.
context OclMessageType
inv: referredOperation->size() + referredSignal->size() = 1
- The parameters of the referredOperation become attributes of the
instance of OclMessageType.
context OclMessageType
inv: referredOperation->size() = 1 implies
self.feature =
referredOperation.parameter.asAttribute()
- The attributes of the referredSignal become attributes of the
instance of OclMessageType.
context OclMessageType
inv: referredSignal->size() = 1 implies
self.feature = referredSignal.feature
OrderedSetType
- The name of a set type is "OrderedSet" followed by the element
type's name in parentheses.
context OrderedSetType
inv: self.name = 'OrderedSet(' + self.elementType.name + ')'
SequenceType
- The name of a sequence type is "Sequence" followed by the
element type's name in parentheses.
context SequenceType
inv: self.name = 'Sequence(' + self.elementType.name + ')'
SetType
- The name of a set type is "Set" followed by the element type's
name in parentheses.
context SetType
inv: self.name = 'Set(' + self.elementType.name + ')'
TupleType
- The name of a tuple type includes the names of the individual
parts and the types of those parts.
context TupleType
inv: name =
'Tuple('.concat (
Sequence{1..allAttributes()->size()}->iterate (pn; s: String = ''
|
let p:
Attribute = allAttributes()->at (pn) in (
s.concat (
(if (pn>1) then ',' else ''
endif)
.concat (p.name).concat (':')
.concat (p.type.name)
)
)
)
).concat (')')
- All parts belonging to a tuple type have unique names.
context TupleType
inv: -- always true, because attributes must have unique names.
- A TupleType instance has only features that are Attributes (tuple
parts).
context TupleType
inv: feature->forAll (f | f.oclIsTypeOf(Attribute))