
import coral

UML=coral.lang.UML14
SMD=coral.lang.SMD01

element2ed={} 

def setTaggedValue(self,name,value=""):
    for tv in self.taggedValue:
        if str(tv.name)==name:
           tv.dataValue=value
           return tv
    return self.taggedValue.insert(UML.TaggedValue(name=name,dataValue=value))

def convert(lang):
    global element2ed
    element2ed={} 
    return ( convertLang(coral.meta.CORE01), convertLang(lang))
    
def convertLang(lang):
    model=UML.Model(name=lang.name)
    global element2ed
    setTaggedValue(model,"version",str(lang.version))
    setTaggedValue(model,"revision",str(lang.revision))
    setTaggedValue(model,"URInamespace",str(lang.URInamespace))
    element2ed[model]=lang
    transform(model,lang)
    return model

def transform(model,lang):
    global element2ed
    model.isAbstract=lang.isAbstract
    for elem in lang.elements:
        if elem.oclIsKindOf(SMD.ElementDefinition):
            umlclass=UML.Class(namespace=model,name=elem.name)            
            element2ed[elem]=umlclass
            umlclass.isAbstract=elem.isAbstract
        if elem.oclIsKindOf(SMD.DatatypeDefinition):
            umlclass=UML.Class(namespace=model,name=elem.name)            
            element2ed[elem]=umlclass
            
    for elem in lang.elements:
        if elem.oclIsKindOf(SMD.Package):
            umlpackage=UML.Package(namespace=model, name=elem.name)
            element2ed[elem]=umlpackage
            transform(umlpacakge,elem)

    for elem in lang.elements: # After creaing all ElementDefinitions the properties are added.
        if elem.oclIsKindOf(SMD.ElementDefinition):
            for super in elem.superclasses:
                model.ownedElement.insert(UML.Generalization(parent=element2ed[super],child=element2ed[elem]))
            for p in elem.properties:
                if p.opposite:
                    umlclass1=element2ed[elem]
                    if not element2ed.has_key(p.opposite.owner):
                        continue
                    umlclass2=element2ed[p.opposite.owner]
                    if umlclass2< umlclass1:
                        continue
                    as=UML.Association(namespace=model)
                    as.connection=[UML.AssociationEnd(),UML.AssociationEnd()]
                    createAEnd(as.connection[0],p,p.opposite)
                    createAEnd(as.connection[1],p.opposite,p)
                else:
                    # create an attribute
                    umlclass=element2ed[elem]
                    attr=UML.Attribute(name=p.name)
                    if element2ed.has_key(p.element_kind):
                        attr.type=element2ed[p.element_kind]
                    attr.multiplicity.range.insert(UML.MultiplicityRange(
                        lower=p.multiplicity_lower,upper=p.multiplicity_upper))
                    if p.isOrdered:
                        attr.ordering=UML.OrderingKind.ordered
                    umlclass.feature.insert(attr)
                    
def createAEnd(ae,p,op):
    ae.name=op.owner.name
    ae.participant=element2ed[p.owner]
    ae.multiplicity.range.insert(UML.MultiplicityRange(
            lower=p.multiplicity_lower,upper=p.multiplicity_upper))
    if p.isOrdered:
        ae.ordering=UML.OrderingKind.ordered
