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 Original line Diff line number Diff line
@@ -10,9 +10,6 @@ context NamedElement


  -- Distinguishable qualified names
  -- Distinguishable qualified names
  inv DistinquishableName ('All qualified names of instances of \'NamedElement\'s shall be distinguishable within a TDL model.' + self.toString()):
  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)
        NamedElement.allInstances()->one(e | e.qualifiedName = self.qualifiedName)
  
  


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


context DataUse
context DataUse
  -- Occurrence of 'argument' and 'reduction'
  -- 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)
        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
  -- 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\'.' + self.toString()):
  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()):
        not self.resolveDataType().oclIsKindOf(StructuredDataType)
        self.reduction->isEmpty()
      or self.reduction->isEmpty()
              or self.reduction->reject(r | self.reduction->indexOf(r) = 1) 
      or self.resolveDataType().oclAsType(StructuredDataType).allMembers()->includes(self.reduction->first().member)
              ->iterate(r; acc = Sequence{Sequence{self.resolveBaseDataType(), self.reduction->at(1)}} 
      and self.reduction->select(m | self.reduction->indexOf(m) > 1)->forAll(m |
          	    | acc->including(Sequence{self.reduction->at(self.reduction->indexOf(r) - 1)->asSequence()
              self.reduction->at(self.reduction->indexOf(m)-1).member.dataType.oclIsKindOf(StructuredDataType)
          		    ->reject(r|r.member.oclIsUndefined()).member.dataType->including(self.resolveBaseDataType())->at(1), r
          and self.reduction->at(self.reduction->indexOf(m)-1).member.dataType.oclAsType(StructuredDataType).allMembers()
          	    }))
      ->includes(m.member))
              ->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
  -- Collection index of first 'reduction'
  inv FirstReduction ('The first \'MemberReference\' in reduction shall not specify both member and collectionIndex. ' + self.toString()):
  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->first().member.oclIsUndefined() or self.reduction->first().collectionIndex.oclIsUndefined()
        self.reduction->isEmpty()
              or not self.reduction->at(1).member.oclIsUndefined()
              or self. resolveBaseDataType().oclIsKindOf(CollectionDataType)
  
  






context ParameterBinding
context ParameterBinding
  -- Matching data type
  -- Members in 'reduction' list of parameter
  inv ParameterBindingTypes ('The provided \'DataUse\' shall conform to the \'DataType\' of the referenced \'Parameter\'.' + self.toString()):
  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.dataUse.resolveDataType().conformsTo(self.resolveParameterType())
        self.reduction->isEmpty()
        or self.dataUse.oclIsKindOf(SpecialValueUse)
              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
  -- Use of a 'StructuredDataInstance' with non-optional 'Member's
@@ -305,10 +326,10 @@ context ParameterBinding


context MemberReference
context MemberReference
  -- Collection index expressions for collections only
  -- 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()
        self.collectionIndex.oclIsUndefined()
              or self.container().oclIsTypeOf(ParameterBinding) --and self.container().oclAsType(ParameterBinding).resolveDataType().oclIsKindOf(CollectionDataType)
              or self.member.oclIsUndefined()
              or self.container().oclAsType(DataUse).resolveDataType().oclIsKindOf(CollectionDataType)
              or self.member.dataType.oclIsKindOf(CollectionDataType)
  
  


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


context LiteralValueUse
context LiteralValueUse
  -- Exactly one value specification
  -- 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() 
        not self.value.oclIsUndefined() 
          xor not self.intValue.oclIsUndefined() 
          xor not self.intValue.oclIsUndefined() 
          xor not self.boolValue.oclIsUndefined()
          xor not self.boolValue.oclIsUndefined()
@@ -406,8 +427,12 @@ context DataElementUse
  -- 'DataElement' reference or non-empty 'argument' or non-empty 'item'
  -- '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()):
  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())
        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(StructuredDataInstance) 
          and (self.dataElement.oclIsKindOf(CollectionDataInstance) or not (self.resolveDataType().oclIsKindOf(CollectionDataType) and self.item->isEmpty()))
                      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
  -- Valid 'DataType' for items
@@ -425,14 +450,20 @@ context DataElementUse


  -- Matching parameters for 'Function's
  -- Matching parameters for 'Function's
  inv FunctionCallParameters ('All \'FormalParameter\'s shall be bound if the \'dataElement\' refers to a \'Function\'.' + self.toString()):
  inv FunctionCallParameters ('All \'FormalParameter\'s shall be bound if the \'dataElement\' refers to a \'Function\'.' + self.toString()):
        self.dataElement.oclIsUndefined()
        not self.dataElement.oclIsTypeOf(Function)
        or 
        not self.dataElement.oclIsKindOf(Function)
      or self.dataElement.oclAsType(Function).formalParameter->forAll(p | self.argument->exists(a | a.parameter = p))
      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
context TimeLabelUse
  -- Empty 'argument' and 'reduction' sets
  -- Empty 'argument' and 'reduction' sets
  inv TimeLabelArgumentReduction ('The \'argument\' and \'reduction\' sets shall be empty.' + self.toString()):
  inv TimeLabelArgumentReduction ('The \'argument\' and \'reduction\' sets shall be empty.' + self.toString()):
@@ -700,31 +731,30 @@ context AlternativeBehaviour


  -- First behaviour of 'Block's
  -- First behaviour of 'Block's
  inv FirstBlockBehaviour ('Each block of an \'AlternativeBehaviour\' shall start with a tester-input event. ' + self.toString()):
  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
  -- 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()):
  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()
        let initial = self.block.behaviour->first() in
          in
          Set{}
          Set{}
          ->union(initials->select(oclIsKindOf(Interaction)).oclAsType(Interaction).target.targetGate.component)
          ->including(initial->select(oclIsKindOf(Interaction)).oclAsType(Interaction).target.targetGate.component)
          ->union(initials->select(oclIsKindOf(Quiescence)).oclAsType(Quiescence).componentInstance)
          ->including(initial->select(oclIsKindOf(Quiescence)).oclAsType(Quiescence).componentInstance)
          ->union(initials->select(oclIsKindOf(TimeOut)).oclAsType(TimeOut).componentInstance)
          -> including(initial->select(oclIsKindOf(TimeOut)).oclAsType(TimeOut).componentInstance)
          ->size() = 1 or not self.getParentTestDescription().isLocallyOrdered
          ->size() = 1 or not self.getParentTestDescription().isLocallyOrdered
  
  


  -- Tester participating in locally ordered case
  -- 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()):
  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{}
          targetComponent = Set{}
          ->union(initials->select(oclIsKindOf(Interaction)).oclAsType(Interaction).target.targetGate.component)
          ->including(initial->select(oclIsKindOf(Interaction)).oclAsType(Interaction).target.targetGate.component)
          ->union(initials->select(oclIsKindOf(Quiescence)).oclAsType(Quiescence).componentInstance)
          ->including(initial->select(oclIsKindOf(Quiescence)).oclAsType(Quiescence).componentInstance)
          -> union(initials->select(oclIsKindOf(TimeOut)).oclAsType(TimeOut).componentInstance),
          -> including(initial->select(oclIsKindOf(TimeOut)).oclAsType(TimeOut).componentInstance),
          nonOptionalBlocks = self.block->closure(
          nonOptionalBlocks = self.block->closure(
              b | b.behaviour->reject(oclIsKindOf(OptionalBehaviour))
              b | b.behaviour->reject(oclIsKindOf(OptionalBehaviour))
                  ->select(oclIsKindOf(SingleCombinedBehaviour)).oclAsType(SingleCombinedBehaviour).block
                  ->select(oclIsKindOf(SingleCombinedBehaviour)).oclAsType(SingleCombinedBehaviour).block
              ->union(b.behaviour
              ->union(b.behaviour->reject(oclIsKindOf(OptionalBehaviour))
                  ->select(oclIsKindOf(MultipleCombinedBehaviour)).oclAsType(MultipleCombinedBehaviour).block)
                  ->select(oclIsKindOf(MultipleCombinedBehaviour)).oclAsType(MultipleCombinedBehaviour).block)
          )
          )
          in
          in
@@ -735,18 +765,14 @@ context AlternativeBehaviour


  -- OptionalBehaviour in locally ordered case
  -- 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()):
  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{}
          targetComponent = Set{}
          ->union(initials->select(oclIsKindOf(Interaction)).oclAsType(Interaction).target.targetGate.component)
          ->including(initial->select(oclIsKindOf(Interaction)).oclAsType(Interaction).target.targetGate.component)
          ->union(initials->select(oclIsKindOf(Quiescence)).oclAsType(Quiescence).componentInstance)
          ->including(initial->select(oclIsKindOf(Quiescence)).oclAsType(Quiescence).componentInstance)
          -> union(initials->select(oclIsKindOf(TimeOut)).oclAsType(TimeOut).componentInstance),
          -> including(initial->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))
          in
          in
            optionalBlocks->isEmpty()
          self.block.behaviour->select(oclIsKindOf(OptionalBehaviour)) .oclAsType(OptionalBehaviour).block
            or optionalBlocks->first().oclAsType(Interaction).sourceGate.component->forAll(c | targetComponent->includes(c))
              ->first().oclAsType(Interaction).sourceGate.component->forAll(c | targetComponent->includes(c))
          or not self.getParentTestDescription().isLocallyOrdered
          or not self.getParentTestDescription().isLocallyOrdered
  
  


@@ -755,13 +781,13 @@ context AlternativeBehaviour
context ConditionalBehaviour
context ConditionalBehaviour
  -- Guard for 'ConditionalBehaviour' with single block
  -- Guard for 'ConditionalBehaviour' with single block
  inv ConditionalFirstGuard ('If there is only one \'Block\' specified, it shall have a \'guard\'.' + self.toString()):
  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
  -- Possible else block for 'ConditionalBehaviour' with multiple blocks
  inv ConditionalLastGuard ('All \'Block\'s specified, except the last one, shall have a \'guard\'.' + self.toString()):
  inv ConditionalLastGuard ('All \'Block\'s specified, except the last one, shall have a \'guard\'.' + self.toString()):
        self.block->size() = 1
        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)