import "../library/common.eol";
import "../library/helper.eol";
import "../library/debug.eol";

//Combining Multiple 'PICSReference's
//A 'Comment' with body containing an 'and' or 'or' shall be attached to the 'PICSReference' as a Boolean operand if there are two or more 'PICSReference's and it is not the first 'PICSReference'.
context PICSReference {
constraint MultiplePICS {
	check: 
    self.container().picsReference->size() < 2 
 or self.container().picsReference->forAll(p | 
        self.container().picsReference->at(0) = p
     or (not p.comment->isEmpty()
     and (p.comment->first().body = 'and'
       or p.comment->first().body = 'or')))
	message:
	"A 'Comment' with body containing an 'and' or 'or' shall be attached to the 'PICSReference' as a Boolean operand if there are two or more 'PICSReference's and it is not the first 'PICSReference'."
}
}

//Either ‘repetition’, or ‘interval’ or neither shall be specified
//At most one of the optional properties ‘repetition’ or ‘interval’ shall be defined.
context RepeatedEventSequence {
constraint RepetitionOrInterval {
	check:
    self.repetitions.oclIsUndefined() or self.interval.oclIsUndefined()
    message:
	"At most one of the optional properties ‘repetition’ or ‘interval’ shall be defined."    
}
}

//Combining Multiple 'EventOccurrence's
//A 'Comment' with body containing an 'and' or 'or' shall be attached to the 'EventOccurrence' as an operand if there are two or more 'EventOccurrence's and it is not the first 'EventOccurrence'.
context EventOccurrence {
constraint MultipleEventOccurrences{
	check:
    self.container().oclIsTypeOf(EventSpecificationTemplate)
 or self.container().events->size() < 2 
 or self.container().events->forAll(o | 
        self.container().events->at(0) = o
     or (not o.comment->isEmpty()
     and (o.comment->first().body = 'and'
       or o.comment->first().body = 'or')))
	message:
	"A 'Comment' with body containing an 'and' or 'or' shall be attached to the 'EventOccurrence' as an operand if there are two or more 'EventOccurrence's and it is not the first 'EventOccurrence'."
}
}


//An 'Entity' or a 'ComponentInstance' shall be referenced.
//There shall be a reference to an 'Entity' or a 'ComponentInstance' but not both.
context EntityReference {
constraint EntityOrComponentInstance {
	check:
    (not self.entity.oclIsUndefined() and self.component.oclIsUndefined())
 or (self.entity.oclIsUndefined() and not self.component.oclIsUndefined())
	message: 
	"There shall be a reference to an 'Entity' or a 'ComponentInstance' but not both."
}
}

//No nested 'Content's if 'Value' is provided 
//Either nested 'Content's or 'Value' may be specified within 'Content', but not both.
context Content {
constraint ContentOrValue {
	check:
    self.content->isEmpty() or self.value.oclIsUndefined()
	message:
	"Either nested 'Content's or 'Value' may be specified within 'Content', but not both."
}
}


//Referenced 'LiteralValue' visibility
//Only 'LiteralValue's defined within previous 'EventOccurrence's of the containing 'StructuredTestObjective' may be referenced.
context LiteralValueReference {
constraint VisibleValue {
	check:
    self.getTestObjective().contains(self.content) 
and self.getTestObjective().indexOf(self.content) < self.getTestObjective().indexOf(self)
	message:
	"Only 'LiteralValue's defined within previous 'EventOccurrence's of the containing 'StructuredTestObjective' may be referenced."
}
}

//Referenced 'Content' visibility
//Only 'Content's defined within previous 'EventOccurrence's of the containing 'StructuredTestObjective' may be referenced.
context ContentReference {
constraint VisibleContent {
	check:
    self.getTestObjective().contains(self.content) 
and self.getTestObjective().indexOf(self.content) < self.getTestObjective().indexOf(self)
	message:
	"Only 'Content's defined within previous 'EventOccurrence's of the containing 'StructuredTestObjective' may be referenced."
}
}


//'DataInstanceUse' restrictions within 'DataReference'
//Only simple and structured data instances may be referenced directly or indirectly in 'ParameterBinding's of the 'StaticDataUse' within a 'DataReference'.
context DataReference {
constraint DataReferenceContents {
	check:
    self.content.oclIsKindOf(StaticDataUse)
and self.content.argument->forAll(a | a.dataUse.oclIsKindOf(StaticDataUse))
and self.content.argument->closure(a | a.dataUse.argument)->forAll(a|a.dataUse.oclIsKindOf(StaticDataUse)) 
	message:
	"Only simple and structured data instances may be referenced directly or indirectly in 'ParameterBinding's of the 'StaticDataUse' within a 'DataReference'."
}
}

//‘EntityReference’ of referenced ‘EventSpecificationTemplate’
//If ‘EntityBinding’s are provided, he ‘Entity’s referenced in the ‘templateEntity’ properties shall also be referenced by one of the ‘EntityReferences’ in the ‘EventOccurrenceSpecification’ of the 'EventSpecificationTemplate' referenced in the ‘EventTemplateOccurrence’.
context EventTemplateOccurrence {
constraint EntityTemplateOccurrenceConsistency {
    check:
    self.entityBinding->forAll(b | 
        (not b.templateEntity.entity.oclIsUndefined() and (b.templateEntity.entity = self.eventTemplate.eventSpecification.entityReference.entity))
     or (not b.templateEntity.component.oclIsUndefined() and (b.templateEntity.component = self.eventTemplate.eventSpecification.entityReference.component)
     or self.eventTemplate.eventSpecification.oppositeEntityReference->exists(e | 
            (not b.templateEntity.entity.oclIsUndefined() and (e.entity = b.templateEntity.entity))
         or (not b.templateEntity.component.oclIsUndefined() and (e.component = b.templateEntity.component)))))

	message:
	"If ‘EntityBinding’s are provided, he ‘Entity’s referenced in the ‘templateEntity’ properties shall also be referenced by one of the ‘EntityReferences’ in the ‘EventOccurrenceSpecification’ of the 'EventSpecificationTemplate' referenced in the ‘EventTemplateOccurrence’."
}
}
