一步一步将PlantUML类图导出为自定义格式的XMI文件

一步一步将PlantUML类图导出为自定义格式的XMI文件

说明:

PlantUML(Java)中获取类图以及plantuml xmi代码是如何遍历实体并获取属性的

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

String source = "@startumln" +             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<Quark<Entity>> classes =  cd.getEntityFactory().root().getChildren(); classes.stream().forEach(c-> System.out.println(c)); 

从中知道如何获取ClassDiagram

查看 net.sourceforge.plantuml.xmi.XmiClassDiagramAbstractXmiClassDiagramStandard的定义:

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的迭代器
  • nameisAbstractisInterfaceisStatic 这些属性是如何获取的

还有 https://github.com/plantuml/plantuml/pull/1298/files 是2023年2月的一个PR(写本文时尚未Merge),可以作为参考(有待阅读)。

使用JAVA代码将PlantUML类图导出为XMI

通过调用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_STANDARDXMI_STARXMI_ARGO等格式

分析getDiagram的调用链

getDiagram方法来自net.sourceforge.plantuml.core.Diagram提供的exportDiagram接口方法,其实现:

    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;     } 

其中主要是调用了net.sourceforge.plantuml.AbstractPSystem中的exportDiagramNow接口方法。而其在net.sourceforge.plantuml.UmlDiagram中的实现如下:

    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);             }         }     } 

可以看出其主要是调用了net.sourceforge.plantuml.UmlDiagram.exportDiagramInternal接口方法,由于当前的类是ClassDiagram,其将调用net.sourceforge.plantuml.classdiagram.ClassDiagram实现的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(); 

其调用了net.atmp.CucaDiagram.createFilesXmi方法,其定义如下:

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

其中调用了net.sourceforge.plantuml.xmi.CucaDiagramXmiMakercreateFiles方法,其定义如下:

    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());         }     } 

可以看出涉及创建xmi文件的关键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方法后,调用内部API导出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文件并打印其中的属性信息

现在了解了一些后,使用以下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 = "@startumln"; //        source += "Bob -> Alice : hellon"; //        source += "@endumln";         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     } } 

创建JAVA项目并打包为JAR包:将PlantUML导出为自定义格式的XMI文件

创建项目

使用IDEA创建一个maven项目,然后打开plantuml的maven仓库页面: https://mvnrepository.com/artifact/net.sourceforge.plantuml/plantuml/1.2024.6 将dependency标签拷贝到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);     } } 

添加导出类(入口)

添加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();          // 导出XMI         XmlDiagramTransformer xmi = new XmiClassDiagramCustom(classDiagram);         xmi.transformerXml(outputCustom);      } } 

打包

接下来,参考 https://blog.csdn.net/weixin_41229430/article/details/138963215 打包为jar包

创建文件: src/main/assembly/assembly.xml, 内容如下:

<assembly>     <id>assembly</id>     <formats>         <format>zip</format>         <format>jar</format>         <format>tar.gz</format>     </formats>     <includeBaseDirectory>false</includeBaseDirectory>     <fileSets>         <!--   -->         <fileSet>             <directory>src/main/resources</directory>             <outputDirectory>conf</outputDirectory>             <includes>                 <include>*.xml</include>                 <include>*.properties</include>                 <include>**/*.xml</include>                 <include>**/*.properties</include>             </includes>             <fileMode>0644</fileMode>         </fileSet>         <fileSet>             <directory>assembly/bin</directory>             <outputDirectory>bin</outputDirectory>             <fileMode>0755</fileMode>         </fileSet>     </fileSets>     <dependencySets>         <dependencySet>             <outputDirectory>lib</outputDirectory>         </dependencySet>     </dependencySets> </assembly> 

然后在pom.xml中添加

    <build>         <plugins>             <!--主要用于将 Maven 项目打包成可执行的程序或分发包 -->             <plugin>                 <groupId>org.apache.maven.plugins</groupId>                 <artifactId>maven-assembly-plugin</artifactId>                 <version>3.3.0</version>                 <executions>                     <execution>                         <id>make-assembly2</id><!--名字任意 -->                         <phase>package</phase><!-- 绑定到package生命周期阶段上 -->                         <goals>                             <goal>single</goal><!-- 只运行一次 -->                         </goals>                         <configuration>                             <descriptors>                                 <descriptor>${basedir}/src/main/assembly/assembly.xml</descriptor>                             </descriptors>                             <archive>                                 <manifest>                                     <mainClass>org.export.UML2XMIExporter</mainClass>                                     <addClasspath>true</addClasspath>                                     <classpathPrefix>lib/</classpathPrefix>                                     <useUniqueVersions>false</useUniqueVersions>                                 </manifest>                             </archive>                             <descriptorRefs>                                 <descriptorRef>jar-with-dependencies</descriptorRef>                             </descriptorRefs>                         </configuration>                     </execution>                 </executions>             </plugin>              <plugin>                 <groupId>org.apache.maven.plugins</groupId>                 <artifactId>maven-compiler-plugin</artifactId>                 <version>3.8.1</version>                 <configuration>                     <source>1.8</source>                     <target>1.8</target>                 </configuration>             </plugin>         </plugins>     </build> 

点击IDEA右侧的m图标(maven),双击Lifecycle下的package。然后在target目录下可以看到已经生成了jar包。

打开command prompt命令行(不要使用powershell)运行:

java -Dfile.encoding=UTF-8 -jar custom-plantuml-xmi-export-1.0-SNAPSHOT-jar-with-dependencies.jar input.puml output.xmi 

发表评论

相关文章