#!/usr/bin/env python
#
# General-purpose routine for generating an XMI[DI] diagram from
# a DIML model.
#
# BUGS: still several
#
# DO NOT USE THIS CODE YET
#
#
#

import coral

from coral.modeler.diagram import di_support

prjs = []
for f in [ "ClassDiagram.xml", "CollaborationDiagram.xml", "DeploymentDiagram.xml", "StateDiagram.xml", "UseCaseDiagram.xml" ]:
    p = coral.loadDocument("../../../coral/addins/UML14/" + f)
    prjs.append(p)

L = coral.lang.DIML10

import itertools
roots = []
for p in prjs:
    for r in p.contents():
        if not r.oclIsKindOf(L.MappingModel):
            continue
        roots.extend( [e for e in r.ownedElement if e.oclIsKindOf(L.ElementToXMIDIMapping) ] )


def __delegation(e, xparent):
    t = e.__meta__
    # BUG check superclass mappings as well
    mappings = t.__getSlotByOppositeName__(L.ElementToXMIDIMapping, "element")

    xparent_element = di_support.findUpwardsModelElement(xparent)
    l = { "self": e,
          "xparent": xparent,
          "xparent_element": xparent_element}

    for i in t.package.elements:
        l[str(i.name)] = i


    for m in mappings:
        if m.contextGuard:
            if not eval(str(m.contextGuard.expression), l, l):
                continue
        if xparent == None:
            if not m.root.oclIsKindOf(L.DiagramPart):
                print "You have an error in your DIML model"
                print "The ", m.root, " (UUID", m.root.__XMIid__(), ") should"
                print "have a proper guard (xparent != None)."
                print "(Ignoring, continuing correctly...)"
                continue
        else:
            if m.root.oclIsKindOf(L.DiagramPart):
                print "You have an error in your DIML model"
                print "The ", m.root, " (UUID", m.root.__XMIid__(), ") should"
                print "have a proper guard (xparent == None)."
                print "(Ignoring, continuing correctly...)"
                continue
        return create_xmidi_elements(e, xparent, m.root)
    return None

X = coral.lang.XMIDI20

type2xmidi = { L.GraphNodePart: X.GraphNode,
               L.GraphEdgePart: X.GraphEdge,
               L.DiagramPart:   X.Diagram }

def create_xmidi_elements(e, xparent, part):
    print "Doing", e
    if part.oclIsKindOf(L.Delegation):
        return __delegation(e, xparent)
    if part.oclIsKindOf(L.Separator):
        return create_xmidi_elements(e, xparent, part.subtree)
    graphElement = type2xmidi[part.__type__()]()
    graphElement.isVisible = True
    if part.oclIsKindOf(L.DiagramPart):
        sm2 = X.Uml1SemanticModelBridge()
        sm2.element = e
        graphElement.owner = sm2
        graphElement.size = X.Dimension(width = 1000, height = 1000)
    if part.typeInfo:
        sm = X.SimpleSemanticModelElement()
        sm.typeInfo = part.typeInfo
    else:
        sm = X.Uml1SemanticModelBridge()
        sm.element = e
    graphElement.semanticModel = sm

    if graphElement.oclIsKindOf(X.GraphNode):
        graphElement.size = X.Dimension(width = 10, height = 10)

    if xparent:
        graphElement.container = xparent
    for c in part.children:
        g = c.guard
        if g:
            xparent_element = di_support.findUpwardsModelElement(xparent)
            l = { "element": e,
                  "xparent": xparent,
                  "xparent_element": xparent_element}
            if not eval(str(g.expression), l, l):
                continue
        sel = c.selection
        if not sel:
            childGraphElement = create_xmidi_elements(e,
                                                      graphElement,
                                                      c.child)
            if childGraphElement:
                graphElement.contained.append(childGraphElement)
            continue
            
        children = e.__getSlotRO__(str(sel.property.name))
        # BUG not all info in sel taken care of
        last = len(children)-1
        sep = c.separator
        for idx, s in enumerate(children):
            childGraphElement = create_xmidi_elements(s,
                                                       graphElement,
                                                       c.child)
            if childGraphElement:
                graphElement.contained.append(childGraphElement)
            if sep and idx != last:
                childGraphElement = create_xmidi_elements(s,
                                                          graphElement,
                                                          sep)
                if childGraphElement:
                    graphElement.contained.append(childGraphElement)
    print "Returning"
    return graphElement

def create_diagram(e):
    return __delegation(e, None)

prj = coral.loadDocument("example_uml14_model.xml")

r = prj.contents()[0]
x = create_diagram(r)

x.__setProject__(prj)
prj.setFilename("out.xml")
coral.saveDocument(prj)

