# This file is part of the Coral project.
# Please read the copyright notice in the LICENSE file.

##class ScopeKind(MMEnumeration):
##   sk_instance=0
##   sk_classifier=1
##   description=["instance","classifier"]
   
##class VisibilityKind(MMEnumeration):
##    vk_public=0
##    vk_protected=1
##    vk_private=2
##    vk_package=3

##    description=["public","protected","private","package"]

##class CallConcurrencyKind(MMEnumeration):
##    cck_sequential=0
##    cck_guarded=1
##    cck_concurrent=2

##    description=["sequential","guarded","concurrent"]
    
##class PseudostateKind(MMEnumeration):
##    pk_choice=0
##    pk_deepHistory=1
##    pk_fork=2
##    pk_initial=3
##    pk_join=4
##    pk_junction=5
##    pk_shallowHistory=6

##    description=["choice","deepHistory","fork","initial",
##                 "join","junction","shallowHistory"]

##class AggregationKind(MMEnumeration):
##    ak_none=0
##    ak_aggregate=1
##    ak_composite=2

##    description=['none','aggregate','composite']

##class ChangeableKind(MMEnumeration):
##    ck_changeable=0
##    ck_frozen=1
##    ck_addOnly=2

##    description=['changeable','frozen','addOnly']
    
##class OrderingKind(MMEnumeration):
##    ok_unordered=0
##    ok_ordered=1

##    description=['unordered','ordered']

##class ParameterDirectionKind(MMEnumeration):
##    pdk_in=0
##    pdk_inout=1
##    pdk_out=2
##    pdk_return=3

##    description=['in','inout','out','return']

def newMultiplicity(lower=1,upper=1):
    m=Multiplicity()
    m.addRange(MultiplicityRange(lower=lower,upper=upper))
    return m
           

class Association:
    def wfrAssociation1(self):
        return self.connection.forAll(
            lambda r1,r2: implies(r1.name==r2.name,r1==r2 or not r1.name))
    def wfrAssociation2(self):
        return self.connection.select(lambda c: c.aggregation != AggregationKind.ak_none).size()<=1
    def wfrAssociation3(self):
        return implies(self.connection.size()>=3,
                       self.connection.forAll(
            lambda c: c.aggregation == AggregationKind.ak_none))

    def allConnections(self):
        return self.connection
                                            
class Classifier:
    def allFeatures(self):
        return self.feature
    
    def allOperations(self):
        return self.feature.select(lambda f: f.oclIsKindOf(Operation))

    def allMethods(self):
        return self.feature.select(lambda f: f.oclIsKindOf(Method))
                                       
class Class:
    def wfrClass1(self):
        "If a Class is concrete, all the Operations of the Class should have a realizing Method in the full descriptor [1.4,01.02.01,2-60]"
        return self.isAbstract or Classifier_allOperations(self).forAll(lambda op: Classifier_allMethods(self).exist(lambda m: m.specification.__asSet__().includes(op)))
        
class Transition:
    def getDescription(self):
        text=''
        if self.trigger:
            text=self.trigger.getDescription()
        if self.guard:
            text=text+'['+self.guard.expression.body+']'
        if self.effect:
            text=text+'/'+self.effect.script.body
        return text

class SignalEvent:
    def getDescription(self):
        return self.signal.name

class CallEvent:
    def getDescription(self):
        return self.operation.name

class TimeEvent:
    def getDescription(self):
        return self.when

class ChangeEvent:
    def getDescription(self):
        return self.changeExpression


class CompositeState:
    def wfrCompositeState1(self):
        "A composite state can have at most one initial vertex"
        return self.subvertex.select(
            lambda v: v.oclIsKindOf(Pseudostate) and v.kind== PseudostateKind.pk_initial).size() <=1
    
    def wfrCompositeState2(self):
        "A composite state can have at most one deep history vertex"
        return self.subvertex.select(
            lambda v: v.oclIsKindOf(Pseudostate) and v.kind== PseudostateKind.pk_deepHistory).size() <=1

    def wfrCompositeState3(self):
        "A composite state can have at most one shallow history vertex"
        return self.subvertex.select(
            lambda v: v.oclIsKindOf(Pseudostate) and v.kind== PseudostateKind.pk_shallowHistory).size() <=1

    def wfrCompositeState4(self):
        "There have to be at least two composite substates in a concurrent composite state"
        return implies(self.isConcurrent,
                       self.subvertex.select(lambda v:
                                             v.oclIsKindOf(CompositeState)).size()>=2)

    def wfrCompositeState5(self):
        "A concurrent state can only have composite states as substates"
        return implies(self.isConcurrent,
                       self.subvertex.forAll(lambda s:
                                             s.oclIsKindOf(CompositeState)))

    def wfrCompositeState6(self):
        "The substates of a composite state are part of only that composite state"
        return self.subvertex.forAll(lambda s: s.container.__asSet__().size()==1 and s.container == self)


class FinalState:

    def wfrFinalState1(self):
        "A final state cannot have any outgoing transitions"
        return self.outgoing.size()==0


class Pseudostate:

    def wfrPseudostate1(self):
        "An initial vertex can have at most one outgoing transition and no incoming transitions"
        return implies(self.kind == PseudostateKind.pk_initial,
                       self.outgoing.size()<=1 and self.incoming.isEmpty())

    def wftPseudostate2(self):
        "History vertices can have at most one outgoing transition"
        return implies(self.kind == PseudostateKind.pk_deepHistory or self.kind== PseudostateKind.pk_shallowHistory,
                       self.outgoing.size()<=1)

    

    
    
