Step-by-step export of PlantUML class diagrams to a customized format XMI file
Description:
- First published: 2024-09-08
- PlantUML official website:/zh/
- PlantUML command line documentation:/zh/command-line#6a26f548831e6a8c
- PlantUML XMI documentation./zh/xmi
- Further use: generating code from exported XMI files
Getting class diagrams in PlantUML (Java) and how plantuml xmi code traverses entities and gets attributes
The following is from/questions/76599075/parse-uml-class-diagram-with-plantuml-java-api of the code:
String source = "@startuml\n" +
PUT YOUR CLASS DIAGRAM HERE
"@enduml";
SourceStringReader r = new SourceStringReader(source);
FileOutputStream file = new FileOutputStream("");
ClassDiagram cd = (ClassDiagram) ().get(0).getDiagram();
Collection<Quark<Entity>> classes =
().root().getChildren();
().forEach(c-> (c));
Know how to get ClassDiagram from
ferret out center
XmiClassDiagramStandard
Definition of:
public class XmiClassDiagramStandard extends XmiClassDiagramAbstract implements XmlDiagramTransformer {
public XmiClassDiagramStandard(ClassDiagram classDiagram) throws ParserConfigurationException {
super(classDiagram);
Iterator var2 = ().leafs().iterator();
while(()) {
Entity ent = (Entity)();
Element cla = (ent);
if (cla != null) {
(cla);
(ent);
}
}
}
}
From this, we know how to traverse the entity
ferret out hit the nail on the head
createEntityNode
Methods:
protected final Element createEntityNode(Entity entity) {
Element cla = ("UML:Class");
if (() == ) {
return null;
} else {
("", ());
("name", ().get(0).toString());
Stereotype stereotype = ();
if (stereotype != null) {
Element stereo = ("UML:");
Iterator var5 = ().iterator();
while(()) {
String s = (String)();
Element name = ("UML:Stereotype");
("name", s);
(name);
}
(stereo);
}
LeafType type = ();
if (type == LeafType.ABSTRACT_CLASS) {
("isAbstract", "true");
} else if (type == ) {
("isInterface", "true");
}
if (()) {
("isStatic", "true");
}
if (() == VisibilityModifier.PRIVATE_FIELD || () == VisibilityModifier.PRIVATE_METHOD) {
("visibility", ().getXmiVisibility());
}
Element feature = ("UML:");
(feature);
Member m;
Element operation;
VisibilityModifier visibility;
ListIterator var13;
CharSequence cs;
for(var13 = ().getFieldsToDisplay().iterator(); (); (operation)) {
cs = (CharSequence)();
m = (Member)cs;
operation = ("UML:Attribute");
("", "att" + ());
("name", (false));
visibility = ();
if (visibility != null) {
("visibility", ());
}
if (()) {
("isStatic", "true");
}
}
for(var13 = ().getMethodsToDisplay().iterator(); (); (operation)) {
cs = (CharSequence)();
m = (Member)cs;
operation = ("UML:Operation");
("", "att" + ());
("name", (false));
visibility = ();
if (visibility != null) {
("visibility", ());
}
if (()) {
("isStatic", "true");
}
}
return cla;
}
}
As you can see from this:
-
().getFieldsToDisplay().iterator()
is an iterator that gets the entity's attribute. -
().getMethodsToDisplay().iterator()
is an iterator that gets the entity's operation. -
name
,isAbstract
,isInterface
cap (a poem)isStatic
How these attributes are obtained
there are/plantuml/plantuml/pull/1298/files It's a PR from February 2023 (not yet Merge at the time of writing this article) that can be used as a reference (to be read).
Exporting PlantUML Class Diagrams to XMI Using JAVA Code
By calling the exportDiagram method
import ;
import ;
import ;
import ;
public class Main {
public static void main(String[] args) throws IOException {
OutputStream output = new FileOutputStream("");
FileFormatOption fileFormatOption = new FileFormatOption(FileFormat.XMI_ARGO);
String content = new String((("")));
SourceStringReader reader = new SourceStringReader(content);
().get(0).getDiagram().exportDiagram(output, 0, fileFormatOption);
}
}
included among theseFileFormat
is an enumeration that defines theXMI_STANDARD
,XMI_STAR
cap (a poem)XMI_ARGO
iso-format
Analyzing the call chain of getDiagram
getDiagram
Methods fromoffered
exportDiagram
interface method, its implementation:
public final ImageData exportDiagram(OutputStream os, int index, FileFormatOption fileFormatOption) throws IOException {
long now = ();
ImageData var6;
try {
var6 = (os, index, fileFormatOption);
} finally {
if (().isEnableStats()) {
(() - now, (), ());
}
}
return var6;
}
which is mainly a call to thehit the nail on the head
exportDiagramNow
interface method. And its interface methods in theThe implementation in is as follows:
protected final ImageData exportDiagramNow(OutputStream os, int index, FileFormatOption fileFormatOption) throws IOException {
fileFormatOption = (().getTikzFontDistortion());
if (() == ) {
return (os, index);
} else {
try {
ImageData imageData = (os, index, fileFormatOption);
= new XDimension2D((double)(), (double)());
return imageData;
} catch (NoStyleAvailableException var5) {
(os, var5, fileFormatOption, (String)null);
return (var5);
} catch (UnparsableGraphvizException var6) {
(var6);
(os, (), fileFormatOption, ());
return (var6);
} catch (Throwable var7) {
(os, var7, fileFormatOption, (String)null);
return (var7);
}
}
}
It can be seen that it mainly calls theinterface method, since the current class is
ClassDiagram
It will call thepractical
exportDiagramInternal
Methods:
protected final ImageData exportDiagramInternal(OutputStream os, int index, FileFormatOption fileFormatOption) throws IOException {
return != 0 ? (os, index, fileFormatOption) : (os, index, fileFormatOption);
}
included among thesepredecessor
predecessor
predecessor
(indicates contrast)The part of the method that deals with XMI is as follows:
(os, fileFormat);
return ();
It calls themethod, which is defined below:
private void createFilesXmi(OutputStream suggestedFile, FileFormat fileFormat) throws IOException {
CucaDiagramXmiMaker maker = new CucaDiagramXmiMaker(this, fileFormat);
(suggestedFile);
}
which calls the(used form a nominal expression)
createFiles
method, which is defined below:
public void createFiles(OutputStream fos) throws IOException {
try {
Object xmi;
if ( instanceof StateDiagram) {
xmi = new XmiStateDiagram((StateDiagram));
} else if ( instanceof DescriptionDiagram) {
xmi = ();
} else {
if (!( instanceof ClassDiagram)) {
throw new UnsupportedOperationException("Diagram type " + () + " is not supported in XMI");
}
xmi = ();
}
((XmlDiagramTransformer)xmi).transformerXml(fos);
} catch (ParserConfigurationException var3) {
(());
(var3);
throw new IOException(());
} catch (TransformerException var4) {
(());
(var4);
throw new IOException(());
}
}
You can see the key 2 behaviors involved in creating an xmi file:
xmi = ();
((XmlDiagramTransformer)xmi).transformerXml(fos);
(indicates contrast)createClassDiagram
The definitions are as follows:
private XmlDiagramTransformer createClassDiagram() throws ParserConfigurationException {
if ( == FileFormat.XMI_STANDARD) {
return new XmiClassDiagramStandard((ClassDiagram));
} else if ( == FileFormat.XMI_ARGO) {
return new XmiClassDiagramArgo((ClassDiagram));
} else if ( == FileFormat.XMI_SCRIPT) {
return new XmiClassDiagramScript((ClassDiagram));
} else if ( == FileFormat.XMI_STAR) {
return new XmiClassDiagramStar((ClassDiagram));
} else {
throw new UnsupportedOperationException();
}
}
After analyzing the getDiagram method, call the internal API to export the XMI
import ;
import ;
import ;
import ;
import ;
import ;
import ;
public class Main {
public static void main(String[] args) throws IOException, ParserConfigurationException, TransformerException {
OutputStream fos = new FileOutputStream("");
FileFormatOption fileFormatOption = new FileFormatOption(FileFormat.XMI_ARGO);
String content = new String((("")));
SourceStringReader reader = new SourceStringReader(content);
ClassDiagram classDiagram = (ClassDiagram) ().get(0).getDiagram();
Object xmi = new XmiClassDiagramArgo(classDiagram);
((XmlDiagramTransformer)xmi).transformerXml(fos);
}
}
Reads an uml file and prints its properties.
Now that you know a bit more, use the following Java code to view the information in the UML file
package ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
public class Main {
public static void main(String[] args) throws IOException, ParserConfigurationException, TransformerException {
OutputStream output = new FileOutputStream("");
// String source = "@startuml\n";
// source += "Bob -> Alice : hello\n";
// source += "@enduml\n";
String content = new String((("")));
SourceStringReader reader = new SourceStringReader(content);
ClassDiagram classDiagram = (ClassDiagram) ().get(0).getDiagram();
String titleName = ().get(0).toString();
("title: " + titleName);
Iterator var2 = ().leafs().iterator();
while(()) {
Entity entity = (Entity)();
("----------------------------------");
("uid: " + ());
if (() == ) {
// ();
// ("Entity type: " + ());
} else {
Iterator var1 = ().iterator();
while(()) {
Link link = (Link)();
if ((entity)) {
Entity other = (entity);
if (() == ) {
("Note: " + ().get(0).toString());
}
}
}
("Entity type: " + ());
String entityName = ().get(0).toString();
("Entity name: " + entityName);
("Package: " + ().getParent().toString());
LeafType type = ();
if (type == LeafType.ABSTRACT_CLASS) {
("isAbstract");
} else if (type == ) {
("isInterface");
}
if (()) {
(("isStatic"));
}
if (() == VisibilityModifier.PRIVATE_FIELD || () == VisibilityModifier.PRIVATE_METHOD) {
("visibility: " + ().getXmiVisibility());
}
Member m;
VisibilityModifier visibility;
ListIterator var13;
CharSequence cs;
for (var13 = ().getFieldsToDisplay().iterator(); ();) {
cs = (CharSequence)();
m = (Member) cs;
("field name: " + (false));
visibility = ();
if (visibility != null) {
("visibility: " + ());
}
if (()) {
("isStatic");
}
}
for (var13 = ().getMethodsToDisplay().iterator(); ();) {
cs = (CharSequence)();
m = (Member) cs;
("operation name: " + (false));
visibility = ();
if (visibility != null) {
("visibility: " + ());
}
if (()) {
("isStatic");
}
}
}
}
// Write the first image to "png"
// String desc = (output).getDescription();
// Return a null string if no generation
}
}
Creating a JAVA project and packaging it as a JAR package: Exporting PlantUML to a custom formatted XMI file
Create a project
Create a maven project using IDEA and open the plantuml maven repository page:/artifact//plantuml/1.2024.6 Copy the dependency tag into the
Add classes for customizing the XMI format
Since it is not possible to quote theXmiClassDiagramAbstract
(draw attention to sth. is not public in ''. Cannot be accessed from outside package),thus insrc/main/java
Create a new package under
Then add the classXmiClassDiagramCustom
(extends XmiClassDiagramAbstract):
package ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import org.;
public class XmiClassDiagramCustom extends XmiClassDiagramAbstract implements XmlDiagramTransformer {
public XmiClassDiagramCustom(ClassDiagram classDiagram) throws ParserConfigurationException {
super(classDiagram);
Iterator var2 = ().leafs().iterator();
Element titleElement = ("UML:Title");
("name", ().get(0).toString());
(titleElement);
while(()) {
Entity ent = (Entity)();
Element cla = (ent, classDiagram);
if (cla != null) {
(cla);
(ent);
}
}
var2 = ().iterator();
while(()) {
Link link = (Link)();
(link);
}
}
protected final Element createEntityNodeCustom(Entity entity, ClassDiagram classDiagram) {
Element cla = ("UML:Class");
if (() == ) {
return null;
} else {
("", ());
("name", ().get(0).toString());
// Get Note:
Iterator var1 = ().iterator();
while(()) {
Link link = (Link)();
if ((entity)) {
Entity other = (entity);
if (() == ) {
("note", ().get(0).toString());
// ("Note: " + ().get(0).toString());
}
}
}
("package", ().getParent().toString());
Stereotype stereotype = ();
if (stereotype != null) {
Element stereo = ("UML:");
Iterator var5 = ().iterator();
while(()) {
String s = (String)();
Element name = ("UML:Stereotype");
("name", s);
(name);
}
(stereo);
}
LeafType type = ();
if (type == LeafType.ABSTRACT_CLASS) {
("isAbstract", "true");
} else if (type == ) {
("isInterface", "true");
}
if (()) {
("isStatic", "true");
}
if (() == VisibilityModifier.PRIVATE_FIELD || () == VisibilityModifier.PRIVATE_METHOD) {
("visibility", ().getXmiVisibility());
}
Element feature = ("UML:");
(feature);
Member m;
Element operation;
VisibilityModifier visibility;
ListIterator var13;
CharSequence cs;
for(var13 = ().getFieldsToDisplay().iterator(); (); (operation)) {
cs = (CharSequence)();
m = (Member)cs;
operation = ("UML:Attribute");
("", "att" + ());
("name", (false));
visibility = ();
if (visibility != null) {
("visibility", ());
}
if (()) {
("isStatic", "true");
}
}
for(var13 = ().getMethodsToDisplay().iterator(); (); (operation)) {
cs = (CharSequence)();
m = (Member)cs;
operation = ("UML:Operation");
("", "att" + ());
("name", (false));
visibility = ();
if (visibility != null) {
("visibility", ());
}
if (()) {
("isStatic", "true");
}
}
return cla;
}
}
// copy from XmiClassDiagramStar
private void addLink(Link link) {
if (!() && !()) {
String assId = "ass" + ();
if (().getDecor1() != && ().getDecor2() != ) {
Element association = ("UML:Association");
("", assId);
("namespace", ());
if (!(())) {
("name", (()));
}
Element connection = ("UML:");
Element end1 = ("UML:AssociationEnd");
("", "end" + ());
("association", assId);
("type", link.getEntity1().getUid());
if (link.getQuantifier1() != null) {
("name", (link.getQuantifier1()));
}
Element endparticipant1 = ("UML:");
if (().getDecor2() == ) {
("aggregation", "composite");
}
if (().getDecor2() == ) {
("aggregation", "aggregate");
}
(endparticipant1);
(end1);
Element end2 = ("UML:AssociationEnd");
("", "end" + ());
("association", assId);
("type", link.getEntity2().getUid());
if (link.getQuantifier2() != null) {
("name", (link.getQuantifier2()));
}
Element endparticipant2 = ("UML:");
if (().getDecor1() == ) {
("aggregation", "composite");
}
if (().getDecor1() == ) {
("aggregation", "aggregate");
}
(endparticipant2);
(end2);
(connection);
(association);
} else {
(link, assId);
}
}
}
// copy from XmiClassDiagramStar
private void addExtension(Link link, String assId) {
Element association = ("UML:Generalization");
("", assId);
("namespace", ());
if (() != null) {
("name", (()));
}
if (().getDecor1() == ) {
("child", link.getEntity1().getUid());
("parent", link.getEntity2().getUid());
} else {
if (().getDecor2() != ) {
throw new IllegalStateException();
}
("child", link.getEntity2().getUid());
("parent", link.getEntity1().getUid());
}
(association);
}
}
Add export class (portal)
Adding a packageand add classes
UML2XMIExporter
:
package ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
public class UML2XMIExporter {
public static void main(String[] args) throws IOException, ParserConfigurationException, TransformerException {
String content = new String(((args[0])));
OutputStream outputCustom = ((args[1]));
SourceStringReader reader = new SourceStringReader(content);
ClassDiagram classDiagram = (ClassDiagram) ().get(0).getDiagram();
// deriveXMI
XmlDiagramTransformer xmi = new XmiClassDiagramCustom(classDiagram);
(outputCustom);
}
}
ask for a doggy bag (at a restaurant)
Next, refer to/weixin_41229430/article/details/138963215 Packaged as a jar package
Create a file: src/main/assembly/ with the following contents:
<assembly>
<id>assembly</id>
<formats>
<format>zip</format>
<format>jar</format>
<format></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>
Then add the
<build>
<plugins>
<!--Primarily for use in placing Maven Packaging of projects into executable programs or distribution packages -->
<plugin>
<groupId></groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>make-assembly2</id><!--Any name -->
<phase>package</phase><!-- Bind topackagelife cycle stage -->
<goals>
<goal>single</goal><!-- Run only once -->
</goals>
<configuration>
<descriptors>
<descriptor>${basedir}/src/main/assembly/</descriptor>
</descriptors>
<archive>
<manifest>
<mainClass>.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></groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
Click on the m icon (maven) on the right side of IDEA and double click on package under Lifecycle. then you can see in the target directory that the jar package has been generated.
Open comman prompt command line (do not use powershell) and run it:
java -=UTF-8 -jar custom-plantuml-xmi-export-1.