您的位置:首頁 > 軟件教程 > 教程 > 一步一步將PlantUML類圖導(dǎo)出為自定義格式的XMI文件

一步一步將PlantUML類圖導(dǎo)出為自定義格式的XMI文件

來源:好特整理 | 時間:2024-09-08 10:22:19 | 閱讀:175 |  標(biāo)簽: a T 格   | 分享到:

一步一步將PlantUML類圖導(dǎo)出為自定義格式的XMI文件 說明: 首次發(fā)表日期:2024-09-08 PlantUML官網(wǎng): https://plantuml.com/zh/ PlantUML命令行文檔: https://plantuml.com/zh/command-line#6a26f5488

一步一步將PlantUML類圖導(dǎo)出為自定義格式的XMI文件

說明:

PlantUML(Java)中獲取類圖以及plantuml xmi代碼是如何遍歷實體并獲取屬性的

以下是來自 https://stackoverflow.com/questions/76599075/parse-uml-class-diagram-with-plantuml-java-api 的代碼:

String source = "@startuml\n" +
            PUT YOUR CLASS DIAGRAM HERE
            "@enduml";

SourceStringReader r = new SourceStringReader(source);
FileOutputStream file = new FileOutputStream("testGroovy2.png");
ClassDiagram cd = (ClassDiagram) r.getBlocks().get(0).getDiagram();
Collection> classes = 
cd.getEntityFactory().root().getChildren();
classes.stream().forEach(c-> System.out.println(c));

從中知道如何獲取ClassDiagram

查看 net.sourceforge.plantuml.xmi.XmiClassDiagramAbstract XmiClassDiagramStandard 的定義:

public class XmiClassDiagramStandard extends XmiClassDiagramAbstract implements XmlDiagramTransformer {
    public XmiClassDiagramStandard(ClassDiagram classDiagram) throws ParserConfigurationException {
        super(classDiagram);
        Iterator var2 = classDiagram.getEntityFactory().leafs().iterator();

        while(var2.hasNext()) {
            Entity ent = (Entity)var2.next();
            Element cla = this.createEntityNode(ent);
            if (cla != null) {
                this.ownedElementRoot.appendChild(cla);
                this.done.add(ent);
            }
        }

    }
}

從中知道如何遍歷entity

查看 net.sourceforge.plantuml.xmi.XmiClassDiagramStandard 中的 createEntityNode 方法:

    protected final Element createEntityNode(Entity entity) {
        Element cla = this.document.createElement("UML:Class");
        if (entity.getLeafType() == LeafType.NOTE) {
            return null;
        } else {
            cla.setAttribute("xmi.id", entity.getUid());
            cla.setAttribute("name", entity.getDisplay().get(0).toString());
            Stereotype stereotype = entity.getStereotype();
            if (stereotype != null) {
                Element stereo = this.document.createElement("UML:ModelElement.stereotype");
                Iterator var5 = stereotype.getMultipleLabels().iterator();

                while(var5.hasNext()) {
                    String s = (String)var5.next();
                    Element name = this.document.createElement("UML:Stereotype");
                    name.setAttribute("name", s);
                    stereo.appendChild(name);
                }

                cla.appendChild(stereo);
            }

            LeafType type = entity.getLeafType();
            if (type == LeafType.ABSTRACT_CLASS) {
                cla.setAttribute("isAbstract", "true");
            } else if (type == LeafType.INTERFACE) {
                cla.setAttribute("isInterface", "true");
            }

            if (entity.isStatic()) {
                cla.setAttribute("isStatic", "true");
            }

            if (entity.getVisibilityModifier() == VisibilityModifier.PRIVATE_FIELD || entity.getVisibilityModifier() == VisibilityModifier.PRIVATE_METHOD) {
                cla.setAttribute("visibility", entity.getVisibilityModifier().getXmiVisibility());
            }

            Element feature = this.document.createElement("UML:Classifier.feature");
            cla.appendChild(feature);

            Member m;
            Element operation;
            VisibilityModifier visibility;
            ListIterator var13;
            CharSequence cs;
            for(var13 = entity.getBodier().getFieldsToDisplay().iterator(); var13.hasNext(); feature.appendChild(operation)) {
                cs = (CharSequence)var13.next();
                m = (Member)cs;
                operation = this.document.createElement("UML:Attribute");
                operation.setAttribute("xmi.id", "att" + this.classDiagram.getUniqueSequence());
                operation.setAttribute("name", m.getDisplay(false));
                visibility = m.getVisibilityModifier();
                if (visibility != null) {
                    operation.setAttribute("visibility", visibility.getXmiVisibility());
                }

                if (m.isStatic()) {
                    operation.setAttribute("isStatic", "true");
                }
            }

            for(var13 = entity.getBodier().getMethodsToDisplay().iterator(); var13.hasNext(); feature.appendChild(operation)) {
                cs = (CharSequence)var13.next();
                m = (Member)cs;
                operation = this.document.createElement("UML:Operation");
                operation.setAttribute("xmi.id", "att" + this.classDiagram.getUniqueSequence());
                operation.setAttribute("name", m.getDisplay(false));
                visibility = m.getVisibilityModifier();
                if (visibility != null) {
                    operation.setAttribute("visibility", visibility.getXmiVisibility());
                }

                if (m.isStatic()) {
                    operation.setAttribute("isStatic", "true");
                }
            }

            return cla;
        }
    }

從中可以看出:

  • entity.getBodier().getFieldsToDisplay().iterator() 是獲取entity的attribute的迭代器
  • entity.getBodier().getMethodsToDisplay().iterator() 是獲取entity的operation的迭代器
  • name , isAbstract isInterface isStatic 這些屬性是如何獲取的

還有 https://github.com/plantuml/plantuml/pull/1298/files 是2023年2月的一個PR(寫本文時尚未Merge),可以作為參考(有待閱讀)。

使用JAVA代碼將PlantUML類圖導(dǎo)出為XMI

通過調(diào)用exportDiagram方法

import net.sourceforge.plantuml.FileFormat;  
import net.sourceforge.plantuml.FileFormatOption;  
import net.sourceforge.plantuml.SourceStringReader;

import java.io.FileOutputStream;

public class Main {  
    public static void main(String[] args) throws IOException {
        OutputStream output = new FileOutputStream("test.xmi");
        
        FileFormatOption fileFormatOption = new FileFormatOption(FileFormat.XMI_ARGO);

        String content = new String(Files.readAllBytes(Paths.get("a.puml")));
        SourceStringReader reader = new SourceStringReader(content);

        reader.getBlocks().get(0).getDiagram().exportDiagram(output, 0, fileFormatOption);
    }
}

其中 FileFormat 是一個枚舉,定義了 XMI_STANDARD XMI_STAR XMI_ARGO 等格式

分析getDiagram的調(diào)用鏈

getDiagram 方法來自 net.sourceforge.plantuml.core.Diagram 提供的 exportDiagram 接口方法,其實現(xiàn):

    public final ImageData exportDiagram(OutputStream os, int index, FileFormatOption fileFormatOption) throws IOException {
        long now = System.currentTimeMillis();

        ImageData var6;
        try {
            var6 = this.exportDiagramNow(os, index, fileFormatOption);
        } finally {
            if (OptionFlags.getInstance().isEnableStats()) {
                StatsUtilsIncrement.onceMoreGenerate(System.currentTimeMillis() - now, this.getClass(), fileFormatOption.getFileFormat());
            }

        }

        return var6;
    }

其中主要是調(diào)用了 net.sourceforge.plantuml.AbstractPSystem 中的 exportDiagramNow 接口方法。而其在 net.sourceforge.plantuml.UmlDiagram 中的實現(xiàn)如下:

    protected final ImageData exportDiagramNow(OutputStream os, int index, FileFormatOption fileFormatOption) throws IOException {
        fileFormatOption = fileFormatOption.withTikzFontDistortion(this.getSkinParam().getTikzFontDistortion());
        if (fileFormatOption.getFileFormat() == FileFormat.PDF) {
            return this.exportDiagramInternalPdf(os, index);
        } else {
            try {
                ImageData imageData = this.exportDiagramInternal(os, index, fileFormatOption);
                this.lastInfo = new XDimension2D((double)imageData.getWidth(), (double)imageData.getHeight());
                return imageData;
            } catch (NoStyleAvailableException var5) {
                this.exportDiagramError(os, var5, fileFormatOption, (String)null);
                return ImageDataSimple.error(var5);
            } catch (UnparsableGraphvizException var6) {
                Logme.error(var6);
                this.exportDiagramError(os, var6.getCause(), fileFormatOption, var6.getGraphvizVersion());
                return ImageDataSimple.error(var6);
            } catch (Throwable var7) {
                this.exportDiagramError(os, var7, fileFormatOption, (String)null);
                return ImageDataSimple.error(var7);
            }
        }
    }

可以看出其主要是調(diào)用了 net.sourceforge.plantuml.UmlDiagram.exportDiagramInternal 接口方法,由于當(dāng)前的類是 ClassDiagram ,其將調(diào)用 net.sourceforge.plantuml.classdiagram.ClassDiagram 實現(xiàn)的 exportDiagramInternal 方法:

    protected final ImageData exportDiagramInternal(OutputStream os, int index, FileFormatOption fileFormatOption) throws IOException {
        return this.useLayoutExplicit != 0 ? this.exportLayoutExplicit(os, index, fileFormatOption) : super.exportDiagramInternal(os, index, fileFormatOption);
    }

其中 net.sourceforge.plantuml.classdiagram.ClassDiagram 繼承 net.sourceforge.plantuml.objectdiagram.AbstractClassOrObjectDiagram 繼承 net.sourceforge.plantuml.classdiagram.AbstractEntityDiagram 繼承 net.atmp.CucaDiagram

net.atmp.CucaDiagram.exportDiagramInternal 方法中涉及XMI的部分如下:

                this.createFilesXmi(os, fileFormat);
                return ImageDataSimple.ok();

其調(diào)用了 net.atmp.CucaDiagram.createFilesXmi 方法,其定義如下:

    private void createFilesXmi(OutputStream suggestedFile, FileFormat fileFormat) throws IOException {
        CucaDiagramXmiMaker maker = new CucaDiagramXmiMaker(this, fileFormat);
        maker.createFiles(suggestedFile);
    }

其中調(diào)用了 net.sourceforge.plantuml.xmi.CucaDiagramXmiMaker createFiles 方法,其定義如下:

    public void createFiles(OutputStream fos) throws IOException {
        try {
            Object xmi;
            if (this.diagram instanceof StateDiagram) {
                xmi = new XmiStateDiagram((StateDiagram)this.diagram);
            } else if (this.diagram instanceof DescriptionDiagram) {
                xmi = this.createDescriptionDiagram();
            } else {
                if (!(this.diagram instanceof ClassDiagram)) {
                    throw new UnsupportedOperationException("Diagram type " + this.diagram.getUmlDiagramType() + " is not supported in XMI");
                }

                xmi = this.createClassDiagram();
            }

            ((XmlDiagramTransformer)xmi).transformerXml(fos);
        } catch (ParserConfigurationException var3) {
            Log.error(var3.toString());
            Logme.error(var3);
            throw new IOException(var3.toString());
        } catch (TransformerException var4) {
            Log.error(var4.toString());
            Logme.error(var4);
            throw new IOException(var4.toString());
        }
    }

可以看出涉及創(chuàng)建xmi文件的關(guān)鍵2行為:

xmi = this.createClassDiagram();
((XmlDiagramTransformer)xmi).transformerXml(fos);

createClassDiagram 的定義如下:

    private XmlDiagramTransformer createClassDiagram() throws ParserConfigurationException {
        if (this.fileFormat == FileFormat.XMI_STANDARD) {
            return new XmiClassDiagramStandard((ClassDiagram)this.diagram);
        } else if (this.fileFormat == FileFormat.XMI_ARGO) {
            return new XmiClassDiagramArgo((ClassDiagram)this.diagram);
        } else if (this.fileFormat == FileFormat.XMI_SCRIPT) {
            return new XmiClassDiagramScript((ClassDiagram)this.diagram);
        } else if (this.fileFormat == FileFormat.XMI_STAR) {
            return new XmiClassDiagramStar((ClassDiagram)this.diagram);
        } else {
            throw new UnsupportedOperationException();
        }
    }

分析getDiagram方法后,調(diào)用內(nèi)部API導(dǎo)出XMI

import net.sourceforge.plantuml.FileFormat;  
import net.sourceforge.plantuml.FileFormatOption;  
import net.sourceforge.plantuml.SourceStringReader;
import net.sourceforge.plantuml.xmi.XmiClassDiagramArgo;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;

import java.io.FileOutputStream;

public class Main {  
    public static void main(String[] args) throws IOException, ParserConfigurationException, TransformerException {
        OutputStream fos = new FileOutputStream("test2.xmi");
        
        FileFormatOption fileFormatOption = new FileFormatOption(FileFormat.XMI_ARGO);

        String content = new String(Files.readAllBytes(Paths.get("a.puml")));
        SourceStringReader reader = new SourceStringReader(content);
        ClassDiagram classDiagram = (ClassDiagram) reader.getBlocks().get(0).getDiagram();

        Object xmi = new XmiClassDiagramArgo(classDiagram);
        ((XmlDiagramTransformer)xmi).transformerXml(fos);
    }
}

讀取一個uml文件并打印其中的屬性信息

現(xiàn)在了解了一些后,使用以下Java代碼來查看UML文件的信息

package org.example;

import net.sourceforge.plantuml.SourceStringReader;
import net.sourceforge.plantuml.abel.Entity;
import net.sourceforge.plantuml.abel.LeafType;
import net.sourceforge.plantuml.abel.Link;
import net.sourceforge.plantuml.classdiagram.ClassDiagram;
import net.sourceforge.plantuml.cucadiagram.Member;
import net.sourceforge.plantuml.skin.VisibilityModifier;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Iterator;

import java.util.ListIterator;


public class Main {
    public static void main(String[] args) throws IOException, ParserConfigurationException, TransformerException {
        OutputStream output = new FileOutputStream("test.xmi");
//        String source = "@startuml\n";
//        source += "Bob -> Alice : hello\n";
//        source += "@enduml\n";
        String content = new String(Files.readAllBytes(Paths.get("a.puml")));

        SourceStringReader reader = new SourceStringReader(content);
        ClassDiagram classDiagram = (ClassDiagram) reader.getBlocks().get(0).getDiagram();

        String titleName = classDiagram.getTitleDisplay().get(0).toString();
        System.out.println("title: " + titleName);
        Iterator var2 = classDiagram.getEntityFactory().leafs().iterator();

        while(var2.hasNext()) {
            Entity entity = (Entity)var2.next();

            System.out.println("----------------------------------");
            System.out.println("uid: " + entity.getUid());
            if (entity.getLeafType() == LeafType.NOTE) {
//                entity.isAloneAndUnlinked();
//                System.out.println("Entity type: " + entity.getLeafType());
            } else {

                Iterator var1 = classDiagram.getLinks().iterator();
                while(var1.hasNext()) {
                    Link link = (Link)var1.next();
                    if (link.contains(entity)) {
                        Entity other = link.getOther(entity);
                        if (other.getLeafType() == LeafType.NOTE) {
                            System.out.println("Note: "  + other.getDisplay().get(0).toString());
                        }
                    }
                }

                System.out.println("Entity type: " + entity.getLeafType());

                String entityName = entity.getDisplay().get(0).toString();
                System.out.println("Entity name: " + entityName);
                System.out.println("Package: " + entity.getQuark().getParent().toString());

                LeafType type = entity.getLeafType();

                if (type == LeafType.ABSTRACT_CLASS) {
                    System.out.println("isAbstract");
                } else if (type == LeafType.INTERFACE) {
                    System.out.println("isInterface");
                }

                if (entity.isStatic()) {
                    System.out.println(("isStatic"));
                }

                if (entity.getVisibilityModifier() == VisibilityModifier.PRIVATE_FIELD || entity.getVisibilityModifier() == VisibilityModifier.PRIVATE_METHOD) {
                    System.out.println("visibility: " + entity.getVisibilityModifier().getXmiVisibility());
                }

                Member m;
                VisibilityModifier visibility;
                ListIterator var13;
                CharSequence cs;
                for (var13 = entity.getBodier().getFieldsToDisplay().iterator(); var13.hasNext();) {
                    cs = (CharSequence)var13.next();
                    m = (Member) cs;
                    System.out.println("field name: " + m.getDisplay(false));
                    visibility = m.getVisibilityModifier();
                    if (visibility != null) {
                        System.out.println("visibility: " + visibility.getXmiVisibility());
                    }

                    if (m.isStatic()) {
                        System.out.println("isStatic");
                    }
                }

                for (var13 = entity.getBodier().getMethodsToDisplay().iterator(); var13.hasNext();) {
                    cs = (CharSequence)var13.next();
                    m = (Member) cs;
                    System.out.println("operation name: " + m.getDisplay(false));

                    visibility = m.getVisibilityModifier();
                    if (visibility != null) {
                        System.out.println("visibility: " + visibility.getXmiVisibility());
                    }

                    if (m.isStatic()) {
                        System.out.println("isStatic");
                    }
                }
            }

        }

// Write the first image to "png"
//        String desc = reader.outputImage(output).getDescription();
// Return a null string if no generation
    }
}

創(chuàng)建JAVA項目并打包為JAR包:將PlantUML導(dǎo)出為自定義格式的XMI文件

創(chuàng)建項目

使用IDEA創(chuàng)建一個maven項目,然后打開plantuml的maven倉庫頁面: https://mvnrepository.com/artifact/net.sourceforge.plantuml/plantuml/1.2024.6 將dependency標(biāo)簽拷貝到pom.xml中

添加用于自定義XMI格式的類

由于不能引用 XmiClassDiagramAbstract (提示 is not public in 'net.sourceforge.plantuml.xmi'. Cannot be accessed from outside package),所以在 src/main/java 下新建package net.sourceforge.plantuml.xmi

然后添加類 XmiClassDiagramCustom (extends XmiClassDiagramAbstract):

package net.sourceforge.plantuml.xmi;

import java.util.Iterator;
import java.util.ListIterator;
import javax.xml.parsers.ParserConfigurationException;

import net.sourceforge.plantuml.abel.Entity;
import net.sourceforge.plantuml.abel.LeafType;
import net.sourceforge.plantuml.abel.Link;
import net.sourceforge.plantuml.classdiagram.ClassDiagram;
import net.sourceforge.plantuml.cucadiagram.Member;
import net.sourceforge.plantuml.decoration.LinkDecor;
import net.sourceforge.plantuml.klimt.creole.Display;
import net.sourceforge.plantuml.skin.VisibilityModifier;
import net.sourceforge.plantuml.stereo.Stereotype;
import org.w3c.dom.Element;

public class XmiClassDiagramCustom extends XmiClassDiagramAbstract implements XmlDiagramTransformer {
    public XmiClassDiagramCustom(ClassDiagram classDiagram) throws ParserConfigurationException {
        super(classDiagram);
        Iterator var2 = classDiagram.getEntityFactory().leafs().iterator();

        Element titleElement = this.document.createElement("UML:Title");
        titleElement.setAttribute("name", classDiagram.getTitleDisplay().get(0).toString());
        this.ownedElementRoot.appendChild(titleElement);

        while(var2.hasNext()) {
            Entity ent = (Entity)var2.next();
            Element cla = this.createEntityNodeCustom(ent, classDiagram);
            if (cla != null) {
                this.ownedElementRoot.appendChild(cla);
                this.done.add(ent);
            }
        }

        var2 = classDiagram.getLinks().iterator();

        while(var2.hasNext()) {
            Link link = (Link)var2.next();
            this.addLink(link);
        }

    }

    protected final Element createEntityNodeCustom(Entity entity, ClassDiagram classDiagram) {
        Element cla = this.document.createElement("UML:Class");
        if (entity.getLeafType() == LeafType.NOTE) {
            return null;
        } else {
            cla.setAttribute("xmi.id", entity.getUid());
            cla.setAttribute("name", entity.getDisplay().get(0).toString());

            // Get Note:
            Iterator var1 = classDiagram.getLinks().iterator();
            while(var1.hasNext()) {
                Link link = (Link)var1.next();
                if (link.contains(entity)) {
                    Entity other = link.getOther(entity);
                    if (other.getLeafType() == LeafType.NOTE) {
                        cla.setAttribute("note", other.getDisplay().get(0).toString());
//                        System.out.println("Note: "  + other.getDisplay().get(0).toString());
                    }
                }
            }

            cla.setAttribute("package", entity.getQuark().getParent().toString());

            Stereotype stereotype = entity.getStereotype();
            if (stereotype != null) {
                Element stereo = this.document.createElement("UML:ModelElement.stereotype");
                Iterator var5 = stereotype.getMultipleLabels().iterator();

                while(var5.hasNext()) {
                    String s = (String)var5.next();
                    Element name = this.document.createElement("UML:Stereotype");
                    name.setAttribute("name", s);
                    stereo.appendChild(name);
                }

                cla.appendChild(stereo);
            }

            LeafType type = entity.getLeafType();
            if (type == LeafType.ABSTRACT_CLASS) {
                cla.setAttribute("isAbstract", "true");
            } else if (type == LeafType.INTERFACE) {
                cla.setAttribute("isInterface", "true");
            }

            if (entity.isStatic()) {
                cla.setAttribute("isStatic", "true");
            }

            if (entity.getVisibilityModifier() == VisibilityModifier.PRIVATE_FIELD || entity.getVisibilityModifier() == VisibilityModifier.PRIVATE_METHOD) {
                cla.setAttribute("visibility", entity.getVisibilityModifier().getXmiVisibility());
            }

            Element feature = this.document.createElement("UML:Classifier.feature");
            cla.appendChild(feature);

            Member m;
            Element operation;
            VisibilityModifier visibility;
            ListIterator var13;
            CharSequence cs;
            for(var13 = entity.getBodier().getFieldsToDisplay().iterator(); var13.hasNext(); feature.appendChild(operation)) {
                cs = (CharSequence)var13.next();
                m = (Member)cs;
                operation = this.document.createElement("UML:Attribute");
                operation.setAttribute("xmi.id", "att" + this.classDiagram.getUniqueSequence());
                operation.setAttribute("name", m.getDisplay(false));
                visibility = m.getVisibilityModifier();
                if (visibility != null) {
                    operation.setAttribute("visibility", visibility.getXmiVisibility());
                }

                if (m.isStatic()) {
                    operation.setAttribute("isStatic", "true");
                }
            }

            for(var13 = entity.getBodier().getMethodsToDisplay().iterator(); var13.hasNext(); feature.appendChild(operation)) {
                cs = (CharSequence)var13.next();
                m = (Member)cs;
                operation = this.document.createElement("UML:Operation");
                operation.setAttribute("xmi.id", "att" + this.classDiagram.getUniqueSequence());
                operation.setAttribute("name", m.getDisplay(false));
                visibility = m.getVisibilityModifier();
                if (visibility != null) {
                    operation.setAttribute("visibility", visibility.getXmiVisibility());
                }

                if (m.isStatic()) {
                    operation.setAttribute("isStatic", "true");
                }
            }

            return cla;
        }
    }

    // copy from XmiClassDiagramStar
    private void addLink(Link link) {
        if (!link.isHidden() && !link.isInvis()) {
            String assId = "ass" + this.classDiagram.getUniqueSequence();
            if (link.getType().getDecor1() != LinkDecor.EXTENDS && link.getType().getDecor2() != LinkDecor.EXTENDS) {
                Element association = this.document.createElement("UML:Association");
                association.setAttribute("xmi.id", assId);
                association.setAttribute("namespace", CucaDiagramXmiMaker.getModel(this.classDiagram));
                if (!Display.isNull(link.getLabel())) {
                    association.setAttribute("name", this.forXMI(link.getLabel()));
                }

                Element connection = this.document.createElement("UML:Association.connection");
                Element end1 = this.document.createElement("UML:AssociationEnd");
                end1.setAttribute("xmi.id", "end" + this.classDiagram.getUniqueSequence());
                end1.setAttribute("association", assId);
                end1.setAttribute("type", link.getEntity1().getUid());
                if (link.getQuantifier1() != null) {
                    end1.setAttribute("name", this.forXMI(link.getQuantifier1()));
                }

                Element endparticipant1 = this.document.createElement("UML:AssociationEnd.participant");
                if (link.getType().getDecor2() == LinkDecor.COMPOSITION) {
                    end1.setAttribute("aggregation", "composite");
                }

                if (link.getType().getDecor2() == LinkDecor.AGREGATION) {
                    end1.setAttribute("aggregation", "aggregate");
                }

                end1.appendChild(endparticipant1);
                connection.appendChild(end1);
                Element end2 = this.document.createElement("UML:AssociationEnd");
                end2.setAttribute("xmi.id", "end" + this.classDiagram.getUniqueSequence());
                end2.setAttribute("association", assId);
                end2.setAttribute("type", link.getEntity2().getUid());
                if (link.getQuantifier2() != null) {
                    end2.setAttribute("name", this.forXMI(link.getQuantifier2()));
                }

                Element endparticipant2 = this.document.createElement("UML:AssociationEnd.participant");
                if (link.getType().getDecor1() == LinkDecor.COMPOSITION) {
                    end2.setAttribute("aggregation", "composite");
                }

                if (link.getType().getDecor1() == LinkDecor.AGREGATION) {
                    end2.setAttribute("aggregation", "aggregate");
                }

                end2.appendChild(endparticipant2);
                connection.appendChild(end2);
                association.appendChild(connection);
                this.ownedElementRoot.appendChild(association);
            } else {
                this.addExtension(link, assId);
            }
        }
    }

    // copy from XmiClassDiagramStar
    private void addExtension(Link link, String assId) {
        Element association = this.document.createElement("UML:Generalization");
        association.setAttribute("xmi.id", assId);
        association.setAttribute("namespace", CucaDiagramXmiMaker.getModel(this.classDiagram));
        if (link.getLabel() != null) {
            association.setAttribute("name", this.forXMI(link.getLabel()));
        }

        if (link.getType().getDecor1() == LinkDecor.EXTENDS) {
            association.setAttribute("child", link.getEntity1().getUid());
            association.setAttribute("parent", link.getEntity2().getUid());
        } else {
            if (link.getType().getDecor2() != LinkDecor.EXTENDS) {
                throw new IllegalStateException();
            }

            association.setAttribute("child", link.getEntity2().getUid());
            association.setAttribute("parent", link.getEntity1().getUid());
        }

        this.ownedElementRoot.appendChild(association);
    }
}

添加導(dǎo)出類(入口)

添加package org.export ,并添加類 UML2XMIExporter

package org.export;

import net.sourceforge.plantuml.SourceStringReader;
import net.sourceforge.plantuml.classdiagram.ClassDiagram;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Paths;


import net.sourceforge.plantuml.xmi.XmiClassDiagramCustom;
import net.sourceforge.plantuml.xmi.XmlDiagramTransformer;

public class UML2XMIExporter {
    public static void main(String[] args) throws IOException, ParserConfigurationException, TransformerException {

        String content = new String(Files.readAllBytes(Paths.get(args[0])));
        OutputStream outputCustom = Files.newOutputStream(Paths.get(args[1]));

        SourceStringReader reader = new SourceStringReader(content);
        ClassDiagram classDiagram = (ClassDiagram) reader.getBlocks().get(0).getDiagram();

        // 導(dǎo)出XMI
        XmlDiagramTransformer xmi = new XmiClassDiagramCustom(classDiagram);
        xmi.transformerXml(outputCustom);

    }
}

打包

接下來,參考 https://blog.csdn.net/weixin_41229430/article/details/138963215 打包為jar包

創(chuàng)建文件: src/main/assembly/assembly.xml, 內(nèi)容如下:


    assembly
    
        zip
        jar
        tar.gz
    
    false
    
        
        
            src/main/resources
            conf
            
                *.xml
                *.properties
                **/*.xml
                **/*.properties
            
            0644
        
        
            assembly/bin
            bin
            0755
        
    
    
        
            lib
        
    

然后在pom.xml中添加

    
        
            
            
                org.apache.maven.plugins
                maven-assembly-plugin
                3.3.0
                
                    
                        make-assembly2
                        package
                        
                            single
                        
                        
                            
                                ${basedir}/src/main/assembly/assembly.xml
                            
                            
                                
                                    org.export.UML2XMIExporter
                                    true
                                    lib/
                                    false
                                
                            
                            
                                jar-with-dependencies
                            
                        
                    
                
            

            
                org.apache.maven.plugins
                maven-compiler-plugin
                3.8.1
                
                    1.8
                    1.8
                
            
        
    

點擊IDEA右側(cè)的m圖標(biāo)(maven),雙擊Lifecycle下的package。然后在target目錄下可以看到已經(jīng)生成了jar包。

打開command prompt命令行(不要使用powershell)運(yùn)行:

java -Dfile.encoding=UTF-8 -jar custom-plantuml-xmi-export-1.0-SNAPSHOT-jar-with-dependencies.jar input.puml output.xmi
小編推薦閱讀

好特網(wǎng)發(fā)布此文僅為傳遞信息,不代表好特網(wǎng)認(rèn)同期限觀點或證實其描述。

a 1.0
a 1.0
類型:休閑益智  運(yùn)營狀態(tài):正式運(yùn)營  語言:中文   

游戲攻略

游戲禮包

游戲視頻

游戲下載

游戲活動

《alittletotheleft》官網(wǎng)正版是一款備受歡迎的休閑益智整理游戲。玩家的任務(wù)是對日常生活中的各種雜亂物
格
類型:休閑益智  運(yùn)營狀態(tài):正式運(yùn)營  語言:中文   

游戲攻略

游戲禮包

游戲視頻

游戲下載

游戲活動

《格》是RikiGame開發(fā)的一款休閑益智解謎手游,在游戲中玩家將通過一路的解謎通關(guān),了解故事小女孩的成長

相關(guān)視頻攻略

更多

掃二維碼進(jìn)入好特網(wǎng)手機(jī)版本!

掃二維碼進(jìn)入好特網(wǎng)微信公眾號!

本站所有軟件,都由網(wǎng)友上傳,如有侵犯你的版權(quán),請發(fā)郵件[email protected]

湘ICP備2022002427號-10 湘公網(wǎng)安備:43070202000427號© 2013~2024 haote.com 好特網(wǎng)