Commit 7799fb35 authored by Martti Käärik's avatar Martti Käärik
Browse files

Updated constraints from part 1

parent b00f5d95
Loading
Loading
Loading
Loading
+82 −56
Original line number Diff line number Diff line
@@ -10,9 +10,6 @@ context NamedElement

  -- Distinguishable qualified names
  inv DistinquishableName ('All qualified names of instances of \'NamedElement\'s shall be distinguishable within a TDL model.' + self.toString()):
--        TODO: Weird workaround, not sure why it is needed
        self.oclIsTypeOf(EnumDataType) 
        or 
        NamedElement.allInstances()->one(e | e.qualifiedName = self.qualifiedName)
  

@@ -266,33 +263,57 @@ context EnumDataType

context DataUse
  -- Occurrence of 'argument' and 'reduction'
  inv ArgumentReductionLists ('Only in case of a \'FunctionCall\' both the \'argument\' list and the \'reduction\' list may be provided, otherwise either the \'argument\' list, the \'reduction\' list, or none of them shall be provided.' + self.toString()):
  inv ArgumentReductionLists ('Only in case of a \'FunctionCall\', or a \'DataElementUse\' which refers to a \'Function\', both the \'argument\' list and the \'reduction\' list may be provided, otherwise either the \'argument\' list, the \'reduction\' list, or none of them shall be provided.' + self.toString()):
        self.argument->isEmpty() or self.reduction->isEmpty() or self.oclIsTypeOf(FunctionCall)
      or (self.oclIsTypeOf(DataElementUse) 
           and self.oclAsType(DataElementUse).dataElement.oclIsTypeOf(Function))
  

  -- Structured data types in 'reduction' set
  inv ReductionMembers ('The \'Member\' referenced by the \'MemberReference\' at index i of a \'reduction\' shall be contained in or inherited by the \'StructuredDataType\' of the \'Member\' referenced by the \'MemberReference\' at index (i - 1) of that \'reduction\'.' + self.toString()):
        not self.resolveDataType().oclIsKindOf(StructuredDataType)
      or self.reduction->isEmpty()
      or self.resolveDataType().oclAsType(StructuredDataType).allMembers()->includes(self.reduction->first().member)
      and self.reduction->select(m | self.reduction->indexOf(m) > 1)->forAll(m |
              self.reduction->at(self.reduction->indexOf(m)-1).member.dataType.oclIsKindOf(StructuredDataType)
          and self.reduction->at(self.reduction->indexOf(m)-1).member.dataType.oclAsType(StructuredDataType).allMembers()
      ->includes(m.member))
  -- Members in 'reduction' list
  inv ReductionMembers ('The \'Member\' referenced by the \'MemberReference\' at index i of a \'reduction\' shall be contained in or inherited by the \'StructuredDataType\' of the \'Member\' referenced by the \'MemberReference\' at index (i - 1) of that \'reduction\' or the \'StructuredDataType\' of this \'DataUse\' if the \'MemberReference\' is the first element of the \'reduction\'.' + self.toString()):
        self.reduction->isEmpty()
              or self.reduction->reject(r | self.reduction->indexOf(r) = 1) 
              ->iterate(r; acc = Sequence{Sequence{self.resolveBaseDataType(), self.reduction->at(1)}} 
          	    | acc->including(Sequence{self.reduction->at(self.reduction->indexOf(r) - 1)->asSequence()
          		    ->reject(r|r.member.oclIsUndefined()).member.dataType->including(self.resolveBaseDataType())->at(1), r
          	    }))
              ->reject(tr | tr->at(1).oclIsUndefined() or tr->at(2).oclAsType(MemberReference).member.oclIsUndefined())
              ->iterate(tr; acc = Sequence{} | acc->including(Sequence{tr->at(1)->asSequence()
          	    ->select(t|t.oclIsKindOf(CollectionDataType)).oclAsType(CollectionDataType).itemType->including(tr->at(1))->at(1), tr->at(2) 
              }))
              ->forAll(tr | tr->at(1).oclAsType(StructuredDataType).allMembers()->includes(tr->at(2).oclAsType(MemberReference).member))
  

  -- No member with collection index in the first element in reduction
  inv FirstReduction ('The first \'MemberReference\' in reduction shall not specify both member and collectionIndex. ' + self.toString()):
        self.reduction->first().member.oclIsUndefined() or self.reduction->first().collectionIndex.oclIsUndefined()
  -- Collection index of first 'reduction'
  inv ReductionMembers ('If the \'member\' is not specified for the first element of the \'reduction\' then the type of this \'DataUse\' shall be \'CollectionDataType\'.' + self.toString()):
        self.reduction->isEmpty()
              or not self.reduction->at(1).member.oclIsUndefined()
              or self. resolveBaseDataType().oclIsKindOf(CollectionDataType)
  



context ParameterBinding
  -- Matching data type
  inv ParameterBindingTypes ('The provided \'DataUse\' shall conform to the \'DataType\' of the referenced \'Parameter\'.' + self.toString()):
        self.dataUse.resolveDataType().conformsTo(self.resolveParameterType())
        or self.dataUse.oclIsKindOf(SpecialValueUse)
  -- Members in 'reduction' list of parameter
  inv ReductionMembers ('The \'Member\' referenced by the \'MemberReference\' at index i of a \'reduction\' shall be contained in or inherited by the \'StructuredDataType\' of the \'Member\' referenced by the \'MemberReference\' at index (i - 1) of that \'reduction\' or the \'StructuredDataType\' of the \'parameter\' if the \'MemberReference\' is the first element of the \'reduction\'.' + self.toString()):
        self.reduction->isEmpty()
              or self.reduction->reject(r | self.reduction->indexOf(r) = 1) 
              ->iterate(r; acc = Sequence{Sequence{self.parameter.dataType, self.reduction->at(1)}} 
          	    | acc->including(Sequence{self.reduction->at(self.reduction->indexOf(r) - 1)->asSequence()
          		    ->reject(r|r.member.oclIsUndefined()).member.dataType->including(self.parameter.dataType)->at(1), r
          	    }))
              ->reject(tr | tr->at(1).oclIsUndefined() or tr->at(2).oclAsType(MemberReference).member.oclIsUndefined())
              ->iterate(tr; acc = Sequence{} | acc->including(Sequence{tr->at(1)->asSequence()
          	    ->select(t|t.oclIsKindOf(CollectionDataType)).oclAsType(CollectionDataType).itemType->including(tr->at(1))->at(1), tr->at(2) 
              }))
              ->forAll(tr | tr->at(1).oclAsType(StructuredDataType).allMembers()->includes(tr->at(2).oclAsType(MemberReference).member))
  

  -- Collection index of first 'reduction' of parameter
  inv ReductionMembers ('If the \'member\' is not specified for the first element of the \'reduction\' then the type of the \'parameter\' shall be \'CollectionDataType\'.' + self.toString()):
        self.reduction->isEmpty()
              or not self.reduction->at(1).member.oclIsUndefined()
              or self.parameter.dataType.oclIsKindOf(CollectionDataType)
  

  -- Use of a 'StructuredDataInstance' with non-optional 'Member's
@@ -305,10 +326,10 @@ context ParameterBinding

context MemberReference
  -- Collection index expressions for collections only
  inv CollectionIndex ('If the type of the related \'DataUse\' is not \'CollectionDataType\' then the collectionIndex shall be undefined. ' + self.toString()):
  inv CollectionIndex ('If the \'member\' is specified and the type of the \'member\' is not \'CollectionDataType\' then the collectionIndex shall be undefined. ' + self.toString()):
        self.collectionIndex.oclIsUndefined()
              or self.container().oclIsTypeOf(ParameterBinding) --and self.container().oclAsType(ParameterBinding).resolveDataType().oclIsKindOf(CollectionDataType)
              or self.container().oclAsType(DataUse).resolveDataType().oclIsKindOf(CollectionDataType)
              or self.member.oclIsUndefined()
              or self.member.dataType.oclIsKindOf(CollectionDataType)
  

  -- Either member or collection index is required
@@ -376,7 +397,7 @@ context PredefinedFunctionCall

context LiteralValueUse
  -- Exactly one value specification
  inv SpecifiedLiteralValue ('There shall be exactly one value specification, where either the \'value\', or the \'intValue\', or the \'boolValue\' property is be specified, but not more than one of them.' + self.toString()):
  inv SpecifiedLiteralValue ('There shall be exactly one value specification, where either the \'value\', or the \'intValue\', or the \'boolValue\' property is specified, but not more than one of them.' + self.toString()):
        not self.value.oclIsUndefined() 
          xor not self.intValue.oclIsUndefined() 
          xor not self.boolValue.oclIsUndefined()
@@ -406,8 +427,12 @@ context DataElementUse
  -- 'DataElement' reference or non-empty 'argument' or non-empty 'item'
  inv DataInstanceOrArgumentsOrItemsInDataElementUse ('If a \'dataElement\' is not specified, or if the \'dataElement\' is resolved to a \'StructuredDataType\' or a \'CollectionDataType\', either a non-empty \'argument\' set or a non-empty \'item\' set shall be specified.' + self.toString()):
        not (self.dataElement.oclIsUndefined() and self.argument->isEmpty() and self.item->isEmpty())
          and (self.dataElement.oclIsKindOf(StructuredDataInstance) or not (self.resolveDataType().oclIsKindOf(StructuredDataType) and self.argument->isEmpty()))
          and (self.dataElement.oclIsKindOf(CollectionDataInstance) or not (self.resolveDataType().oclIsKindOf(CollectionDataType) and self.item->isEmpty()))
                and (self.dataElement.oclIsKindOf(StructuredDataInstance) 
                      or not (self.resolveDataType().oclIsKindOf(StructuredDataType) 
                          and self.argument->isEmpty()))
                and (self.dataElement.oclIsKindOf(CollectionDataInstance) 
                      or not (self.resolveDataType().oclIsKindOf(CollectionDataType) 
                          and self.item->isEmpty()))
  

  -- Valid 'DataType' for items
@@ -425,14 +450,20 @@ context DataElementUse

  -- Matching parameters for 'Function's
  inv FunctionCallParameters ('All \'FormalParameter\'s shall be bound if the \'dataElement\' refers to a \'Function\'.' + self.toString()):
        self.dataElement.oclIsUndefined()
        or 
        not self.dataElement.oclIsKindOf(Function)
        not self.dataElement.oclIsTypeOf(Function)
      or self.dataElement.oclAsType(Function).formalParameter->forAll(p | self.argument->exists(a | a.parameter = p))
  



context CastDataUse
  -- Compatible 'DataType's
  inv CompatibleDataTypesInCastDataUse ('The specified \'dataType\' shall directly or indirectly extend the resolved \'DataType\' of the specified \'dataUse\'.' + self.toString()):
        self.dataType.conformsTo(self.dataUse.resolveDataType())
  



context TimeLabelUse
  -- Empty 'argument' and 'reduction' sets
  inv TimeLabelArgumentReduction ('The \'argument\' and \'reduction\' sets shall be empty.' + self.toString()):
@@ -700,31 +731,30 @@ context AlternativeBehaviour

  -- First behaviour of 'Block's
  inv FirstBlockBehaviour ('Each block of an \'AlternativeBehaviour\' shall start with a tester-input event. ' + self.toString()):
        self.block->forAll(b | b.behaviour->isEmpty() or b.behaviour->first().isTesterInputEvent())
        self.block->forAll(b | b.behaviour->first().isTesterInputEvent())
  

  -- Same component if locally ordered
  inv AlternativeBlocksComponent ('If the containing \'TestDescription\' is locally ordered then all \'Block\'s shall start with a tester-input event of the same \'ComponentInstance\'. ' + self.toString()):
        let initials = self.block->reject(b | b.behaviour->first()->isEmpty() or b.behaviour->first().oclIsKindOf(OptionalBehaviour)).behaviour->first()
          in
        let initial = self.block.behaviour->first() in
          Set{}
          ->union(initials->select(oclIsKindOf(Interaction)).oclAsType(Interaction).target.targetGate.component)
          ->union(initials->select(oclIsKindOf(Quiescence)).oclAsType(Quiescence).componentInstance)
          ->union(initials->select(oclIsKindOf(TimeOut)).oclAsType(TimeOut).componentInstance)
          ->including(initial->select(oclIsKindOf(Interaction)).oclAsType(Interaction).target.targetGate.component)
          ->including(initial->select(oclIsKindOf(Quiescence)).oclAsType(Quiescence).componentInstance)
          -> including(initial->select(oclIsKindOf(TimeOut)).oclAsType(TimeOut).componentInstance)
          ->size() = 1 or not self.getParentTestDescription().isLocallyOrdered
  

  -- Tester participating in locally ordered case
  inv AlternativeBehaviourParticipation ('If the \'AlternativeBehaviour\' is contained in a locally ordered \'TestDescription\' then no other tester \'ComponentInstance\' shall participate in any block than the target of the first tester-input event and \'ComponentInstance\'s participating in blocks of contained \'OptionalBehaviour\'s. ' + self.toString()):
        let initials = self.block->reject(b | b.behaviour->first()->isEmpty() or b.behaviour->first().oclIsKindOf(OptionalBehaviour)).behaviour->first(),
        let initial = self.block.behaviour->first(),
          targetComponent = Set{}
          ->union(initials->select(oclIsKindOf(Interaction)).oclAsType(Interaction).target.targetGate.component)
          ->union(initials->select(oclIsKindOf(Quiescence)).oclAsType(Quiescence).componentInstance)
          -> union(initials->select(oclIsKindOf(TimeOut)).oclAsType(TimeOut).componentInstance),
          ->including(initial->select(oclIsKindOf(Interaction)).oclAsType(Interaction).target.targetGate.component)
          ->including(initial->select(oclIsKindOf(Quiescence)).oclAsType(Quiescence).componentInstance)
          -> including(initial->select(oclIsKindOf(TimeOut)).oclAsType(TimeOut).componentInstance),
          nonOptionalBlocks = self.block->closure(
              b | b.behaviour->reject(oclIsKindOf(OptionalBehaviour))
                  ->select(oclIsKindOf(SingleCombinedBehaviour)).oclAsType(SingleCombinedBehaviour).block
              ->union(b.behaviour
              ->union(b.behaviour->reject(oclIsKindOf(OptionalBehaviour))
                  ->select(oclIsKindOf(MultipleCombinedBehaviour)).oclAsType(MultipleCombinedBehaviour).block)
          )
          in
@@ -735,18 +765,14 @@ context AlternativeBehaviour

  -- OptionalBehaviour in locally ordered case
  inv OptionalAlternativeBehaviour ('A block of an \'AlternativeBehaviour\' if the containing \'TestDescription\' is locally ordered, shall only contain \'OptionalBehaviour\'(s) whose source \'ComponentInstance\' is the same as the target of the first tester-input event of that \'Block\'. ' + self.toString()):
        let initials = self.block->reject(b | b.behaviour->first()->isEmpty() or b.behaviour->first().oclIsKindOf(OptionalBehaviour)).behaviour->first(),
        let initial = self.block.behaviour->first(),
          targetComponent = Set{}
          ->union(initials->select(oclIsKindOf(Interaction)).oclAsType(Interaction).target.targetGate.component)
          ->union(initials->select(oclIsKindOf(Quiescence)).oclAsType(Quiescence).componentInstance)
          -> union(initials->select(oclIsKindOf(TimeOut)).oclAsType(TimeOut).componentInstance),
          optionalBlocks = self.block->closure(
            b | b.behaviour->select(oclIsKindOf(SingleCombinedBehaviour)).oclAsType(SingleCombinedBehaviour).block
            ->union(b.behaviour->select(oclIsKindOf(MultipleCombinedBehaviour)).oclAsType(MultipleCombinedBehaviour).block)
          )->select(oclIsKindOf(OptionalBehaviour))
          ->including(initial->select(oclIsKindOf(Interaction)).oclAsType(Interaction).target.targetGate.component)
          ->including(initial->select(oclIsKindOf(Quiescence)).oclAsType(Quiescence).componentInstance)
          -> including(initial->select(oclIsKindOf(TimeOut)).oclAsType(TimeOut).componentInstance)
          in
            optionalBlocks->isEmpty()
            or optionalBlocks->first().oclAsType(Interaction).sourceGate.component->forAll(c | targetComponent->includes(c))
          self.block.behaviour->select(oclIsKindOf(OptionalBehaviour)) .oclAsType(OptionalBehaviour).block
              ->first().oclAsType(Interaction).sourceGate.component->forAll(c | targetComponent->includes(c))
          or not self.getParentTestDescription().isLocallyOrdered
  

@@ -755,13 +781,13 @@ context AlternativeBehaviour
context ConditionalBehaviour
  -- Guard for 'ConditionalBehaviour' with single block
  inv ConditionalFirstGuard ('If there is only one \'Block\' specified, it shall have a \'guard\'.' + self.toString()):
        self.block->size() > 1 or self.block->first().guard->size() > 0
        self.block->size() > 1 or self.block->first().guard->size() > 1
  

  -- Possible else block for 'ConditionalBehaviour' with multiple blocks
  inv ConditionalLastGuard ('All \'Block\'s specified, except the last one, shall have a \'guard\'.' + self.toString()):
        self.block->size() = 1
      or self.block->forAll(b | b = self.block->last() or b.guard ->size() > 1)
      or self.block->forAll(b | b = self.block->last() or b.guard ->size() > 0)