blob: 3a255d58fd7c52d67caf2057244a825e62c7bc71 [file] [log] [blame]
import 'Pivot.ecore'
include 'Types.ocl'
package ocl
context Constraint
inv UniqueName: _'context'.ownedRule->excluding(self)->forAll(name <> self.name or stereotype <> self.stereotype)
context Element
def: allOwnedElements() : Set(Element) =
--self->closure(oclContents())
oclContents()
--FIXME oclContainer() suspect on DomainElements
--def: owner : Element = oclContainer()
/**
* Elements that must be owned must have an owner.
*/
-- inv has_owner:
-- mustBeOwned() implies owner->notEmpty()
/**
* An element may not directly or indirectly own itself.
*/
inv not_own_self:
not allOwnedElements()->includes(self)
-- def: allOwnedElements() : Set(Element) =
-- ownedElement->union(ownedElement->collect(e | e.allOwnedElements()))->asSet()
-- def: mustBeOwned() : Boolean = true
context ParameterableElement
def: isCompatibleWith(p : ParameterableElement) : Boolean =
p.oclIsKindOf(self.oclType())
context Property
def: isAttribute(p : Property) : Boolean =
--Type.allInstances()->exists(c| c.ownedAttribute->includes(p))
let container : ocl::OclElement = oclContainer() in container.oclIsKindOf(Type) and container.oclAsType(Type).ownedAttribute->includes(self)
--inv DerivedIsInitialised: isDerived implies ownedRule->one(stereotype = 'derivation') or ownedRule->one(stereotype = 'initial')
inv CompatibleInitialiser: isDerived implies
let derivedConstraint : Constraint = ownedRule->any(stereotype = 'derivation') in
let initialConstraint : Constraint = ownedRule->any(stereotype = 'initial') in
let derivedSpecification : ValueSpecification = if derivedConstraint <> null then derivedConstraint.specification else null endif in
let initialSpecification : ValueSpecification = if initialConstraint <> null then initialConstraint.specification else null endif in
let initialiser: ValueSpecification = if derivedSpecification <> null then derivedSpecification else initialSpecification endif in
initialiser <> null and initialiser.oclIsKindOf(ExpressionInOcl) implies CompatibleBody(initialiser)
context Operation
inv CompatibleReturn:
let bodyConstraint : Constraint = ownedRule->any(stereotype = 'body') in
bodyConstraint <> null implies
let bodySpecification : ValueSpecification = bodyConstraint.specification in
bodySpecification <> null and bodySpecification.oclIsKindOf(ExpressionInOcl) implies CompatibleBody(bodySpecification)
context TypedMultiplicityElement
def: CompatibleBody(bodySpecification : ValueSpecification) : Boolean =
let bodyType : Type = bodySpecification.type in
if bodyType.oclIsKindOf(CollectionType) then
let bodyCollectionType : CollectionType = bodyType.oclAsType(CollectionType) in
let bodyElementType : Type = bodyCollectionType.elementType in
bodyElementType.conformsTo(self.type)
and self.isOrdered = (bodyCollectionType.conformsTo(OrderedSet(OclAny)) or bodyCollectionType.conformsTo(Sequence(OclAny)))
and self.isUnique = (bodyCollectionType.conformsTo(OrderedSet(OclAny)) or bodyCollectionType.conformsTo(Set(OclAny)))
else
bodyType.conformsTo(self.type)
endif
def: makeParameter() : Parameter = Parameter{name='name'}
---ExpressionWFRs.ocl-----
--context PropertyCallExp
/** The type of the call expression is the type of the referred property. */
--inv TypeIsReferredPropertyType: type = referredProperty.type
context BooleanLiteralExp
/** The type of a boolean Literal expression is the type Boolean. */
inv TypeIsBoolean: self.type = Boolean
context CollectionLiteralExp
/** 'Collection' is an abstract class on the M1 level and has no M0 instances. */
inv CollectionKindIsConcrete: kind <> CollectionKind::Collection
context CollectionLiteralExp
/** The type of a collection literal expression is determined by the collection kind selection and the common
supertype of all elements. Note that the definition below defines only an upper bound on the elementType. The usage of
the CollectionLiteralExp defines a lower bound. If the elementType is not explicitly specified, the elementType must be
chosen to ensure the well-formedness of the elements of the CollectionLiteralExp and the usage of the
CollectionLiteralExp.
For instance in
acc : Set(Real) = Set{1}->excluding(-1)
Set{1} is well formed for any type Set(T) where T ≤ UnlimitedNatural. Well-formedness of the excluding operation call
requires T ≤ Integer, and well-formedness of the initializer requires Real ≤ T. The overall expression is therefore only
well-formed if Real ≤ T ≤ Integer. Either Set(Real) or Set(Integer) are well-formed. The most general type, Set(Real), is
recommended since it minimizes type conversions and can often be easily deduced by considering the result type.
*/
inv SetKindIsSet: kind = CollectionKind::Set implies type.oclIsKindOf (SetType)
inv OrderedSetKindIsOrderedSet: kind = CollectionKind::OrderedSet implies type.oclIsKindOf (OrderedSetType)
inv SequenceKindIsSequence: kind = CollectionKind::Sequence implies type.oclIsKindOf (SequenceType)
inv BagKindIsBag: kind = CollectionKind::Bag implies type.oclIsKindOf (BagType)
--inv ElementTypeIsCommonElementType: let elementType : Type = part->iterate (p; c : Classifier = OclVoid | c.commonSuperType (p.type))
--in elementType.conformsTo(type.oclAsType (CollectionType).elementType)
/* CollectionLiteralPart
No additional well-formedness rules. */
context CollectionItem
/** The type of a CollectionItem is the type of the item expression. */
inv TypeIsItemType: type = item.type
--context CollectionRange
/** The type of a CollectionRange is the common supertype of the expressions taking part in the range. */
--inv TypeIsCommonType: type = first.type.commonSuperType (last.type)
context EnumLiteralExp
/** The type of an enum Literal expression is the type of the referred literal. */
inv TypeIsEnumerationType: self.type = referredEnumLiteral.enumeration
context IfExp
/** The type of the condition of an if expression must be Boolean. */
inv ConditionTypeIsBoolean: self.condition.type = Boolean
/* The type of the if expression is the most common supertype of the else and then expressions. */
--context IfExp
--inv TypeIsCommonType: self.type = thenExpression.type.commonSuperType(elseExpression.type)
context IntegerLiteralExp
/** The type of an integer Literal expression is the type Integer. */
inv TypeIsInteger: self.type = Integer
context IteratorExp
/** There is exactly one iterator. */
inv AnyHasOneIterator: name = 'any' implies iterator->size() = 1
context IteratorExp
/** The type is the same as the source element type */
inv AnyTypeIsSourceElementType: name = 'any' implies type = source.type.oclAsType(CollectionType).elementType
context IteratorExp
/** The type of the body must be Boolean. */
inv AnyBodyTypeIsBoolean: name = 'any' implies _'body'.type = 'Boolean'
context IteratorExp
/** There is exactly one iterator. */
inv ClosureHasOneIterator: name = 'closure' implies iterator->size() = 1
context IteratorExp
/** The collection type for an OrderedSet or a Sequence source type is OrderedSet.
* For any other source the collection type is Set. */
inv ClosureTypeIsUniqueCollection: name = 'closure' implies
if source.type.oclIsKindOf(SequenceType) or source.type.oclIsKindOf(OrderedSetType) then
type.oclIsKindOf(OrderedSetType)
else
type.oclIsKindOf(SetType)
endif
context IteratorExp
/** The source element type is the same as type of the body elements or element. */
inv ClosureSourceElementTypeIsBodyElementType: name = 'closure' implies
source.type.oclAsType(CollectionType).elementType =
if _'body'.type.oclIsKindOf(CollectionType)
then _'body'.type.oclAsType(CollectionType).elementType
else _'body'.type
endif
context IteratorExp
/** The element type is the same as the source element type. */
inv ClosureElementTypeIsSourceElementType: name = 'closure' implies
type.oclAsType(CollectionType).elementType
= source.type.oclAsType(CollectionType).elementType
context IteratorExp
/** There is exactly one iterator. */
inv CollectHasOneIterator: name = 'collect' implies iterator->size() = 1
context IteratorExp
/* The collection type for an OrderedSet or a Sequence type is a Sequence,
* the result type for any other collection type is a Bag.
*/
inv CollectTypeIsUnordered: name = 'collect' implies
if source.type.oclIsKindOf(SequenceType) or source.type.oclIsKindOf(OrderedSetType) then
type.oclIsKindOf(SequenceType)
else
type.oclIsKindOf(BagType)
endif
context IteratorExp
/** The element type is the type of the body elements. */
inv CollectElementTypeIsSourceElementType: name = 'collect' implies
type.oclAsType(CollectionType).elementType =
_'body'.type.oclAsType(CollectionType).elementType
context IteratorExp
/** There is exactly one iterator. */
inv CollectNestedHasOneIterator: name = 'collectNested' implies iterator->size() = 1
context IteratorExp
/** The type is a Bag. */
inv CollectNestedTypeIsBag: name = 'collectNested' implies type.oclIsKindOf(BagType)
context IteratorExp
/** The type is the type of source. */
inv CollectNestedTypeIsBodyType: name = 'collectNested' implies type = _'body'.type
context IteratorExp
/** The type must be Boolean. */
inv ExistsTypeIsBoolean: name = 'exists' implies type = Boolean
context IteratorExp
/** The type of the body must be Boolean. */
inv ExistsBodyTypeIsBoolean: name = 'exists' implies _'body'.type = Boolean
context IteratorExp
/** The type must be Boolean. */
inv ForAllTypeIsBoolean: name = 'forAll' implies type = Boolean
context IteratorExp
/** The type of the body must be Boolean. */
inv ForAllBodyTypeIsBoolean: name = 'forAll' implies _'body'.type = Boolean
context IteratorExp
/** There is exactly one iterator. */
inv IsUniqueHasOneIterator: name = 'isUnique' implies iterator->size() = 1
context IteratorExp
/** The type must be Boolean. */
inv IsUniqueTypeIsBoolean: name = 'isUnique' implies type = Boolean
context IteratorExp
/** There is exactly one iterator. */
inv OneHasOneIterator: name = 'one' implies iterator->size() = 1
context IteratorExp
/** The type is Boolean */
inv OneTypeIsBoolean: name = 'one' implies type = Boolean
context IteratorExp
/** The type of the body must be Boolean. */
inv OneBodyTypeIsBoolean: name = 'one' implies _'body'.type = Boolean
context IteratorExp
/** There is exactly one iterator. */
inv RejectOrSelectHasOneIterator: name = 'reject' or name = 'select' implies iterator->size() = 1
context IteratorExp
/** The type is the same as the source. */
inv RejectOrSelectTypeIsSourceType: name = 'reject' or name = 'select' implies type = source.type
context IteratorExp
/** The type of the body must be Boolean. */
inv RejectOrSelectTypeIsBoolean: name = 'reject' or name = 'select' implies type = Boolean
context IteratorExp
/** There is exactly one iterator. */
inv SortedByHasOneIterator: name = 'sortedBy' implies iterator->size() = 1
context IteratorExp
/** The collection type for an OrderedSet or a Sequence type is a Sequence, the result type for any other collection type is Bag. */
inv SortedByIsOrderedIfSourceIsOrdered: name = 'sortedBy' implies
if source.type.oclIsKindOf(SequenceType) or source.type.oclIsKindOf(BagType) then
type.oclIsKindOf(SequenceType)
else
type.oclIsKindOf(OrderedSetType)
endif
context IteratorExp
/** The element type is the type of the body elements. */
inv SortedByElementTypeIsSourceElementType: name = 'sortedBy' implies
type.oclAsType(CollectionType).elementType =
_'body'.type.oclAsType(CollectionType).elementType
context IterateExp
/** The type of the iterate is the type of the result variable. */
inv TypeIsResultType: type = result.type
context IterateExp
/** The type of the body expression must conform to the declared type of the result variable. */
inv BodyTypeConformsToResultType: _'body'.type.conformsTo(result.type)
context IterateExp
/** A result variable must have an init expression. */
inv OneInitializer: self.result.initExpression->size() = 1
/*------------- unescaped in */
context LetExp
/** The type of a Let expression is the type of the in expression. */
inv TypeIsInType: type = _'in'.type
/** LiteralExp
No additional well-formedness rules. */
context LoopExp
/** The type of the source expression must be a collection. */
inv SourceIsCollection: source.type.oclIsKindOf (CollectionType)
context LoopExp
/** The loop variable of an iterator expression has no init expression. */
inv NoInitializers: self.iterator->forAll(initExpression->isEmpty())
context IteratorExp
/** The type of each iterator variable must be the type of the elements of the source collection. */
inv IteratorTypeIsSourceElementType: self.iterator->forAll(type = source.type.oclAsType (CollectionType).elementType)
/** FeatureCallExp
No additional well-formedness rules. */
/** NumericLiteralExp
No additional well-formedness rules. */
/** OclExpression
No additional well-formedness rules. */
--context MessageExp
/** If the message is an operation call action, the arguments must conform to the parameters of the operation. */
--inv: calledOperation->notEmpty() implies
--argument->forAll (a | a.type.conformsTo
--(self.calledOperation.operation.ownedParameter->
--select( kind = ParameterDirectionKind::_'in' )
--->at (argument->indexOf (a)).type))
--context MessageExp
/** If the message is a send signal action, the arguments must conform to the attributes of the signal. */
--inv: sentSignal->notEmpty() implies
--argument->forAll (a | a.type.conformsTo
--(self.sentSignal.signal.ownedAttribute
--->at (argument->indexOf (a)).type))
--context MessageExp
/** If the message is a call operation action, the operation must be an operation of the type of the target expression. */
--inv: calledOperation->notEmpty() implies
--target.type.allOperations()->includes(calledOperation.operation)
context MessageExp
/** An OCL message has either a called operation or a sent signal. */
inv OneCallOrOneSend: calledOperation->size() + sentSignal->size() = 1
context MessageExp
/** The target of an OCL message cannot be a collection. */
inv TargetIsNotACollection: not target.type.oclIsKindOf (CollectionType)
/*------------- spelling: arguments */
--context OperationCallExp
/** All the arguments must conform to the parameters of the referred operation. */
/*inv ArgumentType:
let operation : Operation = self.referredOperation in
let parameters : OrderedSet(Parameter) = operation.ownedParameter in
let selfType : Type = operation.owningType in
Sequence{1..argument->size()}->forAll (i |
let argument : OclExpression = argument->at(i) in
let parameter : Parameter = parameters->at(i) in
let parameterType : Type = parameter.type in
argument.type.conformsTo(parameterType.resolveSelfType(selfType))) */
/*------------- spelling: arguments */
context OperationCallExp
/** There must be exactly as many arguments as the referred operation has parameters. */
inv ArgumentCount: argument->size() = referredOperation.ownedParameter->size()
--context OperationCallExp
/** An additional attribute refParams lists all parameters of the referred operation except the return and out parameter(s). */
--def: refParams: Sequence(Parameter) = referredOperation.ownedParameter->select (p |
--p.kind <> ParameterDirectionKind::return or
--p.kind <> ParameterDirectionKind::out)
endpackage