Beispiel #1
0
class PyutXml:

    VERSION: int = 9
    """
    Use this class to save and load a PyUT UML diagram in XML.
    This class offers two main methods.  They are:
    
     * `save()` 
     * `load()`
     
     
    Using the minidom API you can use the save method to get the
    diagram converted to its corresponding XML representation. For loading, you have to parse
    the XML file and indicate the UML frame onto which you want to draw
    (See `UmlFrame`).

    This module is dynamically loaded based on the input XML's version number.  This
    class supports `PyutXml.VERSION`  9
    
    """
    def __init__(self):
        """
        Constructor
        """
        self.logger: Logger = getLogger(__name__)

        # self._idFactory = IDFactory()

        self._dlgGauge: Dialog = cast(Dialog, None)

    def save(self, project: PyutProject) -> Document:
        """
        Save diagram in XML file.

        Args:
            project:  The project to write as XML

        Returns:
            A minidom XML Document
        """
        dlg:    Dialog   = Dialog(None, -1, "Saving...", style=STAY_ON_TOP | ICON_INFORMATION | RESIZE_BORDER, size=Size(207, 70))
        xmlDoc: Document = Document()
        try:
            # xmlDoc: Document  = Document()
            top     = xmlDoc.createElement(PyutXmlConstants.TOP_LEVEL_ELEMENT)
            top.setAttribute(PyutXmlConstants.ATTR_VERSION, str(PyutXml.VERSION))
            codePath: str = project.getCodePath()
            if codePath is None:
                top.setAttribute('CodePath', '')
            else:
                top.setAttribute('CodePath', codePath)

            xmlDoc.appendChild(top)

            gauge = Gauge(dlg, -1, 100, pos=Point(2, 5), size=Size(200, 30))
            dlg.Show(True)
            wxYield()

            toPyutXml: OglToMiniDom = OglToMiniDom()
            # Save all documents in the project
            for document in project.getDocuments():

                document: PyutDocument = cast(PyutDocument, document)

                documentNode = xmlDoc.createElement(PyutXmlConstants.ELEMENT_DOCUMENT)

                docType: str = document.getType().__str__()

                documentNode.setAttribute(PyutXmlConstants.ATTR_TYPE, docType)
                documentNode.setAttribute(PyutXmlConstants.ATTR_TITLE, document.title)
                top.appendChild(documentNode)

                oglObjects: List[OglObject] = document.getFrame().getUmlObjects()
                for i in range(len(oglObjects)):
                    gauge.SetValue(i * 100 / len(oglObjects))
                    wxYield()
                    oglObject = oglObjects[i]
                    if isinstance(oglObject, OglClass):
                        # documentNode.appendChild(self._OglClass2xml(oglObject, xmlDoc))
                        classElement: Element = toPyutXml.oglClassToXml(oglObject, xmlDoc)
                        documentNode.appendChild(classElement)
                    elif isinstance(oglObject, OglNote):
                        # documentNode.appendChild(self._OglNote2xml(oglObject, xmlDoc))
                        noteElement: Element = toPyutXml.oglNoteToXml(oglObject, xmlDoc)
                        documentNode.appendChild(noteElement)
                    elif isinstance(oglObject, OglActor):
                        # documentNode.appendChild(self._OglActor2xml(oglObject, xmlDoc))
                        actorElement: Element = toPyutXml.oglActorToXml(oglObject, xmlDoc)
                        documentNode.appendChild(actorElement)
                    elif isinstance(oglObject, OglUseCase):
                        # documentNode.appendChild(self._OglUseCase2xml(oglObject, xmlDoc))
                        useCaseElement: Element = toPyutXml.oglUseCaseToXml(oglObject, xmlDoc)
                        documentNode.appendChild(useCaseElement)
                    elif isinstance(oglObject, OglSDInstance):
                        # documentNode.appendChild(self._OglSDInstance2xml(oglObject, xmlDoc))
                        sdInstanceElement: Element = toPyutXml.oglSDInstanceToXml(oglObject, xmlDoc)
                        documentNode.appendChild(sdInstanceElement)
                    elif isinstance(oglObject, OglSDMessage):
                        # documentNode.appendChild(self._OglSDMessage2xml(oglObject, xmlDoc))
                        sdMessageElement: Element = toPyutXml.oglSDMessageToXml(oglObject, xmlDoc)
                        documentNode.appendChild(sdMessageElement)
                    # OglLink comes last because OglSDInstance is a subclass of OglLink
                    # Now I know why OglLink used to double inherit from LineShape, ShapeEventHandler
                    # I changed it to inherit from OglLink directly
                    elif isinstance(oglObject, OglLink):
                        # documentNode.appendChild(self._OglLink2xml(oglObject, xmlDoc))
                        linkElement: Element = toPyutXml.oglLinkToXml(oglObject, xmlDoc)
                        documentNode.appendChild(linkElement)
        except (ValueError, Exception) as e:
            try:
                dlg.Destroy()
                self.logger.error(f'{e}')
            except (ValueError, Exception) as e:
                self.logger.error(f'{e}')
            PyutUtils.displayError(_("Can't save file"))
            return xmlDoc

        dlg.Destroy()

        return xmlDoc

    def open(self, dom: Document, project: PyutProject):
        """
        Open a file and create a diagram.

        Args:
            dom:        The minidom document
            project:    The UI Project to fill out
        """
        self.__setupProgressDialog()
        umlFrame: UmlFrame = cast(UmlFrame, None)  # avoid Pycharm warning
        root = self.__validateXmlVersion(dom)
        try:
            project.setCodePath(root.getAttribute("CodePath"))
            self.__updateProgressDialog(newMessage='Reading elements...', newGaugeValue=1)
            toOgl: MiniDomToOgl = MiniDomToOgl()
            for documentNode in dom.getElementsByTagName(PyutXmlConstants.ELEMENT_DOCUMENT):

                documentNode: Element = cast(Element, documentNode)
                docTypeStr:   str     = documentNode.getAttribute(PyutXmlConstants.ATTR_TYPE)
                self.__updateProgressDialog(newMessage=f'Determine Title for document type: {docTypeStr}', newGaugeValue=2)

                docType:  DiagramType  = PyutConstants.diagramTypeFromString(docTypeStr)
                document: PyutDocument = project.newDocument(docType)
                document.title = self.__determineDocumentTitle(documentNode)

                umlFrame: UmlFrame = self.__showAppropriateUmlFrame(document)

                self.__updateProgressDialog(newMessage='Start Conversion...', newGaugeValue=3)

                if docType == DiagramType.CLASS_DIAGRAM:
                    self.__renderClassDiagram(documentNode, toOgl, umlFrame)
                elif docType == DiagramType.USECASE_DIAGRAM:
                    self.__renderUseCaseDiagram(documentNode, toOgl, umlFrame)
                elif docType == DiagramType.SEQUENCE_DIAGRAM:
                    self.__renderSequenceDiagram(documentNode, toOgl, umlFrame)

                self.__updateProgressDialog(newMessage='Conversion Complete...', newGaugeValue=4)

        except (ValueError, Exception) as e:
            self._dlgGauge.Destroy()
            PyutUtils.displayError(_(f"Can not load file {e}"))
            umlFrame.Refresh()
            return

        self.__cleanupProgressDialog(umlFrame)

    def __renderClassDiagram(self, documentNode: Element, toOgl: MiniDomToOgl, umlFrame: UmlFrame):
        """

        Args:
            documentNode:   A minidom document element
            toOgl:          The converter class
            umlFrame:       Where to render
        """
        oglClasses: OglClasses = toOgl.getOglClasses(documentNode.getElementsByTagName(PyutXmlConstants.ELEMENT_GRAPHIC_CLASS))
        oglNotes:   OglNotes   = toOgl.getOglNotes(documentNode.getElementsByTagName('GraphicNote'))

        mergedOglObjects: OglObjects = cast(OglObjects, oglClasses.copy())
        mergedOglObjects.update(oglNotes)

        self.__displayTheClasses(oglClasses, umlFrame)
        oglLinks: OglLinks = toOgl.getOglLinks(documentNode.getElementsByTagName("GraphicLink"), mergedOglObjects)
        self.__displayTheLinks(oglLinks, umlFrame)
        self.__displayTheNotes(oglNotes, umlFrame)

    def __renderUseCaseDiagram(self, documentNode: Element, toOgl: MiniDomToOgl, umlFrame: UmlFrame):
        """

        Args:
            documentNode:   A minidom document element
            toOgl:          The converter class
            umlFrame:       Where to render
        """
        oglObjects: OglObjects = cast(OglObjects, {})

        oglActors:   OglActors   = toOgl.getOglActors(documentNode.getElementsByTagName('GraphicActor'))
        oglUseCases: OglUseCases = toOgl.getOglUseCases(documentNode.getElementsByTagName('GraphicUseCase'))
        oglNotes:    OglNotes    = toOgl.getOglNotes(documentNode.getElementsByTagName('GraphicNote'))

        self.__displayTheActors(oglActors, umlFrame)
        self.__displayTheUseCases(oglUseCases, umlFrame)
        self.__displayTheNotes(oglNotes, umlFrame)

        mergedOglObjects: OglObjects = cast(OglObjects, oglObjects.copy())
        mergedOglObjects.update(oglActors)
        mergedOglObjects.update(oglNotes)
        mergedOglObjects.update(oglUseCases)

        oglLinks: OglLinks = toOgl.getOglLinks(documentNode.getElementsByTagName("GraphicLink"), mergedOglObjects)
        self.__displayTheLinks(oglLinks, umlFrame)

    def __renderSequenceDiagram(self, documentNode, toOgl, umlFrame):
        """

        Args:
            documentNode:   A minidom document element
            toOgl:          The converter class
            umlFrame:       Where to render
        """
        oglSDInstances: OglSDInstances = toOgl.getOglSDInstances(documentNode.getElementsByTagName("GraphicSDInstance"), umlFrame)
        oglSDMessages: OglSDMessages = toOgl.getOglSDMessages(documentNode.getElementsByTagName("GraphicSDMessage"), oglSDInstances)
        self.__displayTheSDMessages(oglSDMessages, umlFrame)

    def __displayTheClasses(self, oglClasses: OglClasses, umlFrame: UmlFrame):
        """
        Place the OGL classes on the input frame at their respective positions

        Args:
            oglClasses: A dictionary of OGL classes
            umlFrame:   The UML Frame to place the OGL objects on
        """
        for oglClass in oglClasses.values():
            self.__displayAnOglObject(oglClass, umlFrame)

    def __displayTheLinks(self, oglLinks: OglLinks, umlFrame: UmlFrame):
        """
        Place the OGL links on the input frame at their respective positions

        Args:
            oglLinks:   A dictionary of OGL links
            umlFrame:   The UML Frame to place the OGL objects on
        """
        for oglLink in oglLinks:
            umlFrame.GetDiagram().AddShape(oglLink, withModelUpdate=True)

    def __displayTheNotes(self, oglNotes: OglNotes, umlFrame: UmlFrame):
        for oglNote in oglNotes.values():
            self.__displayAnOglObject(oglNote, umlFrame)

    def __displayTheActors(self, oglActors: OglActors, umlFrame: UmlFrame):
        for oglActor in oglActors.values():
            self.__displayAnOglObject(oglActor, umlFrame)

    def __displayTheUseCases(self, oglUseCases: OglUseCases, umlFrame: UmlFrame):
        for oglUseCase in oglUseCases.values():
            self.__displayAnOglObject(oglUseCase, umlFrame)

    def __displayTheSDMessages(self, oglSDMessages: OglSDMessages, umlFrame: UmlFrame):
        for oglSDMessage in oglSDMessages.values():
            oglSDMessage: OglSDMessage = cast(OglSDMessage, oglSDMessage)
            umlFrame.getDiagram().AddShape(oglSDMessage)

    def __displayAnOglObject(self, oglObject: OglObject, umlFrame: UmlFrame):
        x, y = oglObject.GetPosition()
        umlFrame.addShape(oglObject, x, y)

    def __setupProgressDialog(self):

        self._dlgGauge = Dialog(None, ID_ANY, "Loading...", style=STAY_ON_TOP | ICON_INFORMATION | RESIZE_BORDER, size=Size(250, 70))
        self._gauge: Gauge = Gauge(self._dlgGauge, ID_ANY, 5, pos=Point(2, 5), size=Size(200, 30))
        self._dlgGauge.Show(True)
        wxYield()

    def __updateProgressDialog(self, newMessage: str, newGaugeValue: int):

        self._dlgGauge.SetTitle(newMessage)
        self._gauge.SetValue(newGaugeValue)
        wxYield()

    def __cleanupProgressDialog(self, umlFrame: UmlFrame):

        umlFrame.Refresh()
        self._gauge.SetValue(5)
        wxYield()
        self._dlgGauge.Destroy()

    def __validateXmlVersion(self, dom: Document) -> Element:
        """

        Args:
            dom: The minidom Document

        Returns:
            The root element unless the XML version is incorrect
        """
        root: Element = dom.getElementsByTagName(PyutXmlConstants.TOP_LEVEL_ELEMENT)[0]
        if root.hasAttribute(PyutXmlConstants.ATTR_VERSION):
            version = int(root.getAttribute(PyutXmlConstants.ATTR_VERSION))
        else:
            version = 1
        if version != PyutXml.VERSION:
            self.logger.error("Wrong version of the file loader")
            eMsg: str = f'This is version {PyutXml.VERSION} and the file version is {version}'
            self.logger.error(eMsg)
            raise Exception(f'VERSION_ERROR:  {eMsg}')

        return root

    def __determineDocumentTitle(self, documentNode) -> str:

        docTitle:   str = documentNode.getAttribute(PyutXmlConstants.ATTR_TITLE)
        docTypeStr: str = documentNode.getAttribute(PyutXmlConstants.ATTR_TYPE)

        if docTitle == '' or docTitle is None:
            return docTypeStr
        else:
            return docTitle

    def __showAppropriateUmlFrame(self, document) -> UmlFrame:

        umlFrame: UmlFrame = document.getFrame()
        ctrl = getMediator()
        ctrl.getFileHandling().showFrame(umlFrame)

        return umlFrame
Beispiel #2
0
class PyutXml:

    VERSION: int = 10
    """
    Use this class to save and load a PyUT UML diagram in XML.
    This class offers two main methods.  They are:
    
     * `save()` 
     * `load()`
     
     
    Using the minidom API you can use the save method to get the
    diagram converted to its corresponding XML representation. For loading, you have to parse
    the XML file and indicate the UML frame onto which you want to draw
    (See `UmlDiagramsFrame`).

    This module is dynamically loaded based on the input XML version number.  This
    class supports `PyutXml.VERSION`  10
    
    """
    def __init__(self):
        """
        Constructor
        """
        self.logger: Logger = getLogger(__name__)
        self._dlgGauge: Dialog = cast(Dialog, None)

    def save(self, project: PyutProject) -> Document:
        """
        Save diagram in XML file.

        Args:
            project:  The project to write as XML

        Returns:
            A minidom XML Document
        """
        assert project is not None, 'Oops someone sent me a bad project'

        dlg: Dialog = Dialog(None,
                             ID_ANY,
                             "Saving...",
                             style=STAY_ON_TOP | ICON_INFORMATION
                             | RESIZE_BORDER,
                             size=Size(207, 70))
        xmlDoc: Document = Document()
        try:
            top = xmlDoc.createElement(PyutXmlConstants.TOP_LEVEL_ELEMENT)
            top.setAttribute(PyutXmlConstants.ATTR_VERSION,
                             str(PyutXml.VERSION))
            codePath: str = project.getCodePath()
            if codePath is None:
                top.setAttribute(PyutXmlConstants.ATTR_CODE_PATH, '')
            else:
                top.setAttribute(PyutXmlConstants.ATTR_CODE_PATH, codePath)

            xmlDoc.appendChild(top)

            gauge = Gauge(dlg,
                          ID_ANY,
                          100,
                          pos=Point(2, 5),
                          size=Size(200, 30))
            dlg.Show(True)
            wxYield()

            toPyutXml: OglToMiniDomV10 = OglToMiniDomV10()
            # Save all documents in the project
            for pyutDocument in project.getDocuments():

                document: PyutDocument = cast(PyutDocument, pyutDocument)
                documentNode: Element = self.__pyutDocumentToPyutXml(
                    xmlDoc=xmlDoc, pyutDocument=document)

                top.appendChild(documentNode)

                from org.pyut.ui.UmlFrame import UmlObjects

                oglObjects: UmlObjects = document.getFrame().getUmlObjects()
                for i in range(len(oglObjects)):
                    gauge.SetValue(i * 100 / len(oglObjects))
                    wxYield()
                    oglObject = oglObjects[i]
                    if isinstance(oglObject, OglClass):
                        classElement: Element = toPyutXml.oglClassToXml(
                            oglObject, xmlDoc)
                        documentNode.appendChild(classElement)
                    elif isinstance(oglObject, OglInterface2):
                        classElement = toPyutXml.oglInterface2ToXml(
                            oglObject, xmlDoc)
                        documentNode.appendChild(classElement)
                    elif isinstance(oglObject, OglNote):
                        noteElement: Element = toPyutXml.oglNoteToXml(
                            oglObject, xmlDoc)
                        documentNode.appendChild(noteElement)
                    elif isinstance(oglObject, OglText):
                        textElement: Element = toPyutXml.oglTextToXml(
                            oglObject, xmlDoc)
                        documentNode.appendChild(textElement)
                    elif isinstance(oglObject, OglActor):
                        actorElement: Element = toPyutXml.oglActorToXml(
                            oglObject, xmlDoc)
                        documentNode.appendChild(actorElement)
                    elif isinstance(oglObject, OglUseCase):
                        useCaseElement: Element = toPyutXml.oglUseCaseToXml(
                            oglObject, xmlDoc)
                        documentNode.appendChild(useCaseElement)
                    elif isinstance(oglObject, OglSDInstance):
                        sdInstanceElement: Element = toPyutXml.oglSDInstanceToXml(
                            oglObject, xmlDoc)
                        documentNode.appendChild(sdInstanceElement)
                    elif isinstance(oglObject, OglSDMessage):
                        sdMessageElement: Element = toPyutXml.oglSDMessageToXml(
                            oglObject, xmlDoc)
                        documentNode.appendChild(sdMessageElement)
                    # OglLink comes last because OglSDInstance is a subclass of OglLink
                    # Now I know why OglLink used to double inherit from LineShape, ShapeEventHandler
                    # I changed it to inherit from OglLink directly
                    elif isinstance(oglObject, OglLink):
                        linkElement: Element = toPyutXml.oglLinkToXml(
                            oglObject, xmlDoc)
                        documentNode.appendChild(linkElement)
                    else:
                        self.logger.warning(
                            f'Unhandled OGL Object: {oglObject}')
        except (ValueError, Exception) as e:
            try:
                dlg.Destroy()
                self.logger.error(f'{e}')
            except (ValueError, Exception) as e:
                self.logger.error(f'{e}')
            PyutUtils.displayError(_("Can't save file"))
            return xmlDoc

        dlg.Destroy()

        return xmlDoc

    def open(self, dom: Document, project: PyutProject):
        """
        Open a file and create a diagram.

        Args:
            dom:        The minidom document
            project:    The UI Project to fill out
        """
        self.__setupProgressDialog()
        umlFrame: UmlDiagramsFrame = cast(UmlDiagramsFrame,
                                          None)  # avoid Pycharm warning
        root = self.__validateXmlVersion(dom)
        try:
            project.setCodePath(root.getAttribute("CodePath"))
            self.__updateProgressDialog(newMessage='Reading elements...',
                                        newGaugeValue=1)
            wxYield()
            toOgl: MiniDomToOglV10 = MiniDomToOglV10()
            for element in dom.getElementsByTagName(
                    PyutXmlConstants.ELEMENT_DOCUMENT):

                documentNode: Element = cast(Element, element)
                docTypeStr: str = documentNode.getAttribute(
                    PyutXmlConstants.ATTR_TYPE)
                self.__updateProgressDialog(
                    newMessage=
                    f'Determine Title for document type: {docTypeStr}',
                    newGaugeValue=2)
                wxYield()

                docType: DiagramType = PyutConstants.diagramTypeFromString(
                    docTypeStr)
                document: PyutDocument = project.newDocument(docType)
                document.title = self.__determineDocumentTitle(documentNode)

                umlFrame = self.__showAppropriateUmlFrame(document)
                self.__positionAndSetupDiagramFrame(umlFrame=umlFrame,
                                                    documentNode=documentNode)

                self.__updateProgressDialog(newMessage='Start Conversion...',
                                            newGaugeValue=3)

                if docType == DiagramType.CLASS_DIAGRAM:
                    self.__renderClassDiagram(documentNode, toOgl, umlFrame)
                elif docType == DiagramType.USECASE_DIAGRAM:
                    self.__renderUseCaseDiagram(documentNode, toOgl, umlFrame)
                elif docType == DiagramType.SEQUENCE_DIAGRAM:
                    self.__renderSequenceDiagram(documentNode, toOgl, umlFrame)

                self.__updateProgressDialog(
                    newMessage='Conversion Complete...', newGaugeValue=4)

        except (ValueError, Exception) as e:
            self._dlgGauge.Destroy()
            PyutUtils.displayError(_(f"Can not load file {e}"))
            umlFrame.Refresh()
            return

        self.__cleanupProgressDialog(umlFrame)

    def __pyutDocumentToPyutXml(self, xmlDoc: Document,
                                pyutDocument: PyutDocument) -> Element:

        documentNode = xmlDoc.createElement(PyutXmlConstants.ELEMENT_DOCUMENT)

        docType: str = pyutDocument.getType().__str__()

        documentNode.setAttribute(PyutXmlConstants.ATTR_TYPE, docType)
        documentNode.setAttribute(PyutXmlConstants.ATTR_TITLE,
                                  pyutDocument.title)

        docFrame: UmlDiagramsFrame = pyutDocument.getFrame()
        scrollPosX, scrollPosY = docFrame.GetViewStart()
        documentNode.setAttribute(PyutXmlConstants.ATTR_SCROLL_POSITION_X,
                                  str(scrollPosX))
        documentNode.setAttribute(PyutXmlConstants.ATTR_SCROLL_POSITION_Y,
                                  str(scrollPosY))

        xUnit, yUnit = docFrame.GetScrollPixelsPerUnit()

        documentNode.setAttribute(PyutXmlConstants.ATTR_PIXELS_PER_UNIT_X,
                                  str(xUnit))
        documentNode.setAttribute(PyutXmlConstants.ATTR_PIXELS_PER_UNIT_Y,
                                  str(yUnit))

        return documentNode

    def __renderClassDiagram(self, documentNode: Element,
                             toOgl: MiniDomToOglV10,
                             umlFrame: UmlDiagramsFrame):
        """

        Args:
            documentNode:   A minidom document element
            toOgl:          The converter class
            umlFrame:       Where to render
        """
        oglClasses: OglClasses = toOgl.getOglClasses(
            documentNode.getElementsByTagName(
                PyutXmlConstants.ELEMENT_GRAPHIC_CLASS))
        oglNotes: OglNotes = toOgl.getOglNotes(
            documentNode.getElementsByTagName(
                PyutXmlConstants.ELEMENT_GRAPHIC_NOTE))
        oglInterfaces: OglInterfaces = toOgl.getOglInterfaces(
            documentNode.getElementsByTagName(
                PyutXmlConstants.ELEMENT_GRAPHIC_LOLLIPOP), oglClasses)
        oglTextShapes: OglTextShapes = toOgl.getOglTextShapes(
            documentNode.getElementsByTagName(
                PyutXmlConstants.ELEMENT_GRAPHIC_TEXT))

        mergedOglObjects: OglObjects = cast(OglObjects, oglClasses.copy())
        mergedOglObjects.update(oglNotes)

        self.__displayTheClasses(oglClasses, umlFrame)
        oglLinks: OglLinks = toOgl.getOglLinks(
            documentNode.getElementsByTagName(
                PyutXmlConstants.ELEMENT_GRAPHIC_LINK), mergedOglObjects)
        self.__displayTheLinks(oglLinks, umlFrame)
        self.__displayTheNotes(oglNotes, umlFrame)
        self.__displayTheTextShapes(oglTextShapes, umlFrame)
        self.__displayTheInterfaces(oglInterfaces, umlFrame)

    def __renderUseCaseDiagram(self, documentNode: Element,
                               toOgl: MiniDomToOglV10,
                               umlFrame: UmlDiagramsFrame):
        """

        Args:
            documentNode:   A minidom document element
            toOgl:          The converter class
            umlFrame:       Where to render
        """
        oglObjects: OglObjects = cast(OglObjects, {})

        oglActors: OglActors = toOgl.getOglActors(
            documentNode.getElementsByTagName('GraphicActor'))
        oglUseCases: OglUseCases = toOgl.getOglUseCases(
            documentNode.getElementsByTagName('GraphicUseCase'))
        oglNotes: OglNotes = toOgl.getOglNotes(
            documentNode.getElementsByTagName('GraphicNote'))

        self.__displayTheActors(oglActors, umlFrame)
        self.__displayTheUseCases(oglUseCases, umlFrame)
        self.__displayTheNotes(oglNotes, umlFrame)

        mergedOglObjects: OglObjects = cast(OglObjects, oglObjects.copy())
        mergedOglObjects.update(oglActors)
        mergedOglObjects.update(oglNotes)
        mergedOglObjects.update(oglUseCases)

        oglLinks: OglLinks = toOgl.getOglLinks(
            documentNode.getElementsByTagName("GraphicLink"), mergedOglObjects)
        self.__displayTheLinks(oglLinks, umlFrame)

    def __renderSequenceDiagram(self, documentNode, toOgl, umlFrame):
        """

        Args:
            documentNode:   A minidom document element
            toOgl:          The converter class
            umlFrame:       Where to render
        """
        oglSDInstances: OglSDInstances = toOgl.getOglSDInstances(
            documentNode.getElementsByTagName("GraphicSDInstance"), umlFrame)
        oglSDMessages: OglSDMessages = toOgl.getOglSDMessages(
            documentNode.getElementsByTagName("GraphicSDMessage"),
            oglSDInstances)
        self.__displayTheSDMessages(oglSDMessages, umlFrame)

    def __displayTheClasses(self, oglClasses: OglClasses,
                            umlFrame: UmlDiagramsFrame):
        """
        Place the OGL classes on the input frame at their respective positions

        Args:
            oglClasses: A dictionary of OGL classes
            umlFrame:   The UML Frame to place the OGL objects on
        """
        for oglClass in oglClasses.values():
            self.__displayAnOglObject(oglClass, umlFrame)

    def __displayTheInterfaces(self, oglInterfaces: OglInterfaces,
                               umlFrame: UmlDiagramsFrame):

        for oglInterface in oglInterfaces:

            attachmentAnchor = oglInterface.destinationAnchor
            x, y = attachmentAnchor.GetPosition()

            umlFrame.addShape(oglInterface, x, y, withModelUpdate=True)
            umlFrame.addShape(attachmentAnchor, x, y, withModelUpdate=True)

    def __displayTheTextShapes(self, oglTextShapes: OglTextShapes,
                               umlFrame: UmlDiagramsFrame):

        for oglTextShape in oglTextShapes:
            self.__displayAnOglObject(oglTextShape, umlFrame)

    def __displayTheLinks(self, oglLinks: OglLinks,
                          umlFrame: UmlDiagramsFrame):
        """
        Place the OGL links on the input frame at their respective positions

        Args:
            oglLinks:   A dictionary of OGL links
            umlFrame:   The UML Frame to place the OGL objects on
        """
        umlDiagram = umlFrame.GetDiagram()
        for oglLink in oglLinks:
            umlDiagram.AddShape(oglLink, withModelUpdate=True)
            controlPoints = oglLink.GetControlPoints()
            for controlPoint in controlPoints:
                umlDiagram.AddShape(controlPoint)

    def __displayTheNotes(self, oglNotes: OglNotes,
                          umlFrame: UmlDiagramsFrame):
        for oglNote in oglNotes.values():
            self.__displayAnOglObject(oglNote, umlFrame)

    def __displayTheActors(self, oglActors: OglActors,
                           umlFrame: UmlDiagramsFrame):
        for oglActor in oglActors.values():
            self.__displayAnOglObject(oglActor, umlFrame)

    def __displayTheUseCases(self, oglUseCases: OglUseCases,
                             umlFrame: UmlDiagramsFrame):
        for oglUseCase in oglUseCases.values():
            self.__displayAnOglObject(oglUseCase, umlFrame)

    def __displayTheSDMessages(self, oglSDMessages: OglSDMessages,
                               umlFrame: UmlDiagramsFrame):

        for oglSDMessage in oglSDMessages.values():
            umlFrame.getDiagram().AddShape(oglSDMessage)

    def __displayAnOglObject(self, oglObject: OglObject,
                             umlFrame: UmlDiagramsFrame):
        x, y = oglObject.GetPosition()
        umlFrame.addShape(oglObject, x, y)

    def __setupProgressDialog(self):

        self._dlgGauge = Dialog(None,
                                ID_ANY,
                                "Loading...",
                                style=STAY_ON_TOP | ICON_INFORMATION
                                | RESIZE_BORDER,
                                size=Size(250, 70))
        self._gauge: Gauge = Gauge(self._dlgGauge,
                                   ID_ANY,
                                   5,
                                   pos=Point(2, 5),
                                   size=Size(200, 30))
        self._dlgGauge.Show(True)
        wxYield()

    def __updateProgressDialog(self, newMessage: str, newGaugeValue: int):

        self._dlgGauge.SetTitle(newMessage)
        self._gauge.SetValue(newGaugeValue)
        wxYield()

    def __cleanupProgressDialog(self, umlFrame: UmlDiagramsFrame):

        umlFrame.Refresh()
        self._gauge.SetValue(5)
        wxYield()
        self._dlgGauge.Destroy()

    def __validateXmlVersion(self, dom: Document) -> Element:
        """

        Args:
            dom: The minidom Document

        Returns:
            The root element unless the XML version is incorrect
        """
        root: Element = dom.getElementsByTagName(
            PyutXmlConstants.TOP_LEVEL_ELEMENT)[0]
        if root.hasAttribute(PyutXmlConstants.ATTR_VERSION):
            version = int(root.getAttribute(PyutXmlConstants.ATTR_VERSION))
        else:
            version = 1
        if version != PyutXml.VERSION:
            self.logger.error("Wrong version of the file loader")
            eMsg: str = f'This is version {PyutXml.VERSION} and the file version is {version}'
            self.logger.error(eMsg)
            raise Exception(f'VERSION_ERROR:  {eMsg}')

        return root

    def __determineDocumentTitle(self, documentNode) -> str:

        docTitle: str = documentNode.getAttribute(PyutXmlConstants.ATTR_TITLE)
        docTypeStr: str = documentNode.getAttribute(PyutXmlConstants.ATTR_TYPE)

        if docTitle == '' or docTitle is None:
            return docTypeStr
        else:
            return docTitle

    def __showAppropriateUmlFrame(self, document) -> UmlDiagramsFrame:

        umlFrame: UmlDiagramsFrame = document.getFrame()
        mediator: Mediator = Mediator()
        mediator.getFileHandling().showFrame(umlFrame)

        return umlFrame

    def __positionAndSetupDiagramFrame(
        self,
        umlFrame: UmlDiagramsFrame,
        documentNode: Element,
    ):

        xStr: str = documentNode.getAttribute(
            PyutXmlConstants.ATTR_SCROLL_POSITION_X)
        yStr: str = documentNode.getAttribute(
            PyutXmlConstants.ATTR_SCROLL_POSITION_Y)

        scrollPosX: int = PyutUtils.secureInteger(xStr)
        scrollPosY: int = PyutUtils.secureInteger(yStr)

        umlFrame.Scroll(scrollPosX, scrollPosY)

        xPerUnitStr: str = documentNode.getAttribute(
            PyutXmlConstants.ATTR_PIXELS_PER_UNIT_X)
        yPerUnitStr: str = documentNode.getAttribute(
            PyutXmlConstants.ATTR_PIXELS_PER_UNIT_Y)

        pixelsPerUnitX: int = PyutUtils.secureInteger(xPerUnitStr)
        pixelsPerUnitY: int = PyutUtils.secureInteger(yPerUnitStr)
        if pixelsPerUnitX != 0 and pixelsPerUnitY != 0:
            umlFrame.SetScrollRate(xstep=pixelsPerUnitX, ystep=pixelsPerUnitY)

    def _nonEmptyParameters(self, params: Dict[str, str]) -> bool:
        """

        Args:
            params: A dictionary where the key is the name of the value and the value is the value

        Returns:    `True` if all the parameters are valid else `False`
        """
        areValid: bool = True
        for paramName in params.keys():
            if self._isNoneEmptyParameter(params[paramName]):
                continue
            else:
                areValid = False
                self.logger.info(
                    f'Parameter: {paramName} is either `None` or empty')

        return areValid

    def _isNoneEmptyParameter(self, valueToValidate: str):

        isValid: bool = True

        if valueToValidate is None or valueToValidate == '':
            isValid = False

        return isValid
Beispiel #3
0
    def open(self, dom, project):
        """
        Open a file and create a diagram.
        """
        dlgGauge = None
        umlFrame = None  # avoid Pycharm warning
        try:
            root = dom.getElementsByTagName("PyutProject")[0]
            if root.hasAttribute('version'):
                version = int(root.getAttribute("version"))
            else:
                version = 1
            if version != self._this_version:
                self.logger.error("Wrong version of the file loader")
                eMsg: str = f'This is version {self._this_version} and the file version is {version}'
                self.logger.error(eMsg)
                raise Exception(f'VERSION_ERROR:  {eMsg}')
            project.setCodePath(root.getAttribute("CodePath"))

            # Create and init gauge
            dlgGauge = Dialog(None,
                              -1,
                              "Loading...",
                              style=STAY_ON_TOP | ICON_INFORMATION
                              | RESIZE_BORDER,
                              size=Size(207, 70))
            gauge = Gauge(dlgGauge, -1, 5, pos=Point(2, 5), size=Size(200, 30))
            dlgGauge.Show(True)

            # for all elements il xml file
            dlgGauge.SetTitle("Reading file...")
            gauge.SetValue(1)

            for documentNode in dom.getElementsByTagName("PyutDocument"):

                dicoOglObjects = {}  # format {id/name : oglClass}
                dicoLink = {}  # format [id/name : PyutLink}
                dicoFather = {}  # format {id child oglClass : [id fathers]}

                docType = documentNode.getAttribute("type")  # Python 3 update

                document = project.newDocument(
                    PyutConstants.diagramTypeFromString(docType))
                umlFrame = document.getFrame()

                mediator: Mediator = Mediator()
                mediator.getFileHandling().showFrame(umlFrame)

                self._getOglClasses(
                    documentNode.getElementsByTagName('GraphicClass'),
                    dicoOglObjects, dicoLink, dicoFather, umlFrame)
                self._getOglNotes(
                    documentNode.getElementsByTagName('GraphicNote'),
                    dicoOglObjects, dicoLink, dicoFather, umlFrame)
                self._getOglActors(
                    documentNode.getElementsByTagName('GraphicActor'),
                    dicoOglObjects, dicoLink, dicoFather, umlFrame)
                self._getOglUseCases(
                    documentNode.getElementsByTagName('GraphicUseCase'),
                    dicoOglObjects, dicoLink, dicoFather, umlFrame)
                self._getOglLinks(
                    documentNode.getElementsByTagName("GraphicLink"),
                    dicoOglObjects, dicoLink, dicoFather, umlFrame)
                self._getOglSDInstances(
                    documentNode.getElementsByTagName("GraphicSDInstance"),
                    dicoOglObjects, dicoLink, dicoFather, umlFrame)
                self._getOglSDMessages(
                    documentNode.getElementsByTagName("GraphicSDMessage"),
                    dicoOglObjects, dicoLink, dicoFather, umlFrame)

                # fix the link's destination field
                gauge.SetValue(2)
                dlgGauge.SetTitle("Fixing link's destination...")
                for links in list(dicoLink.values()):
                    for link in links:
                        link[1].setDestination(
                            dicoOglObjects[link[0]].getPyutObject())
                # adding fathers
                dlgGauge.SetTitle("Adding fathers...")
                gauge.SetValue(3)
                for child, fathers in list(dicoFather.items()):
                    for father in fathers:
                        umlFrame.createInheritanceLink(dicoOglObjects[child],
                                                       dicoOglObjects[father])

                # adding links to this OGL object
                dlgGauge.SetTitle("Adding Links...")
                gauge.SetValue(4)
                for src, links in list(dicoLink.items()):
                    for link in links:
                        createdLink = umlFrame.createNewLink(
                            dicoOglObjects[src],
                            dicoOglObjects[link[1].getDestination().getId()])

                        # fix link with the loaded information
                        pyutLink = createdLink.getPyutObject()
                        traversalLink: PyutLink = link[1]
                        pyutLink.setBidir(traversalLink.getBidir())

                        # pyutLink.setDestinationCardinality(link[1].getDestinationCardinality())
                        # pyutLink.setSourceCardinality(link[1].getSrcCard())
                        pyutLink.destinationCardinality = traversalLink.destinationCardinality
                        pyutLink.sourceCardinality = traversalLink.sourceCardinality

                        pyutLink.setName(link[1].getName())
        except (ValueError, Exception) as e:
            if dlgGauge is not None:
                dlgGauge.Destroy()
            PyutUtils.displayError(_(f"Can't load file {e}"))
            umlFrame.Refresh()
            return

        # to draw diagram
        umlFrame.Refresh()
        gauge.SetValue(5)

        if dlgGauge is not None:
            dlgGauge.Destroy()