diff --git a/src/net/sourceforge/plantuml/FileFormat.java b/src/net/sourceforge/plantuml/FileFormat.java
index 0e42638fc..501fce883 100644
--- a/src/net/sourceforge/plantuml/FileFormat.java
+++ b/src/net/sourceforge/plantuml/FileFormat.java
@@ -62,28 +62,30 @@ import net.sourceforge.plantuml.ugraphic.debug.StringBounderDebug;
*
*/
public enum FileFormat {
- PNG("image/png"),
- SVG("image/svg+xml"),
- EPS("application/postscript"),
- EPS_TEXT("application/postscript"),
- ATXT("text/plain"),
- UTXT("text/plain;charset=UTF-8"),
- XMI_STANDARD("application/vnd.xmi+xml"),
- XMI_STAR("application/vnd.xmi+xml"),
- XMI_ARGO("application/vnd.xmi+xml"),
- SCXML("application/scxml+xml"),
- PDF("application/pdf"),
- MJPEG("video/x-msvideo"),
- ANIMATED_GIF("image/gif"),
- HTML("text/html"),
- HTML5("text/html"),
- VDX("application/vnd.visio.xml"),
- LATEX("application/x-latex"),
- LATEX_NO_PREAMBLE("application/x-latex"),
- BASE64("text/plain; charset=x-user-defined"),
- BRAILLE_PNG("image/png"),
- PREPROC("text/plain"),
- DEBUG("text/plain");
+
+ PNG("image/png"), //
+ SVG("image/svg+xml"), //
+ EPS("application/postscript"), //
+ EPS_TEXT("application/postscript"), //
+ ATXT("text/plain"), //
+ UTXT("text/plain;charset=UTF-8"), //
+ XMI_STANDARD("application/vnd.xmi+xml"), //
+ XMI_STAR("application/vnd.xmi+xml"), //
+ XMI_ARGO("application/vnd.xmi+xml"), //
+ SCXML("application/scxml+xml"), //
+ GRAPHML("application/graphml+xml"), //
+ PDF("application/pdf"), //
+ MJPEG("video/x-msvideo"), //
+ ANIMATED_GIF("image/gif"), //
+ HTML("text/html"), //
+ HTML5("text/html"), //
+ VDX("application/vnd.visio.xml"), //
+ LATEX("application/x-latex"), //
+ LATEX_NO_PREAMBLE("application/x-latex"), //
+ BASE64("text/plain; charset=x-user-defined"), //
+ BRAILLE_PNG("image/png"), //
+ PREPROC("text/plain"), //
+ DEBUG("text/plain"); //
private final String mimeType;
@@ -101,24 +103,24 @@ public enum FileFormat {
* @return a string starting by a point.
*/
public String getFileSuffix() {
- if (name().startsWith("XMI")) {
+ if (name().startsWith("XMI"))
return ".xmi";
- }
- if (this == MJPEG) {
+
+ if (this == MJPEG)
return ".avi";
- }
- if (this == LATEX_NO_PREAMBLE) {
+
+ if (this == LATEX_NO_PREAMBLE)
return ".latex";
- }
- if (this == ANIMATED_GIF) {
+
+ if (this == ANIMATED_GIF)
return ".gif";
- }
- if (this == BRAILLE_PNG) {
+
+ if (this == BRAILLE_PNG)
return ".braille.png";
- }
- if (this == EPS_TEXT) {
+
+ if (this == EPS_TEXT)
return EPS.getFileSuffix();
- }
+
return "." + StringUtils.goLowerCase(name());
}
@@ -134,18 +136,18 @@ public enum FileFormat {
}
public StringBounder getDefaultStringBounder(TikzFontDistortion tikzFontDistortion, SvgCharSizeHack charSizeHack) {
- if (this == LATEX || this == LATEX_NO_PREAMBLE) {
+ if (this == LATEX || this == LATEX_NO_PREAMBLE)
return getTikzStringBounder(tikzFontDistortion);
- }
- if (this == BRAILLE_PNG) {
+
+ if (this == BRAILLE_PNG)
return getBrailleStringBounder();
- }
- if (this == SVG) {
+
+ if (this == SVG)
return getSvgStringBounder(charSizeHack);
- }
- if (this == DEBUG) {
+
+ if (this == DEBUG)
return new StringBounderDebug();
- }
+
return getNormalStringBounder();
}
@@ -233,43 +235,43 @@ public enum FileFormat {
* @return true
for EPS.
*/
public boolean isEps() {
- if (this == EPS) {
+ if (this == EPS)
return true;
- }
- if (this == EPS_TEXT) {
+
+ if (this == EPS_TEXT)
return true;
- }
+
return false;
}
public String changeName(String fileName, int cpt) {
- if (cpt == 0) {
+ if (cpt == 0)
return changeName(fileName, getFileSuffix());
- }
+
return changeName(fileName,
OptionFlags.getInstance().getFileSeparator() + String.format("%03d", cpt) + getFileSuffix());
}
private SFile computeFilename(SFile pngFile, int i) {
- if (i == 0) {
+ if (i == 0)
return pngFile;
- }
+
final SFile dir = pngFile.getParentFile();
return dir.file(computeFilenameInternal(pngFile.getName(), i));
}
private String changeName(String fileName, String replacement) {
String result = fileName.replaceAll("\\.\\w+$", replacement);
- if (result.equals(fileName)) {
+ if (result.equals(fileName))
result = fileName + replacement;
- }
+
return result;
}
private String computeFilenameInternal(String name, int i) {
- if (i == 0) {
+ if (i == 0)
return name;
- }
+
return name.replaceAll("\\" + getFileSuffix() + "$",
OptionFlags.getInstance().getFileSeparator() + String.format("%03d", i) + getFileSuffix());
}
@@ -288,9 +290,9 @@ public enum FileFormat {
}
if (this == SVG) {
final String svg = FileUtils.readSvg(existingFile);
- if (svg == null) {
+ if (svg == null)
return false;
- }
+
final String currentSignature = SvgGraphics.getMD5Hex(currentMetadata);
final int idx = svg.lastIndexOf(SvgGraphics.MD5_HEADER);
if (idx != -1) {
diff --git a/src/net/sourceforge/plantuml/activitydiagram/ActivityDiagram.java b/src/net/sourceforge/plantuml/activitydiagram/ActivityDiagram.java
index 86402f477..c267c9e12 100644
--- a/src/net/sourceforge/plantuml/activitydiagram/ActivityDiagram.java
+++ b/src/net/sourceforge/plantuml/activitydiagram/ActivityDiagram.java
@@ -55,7 +55,6 @@ import net.sourceforge.plantuml.cucadiagram.Ident;
import net.sourceforge.plantuml.cucadiagram.LeafType;
import net.sourceforge.plantuml.cucadiagram.NamespaceStrategy;
import net.sourceforge.plantuml.graphic.USymbol;
-import net.sourceforge.plantuml.utils.UniqueSequence;
public class ActivityDiagram extends CucaDiagram {
@@ -73,7 +72,7 @@ public class ActivityDiagram extends CucaDiagram {
}
private String getAutoBranch() {
- return "#" + UniqueSequence.getValue();
+ return "#" + this.getUniqueSequence();
}
public IEntity getOrCreate(Ident idNewLong, Code code, Display display, LeafType type) {
@@ -173,7 +172,7 @@ public class ActivityDiagram extends CucaDiagram {
public IEntity createInnerActivity() {
// Log.println("createInnerActivity A");
- final String idShort = "##" + UniqueSequence.getValue();
+ final String idShort = "##" + this.getUniqueSequence();
final Ident idNewLong = buildLeafIdent(idShort);
final Code code = this.V1972() ? idNewLong : buildCode(idShort);
gotoGroup(idNewLong, code, Display.getWithNewlines(code), GroupType.INNER_ACTIVITY, getCurrentGroup(),
@@ -193,7 +192,7 @@ public class ActivityDiagram extends CucaDiagram {
endGroup();
// Log.println("endgroup");
}
- final String idShort = "##" + UniqueSequence.getValue();
+ final String idShort = "##" + this.getUniqueSequence();
// Log.println("concurrentActivity A name=" + name+" "+getCurrentGroup());
final Code code = buildCode(idShort);
if (getCurrentGroup().getGroupType() != GroupType.INNER_ACTIVITY) {
diff --git a/src/net/sourceforge/plantuml/activitydiagram/ActivityDiagramFactory.java b/src/net/sourceforge/plantuml/activitydiagram/ActivityDiagramFactory.java
index 353199b0a..2647ae6ff 100644
--- a/src/net/sourceforge/plantuml/activitydiagram/ActivityDiagramFactory.java
+++ b/src/net/sourceforge/plantuml/activitydiagram/ActivityDiagramFactory.java
@@ -51,8 +51,8 @@ import net.sourceforge.plantuml.classdiagram.command.CommandHideShow2;
import net.sourceforge.plantuml.command.Command;
import net.sourceforge.plantuml.command.CommandFootboxIgnored;
import net.sourceforge.plantuml.command.CommandRankDir;
-import net.sourceforge.plantuml.command.PSystemCommandFactory;
import net.sourceforge.plantuml.command.CommonCommands;
+import net.sourceforge.plantuml.command.PSystemCommandFactory;
import net.sourceforge.plantuml.command.note.CommandFactoryNoteActivity;
import net.sourceforge.plantuml.command.note.CommandFactoryNoteOnLink;
import net.sourceforge.plantuml.core.UmlSource;
diff --git a/src/net/sourceforge/plantuml/classdiagram/command/CommandCreateClass.java b/src/net/sourceforge/plantuml/classdiagram/command/CommandCreateClass.java
index a4c1a8b18..f80d844c0 100644
--- a/src/net/sourceforge/plantuml/classdiagram/command/CommandCreateClass.java
+++ b/src/net/sourceforge/plantuml/classdiagram/command/CommandCreateClass.java
@@ -126,7 +126,8 @@ public class CommandCreateClass extends SingleLineCommand2 {
@Override
protected CommandExecutionResult executeArg(ClassDiagram diagram, LineLocation location, RegexResult arg)
throws NoSuchColorException {
- final LeafType type = LeafType.getLeafType(StringUtils.goUpperCase(arg.get("TYPE", 0)));
+ final String typeString = StringUtils.goUpperCase(arg.get("TYPE", 0));
+ final LeafType type = LeafType.getLeafType(typeString);
final String idShort = StringUtils.eventuallyRemoveStartingAndEndingDoubleQuote(arg.getLazzy("CODE", 0),
"\"([:");
final String display = arg.getLazzy("DISPLAY", 0);
@@ -191,6 +192,9 @@ public class CommandCreateClass extends SingleLineCommand2 {
CommandCreateClassMultilines.manageExtends("IMPLEMENTS", diagram, arg, entity);
CommandCreateClassMultilines.addTags(entity, arg.get("TAGS", 0));
+ if (typeString.contains("STATIC"))
+ entity.setStatic(true);
+
return CommandExecutionResult.ok();
}
diff --git a/src/net/sourceforge/plantuml/classdiagram/command/CommandCreateClassMultilines.java b/src/net/sourceforge/plantuml/classdiagram/command/CommandCreateClassMultilines.java
index 117faae7b..9f9341a91 100644
--- a/src/net/sourceforge/plantuml/classdiagram/command/CommandCreateClassMultilines.java
+++ b/src/net/sourceforge/plantuml/classdiagram/command/CommandCreateClassMultilines.java
@@ -226,7 +226,8 @@ public class CommandCreateClassMultilines extends CommandMultilines2 {
@@ -124,7 +123,7 @@ final public class CommandLinkLollipop extends SingleLineCommand2 {
@@ -111,7 +110,7 @@ public class CommandPackage extends SingleLineCommand2 {
boolean override1972 = false;
if (arg.get("AS", 0) == null) {
if (name.length() == 0) {
- idShort = "##" + UniqueSequence.getValue();
+ idShort = "##" + diagram.getUniqueSequence();
display = null;
} else {
idShort = name;
diff --git a/src/net/sourceforge/plantuml/command/CommandPackageEmpty.java b/src/net/sourceforge/plantuml/command/CommandPackageEmpty.java
index f858833d2..3ba9c5d64 100644
--- a/src/net/sourceforge/plantuml/command/CommandPackageEmpty.java
+++ b/src/net/sourceforge/plantuml/command/CommandPackageEmpty.java
@@ -52,7 +52,6 @@ import net.sourceforge.plantuml.cucadiagram.Ident;
import net.sourceforge.plantuml.cucadiagram.NamespaceStrategy;
import net.sourceforge.plantuml.graphic.color.ColorType;
import net.sourceforge.plantuml.ugraphic.color.NoSuchColorException;
-import net.sourceforge.plantuml.utils.UniqueSequence;
public class CommandPackageEmpty extends SingleLineCommand2 {
@@ -88,7 +87,7 @@ public class CommandPackageEmpty extends SingleLineCommand2 {
@@ -121,7 +120,7 @@ public final class CommandFactoryNoteActivity implements SingleMultiFactoryComma
// final String s = StringUtils.getMergedLines(strings);
- final String codeString = UniqueSequence.getString("GMN");
+ final String codeString = diagram.getUniqueSequence("GMN");
final Ident ident = diagram.buildLeafIdent(codeString);
final Code code = diagram.V1972() ? ident : diagram.buildCode(codeString);
final IEntity note = diagram.createLeaf(ident, code, strings, LeafType.NOTE, null);
@@ -139,7 +138,7 @@ public final class CommandFactoryNoteActivity implements SingleMultiFactoryComma
@Override
protected CommandExecutionResult executeArg(final ActivityDiagram diagram, LineLocation location,
RegexResult arg) throws NoSuchColorException {
- final String tmp = UniqueSequence.getString("GN");
+ final String tmp = diagram.getUniqueSequence("GN");
final Ident ident = diagram.buildLeafIdent(tmp);
final Code code = diagram.V1972() ? ident : diagram.buildCode(tmp);
final IEntity note = diagram.createNote(ident, code, Display.getWithNewlines(arg.get("NOTE", 0)));
diff --git a/src/net/sourceforge/plantuml/command/note/CommandFactoryNoteOnEntity.java b/src/net/sourceforge/plantuml/command/note/CommandFactoryNoteOnEntity.java
index 9d743383c..0be05ac3f 100644
--- a/src/net/sourceforge/plantuml/command/note/CommandFactoryNoteOnEntity.java
+++ b/src/net/sourceforge/plantuml/command/note/CommandFactoryNoteOnEntity.java
@@ -56,7 +56,6 @@ import net.sourceforge.plantuml.command.regex.RegexLeaf;
import net.sourceforge.plantuml.command.regex.RegexOr;
import net.sourceforge.plantuml.command.regex.RegexResult;
import net.sourceforge.plantuml.cucadiagram.Code;
-import net.sourceforge.plantuml.cucadiagram.Display;
import net.sourceforge.plantuml.cucadiagram.IEntity;
import net.sourceforge.plantuml.cucadiagram.Ident;
import net.sourceforge.plantuml.cucadiagram.LeafType;
@@ -70,7 +69,6 @@ import net.sourceforge.plantuml.graphic.color.ColorParser;
import net.sourceforge.plantuml.graphic.color.ColorType;
import net.sourceforge.plantuml.graphic.color.Colors;
import net.sourceforge.plantuml.ugraphic.color.NoSuchColorException;
-import net.sourceforge.plantuml.utils.UniqueSequence;
public final class CommandFactoryNoteOnEntity implements SingleMultiFactoryCommand {
@@ -229,7 +227,7 @@ public final class CommandFactoryNoteOnEntity implements SingleMultiFactoryComma
}
}
- final String tmp = UniqueSequence.getString("GMN");
+ final String tmp = diagram.getUniqueSequence("GMN");
final Ident idNewLong = diagram.buildLeafIdent(tmp);
final IEntity note;
if (diagram.V1972())
diff --git a/src/net/sourceforge/plantuml/command/note/CommandFactoryTipOnEntity.java b/src/net/sourceforge/plantuml/command/note/CommandFactoryTipOnEntity.java
index 0872a9c6d..6e692726c 100644
--- a/src/net/sourceforge/plantuml/command/note/CommandFactoryTipOnEntity.java
+++ b/src/net/sourceforge/plantuml/command/note/CommandFactoryTipOnEntity.java
@@ -51,7 +51,6 @@ import net.sourceforge.plantuml.command.regex.RegexConcat;
import net.sourceforge.plantuml.command.regex.RegexLeaf;
import net.sourceforge.plantuml.command.regex.RegexResult;
import net.sourceforge.plantuml.cucadiagram.Code;
-import net.sourceforge.plantuml.cucadiagram.Display;
import net.sourceforge.plantuml.cucadiagram.IEntity;
import net.sourceforge.plantuml.cucadiagram.Ident;
import net.sourceforge.plantuml.cucadiagram.LeafType;
diff --git a/src/net/sourceforge/plantuml/cucadiagram/CucaDiagram.java b/src/net/sourceforge/plantuml/cucadiagram/CucaDiagram.java
index 60232f322..6abc9997d 100644
--- a/src/net/sourceforge/plantuml/cucadiagram/CucaDiagram.java
+++ b/src/net/sourceforge/plantuml/cucadiagram/CucaDiagram.java
@@ -44,6 +44,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
import net.sourceforge.plantuml.BackSlash;
import net.sourceforge.plantuml.FileFormat;
@@ -62,6 +63,7 @@ import net.sourceforge.plantuml.cucadiagram.dot.CucaDiagramTxtMaker;
import net.sourceforge.plantuml.cucadiagram.entity.EntityFactory;
import net.sourceforge.plantuml.elk.CucaDiagramFileMakerElk;
import net.sourceforge.plantuml.graphic.USymbol;
+import net.sourceforge.plantuml.graphml.CucaDiagramGraphmlMaker;
import net.sourceforge.plantuml.sdot.CucaDiagramFileMakerSmetana;
import net.sourceforge.plantuml.security.SecurityUtils;
import net.sourceforge.plantuml.skin.VisibilityModifier;
@@ -559,6 +561,11 @@ public abstract class CucaDiagram extends UmlDiagram implements GroupHierarchy,
return result.toArray(new String[result.size()]);
}
+ private void createFilesGraphml(OutputStream suggestedFile) throws IOException {
+ final CucaDiagramGraphmlMaker maker = new CucaDiagramGraphmlMaker(this);
+ maker.createFiles(suggestedFile);
+ }
+
private void createFilesXmi(OutputStream suggestedFile, FileFormat fileFormat) throws IOException {
final CucaDiagramXmiMaker maker = new CucaDiagramXmiMaker(this, fileFormat);
maker.createFiles(suggestedFile);
@@ -583,6 +590,11 @@ public abstract class CucaDiagram extends UmlDiagram implements GroupHierarchy,
return ImageDataSimple.ok();
}
+ if (fileFormat == FileFormat.GRAPHML) {
+ createFilesGraphml(os);
+ return ImageDataSimple.ok();
+ }
+
if (fileFormat.name().startsWith("XMI")) {
createFilesXmi(os, fileFormat);
return ImageDataSimple.ok();
@@ -789,6 +801,17 @@ public abstract class CucaDiagram extends UmlDiagram implements GroupHierarchy,
return true;
}
+ final public boolean isStandaloneForArgo(IEntity ent) {
+ for (final Link link : getLinks()) {
+ if (link.isHidden() || link.isInvis())
+ continue;
+ if (link.getEntity1() == ent || link.getEntity2() == ent)
+ return false;
+ }
+
+ return true;
+ }
+
final public Link getLastLink() {
final List links = getLinks();
for (int i = links.size() - 1; i >= 0; i--) {
@@ -874,4 +897,14 @@ public abstract class CucaDiagram extends UmlDiagram implements GroupHierarchy,
return ClockwiseTopRightBottomLeft.topRightBottomLeft(0, 5, 5, 0);
}
+ private final AtomicInteger cpt = new AtomicInteger(1);
+
+ public int getUniqueSequence() {
+ return cpt.addAndGet(1);
+ }
+
+ public String getUniqueSequence(String prefix) {
+ return prefix + getUniqueSequence();
+ }
+
}
diff --git a/src/net/sourceforge/plantuml/cucadiagram/EntityPosition.java b/src/net/sourceforge/plantuml/cucadiagram/EntityPosition.java
index 8efd9c3a3..4e93a0f55 100644
--- a/src/net/sourceforge/plantuml/cucadiagram/EntityPosition.java
+++ b/src/net/sourceforge/plantuml/cucadiagram/EntityPosition.java
@@ -95,9 +95,9 @@ public enum EntityPosition {
public Dimension2D getDimension(Rankdir rankdir) {
if (this == EXPANSION_INPUT || this == EXPANSION_OUTPUT) {
- if (rankdir == Rankdir.TOP_TO_BOTTOM) {
+ if (rankdir == Rankdir.TOP_TO_BOTTOM)
return new Dimension2DDouble(EntityPosition.RADIUS * 2 * 4, EntityPosition.RADIUS * 2);
- }
+
return new Dimension2DDouble(EntityPosition.RADIUS * 2, EntityPosition.RADIUS * 2 * 4);
}
return new Dimension2DDouble(EntityPosition.RADIUS * 2, EntityPosition.RADIUS * 2);
@@ -117,37 +117,37 @@ public enum EntityPosition {
}
public ShapeType getShapeType() {
- if (this == NORMAL) {
+ if (this == NORMAL)
throw new IllegalStateException();
- }
- if (this == ENTRY_POINT || this == EXIT_POINT) {
+
+ if (this == ENTRY_POINT || this == EXIT_POINT)
return ShapeType.CIRCLE;
- }
+
return ShapeType.RECTANGLE;
}
public static EntityPosition fromStereotype(String label) {
- if ("<>".equalsIgnoreCase(label)) {
+ if ("<>".equalsIgnoreCase(label))
return PORT;
- }
- if ("<>".equalsIgnoreCase(label)) {
+
+ if ("<>".equalsIgnoreCase(label))
return ENTRY_POINT;
- }
- if ("<>".equalsIgnoreCase(label)) {
+
+ if ("<>".equalsIgnoreCase(label))
return EXIT_POINT;
- }
- if ("<>".equalsIgnoreCase(label)) {
+
+ if ("<>".equalsIgnoreCase(label))
return INPUT_PIN;
- }
- if ("<>".equalsIgnoreCase(label)) {
+
+ if ("<>".equalsIgnoreCase(label))
return OUTPUT_PIN;
- }
- if ("<>".equalsIgnoreCase(label)) {
+
+ if ("<>".equalsIgnoreCase(label))
return EXPANSION_INPUT;
- }
- if ("<>".equalsIgnoreCase(label)) {
+
+ if ("<>".equalsIgnoreCase(label))
return EXPANSION_OUTPUT;
- }
+
return EntityPosition.NORMAL;
}
diff --git a/src/net/sourceforge/plantuml/cucadiagram/ILeaf.java b/src/net/sourceforge/plantuml/cucadiagram/ILeaf.java
index 6e5895955..900c083a3 100644
--- a/src/net/sourceforge/plantuml/cucadiagram/ILeaf.java
+++ b/src/net/sourceforge/plantuml/cucadiagram/ILeaf.java
@@ -81,4 +81,8 @@ public interface ILeaf extends IEntity {
public VisibilityModifier getVisibilityModifier();
+ public void setStatic(boolean isStatic);
+
+ public boolean isStatic();
+
}
diff --git a/src/net/sourceforge/plantuml/cucadiagram/Link.java b/src/net/sourceforge/plantuml/cucadiagram/Link.java
index 01b2dd697..bf851ffca 100644
--- a/src/net/sourceforge/plantuml/cucadiagram/Link.java
+++ b/src/net/sourceforge/plantuml/cucadiagram/Link.java
@@ -46,6 +46,7 @@ import net.sourceforge.plantuml.UmlDiagramType;
import net.sourceforge.plantuml.Url;
import net.sourceforge.plantuml.awt.geom.Dimension2D;
import net.sourceforge.plantuml.command.Position;
+import net.sourceforge.plantuml.cucadiagram.entity.EntityImpl;
import net.sourceforge.plantuml.graphic.FontConfiguration;
import net.sourceforge.plantuml.graphic.HorizontalAlignment;
import net.sourceforge.plantuml.graphic.StringBounder;
@@ -57,7 +58,6 @@ import net.sourceforge.plantuml.style.StyleBuilder;
import net.sourceforge.plantuml.svek.Bibliotekon;
import net.sourceforge.plantuml.ugraphic.UComment;
import net.sourceforge.plantuml.ugraphic.UFont;
-import net.sourceforge.plantuml.utils.UniqueSequence;
public class Link extends WithLinkType implements Hideable, Removeable {
@@ -73,7 +73,7 @@ public class Link extends WithLinkType implements Hideable, Removeable {
private final LinkArg linkArg;
- final private String uid = "LNK" + UniqueSequence.getValue();
+ final private String uid;
private Display note;
private Position notePosition;
@@ -120,7 +120,9 @@ public class Link extends WithLinkType implements Hideable, Removeable {
this.styleBuilder = styleBuilder;
this.cl1 = Objects.requireNonNull(cl1);
this.cl2 = Objects.requireNonNull(cl2);
+
this.type = type;
+ this.uid = "LNK" + ((EntityImpl) cl1).getDiagram().getUniqueSequence();
this.linkArg = linkArg;
}
diff --git a/src/net/sourceforge/plantuml/cucadiagram/entity/EntityFactory.java b/src/net/sourceforge/plantuml/cucadiagram/entity/EntityFactory.java
index ddb13921a..1ab1af417 100644
--- a/src/net/sourceforge/plantuml/cucadiagram/entity/EntityFactory.java
+++ b/src/net/sourceforge/plantuml/cucadiagram/entity/EntityFactory.java
@@ -512,4 +512,8 @@ public final class EntityFactory {
return Objects.requireNonNull(parentContainer);
}
+ public CucaDiagram getDiagram() {
+ return namespaceSeparator;
+ }
+
}
diff --git a/src/net/sourceforge/plantuml/cucadiagram/entity/EntityImpl.java b/src/net/sourceforge/plantuml/cucadiagram/entity/EntityImpl.java
index 42280e562..7f1e614d2 100644
--- a/src/net/sourceforge/plantuml/cucadiagram/entity/EntityImpl.java
+++ b/src/net/sourceforge/plantuml/cucadiagram/entity/EntityImpl.java
@@ -57,6 +57,7 @@ import net.sourceforge.plantuml.StringUtils;
import net.sourceforge.plantuml.Url;
import net.sourceforge.plantuml.cucadiagram.Bodier;
import net.sourceforge.plantuml.cucadiagram.Code;
+import net.sourceforge.plantuml.cucadiagram.CucaDiagram;
import net.sourceforge.plantuml.cucadiagram.Display;
import net.sourceforge.plantuml.cucadiagram.DisplayPositioned;
import net.sourceforge.plantuml.cucadiagram.EntityPosition;
@@ -85,7 +86,6 @@ import net.sourceforge.plantuml.svek.PackageStyle;
import net.sourceforge.plantuml.svek.SingleStrategy;
import net.sourceforge.plantuml.ugraphic.UFont;
import net.sourceforge.plantuml.ugraphic.color.HColor;
-import net.sourceforge.plantuml.utils.UniqueSequence;
final public class EntityImpl implements ILeaf, IGroup {
@@ -98,7 +98,7 @@ final public class EntityImpl implements ILeaf, IGroup {
private Url url;
private final Bodier bodier;
- private final String uid = StringUtils.getUid("cl", UniqueSequence.getValue());
+ private final String uid;
private Display display = Display.empty();
private DisplayPositioned legend = null;
@@ -150,6 +150,7 @@ final public class EntityImpl implements ILeaf, IGroup {
private EntityImpl(Ident ident, EntityFactory entityFactory, Code code, Bodier bodier, IGroup parentContainer,
String namespaceSeparator, int rawLayout) {
this.ident = Objects.requireNonNull(ident);
+ this.uid = StringUtils.getUid("cl", entityFactory.getDiagram().getUniqueSequence());
if (entityFactory.namespaceSeparator.V1972())
code = ident;
@@ -810,4 +811,20 @@ final public class EntityImpl implements ILeaf, IGroup {
return Collections.unmodifiableList(result);
}
+ public CucaDiagram getDiagram() {
+ return entityFactory.getDiagram();
+ }
+
+ private boolean isStatic;
+
+ @Override
+ public void setStatic(boolean isStatic) {
+ this.isStatic = isStatic;
+ }
+
+ @Override
+ public boolean isStatic() {
+ return isStatic;
+ }
+
}
diff --git a/src/net/sourceforge/plantuml/descdiagram/command/CommandPackageWithUSymbol.java b/src/net/sourceforge/plantuml/descdiagram/command/CommandPackageWithUSymbol.java
index f5fb05822..28e235f3b 100644
--- a/src/net/sourceforge/plantuml/descdiagram/command/CommandPackageWithUSymbol.java
+++ b/src/net/sourceforge/plantuml/descdiagram/command/CommandPackageWithUSymbol.java
@@ -64,7 +64,6 @@ import net.sourceforge.plantuml.graphic.color.ColorParser;
import net.sourceforge.plantuml.graphic.color.ColorType;
import net.sourceforge.plantuml.graphic.color.Colors;
import net.sourceforge.plantuml.ugraphic.color.NoSuchColorException;
-import net.sourceforge.plantuml.utils.UniqueSequence;
public class CommandPackageWithUSymbol extends SingleLineCommand2 {
@@ -141,7 +140,7 @@ public class CommandPackageWithUSymbol extends SingleLineCommand2 same1 = getExistingAssociatedPoints(entity1A, entity1B);
final List same2 = getExistingAssociatedPoints(entity2A, entity2B);
if (same1.size() == 0 && same2.size() == 0) {
- final String tmp1 = UniqueSequence.getString("apoint");
- final String tmp2 = UniqueSequence.getString("apoint");
+ final String tmp1 = this.getUniqueSequence("apoint");
+ final String tmp2 = this.getUniqueSequence("apoint");
final Ident ident1 = buildLeafIdent(tmp1);
final Ident ident2 = buildLeafIdent(tmp2);
final Code code1 = this.V1972() ? ident1 : buildCode(tmp1);
@@ -252,7 +251,7 @@ public abstract class AbstractClassOrObjectDiagram extends AbstractEntityDiagram
this.entity1 = entity1;
this.entity2 = entity2;
this.associed = associed;
- final String idShort = UniqueSequence.getString("apoint");
+ final String idShort = AbstractClassOrObjectDiagram.this.getUniqueSequence("apoint");
final Ident ident = buildLeafIdent(idShort);
final Code code = AbstractClassOrObjectDiagram.this.V1972() ? ident : buildCode(idShort);
point = getOrCreateLeaf(ident, code, LeafType.POINT_FOR_ASSOCIATION, null);
diff --git a/src/net/sourceforge/plantuml/statediagram/StateDiagram.java b/src/net/sourceforge/plantuml/statediagram/StateDiagram.java
index 2a8fb8239..a432f88be 100644
--- a/src/net/sourceforge/plantuml/statediagram/StateDiagram.java
+++ b/src/net/sourceforge/plantuml/statediagram/StateDiagram.java
@@ -54,7 +54,6 @@ import net.sourceforge.plantuml.cucadiagram.LeafType;
import net.sourceforge.plantuml.cucadiagram.Link;
import net.sourceforge.plantuml.cucadiagram.NamespaceStrategy;
import net.sourceforge.plantuml.graphic.USymbol;
-import net.sourceforge.plantuml.utils.UniqueSequence;
public class StateDiagram extends AbstractEntityDiagram {
@@ -228,7 +227,7 @@ public class StateDiagram extends AbstractEntityDiagram {
super.endGroup();
}
getCurrentGroup().setConcurrentSeparator(direction);
- final String tmp1 = UniqueSequence.getString(CONCURRENT_PREFIX);
+ final String tmp1 = this.getUniqueSequence(CONCURRENT_PREFIX);
final Ident ident1 = buildLeafIdent(tmp1);
final Code code1 = this.V1972() ? ident1 : buildCode(tmp1);
gotoGroup(ident1, code1, Display.create(""), GroupType.CONCURRENT_STATE, getCurrentGroup(),
@@ -237,7 +236,7 @@ public class StateDiagram extends AbstractEntityDiagram {
if (EntityUtils.groupRoot(cur) == false && cur.getGroupType() == GroupType.STATE) {
cur.moveEntitiesTo(conc1);
super.endGroup();
- final String tmp2 = UniqueSequence.getString(CONCURRENT_PREFIX);
+ final String tmp2 = this.getUniqueSequence(CONCURRENT_PREFIX);
final Ident ident2 = buildLeafIdent(tmp2);
final Code code2 = this.V1972() ? ident2 : buildCode(tmp2);
gotoGroup(ident2, code2, Display.create(""), GroupType.CONCURRENT_STATE, getCurrentGroup(),
diff --git a/src/net/sourceforge/plantuml/svek/Cluster.java b/src/net/sourceforge/plantuml/svek/Cluster.java
index 099b8c2c8..76f8a6256 100644
--- a/src/net/sourceforge/plantuml/svek/Cluster.java
+++ b/src/net/sourceforge/plantuml/svek/Cluster.java
@@ -52,18 +52,17 @@ import java.util.Set;
import net.sourceforge.plantuml.AlignmentParam;
import net.sourceforge.plantuml.Dimension2DDouble;
import net.sourceforge.plantuml.ISkinParam;
-import net.sourceforge.plantuml.StringUtils;
import net.sourceforge.plantuml.UmlDiagramType;
import net.sourceforge.plantuml.Url;
import net.sourceforge.plantuml.api.ThemeStyle;
import net.sourceforge.plantuml.awt.geom.Dimension2D;
+import net.sourceforge.plantuml.cucadiagram.CucaDiagram;
import net.sourceforge.plantuml.cucadiagram.EntityPosition;
import net.sourceforge.plantuml.cucadiagram.EntityUtils;
import net.sourceforge.plantuml.cucadiagram.IEntity;
import net.sourceforge.plantuml.cucadiagram.IGroup;
import net.sourceforge.plantuml.cucadiagram.Stereotype;
import net.sourceforge.plantuml.cucadiagram.dot.GraphvizVersion;
-import net.sourceforge.plantuml.graphic.HorizontalAlignment;
import net.sourceforge.plantuml.graphic.StringBounder;
import net.sourceforge.plantuml.graphic.TextBlock;
import net.sourceforge.plantuml.graphic.USymbol;
@@ -88,14 +87,13 @@ import net.sourceforge.plantuml.ugraphic.UTranslate;
import net.sourceforge.plantuml.ugraphic.color.HColor;
import net.sourceforge.plantuml.ugraphic.color.HColorSet;
import net.sourceforge.plantuml.ugraphic.color.HColors;
-import net.sourceforge.plantuml.utils.UniqueSequence;
public class Cluster implements Moveable {
- private static final String RANK_SAME = "same";
- private static final String RANK_SOURCE = "source";
- private static final String RANK_SINK = "sink";
- private static final String ID_EE = "ee";
+ /* private */ static final String RANK_SAME = "same";
+ /* private */ static final String RANK_SOURCE = "source";
+ /* private */ static final String RANK_SINK = "sink";
+ /* private */ static final String ID_EE = "ee";
public final static String CENTER_ID = "za";
private final Cluster parentCluster;
@@ -105,6 +103,7 @@ public class Cluster implements Moveable {
private final int color;
private final int colorTitle;
private final ISkinParam skinParam;
+ protected final CucaDiagram diagram;
private int titleAndAttributeWidth;
private int titleAndAttributeHeight;
@@ -138,16 +137,18 @@ public class Cluster implements Moveable {
return Collections.unmodifiableSet(result);
}
- public Cluster(ColorSequence colorSequence, ISkinParam skinParam, IGroup root) {
- this(null, colorSequence, skinParam, root);
+ public Cluster(CucaDiagram diagram, ColorSequence colorSequence, ISkinParam skinParam, IGroup root) {
+ this(diagram, null, colorSequence, skinParam, root);
}
- private Cluster(Cluster parentCluster, ColorSequence colorSequence, ISkinParam skinParam, IGroup group) {
+ private Cluster(CucaDiagram diagram, Cluster parentCluster, ColorSequence colorSequence, ISkinParam skinParam,
+ IGroup group) {
if (group == null)
throw new IllegalStateException();
this.parentCluster = parentCluster;
this.group = group;
+ this.diagram = diagram;
this.color = colorSequence.getValue();
this.colorTitle = colorSequence.getValue();
@@ -244,7 +245,7 @@ public class Cluster implements Moveable {
public Cluster createChild(int titleAndAttributeWidth, int titleAndAttributeHeight, TextBlock title,
TextBlock stereo, ColorSequence colorSequence, ISkinParam skinParam, IGroup g) {
- final Cluster child = new Cluster(this, colorSequence, skinParam, g);
+ final Cluster child = new Cluster(diagram, this, colorSequence, skinParam, g);
child.titleAndAttributeWidth = titleAndAttributeWidth;
child.titleAndAttributeHeight = titleAndAttributeHeight;
child.ztitle = title;
@@ -257,6 +258,10 @@ public class Cluster implements Moveable {
return Collections.singleton(group);
}
+ final IGroup getGroup() {
+ return group;
+ }
+
public final int getTitleAndAttributeWidth() {
return titleAndAttributeWidth;
}
@@ -375,7 +380,7 @@ public class Cluster implements Moveable {
return style.getStroke();
}
- public void manageEntryExitPoint(StringBounder stringBounder) {
+ void manageEntryExitPoint(StringBounder stringBounder) {
final Collection insides = new ArrayList<>();
final List points = new ArrayList<>();
for (SvekNode sh : nodes)
@@ -499,106 +504,12 @@ public class Cluster implements Moveable {
this.maxY = maxY;
}
- private boolean isThereALinkFromOrToGroup(Collection lines) {
- for (SvekLine line : lines)
- if (line.isLinkFromOrTo(group))
- return true;
-
- return false;
- }
-
public void printCluster1(StringBuilder sb, Collection lines, StringBounder stringBounder) {
for (SvekNode node : getNodesOrderedTop(lines))
node.appendShape(sb, stringBounder);
}
- private List addProtection(List extends IShapePseudo> entries, double width) {
- final List result = new ArrayList<>();
- result.add(entries.get(0));
- for (int i = 1; i < entries.size(); i++) {
- // Pseudo space for the label
- result.add(new ShapePseudoImpl("psd" + UniqueSequence.getValue(), width, 5));
- result.add(entries.get(i));
- }
- return result;
- }
-
- private double getMaxWidthFromLabelForEntryExit(List extends IShapePseudo> entries, StringBounder stringBounder) {
- double result = -Double.MAX_VALUE;
- for (IShapePseudo node : entries) {
- final double w = getMaxWidthFromLabelForEntryExit(node, stringBounder);
- if (w > result)
- result = w;
-
- }
- return result;
- }
-
- private double getMaxWidthFromLabelForEntryExit(IShapePseudo node, StringBounder stringBounder) {
- return node.getMaxWidthFromLabelForEntryExit(stringBounder);
- }
-
- private void printRanks(String rank, List extends IShapePseudo> entries, StringBuilder sb,
- StringBounder stringBounder) {
- if (entries.size() > 0) {
- sb.append("{rank=" + rank + ";");
- for (IShapePseudo sh1 : entries)
- sb.append(sh1.getUid() + ";");
-
- sb.append("}");
- SvekUtils.println(sb);
- for (IShapePseudo sh2 : entries)
- sh2.appendShape(sb, stringBounder);
-
- SvekUtils.println(sb);
- if (hasPort()) {
- boolean arrow = false;
- String node = null;
- for (IShapePseudo sh : entries) {
- if (arrow)
- sb.append("->");
-
- arrow = true;
- node = sh.getUid();
- sb.append(node);
- }
- sb.append(';');
- SvekUtils.println(sb);
- sb.append(node + "->" + empty() + ";");
- SvekUtils.println(sb);
- }
- }
- }
-
- private List extends IShapePseudo> withPositionProtected(StringBounder stringBounder,
- Set targets) {
- final List result = withPosition(targets);
- final double maxWith = getMaxWidthFromLabelForEntryExit(result, stringBounder);
- final double naturalSpace = 70;
- if (maxWith > naturalSpace)
- return addProtection(result, maxWith - naturalSpace);
-
- return result;
- }
-
- private List withPosition(Set positions) {
- final List result = new ArrayList<>();
- for (final Iterator it = nodes.iterator(); it.hasNext();) {
- final SvekNode sh = it.next();
- if (positions.contains(sh.getEntityPosition()))
- result.add(sh);
-
- }
- return result;
- }
-
- private void printClusterEntryExit(StringBuilder sb, StringBounder stringBounder) {
- printRanks(RANK_SOURCE, withPositionProtected(stringBounder, EntityPosition.getInputs()), sb, stringBounder);
- printRanks(RANK_SAME, withPositionProtected(stringBounder, EntityPosition.getSame()), sb, stringBounder);
- printRanks(RANK_SINK, withPositionProtected(stringBounder, EntityPosition.getOutputs()), sb, stringBounder);
- }
-
public SvekNode printCluster2(StringBuilder sb, Collection lines, StringBounder stringBounder,
DotMode dotMode, GraphvizVersion graphvizVersion, UmlDiagramType type) {
@@ -618,6 +529,11 @@ public class Cluster implements Moveable {
return added;
}
+ private void printInternal(StringBuilder sb, Collection lines, StringBounder stringBounder,
+ DotMode dotMode, GraphvizVersion graphvizVersion, UmlDiagramType type) {
+ new ClusterDotString(this, skinParam).printInternal(sb, lines, stringBounder, dotMode, graphvizVersion, type);
+ }
+
private void appendRankSame(StringBuilder sb, Collection lines) {
for (String same : getRankSame(lines)) {
sb.append(same);
@@ -643,7 +559,7 @@ public class Cluster implements Moveable {
return rankSame;
}
- public void fillRankMin(Set rankMin) {
+ void fillRankMin(Set rankMin) {
for (SvekNode sh : getNodes())
if (sh.isTop())
rankMin.add(sh.getUid());
@@ -665,204 +581,33 @@ public class Cluster implements Moveable {
return "cluster" + color;
}
- public static String getSpecialPointId(IEntity group) {
+ static String getSpecialPointId(IEntity group) {
return CENTER_ID + group.getUid();
}
- private boolean protection0(UmlDiagramType type) {
- if (skinParam.useSwimlanes(type))
- return false;
-
- return true;
- }
-
- private boolean protection1(UmlDiagramType type) {
- if (group.getUSymbol() == USymbols.NODE)
- return true;
-
- if (skinParam.useSwimlanes(type))
- return false;
-
- return true;
- }
-
- public String getMinPoint(UmlDiagramType type) {
+ String getMinPoint(UmlDiagramType type) {
if (skinParam.useSwimlanes(type))
return "minPoint" + color;
return null;
}
- public String getMaxPoint(UmlDiagramType type) {
+ String getMaxPoint(UmlDiagramType type) {
if (skinParam.useSwimlanes(type))
return "maxPoint" + color;
return null;
}
- private String getSourceInPoint(UmlDiagramType type) {
- if (skinParam.useSwimlanes(type))
- return "sourceIn" + color;
-
- return null;
- }
-
- private String getSinkInPoint(UmlDiagramType type) {
- if (skinParam.useSwimlanes(type))
- return "sinkIn" + color;
-
- return null;
- }
-
- private void printInternal(StringBuilder sb, Collection lines, StringBounder stringBounder,
- DotMode dotMode, GraphvizVersion graphvizVersion, UmlDiagramType type) {
- final boolean thereALinkFromOrToGroup2 = isThereALinkFromOrToGroup(lines);
- boolean thereALinkFromOrToGroup1 = thereALinkFromOrToGroup2;
- final boolean useProtectionWhenThereALinkFromOrToGroup = graphvizVersion
- .useProtectionWhenThereALinkFromOrToGroup();
- if (useProtectionWhenThereALinkFromOrToGroup == false)
- thereALinkFromOrToGroup1 = false;
-
- // final boolean thereALinkFromOrToGroup1 = false;
- if (thereALinkFromOrToGroup1)
- subgraphClusterNoLabel(sb, "a");
-
- final Set entityPositionsExceptNormal = entityPositionsExceptNormal();
- if (entityPositionsExceptNormal.size() > 0)
- for (SvekLine line : lines)
- if (line.isLinkFromOrTo(group))
- line.setProjectionCluster(this);
-
- boolean protection0 = protection0(type);
- boolean protection1 = protection1(type);
- if (entityPositionsExceptNormal.size() > 0 || useProtectionWhenThereALinkFromOrToGroup == false) {
- protection0 = false;
- protection1 = false;
- }
- // if (graphvizVersion.modeSafe()) {
- // protection0 = false;
- // protection1 = false;
- // }
- if (protection0)
- subgraphClusterNoLabel(sb, "p0");
-
- sb.append("subgraph " + getClusterId() + " {");
- sb.append("style=solid;");
- sb.append("color=\"" + StringUtils.sharp000000(color) + "\";");
-
- final String label;
- if (isLabel()) {
- final StringBuilder sblabel = new StringBuilder("<");
- SvekLine.appendTable(sblabel, getTitleAndAttributeWidth(), getTitleAndAttributeHeight() - 5, colorTitle);
- sblabel.append(">");
- label = sblabel.toString();
- final HorizontalAlignment align = skinParam.getHorizontalAlignment(AlignmentParam.packageTitleAlignment,
- null, false, null);
- sb.append("labeljust=\"" + align.getGraphVizValue() + "\";");
- } else {
- label = "\"\"";
- }
-
- if (entityPositionsExceptNormal.size() > 0) {
- printClusterEntryExit(sb, stringBounder);
- if (hasPort())
- subgraphClusterNoLabel(sb, ID_EE);
- else
- subgraphClusterWithLabel(sb, ID_EE, label);
-
- } else {
- sb.append("label=" + label + ";");
- SvekUtils.println(sb);
- }
-
- if (thereALinkFromOrToGroup2)
- sb.append(getSpecialPointId(group) + " [shape=point,width=.01,label=\"\"];");
-
- if (thereALinkFromOrToGroup1)
- subgraphClusterNoLabel(sb, "i");
-
- if (protection1)
- subgraphClusterNoLabel(sb, "p1");
-
- if (skinParam.useSwimlanes(type)) {
- sb.append("{rank = source; ");
- sb.append(getSourceInPoint(type));
- sb.append(" [shape=point,width=.01,label=\"\"];");
- sb.append(getMinPoint(type) + "->" + getSourceInPoint(type) + " [weight=999];");
- sb.append("}");
- SvekUtils.println(sb);
- sb.append("{rank = sink; ");
- sb.append(getSinkInPoint(type));
- sb.append(" [shape=point,width=.01,label=\"\"];");
- sb.append("}");
- sb.append(getSinkInPoint(type) + "->" + getMaxPoint(type) + " [weight=999];");
- SvekUtils.println(sb);
- }
- SvekUtils.println(sb);
- printCluster1(sb, lines, stringBounder);
-
- final SvekNode added = printCluster2(sb, lines, stringBounder, dotMode, graphvizVersion, type);
- if (entityPositionsExceptNormal.size() > 0)
- if (hasPort()) {
- sb.append(empty() + " [shape=rect,width=.01,height=.01,label=");
- sb.append(label);
- sb.append("];");
- } else if (added == null) {
- sb.append(empty() + " [shape=point,width=.01,label=\"\"];");
- }
- SvekUtils.println(sb);
-
- sb.append("}");
- if (protection1)
- sb.append("}");
-
- if (thereALinkFromOrToGroup1) {
- sb.append("}");
- sb.append("}");
- }
- if (entityPositionsExceptNormal.size() > 0)
- sb.append("}");
-
- if (protection0)
- sb.append("}");
-
- SvekUtils.println(sb);
- }
-
- private boolean hasPort() {
- for (EntityPosition pos : entityPositionsExceptNormal())
- if (pos.isPort())
- return true;
-
- return false;
- }
-
- private String empty() {
- // return "empty" + color;
- // We use the same node with one for thereALinkFromOrToGroup2 as an empty
- // because we cannot put a new node in the nested inside of the cluster
- // if thereALinkFromOrToGroup2 is enabled.
- return getSpecialPointId(group);
- }
-
public boolean isLabel() {
return getTitleAndAttributeHeight() > 0 && getTitleAndAttributeWidth() > 0;
}
- private void subgraphClusterNoLabel(StringBuilder sb, String id) {
- subgraphClusterWithLabel(sb, id, "\"\"");
- }
-
- private void subgraphClusterWithLabel(StringBuilder sb, String id, String label) {
- sb.append("subgraph " + getClusterId() + id + " {");
- sb.append("label=" + label + ";");
- }
-
- public int getColor() {
+ int getColor() {
return color;
}
- public int getTitleColor() {
+ int getTitleColor() {
return colorTitle;
}
@@ -891,7 +636,7 @@ public class Cluster implements Moveable {
// return parentCluster.getBackColor(umlDiagramType, style);
}
- public boolean isClusterOf(IEntity ent) {
+ boolean isClusterOf(IEntity ent) {
if (ent.isGroup() == false)
return false;
@@ -911,7 +656,7 @@ public class Cluster implements Moveable {
return backColor;
}
- public double checkFolderPosition(Point2D pt, StringBounder stringBounder) {
+ double checkFolderPosition(Point2D pt, StringBounder stringBounder) {
if (getClusterPosition().isPointJustUpper(pt)) {
if (ztitle == null)
return 0;
diff --git a/src/net/sourceforge/plantuml/svek/ClusterDotString.java b/src/net/sourceforge/plantuml/svek/ClusterDotString.java
new file mode 100644
index 000000000..8680d0aff
--- /dev/null
+++ b/src/net/sourceforge/plantuml/svek/ClusterDotString.java
@@ -0,0 +1,344 @@
+/* ========================================================================
+ * PlantUML : a free UML diagram generator
+ * ========================================================================
+ *
+ * (C) Copyright 2009-2023, Arnaud Roques
+ *
+ * Project Info: http://plantuml.com
+ *
+ * If you like this project or if you find it useful, you can support us at:
+ *
+ * http://plantuml.com/patreon (only 1$ per month!)
+ * http://plantuml.com/paypal
+ *
+ * This file is part of PlantUML.
+ *
+ * PlantUML is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * PlantUML distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ *
+ *
+ * Original Author: Arnaud Roques
+ * Contribution : Hisashi Miyashita
+ *
+ *
+ */
+package net.sourceforge.plantuml.svek;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import net.sourceforge.plantuml.AlignmentParam;
+import net.sourceforge.plantuml.ISkinParam;
+import net.sourceforge.plantuml.StringUtils;
+import net.sourceforge.plantuml.UmlDiagramType;
+import net.sourceforge.plantuml.cucadiagram.EntityPosition;
+import net.sourceforge.plantuml.cucadiagram.dot.GraphvizVersion;
+import net.sourceforge.plantuml.graphic.HorizontalAlignment;
+import net.sourceforge.plantuml.graphic.StringBounder;
+import net.sourceforge.plantuml.graphic.USymbols;
+
+public class ClusterDotString {
+
+ private final Cluster cluster;
+ private final ISkinParam skinParam;
+
+ public ClusterDotString(Cluster cluster, ISkinParam skinParam) {
+ this.cluster = cluster;
+ this.skinParam = skinParam;
+ }
+
+ void printInternal(StringBuilder sb, Collection lines, StringBounder stringBounder, DotMode dotMode,
+ GraphvizVersion graphvizVersion, UmlDiagramType type) {
+ final boolean thereALinkFromOrToGroup2 = isThereALinkFromOrToGroup(lines);
+ boolean thereALinkFromOrToGroup1 = thereALinkFromOrToGroup2;
+ final boolean useProtectionWhenThereALinkFromOrToGroup = graphvizVersion
+ .useProtectionWhenThereALinkFromOrToGroup();
+ if (useProtectionWhenThereALinkFromOrToGroup == false)
+ thereALinkFromOrToGroup1 = false;
+
+ if (thereALinkFromOrToGroup1)
+ subgraphClusterNoLabel(sb, "a");
+
+ final Set entityPositionsExceptNormal = entityPositionsExceptNormal();
+ if (entityPositionsExceptNormal.size() > 0)
+ for (SvekLine line : lines)
+ if (line.isLinkFromOrTo(cluster.getGroup()))
+ line.setProjectionCluster(cluster);
+
+ boolean protection0 = protection0(type);
+ boolean protection1 = protection1(type);
+ if (entityPositionsExceptNormal.size() > 0 || useProtectionWhenThereALinkFromOrToGroup == false) {
+ protection0 = false;
+ protection1 = false;
+ }
+
+ if (protection0)
+ subgraphClusterNoLabel(sb, "p0");
+
+ sb.append("subgraph " + cluster.getClusterId() + " {");
+ sb.append("style=solid;");
+ sb.append("color=\"" + StringUtils.sharp000000(cluster.getColor()) + "\";");
+
+ final String label;
+ if (cluster.isLabel()) {
+ final StringBuilder sblabel = new StringBuilder("<");
+ SvekLine.appendTable(sblabel, cluster.getTitleAndAttributeWidth(), cluster.getTitleAndAttributeHeight() - 5,
+ cluster.getTitleColor());
+ sblabel.append(">");
+ label = sblabel.toString();
+ final HorizontalAlignment align = skinParam.getHorizontalAlignment(AlignmentParam.packageTitleAlignment,
+ null, false, null);
+ sb.append("labeljust=\"" + align.getGraphVizValue() + "\";");
+ } else {
+ label = "\"\"";
+ }
+
+ if (entityPositionsExceptNormal.size() > 0) {
+ printClusterEntryExit(sb, stringBounder);
+ if (hasPort())
+ subgraphClusterNoLabel(sb, Cluster.ID_EE);
+ else
+ subgraphClusterWithLabel(sb, Cluster.ID_EE, label);
+
+ } else {
+ sb.append("label=" + label + ";");
+ SvekUtils.println(sb);
+ }
+
+ if (thereALinkFromOrToGroup2)
+ sb.append(Cluster.getSpecialPointId(cluster.getGroup()) + " [shape=point,width=.01,label=\"\"];");
+
+ if (thereALinkFromOrToGroup1)
+ subgraphClusterNoLabel(sb, "i");
+
+ if (protection1)
+ subgraphClusterNoLabel(sb, "p1");
+
+ if (skinParam.useSwimlanes(type)) {
+ sb.append("{rank = source; ");
+ sb.append(getSourceInPoint(type));
+ sb.append(" [shape=point,width=.01,label=\"\"];");
+ sb.append(cluster.getMinPoint(type) + "->" + getSourceInPoint(type) + " [weight=999];");
+ sb.append("}");
+ SvekUtils.println(sb);
+ sb.append("{rank = sink; ");
+ sb.append(getSinkInPoint(type));
+ sb.append(" [shape=point,width=.01,label=\"\"];");
+ sb.append("}");
+ sb.append(getSinkInPoint(type) + "->" + cluster.getMaxPoint(type) + " [weight=999];");
+ SvekUtils.println(sb);
+ }
+ SvekUtils.println(sb);
+ cluster.printCluster1(sb, lines, stringBounder);
+
+ final SvekNode added = cluster.printCluster2(sb, lines, stringBounder, dotMode, graphvizVersion, type);
+ if (entityPositionsExceptNormal.size() > 0)
+ if (hasPort()) {
+ sb.append(empty() + " [shape=rect,width=.01,height=.01,label=");
+ sb.append(label);
+ sb.append("];");
+ } else if (added == null) {
+ sb.append(empty() + " [shape=point,width=.01,label=\"\"];");
+ }
+ SvekUtils.println(sb);
+
+ sb.append("}");
+ if (protection1)
+ sb.append("}");
+
+ if (thereALinkFromOrToGroup1) {
+ sb.append("}");
+ sb.append("}");
+ }
+ if (entityPositionsExceptNormal.size() > 0)
+ sb.append("}");
+
+ if (protection0)
+ sb.append("}");
+
+ SvekUtils.println(sb);
+ }
+
+ private String getSourceInPoint(UmlDiagramType type) {
+ if (skinParam.useSwimlanes(type))
+ return "sourceIn" + cluster.getColor();
+
+ return null;
+ }
+
+ private String getSinkInPoint(UmlDiagramType type) {
+ if (skinParam.useSwimlanes(type))
+ return "sinkIn" + cluster.getColor();
+
+ return null;
+ }
+
+ private String empty() {
+ // return "empty" + color;
+ // We use the same node with one for thereALinkFromOrToGroup2 as an empty
+ // because we cannot put a new node in the nested inside of the cluster
+ // if thereALinkFromOrToGroup2 is enabled.
+ return Cluster.getSpecialPointId(cluster.getGroup());
+ }
+
+ private boolean hasPort() {
+ for (EntityPosition pos : entityPositionsExceptNormal())
+ if (pos.isPort())
+ return true;
+
+ return false;
+ }
+
+ private Set entityPositionsExceptNormal() {
+ final Set result = EnumSet.noneOf(EntityPosition.class);
+ for (SvekNode sh : cluster.getNodes())
+ if (sh.getEntityPosition() != EntityPosition.NORMAL)
+ result.add(sh.getEntityPosition());
+
+ return Collections.unmodifiableSet(result);
+ }
+
+ private void subgraphClusterNoLabel(StringBuilder sb, String id) {
+ subgraphClusterWithLabel(sb, id, "\"\"");
+ }
+
+ private void subgraphClusterWithLabel(StringBuilder sb, String id, String label) {
+ sb.append("subgraph " + cluster.getClusterId() + id + " {");
+ sb.append("label=" + label + ";");
+ }
+
+ private void printClusterEntryExit(StringBuilder sb, StringBounder stringBounder) {
+ printRanks(Cluster.RANK_SOURCE, withPositionProtected(stringBounder, EntityPosition.getInputs()), sb,
+ stringBounder);
+ printRanks(Cluster.RANK_SAME, withPositionProtected(stringBounder, EntityPosition.getSame()), sb,
+ stringBounder);
+ printRanks(Cluster.RANK_SINK, withPositionProtected(stringBounder, EntityPosition.getOutputs()), sb,
+ stringBounder);
+ }
+
+ private void printRanks(String rank, List extends IShapePseudo> entries, StringBuilder sb,
+ StringBounder stringBounder) {
+ if (entries.size() > 0) {
+ sb.append("{rank=" + rank + ";");
+ for (IShapePseudo sh1 : entries)
+ sb.append(sh1.getUid() + ";");
+
+ sb.append("}");
+ SvekUtils.println(sb);
+ for (IShapePseudo sh2 : entries)
+ sh2.appendShape(sb, stringBounder);
+
+ SvekUtils.println(sb);
+ if (hasPort()) {
+ boolean arrow = false;
+ String node = null;
+ for (IShapePseudo sh : entries) {
+ if (arrow)
+ sb.append("->");
+
+ arrow = true;
+ node = sh.getUid();
+ sb.append(node);
+ }
+ if (arrow)
+ sb.append(" [arrowhead=none]");
+
+ sb.append(';');
+ SvekUtils.println(sb);
+ sb.append(node + "->" + empty() + ";");
+ SvekUtils.println(sb);
+ }
+ }
+ }
+
+ private List extends IShapePseudo> withPositionProtected(StringBounder stringBounder,
+ Set targets) {
+ final List result = withPosition(targets);
+ final double maxWith = getMaxWidthFromLabelForEntryExit(result, stringBounder);
+ final double naturalSpace = 70;
+ if (maxWith > naturalSpace)
+ return addProtection(result, maxWith - naturalSpace);
+
+ return result;
+ }
+
+ private List addProtection(List extends IShapePseudo> entries, double width) {
+ final List result = new ArrayList<>();
+ result.add(entries.get(0));
+ for (int i = 1; i < entries.size(); i++) {
+ // Pseudo space for the label
+ result.add(new ShapePseudoImpl("psd" + cluster.diagram.getUniqueSequence(), width, 5));
+ result.add(entries.get(i));
+ }
+ return result;
+ }
+
+ private List withPosition(Set positions) {
+ final List result = new ArrayList<>();
+ for (final Iterator it = cluster.getNodes().iterator(); it.hasNext();) {
+ final SvekNode sh = it.next();
+ if (positions.contains(sh.getEntityPosition()))
+ result.add(sh);
+
+ }
+ return result;
+ }
+
+ private double getMaxWidthFromLabelForEntryExit(List extends IShapePseudo> entries, StringBounder stringBounder) {
+ double result = -Double.MAX_VALUE;
+ for (IShapePseudo node : entries) {
+ final double w = getMaxWidthFromLabelForEntryExit(node, stringBounder);
+ if (w > result)
+ result = w;
+
+ }
+ return result;
+ }
+
+ private double getMaxWidthFromLabelForEntryExit(IShapePseudo node, StringBounder stringBounder) {
+ return node.getMaxWidthFromLabelForEntryExit(stringBounder);
+ }
+
+ private boolean protection0(UmlDiagramType type) {
+ if (skinParam.useSwimlanes(type))
+ return false;
+
+ return true;
+ }
+
+ private boolean protection1(UmlDiagramType type) {
+ if (cluster.getGroup().getUSymbol() == USymbols.NODE)
+ return true;
+
+ if (skinParam.useSwimlanes(type))
+ return false;
+
+ return true;
+ }
+
+ private boolean isThereALinkFromOrToGroup(Collection lines) {
+ for (SvekLine line : lines)
+ if (line.isLinkFromOrTo(cluster.getGroup()))
+ return true;
+
+ return false;
+ }
+
+}
diff --git a/src/net/sourceforge/plantuml/svek/DotStringFactory.java b/src/net/sourceforge/plantuml/svek/DotStringFactory.java
index bf2d7cd5a..9b4ae8190 100644
--- a/src/net/sourceforge/plantuml/svek/DotStringFactory.java
+++ b/src/net/sourceforge/plantuml/svek/DotStringFactory.java
@@ -94,7 +94,7 @@ public class DotStringFactory implements Moveable {
this.colorSequence = new ColorSequence();
this.stringBounder = stringBounder;
- this.root = new Cluster(colorSequence, skinParam, dotData.getRootGroup());
+ this.root = new Cluster(dotData.getEntityFactory().getDiagram(), colorSequence, skinParam, dotData.getRootGroup());
this.current = root;
}
@@ -105,7 +105,7 @@ public class DotStringFactory implements Moveable {
this.colorSequence = new ColorSequence();
this.stringBounder = stringBounder;
- this.root = new Cluster(colorSequence, skinParam, diagram.getEntityFactory().getRootGroup());
+ this.root = new Cluster(diagram, colorSequence, skinParam, diagram.getEntityFactory().getRootGroup());
this.current = root;
}
@@ -173,13 +173,13 @@ public class DotStringFactory implements Moveable {
SvekUtils.println(sb);
for (String s : dotStrings) {
- if (s.startsWith("ranksep")) {
+ if (s.startsWith("ranksep"))
sb.append("ranksep=" + ranksepInches + ";");
- } else if (s.startsWith("nodesep")) {
+ else if (s.startsWith("nodesep"))
sb.append("nodesep=" + nodesepInches + ";");
- } else {
+ else
sb.append(s);
- }
+
SvekUtils.println(sb);
}
// sb.append("newrank=true;");
@@ -309,9 +309,9 @@ public class DotStringFactory implements Moveable {
try {
final ProcessState state = graphviz.createFile3(baos);
baos.close();
- if (state.differs(ProcessState.TERMINATED_OK())) {
+ if (state.differs(ProcessState.TERMINATED_OK()))
throw new IllegalStateException("Timeout4 " + state, state.getCause());
- }
+
} catch (GraphvizJsRuntimeException e) {
System.err.println("GraphvizJsRuntimeException");
graphvizVersion = GraphvizJs.getGraphvizVersion(true);
@@ -367,7 +367,7 @@ public class DotStringFactory implements Moveable {
int idx = svg.indexOf("" + node.getUid() + "");
if (node.getType() == ShapeType.RECTANGLE || node.getType() == ShapeType.RECTANGLE_HTML_FOR_PORTS
|| node.getType() == ShapeType.RECTANGLE_WITH_CIRCLE_INSIDE || node.getType() == ShapeType.FOLDER
- || node.getType() == ShapeType.DIAMOND) {
+ || node.getType() == ShapeType.DIAMOND || node.getType() == ShapeType.RECTANGLE_PORT) {
final List points = svgResult.substring(idx).extractList(SvgResult.POINTS_EQUALS);
final double minY = SvekUtils.getMinY(points);
final double overscanX = node.getOverscanX(stringBounder);
diff --git a/src/net/sourceforge/plantuml/svek/GeneralImageBuilder.java b/src/net/sourceforge/plantuml/svek/GeneralImageBuilder.java
index a34f5fb3e..0bc2e2d17 100644
--- a/src/net/sourceforge/plantuml/svek/GeneralImageBuilder.java
+++ b/src/net/sourceforge/plantuml/svek/GeneralImageBuilder.java
@@ -99,6 +99,8 @@ import net.sourceforge.plantuml.graphic.USymbolHexagon;
import net.sourceforge.plantuml.graphic.USymbolInterface;
import net.sourceforge.plantuml.graphic.USymbols;
import net.sourceforge.plantuml.log.Logme;
+import net.sourceforge.plantuml.security.SecurityProfile;
+import net.sourceforge.plantuml.security.SecurityUtils;
import net.sourceforge.plantuml.style.PName;
import net.sourceforge.plantuml.style.SName;
import net.sourceforge.plantuml.style.Style;
@@ -444,7 +446,10 @@ public final class GeneralImageBuilder {
if (dotStringFactory.illegalDotExe())
return error(dotStringFactory.getDotExe());
- if (basefile == null && isSvekTrace())
+ if (basefile == null && isSvekTrace()
+ && (SecurityUtils.getSecurityProfile() == SecurityProfile.UNSECURE
+ || SecurityUtils.getSecurityProfile() == SecurityProfile.LEGACY
+ || SecurityUtils.getSecurityProfile() == SecurityProfile.SANDBOX))
basefile = new BaseFile(null);
final String svg;
diff --git a/src/net/sourceforge/plantuml/svek/ShapeType.java b/src/net/sourceforge/plantuml/svek/ShapeType.java
index 5fdb0b4b1..253a4bab9 100644
--- a/src/net/sourceforge/plantuml/svek/ShapeType.java
+++ b/src/net/sourceforge/plantuml/svek/ShapeType.java
@@ -37,7 +37,18 @@ package net.sourceforge.plantuml.svek;
public enum ShapeType {
- RECTANGLE, RECTANGLE_WITH_CIRCLE_INSIDE, RECTANGLE_HTML_FOR_PORTS, ROUND_RECTANGLE, CIRCLE, CIRCLE_IN_RECT, OVAL,
- DIAMOND, OCTAGON, FOLDER, HEXAGON
+ RECTANGLE, //
+ RECTANGLE_PORT, //
+ RECTANGLE_WITH_CIRCLE_INSIDE, //
+ RECTANGLE_HTML_FOR_PORTS, //
+ ROUND_RECTANGLE, //
+ CIRCLE, //
+ CIRCLE_IN_RECT, //
+ OVAL, //
+ DIAMOND, //
+ OCTAGON, //
+ FOLDER, //
+ HEXAGON, //
+ PORT //
}
diff --git a/src/net/sourceforge/plantuml/svek/SvekLine.java b/src/net/sourceforge/plantuml/svek/SvekLine.java
index 27fa06880..1503fbfde 100644
--- a/src/net/sourceforge/plantuml/svek/SvekLine.java
+++ b/src/net/sourceforge/plantuml/svek/SvekLine.java
@@ -102,7 +102,6 @@ import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.UGroupType;
import net.sourceforge.plantuml.ugraphic.ULine;
import net.sourceforge.plantuml.ugraphic.UPolygon;
-import net.sourceforge.plantuml.ugraphic.URectangle;
import net.sourceforge.plantuml.ugraphic.UStroke;
import net.sourceforge.plantuml.ugraphic.UTranslate;
import net.sourceforge.plantuml.ugraphic.color.HColor;
diff --git a/src/net/sourceforge/plantuml/svek/SvekNode.java b/src/net/sourceforge/plantuml/svek/SvekNode.java
index c49827f5e..c4e5ff8c4 100644
--- a/src/net/sourceforge/plantuml/svek/SvekNode.java
+++ b/src/net/sourceforge/plantuml/svek/SvekNode.java
@@ -137,6 +137,10 @@ public class SvekNode implements Positionable, IShapePseudo, Hideable {
appendLabelHtmlSpecialForLink(sb, stringBounder);
return;
}
+ if (type == ShapeType.RECTANGLE_PORT) {
+ appendLabelHtmlSpecialForPort(sb, stringBounder);
+ return;
+ }
if (type == ShapeType.RECTANGLE_WITH_CIRCLE_INSIDE) {
appendHtml(sb);
return;
@@ -160,6 +164,21 @@ public class SvekNode implements Positionable, IShapePseudo, Hideable {
SvekUtils.println(sb);
}
+ private void appendLabelHtmlSpecialForPort(StringBuilder sb, StringBounder stringBounder2) {
+ sb.append(uid);
+ sb.append(" [");
+ sb.append("shape=rect");
+ sb.append(",");
+ sb.append("label=\"\"");
+ sb.append(",");
+ sb.append("width=" + SvekUtils.pixelToInches(getWidth()));
+ sb.append(",");
+ sb.append("height=" + SvekUtils.pixelToInches(getHeight()));
+ sb.append(",");
+ sb.append("color=\"" + StringUtils.sharp000000(color) + "\"");
+ sb.append("];");
+ }
+
private Margins shield() {
if (shield == null) {
this.shield = image.getShield(stringBounder);
diff --git a/src/net/sourceforge/plantuml/svek/image/EntityImagePort.java b/src/net/sourceforge/plantuml/svek/image/EntityImagePort.java
index 3a6a276d5..b5c7d61a6 100644
--- a/src/net/sourceforge/plantuml/svek/image/EntityImagePort.java
+++ b/src/net/sourceforge/plantuml/svek/image/EntityImagePort.java
@@ -132,6 +132,6 @@ public class EntityImagePort extends AbstractEntityImageBorder {
}
public ShapeType getShapeType() {
- return ShapeType.RECTANGLE;
+ return ShapeType.RECTANGLE_PORT;
}
}
diff --git a/src/net/sourceforge/plantuml/utils/UniqueSequence.java b/src/net/sourceforge/plantuml/utils/UniqueSequence.java
deleted file mode 100644
index 91be0f82f..000000000
--- a/src/net/sourceforge/plantuml/utils/UniqueSequence.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/* ========================================================================
- * PlantUML : a free UML diagram generator
- * ========================================================================
- *
- * (C) Copyright 2009-2023, Arnaud Roques
- *
- * Project Info: http://plantuml.com
- *
- * If you like this project or if you find it useful, you can support us at:
- *
- * http://plantuml.com/patreon (only 1$ per month!)
- * http://plantuml.com/paypal
- *
- * This file is part of PlantUML.
- *
- * PlantUML is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * PlantUML distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- * License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA.
- *
- *
- * Original Author: Arnaud Roques
- *
- *
- */
-package net.sourceforge.plantuml.utils;
-
-import java.util.concurrent.atomic.AtomicInteger;
-
-public class UniqueSequence {
-
- private static final AtomicInteger cpt = new AtomicInteger(1);
-
- public static int getValue() {
- return cpt.addAndGet(1);
- }
-
- public static String getString(String prefix) {
- return prefix + getValue();
- }
-
-}
diff --git a/src/net/sourceforge/plantuml/version/Version.java b/src/net/sourceforge/plantuml/version/Version.java
index 21ed7c2e5..5e9e10969 100644
--- a/src/net/sourceforge/plantuml/version/Version.java
+++ b/src/net/sourceforge/plantuml/version/Version.java
@@ -81,7 +81,7 @@ public class Version {
}
public static int beta() {
- final int beta = 2;
+ final int beta = 3;
return beta;
}
diff --git a/src/net/sourceforge/plantuml/xmi/CucaDiagramXmiMaker.java b/src/net/sourceforge/plantuml/xmi/CucaDiagramXmiMaker.java
index a698f9a12..af2cf6e04 100644
--- a/src/net/sourceforge/plantuml/xmi/CucaDiagramXmiMaker.java
+++ b/src/net/sourceforge/plantuml/xmi/CucaDiagramXmiMaker.java
@@ -66,20 +66,20 @@ public final class CucaDiagramXmiMaker {
public void createFiles(OutputStream fos) throws IOException {
try {
- final IXmiClassDiagram xmi;
- if (diagram instanceof StateDiagram) {
+ final XmlDiagramTransformer xmi;
+ if (diagram instanceof StateDiagram)
xmi = new XmiStateDiagram((StateDiagram) diagram);
- } else if (diagram instanceof DescriptionDiagram) {
+ else if (diagram instanceof DescriptionDiagram)
xmi = new XmiDescriptionDiagram((DescriptionDiagram) diagram);
- } else if (fileFormat == FileFormat.XMI_STANDARD) {
+ else if (fileFormat == FileFormat.XMI_STANDARD)
xmi = new XmiClassDiagramStandard((ClassDiagram) diagram);
- } else if (fileFormat == FileFormat.XMI_ARGO) {
+ else if (fileFormat == FileFormat.XMI_ARGO)
xmi = new XmiClassDiagramArgo((ClassDiagram) diagram);
- } else if (fileFormat == FileFormat.XMI_STAR) {
+ else if (fileFormat == FileFormat.XMI_STAR)
xmi = new XmiClassDiagramStar((ClassDiagram) diagram);
- } else {
+ else
throw new UnsupportedOperationException();
- }
+
xmi.transformerXml(fos);
} catch (ParserConfigurationException e) {
Log.error(e.toString());
diff --git a/src/net/sourceforge/plantuml/xmi/XmiClassDiagramAbstract.java b/src/net/sourceforge/plantuml/xmi/XmiClassDiagramAbstract.java
index 964e7a649..d2792f0cd 100644
--- a/src/net/sourceforge/plantuml/xmi/XmiClassDiagramAbstract.java
+++ b/src/net/sourceforge/plantuml/xmi/XmiClassDiagramAbstract.java
@@ -57,14 +57,14 @@ import org.w3c.dom.Element;
import net.sourceforge.plantuml.classdiagram.ClassDiagram;
import net.sourceforge.plantuml.cucadiagram.Display;
import net.sourceforge.plantuml.cucadiagram.IEntity;
+import net.sourceforge.plantuml.cucadiagram.ILeaf;
import net.sourceforge.plantuml.cucadiagram.LeafType;
import net.sourceforge.plantuml.cucadiagram.Member;
import net.sourceforge.plantuml.cucadiagram.Stereotype;
import net.sourceforge.plantuml.skin.VisibilityModifier;
-import net.sourceforge.plantuml.utils.UniqueSequence;
import net.sourceforge.plantuml.xml.XmlFactories;
-abstract class XmiClassDiagramAbstract implements IXmiClassDiagram {
+abstract class XmiClassDiagramAbstract implements XmlDiagramTransformer {
// https://www.ibm.com/developerworks/library/x-wxxm24/
// http://pierre.ree7.fr/blog/?p=5
@@ -99,9 +99,6 @@ abstract class XmiClassDiagramAbstract implements IXmiClassDiagram {
final Element content = document.createElement("XMI.content");
xmi.appendChild(content);
- //
final Element model = document.createElement("UML:Model");
model.setAttribute("xmi.id", CucaDiagramXmiMaker.getModel(classDiagram));
model.setAttribute("name", "PlantUML");
@@ -131,32 +128,24 @@ abstract class XmiClassDiagramAbstract implements IXmiClassDiagram {
final Transformer transformer = XmlFactories.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
- // transformer.setOutputProperty(OutputKeys.ENCODING, "ISO-8859-1");
transformer.setOutputProperty(OutputKeys.ENCODING, UTF_8.name());
// tf.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
transformer.transform(source, resultat);
}
final protected Element createEntityNode(IEntity entity) {
- //
final Element cla = document.createElement("UML:Class");
- if (entity.getLeafType() == LeafType.NOTE) {
+ if (entity.getLeafType() == LeafType.NOTE)
return null;
- }
cla.setAttribute("xmi.id", entity.getUid());
cla.setAttribute("name", entity.getDisplay().get(0).toString());
final String parentCode = entity.getIdent().parent().forXmi();
- // final LongCode parentCode = entity.getParentContainer().getLongCode();
- if (parentCode.length() == 0) {
+
+ if (parentCode.length() == 0)
cla.setAttribute("namespace", CucaDiagramXmiMaker.getModel(classDiagram));
- } else {
+ else
cla.setAttribute("namespace", parentCode);
- }
final Stereotype stereotype = entity.getStereotype();
if (stereotype != null) {
@@ -170,45 +159,47 @@ abstract class XmiClassDiagramAbstract implements IXmiClassDiagram {
}
final LeafType type = entity.getLeafType();
- if (type == LeafType.ABSTRACT_CLASS) {
+ if (type == LeafType.ABSTRACT_CLASS)
cla.setAttribute("isAbstract", "true");
- } else if (type == LeafType.INTERFACE) {
+ else if (type == LeafType.INTERFACE)
cla.setAttribute("isInterface", "true");
- }
+
+ if (((ILeaf) entity).isStatic())
+ cla.setAttribute("isStatic", "true");
+
+ if (((ILeaf) entity).getVisibilityModifier() == VisibilityModifier.PRIVATE_FIELD
+ || ((ILeaf) entity).getVisibilityModifier() == VisibilityModifier.PRIVATE_METHOD)
+ cla.setAttribute("visibility", ((ILeaf) entity).getVisibilityModifier().getXmiVisibility());
final Element feature = document.createElement("UML:Classifier.feature");
cla.appendChild(feature);
for (CharSequence cs : entity.getBodier().getFieldsToDisplay()) {
final Member m = (Member) cs;
- //
+
final Element attribute = document.createElement("UML:Attribute");
- attribute.setAttribute("xmi.id", "att" + UniqueSequence.getValue());
+ attribute.setAttribute("xmi.id", "att" + classDiagram.getUniqueSequence());
attribute.setAttribute("name", m.getDisplay(false));
final VisibilityModifier visibility = m.getVisibilityModifier();
- if (visibility != null) {
+ if (visibility != null)
attribute.setAttribute("visibility", visibility.getXmiVisibility());
- }
+ if (m.isStatic())
+ attribute.setAttribute("isStatic", "true");
+
feature.appendChild(attribute);
}
for (CharSequence cs : entity.getBodier().getMethodsToDisplay()) {
final Member m = (Member) cs;
- //
final Element operation = document.createElement("UML:Operation");
- operation.setAttribute("xmi.id", "att" + UniqueSequence.getValue());
+ operation.setAttribute("xmi.id", "att" + classDiagram.getUniqueSequence());
operation.setAttribute("name", m.getDisplay(false));
final VisibilityModifier visibility = m.getVisibilityModifier();
- if (visibility != null) {
+ if (visibility != null)
operation.setAttribute("visibility", visibility.getXmiVisibility());
- }
+ if (m.isStatic())
+ operation.setAttribute("isStatic", "true");
+
feature.appendChild(operation);
}
return cla;
diff --git a/src/net/sourceforge/plantuml/xmi/XmiClassDiagramArgo.java b/src/net/sourceforge/plantuml/xmi/XmiClassDiagramArgo.java
index 2d72e30dc..1ba419516 100644
--- a/src/net/sourceforge/plantuml/xmi/XmiClassDiagramArgo.java
+++ b/src/net/sourceforge/plantuml/xmi/XmiClassDiagramArgo.java
@@ -42,104 +42,84 @@ import org.w3c.dom.Element;
import net.sourceforge.plantuml.classdiagram.ClassDiagram;
import net.sourceforge.plantuml.cucadiagram.IEntity;
import net.sourceforge.plantuml.cucadiagram.Link;
-import net.sourceforge.plantuml.utils.UniqueSequence;
-public class XmiClassDiagramArgo extends XmiClassDiagramAbstract implements IXmiClassDiagram {
+public class XmiClassDiagramArgo extends XmiClassDiagramAbstract implements XmlDiagramTransformer {
public XmiClassDiagramArgo(ClassDiagram classDiagram) throws ParserConfigurationException {
super(classDiagram);
for (final IEntity ent : classDiagram.getLeafsvalues()) {
- if (classDiagram.isStandalone(ent) == false) {
+ if (classDiagram.isStandaloneForArgo(ent) == false)
continue;
- }
+
final Element cla = createEntityNode(ent);
- if (cla == null) {
+ if (cla == null)
continue;
- }
+
ownedElement.appendChild(cla);
done.add(ent);
}
- // if (fileFormat != FileFormat.XMI_STANDARD) {
- for (final Link link : classDiagram.getLinks()) {
+ for (final Link link : classDiagram.getLinks())
addLink(link);
- }
- // }
}
private void addLink(Link link) {
- final String assId = "ass" + UniqueSequence.getValue();
- // if ((link.getType().getDecor1() == LinkDecor.EXTENDS || link.getType().getDecor2() == LinkDecor.EXTENDS)
- // && fileFormat == FileFormat.XMI_STAR) {
- // addExtension(link, assId);
- // return;
- // }
+ if (link.isHidden() || link.isInvis())
+ return;
+
+ final String assId = "ass" + classDiagram.getUniqueSequence();
+
final Element association = document.createElement("UML:Association");
association.setAttribute("xmi.id", assId);
association.setAttribute("namespace", CucaDiagramXmiMaker.getModel(classDiagram));
- if (link.getLabel() != null) {
+ if (link.getLabel() != null)
association.setAttribute("name", forXMI(link.getLabel()));
- }
final Element connection = document.createElement("UML:Association.connection");
final Element end1 = document.createElement("UML:AssociationEnd");
- end1.setAttribute("xmi.id", "end" + UniqueSequence.getValue());
+ end1.setAttribute("xmi.id", "end" + classDiagram.getUniqueSequence());
end1.setAttribute("association", assId);
end1.setAttribute("type", link.getEntity1().getUid());
- if (link.getQualifier1() != null) {
+ if (link.getQualifier1() != null)
end1.setAttribute("name", forXMI(link.getQualifier1()));
- }
+
final Element endparticipant1 = document.createElement("UML:AssociationEnd.participant");
- // if (fileFormat == FileFormat.XMI_ARGO) {
+
if (done.contains(link.getEntity1())) {
endparticipant1.appendChild(createEntityNodeRef(link.getEntity1()));
} else {
final Element element = createEntityNode(link.getEntity1());
- if (element == null) {
+ if (element == null)
return;
- }
+
endparticipant1.appendChild(element);
done.add(link.getEntity1());
}
- // } else if (fileFormat == FileFormat.XMI_STAR) {
- // 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);
final Element end2 = document.createElement("UML:AssociationEnd");
- end2.setAttribute("xmi.id", "end" + UniqueSequence.getValue());
+ end2.setAttribute("xmi.id", "end" + classDiagram.getUniqueSequence());
end2.setAttribute("association", assId);
end2.setAttribute("type", link.getEntity2().getUid());
- if (link.getQualifier2() != null) {
+ if (link.getQualifier2() != null)
end2.setAttribute("name", forXMI(link.getQualifier2()));
- }
+
final Element endparticipant2 = document.createElement("UML:AssociationEnd.participant");
- // if (fileFormat == FileFormat.XMI_ARGO) {
+
if (done.contains(link.getEntity2())) {
endparticipant2.appendChild(createEntityNodeRef(link.getEntity2()));
} else {
final Element element = createEntityNode(link.getEntity2());
- if (element == null) {
+ if (element == null)
return;
- }
+
endparticipant2.appendChild(element);
done.add(link.getEntity2());
}
- // } else if (fileFormat == FileFormat.XMI_STAR) {
- // 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);
diff --git a/src/net/sourceforge/plantuml/xmi/XmiClassDiagramStandard.java b/src/net/sourceforge/plantuml/xmi/XmiClassDiagramStandard.java
index 73db9632a..52b4a26a3 100644
--- a/src/net/sourceforge/plantuml/xmi/XmiClassDiagramStandard.java
+++ b/src/net/sourceforge/plantuml/xmi/XmiClassDiagramStandard.java
@@ -42,7 +42,7 @@ import org.w3c.dom.Element;
import net.sourceforge.plantuml.classdiagram.ClassDiagram;
import net.sourceforge.plantuml.cucadiagram.IEntity;
-public class XmiClassDiagramStandard extends XmiClassDiagramAbstract implements IXmiClassDiagram {
+public class XmiClassDiagramStandard extends XmiClassDiagramAbstract implements XmlDiagramTransformer {
public XmiClassDiagramStandard(ClassDiagram classDiagram) throws ParserConfigurationException {
super(classDiagram);
diff --git a/src/net/sourceforge/plantuml/xmi/XmiClassDiagramStar.java b/src/net/sourceforge/plantuml/xmi/XmiClassDiagramStar.java
index 835d3469e..603289d47 100644
--- a/src/net/sourceforge/plantuml/xmi/XmiClassDiagramStar.java
+++ b/src/net/sourceforge/plantuml/xmi/XmiClassDiagramStar.java
@@ -44,43 +44,31 @@ import net.sourceforge.plantuml.cucadiagram.Display;
import net.sourceforge.plantuml.cucadiagram.IEntity;
import net.sourceforge.plantuml.cucadiagram.Link;
import net.sourceforge.plantuml.cucadiagram.LinkDecor;
-import net.sourceforge.plantuml.utils.UniqueSequence;
-public class XmiClassDiagramStar extends XmiClassDiagramAbstract implements IXmiClassDiagram {
+public class XmiClassDiagramStar extends XmiClassDiagramAbstract implements XmlDiagramTransformer {
public XmiClassDiagramStar(ClassDiagram classDiagram) throws ParserConfigurationException {
super(classDiagram);
for (final IEntity ent : classDiagram.getLeafsvalues()) {
- // if (fileFormat == FileFormat.XMI_ARGO && isStandalone(ent) == false) {
- // continue;
- // }
final Element cla = createEntityNode(ent);
- if (cla == null) {
+ if (cla == null)
continue;
- }
+
ownedElement.appendChild(cla);
done.add(ent);
}
- // if (fileFormat != FileFormat.XMI_STANDARD) {
- for (final Link link : classDiagram.getLinks()) {
+ for (final Link link : classDiagram.getLinks())
addLink(link);
- }
- // }
+
}
- // private boolean isStandalone(IEntity ent) {
- // for (final Link link : classDiagram.getLinks()) {
- // if (link.getEntity1() == ent || link.getEntity2() == ent) {
- // return false;
- // }
- // }
- // return true;
- // }
-
private void addLink(Link link) {
- final String assId = "ass" + UniqueSequence.getValue();
+ if (link.isHidden() || link.isInvis())
+ return;
+
+ final String assId = "ass" + classDiagram.getUniqueSequence();
if (link.getType().getDecor1() == LinkDecor.EXTENDS || link.getType().getDecor2() == LinkDecor.EXTENDS) {
addExtension(link, assId);
return;
@@ -88,60 +76,43 @@ public class XmiClassDiagramStar extends XmiClassDiagramAbstract implements IXmi
final Element association = document.createElement("UML:Association");
association.setAttribute("xmi.id", assId);
association.setAttribute("namespace", CucaDiagramXmiMaker.getModel(classDiagram));
- if (Display.isNull(link.getLabel()) == false) {
+ if (Display.isNull(link.getLabel()) == false)
association.setAttribute("name", forXMI(link.getLabel()));
- }
final Element connection = document.createElement("UML:Association.connection");
final Element end1 = document.createElement("UML:AssociationEnd");
- end1.setAttribute("xmi.id", "end" + UniqueSequence.getValue());
+ end1.setAttribute("xmi.id", "end" + classDiagram.getUniqueSequence());
end1.setAttribute("association", assId);
end1.setAttribute("type", link.getEntity1().getUid());
- if (link.getQualifier1() != null) {
+ if (link.getQualifier1() != null)
end1.setAttribute("name", forXMI(link.getQualifier1()));
- }
+
final Element endparticipant1 = document.createElement("UML:AssociationEnd.participant");
- // if (fileFormat == FileFormat.XMI_ARGO) {
- // if (done.contains(link.getEntity1())) {
- // endparticipant1.appendChild(createEntityNodeRef(link.getEntity1()));
- // } else {
- // endparticipant1.appendChild(createEntityNode(link.getEntity1()));
- // done.add(link.getEntity1());
- // }
- // } else if (fileFormat == FileFormat.XMI_STAR) {
- if (link.getType().getDecor2() == LinkDecor.COMPOSITION) {
+
+ if (link.getType().getDecor2() == LinkDecor.COMPOSITION)
end1.setAttribute("aggregation", "composite");
- }
- if (link.getType().getDecor2() == LinkDecor.AGREGATION) {
+
+ if (link.getType().getDecor2() == LinkDecor.AGREGATION)
end1.setAttribute("aggregation", "aggregate");
- }
- // }
+
end1.appendChild(endparticipant1);
connection.appendChild(end1);
final Element end2 = document.createElement("UML:AssociationEnd");
- end2.setAttribute("xmi.id", "end" + UniqueSequence.getValue());
+ end2.setAttribute("xmi.id", "end" + classDiagram.getUniqueSequence());
end2.setAttribute("association", assId);
end2.setAttribute("type", link.getEntity2().getUid());
- if (link.getQualifier2() != null) {
+ if (link.getQualifier2() != null)
end2.setAttribute("name", forXMI(link.getQualifier2()));
- }
+
final Element endparticipant2 = document.createElement("UML:AssociationEnd.participant");
- // if (fileFormat == FileFormat.XMI_ARGO) {
- // if (done.contains(link.getEntity2())) {
- // endparticipant2.appendChild(createEntityNodeRef(link.getEntity2()));
- // } else {
- // endparticipant2.appendChild(createEntityNode(link.getEntity2()));
- // done.add(link.getEntity2());
- // }
- // } else if (fileFormat == FileFormat.XMI_STAR) {
- if (link.getType().getDecor1() == LinkDecor.COMPOSITION) {
+
+ if (link.getType().getDecor1() == LinkDecor.COMPOSITION)
end2.setAttribute("aggregation", "composite");
- }
- if (link.getType().getDecor1() == LinkDecor.AGREGATION) {
+
+ if (link.getType().getDecor1() == LinkDecor.AGREGATION)
end2.setAttribute("aggregation", "aggregate");
- }
- // }
+
end2.appendChild(endparticipant2);
connection.appendChild(end2);
@@ -155,9 +126,9 @@ public class XmiClassDiagramStar extends XmiClassDiagramAbstract implements IXmi
final Element association = document.createElement("UML:Generalization");
association.setAttribute("xmi.id", assId);
association.setAttribute("namespace", CucaDiagramXmiMaker.getModel(classDiagram));
- if (link.getLabel() != null) {
+ if (link.getLabel() != null)
association.setAttribute("name", forXMI(link.getLabel()));
- }
+
if (link.getType().getDecor1() == LinkDecor.EXTENDS) {
association.setAttribute("child", link.getEntity1().getUid());
association.setAttribute("parent", link.getEntity2().getUid());
diff --git a/src/net/sourceforge/plantuml/xmi/XmiDescriptionDiagram.java b/src/net/sourceforge/plantuml/xmi/XmiDescriptionDiagram.java
index 79e01439f..d5f7d16a3 100644
--- a/src/net/sourceforge/plantuml/xmi/XmiDescriptionDiagram.java
+++ b/src/net/sourceforge/plantuml/xmi/XmiDescriptionDiagram.java
@@ -59,11 +59,10 @@ import net.sourceforge.plantuml.cucadiagram.IGroup;
import net.sourceforge.plantuml.cucadiagram.Link;
import net.sourceforge.plantuml.cucadiagram.LinkDecor;
import net.sourceforge.plantuml.descdiagram.DescriptionDiagram;
-import net.sourceforge.plantuml.utils.UniqueSequence;
import net.sourceforge.plantuml.version.Version;
import net.sourceforge.plantuml.xml.XmlFactories;
-public class XmiDescriptionDiagram implements IXmiClassDiagram {
+public class XmiDescriptionDiagram implements XmlDiagramTransformer {
private final DescriptionDiagram diagram;
private final Document document;
@@ -98,43 +97,37 @@ public class XmiDescriptionDiagram implements IXmiClassDiagram {
// isLeaf="false" isAbstract="false">
final Element model = document.createElement("UML:Model");
model.setAttribute("xmi.id", CucaDiagramXmiMaker.getModel(diagram));
- model.setAttribute("name", "PlantUML "+Version.versionString());
+ model.setAttribute("name", "PlantUML " + Version.versionString());
content.appendChild(model);
//
this.ownedElement = document.createElement("UML:Namespace.ownedElement");
model.appendChild(ownedElement);
- for (final IGroup gr : diagram.getGroups(false)) {
- if (gr.getParentContainer() instanceof GroupRoot) {
- addState(gr, ownedElement);
- }
- }
+ for (final IGroup gr : diagram.getGroups(false))
+ if (gr.getParentContainer() instanceof GroupRoot)
+ addElement(gr, ownedElement);
- for (final IEntity ent : diagram.getLeafsvalues()) {
- if (ent.getParentContainer() instanceof GroupRoot) {
- addState(ent, ownedElement);
- }
- }
+ for (final IEntity ent : diagram.getLeafsvalues())
+ if (ent.getParentContainer() instanceof GroupRoot)
+ addElement(ent, ownedElement);
- for (final Link link : diagram.getLinks()) {
+ for (final Link link : diagram.getLinks())
addLink(link);
- }
+
}
- private void addState(final IEntity tobeAdded, Element container) {
- final Element elementState = createEntityNode(tobeAdded);
- container.appendChild(elementState);
- for (final IEntity ent : diagram.getGroups(false)) {
- if (ent.getParentContainer() == tobeAdded) {
- addState(ent, elementState);
- }
- }
- for (final IEntity ent : diagram.getLeafsvalues()) {
- if (ent.getParentContainer() == tobeAdded) {
- addState(ent, elementState);
- }
- }
+ private void addElement(final IEntity tobeAdded, Element container) {
+ final Element element = createEntityNode(tobeAdded);
+ container.appendChild(element);
+ for (final IEntity ent : diagram.getGroups(false))
+ if (ent.getParentContainer() == tobeAdded)
+ addElement(ent, element);
+
+ for (final IEntity ent : diagram.getLeafsvalues())
+ if (ent.getParentContainer() == tobeAdded)
+ addElement(ent, element);
+
}
public static String forXMI(String s) {
@@ -146,50 +139,47 @@ public class XmiDescriptionDiagram implements IXmiClassDiagram {
}
private void addLink(Link link) {
- final String assId = "ass" + UniqueSequence.getValue();
+ final String assId = "ass" + diagram.getUniqueSequence();
final Element association = document.createElement("UML:Association");
association.setAttribute("xmi.id", assId);
association.setAttribute("namespace", CucaDiagramXmiMaker.getModel(diagram));
- if (Display.isNull(link.getLabel()) == false) {
+ if (Display.isNull(link.getLabel()) == false)
association.setAttribute("name", forXMI(link.getLabel()));
- }
final Element connection = document.createElement("UML:Association.connection");
final Element end1 = document.createElement("UML:AssociationEnd");
- end1.setAttribute("xmi.id", "end" + UniqueSequence.getValue());
+ end1.setAttribute("xmi.id", "end" + diagram.getUniqueSequence());
end1.setAttribute("association", assId);
end1.setAttribute("type", link.getEntity1().getUid());
- if (link.getQualifier1() != null) {
+ if (link.getQualifier1() != null)
end1.setAttribute("name", forXMI(link.getQualifier1()));
- }
+
final Element endparticipant1 = document.createElement("UML:AssociationEnd.participant");
- if (link.getType().getDecor2() == LinkDecor.COMPOSITION) {
+ if (link.getType().getDecor2() == LinkDecor.COMPOSITION)
end1.setAttribute("aggregation", "composite");
- }
- if (link.getType().getDecor2() == LinkDecor.AGREGATION) {
+
+ if (link.getType().getDecor2() == LinkDecor.AGREGATION)
end1.setAttribute("aggregation", "aggregate");
- }
- // }
+
end1.appendChild(endparticipant1);
connection.appendChild(end1);
final Element end2 = document.createElement("UML:AssociationEnd");
- end2.setAttribute("xmi.id", "end" + UniqueSequence.getValue());
+ end2.setAttribute("xmi.id", "end" + diagram.getUniqueSequence());
end2.setAttribute("association", assId);
end2.setAttribute("type", link.getEntity2().getUid());
- if (link.getQualifier2() != null) {
+ if (link.getQualifier2() != null)
end2.setAttribute("name", forXMI(link.getQualifier2()));
- }
+
final Element endparticipant2 = document.createElement("UML:AssociationEnd.participant");
- if (link.getType().getDecor1() == LinkDecor.COMPOSITION) {
+ if (link.getType().getDecor1() == LinkDecor.COMPOSITION)
end2.setAttribute("aggregation", "composite");
- }
- if (link.getType().getDecor1() == LinkDecor.AGREGATION) {
+
+ if (link.getType().getDecor1() == LinkDecor.AGREGATION)
end2.setAttribute("aggregation", "aggregate");
- }
- // }
+
end2.appendChild(endparticipant2);
connection.appendChild(end2);
@@ -232,7 +222,6 @@ public class XmiDescriptionDiagram implements IXmiClassDiagram {
final Transformer transformer = XmlFactories.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
- // transformer.setOutputProperty(OutputKeys.ENCODING, "ISO-8859-1");
transformer.setOutputProperty(OutputKeys.ENCODING, UTF_8.name());
// tf.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
transformer.transform(source, resultat);
diff --git a/src/net/sourceforge/plantuml/xmi/XmiStateDiagram.java b/src/net/sourceforge/plantuml/xmi/XmiStateDiagram.java
index 8aa054053..dd7671831 100644
--- a/src/net/sourceforge/plantuml/xmi/XmiStateDiagram.java
+++ b/src/net/sourceforge/plantuml/xmi/XmiStateDiagram.java
@@ -59,11 +59,10 @@ import net.sourceforge.plantuml.cucadiagram.IGroup;
import net.sourceforge.plantuml.cucadiagram.Link;
import net.sourceforge.plantuml.cucadiagram.LinkDecor;
import net.sourceforge.plantuml.statediagram.StateDiagram;
-import net.sourceforge.plantuml.utils.UniqueSequence;
import net.sourceforge.plantuml.version.Version;
import net.sourceforge.plantuml.xml.XmlFactories;
-public class XmiStateDiagram implements IXmiClassDiagram {
+public class XmiStateDiagram implements XmlDiagramTransformer {
private final StateDiagram diagram;
private final Document document;
@@ -146,7 +145,7 @@ public class XmiStateDiagram implements IXmiClassDiagram {
}
private void addLink(Link link) {
- final String assId = "ass" + UniqueSequence.getValue();
+ final String assId = "ass" + diagram.getUniqueSequence();
final Element association = document.createElement("UML:Association");
association.setAttribute("xmi.id", assId);
@@ -157,7 +156,7 @@ public class XmiStateDiagram implements IXmiClassDiagram {
final Element connection = document.createElement("UML:Association.connection");
final Element end1 = document.createElement("UML:AssociationEnd");
- end1.setAttribute("xmi.id", "end" + UniqueSequence.getValue());
+ end1.setAttribute("xmi.id", "end" + diagram.getUniqueSequence());
end1.setAttribute("association", assId);
end1.setAttribute("type", link.getEntity1().getUid());
if (link.getQualifier1() != null) {
@@ -176,7 +175,7 @@ public class XmiStateDiagram implements IXmiClassDiagram {
connection.appendChild(end1);
final Element end2 = document.createElement("UML:AssociationEnd");
- end2.setAttribute("xmi.id", "end" + UniqueSequence.getValue());
+ end2.setAttribute("xmi.id", "end" + diagram.getUniqueSequence());
end2.setAttribute("association", assId);
end2.setAttribute("type", link.getEntity2().getUid());
if (link.getQualifier2() != null) {
diff --git a/src/net/sourceforge/plantuml/xmi/IXmiClassDiagram.java b/src/net/sourceforge/plantuml/xmi/XmlDiagramTransformer.java
similarity index 97%
rename from src/net/sourceforge/plantuml/xmi/IXmiClassDiagram.java
rename to src/net/sourceforge/plantuml/xmi/XmlDiagramTransformer.java
index faab8ed62..0429dbcda 100644
--- a/src/net/sourceforge/plantuml/xmi/IXmiClassDiagram.java
+++ b/src/net/sourceforge/plantuml/xmi/XmlDiagramTransformer.java
@@ -40,7 +40,7 @@ import java.io.OutputStream;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
-public interface IXmiClassDiagram {
+public interface XmlDiagramTransformer {
void transformerXml(OutputStream os) throws TransformerException, ParserConfigurationException;
diff --git a/test/nonreg/graphml/GraphmlTest.java b/test/nonreg/graphml/GraphmlTest.java
new file mode 100644
index 000000000..b411ceafe
--- /dev/null
+++ b/test/nonreg/graphml/GraphmlTest.java
@@ -0,0 +1,106 @@
+package nonreg.graphml;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import net.sourceforge.plantuml.FileFormat;
+import net.sourceforge.plantuml.FileFormatOption;
+import net.sourceforge.plantuml.SourceStringReader;
+import net.sourceforge.plantuml.core.DiagramDescription;
+
+public class GraphmlTest {
+
+ private static final String TRIPLE_QUOTE = "\"\"\"";
+
+ protected String getXmlAndCheckXmlAndDescription(final String expectedDescription)
+ throws IOException, UnsupportedEncodingException {
+ final String actualResult = runPlantUML(expectedDescription);
+ final String xmlExpected = readStringFromSourceFile(getDiagramFile(), "{{{", "}}}");
+
+ // This is really a hack. Since XML generation does not guarantee the order of
+ // attributes, we make an easy to do check by sorting characters.
+ // Of course, this is really incomplete: a faulty String may match the expected
+ // result if, for example, an attribute is moved from a node to another.
+ // However, we consider that it is a good start.
+ if (sortString(actualResult).equals(sortString(xmlExpected)) == false) {
+ assertEquals(xmlExpected, actualResult, "Generated GraphML is not ok");
+ }
+
+ return actualResult;
+ }
+
+ private String sortString(String s) {
+ final Map map = new TreeMap<>();
+ for (int i = 0; i < s.length(); i++) {
+ final char ch = s.charAt(i);
+ // We ignore non writable characters
+ if (ch <= ' ')
+ continue;
+
+ AtomicInteger count = map.get(ch);
+ if (count == null)
+ map.put(ch, new AtomicInteger(1));
+ else
+ count.addAndGet(1);
+ }
+ return map.toString();
+ }
+
+ private String getLocalFolder() {
+ return "test/" + getPackageName().replace(".", "/");
+ }
+
+ private String getPackageName() {
+ return getClass().getPackage().getName();
+ }
+
+ private Path getDiagramFile() {
+ return Paths.get(getLocalFolder(), getClass().getSimpleName() + ".java");
+ }
+
+ private String runPlantUML(String expectedDescription) throws IOException, UnsupportedEncodingException {
+ final String diagramText = readStringFromSourceFile(getDiagramFile(), TRIPLE_QUOTE, TRIPLE_QUOTE);
+ final SourceStringReader ssr = new SourceStringReader(diagramText, UTF_8);
+ final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ final DiagramDescription diagramDescription = ssr.outputImage(baos, 0,
+ new FileFormatOption(FileFormat.GRAPHML));
+ assertEquals(expectedDescription, diagramDescription.getDescription(), "Bad description");
+
+ return new String(baos.toByteArray(), UTF_8);
+ }
+
+ private String readStringFromSourceFile(Path path, String startMarker, String endMarker) throws IOException {
+ assertTrue(Files.exists(path), "Cannot find " + path);
+ assertTrue(Files.isReadable(path), "Cannot read " + path);
+ final List allLines = Files.readAllLines(path, UTF_8);
+ final int first = allLines.indexOf(startMarker);
+ final int last = allLines.lastIndexOf(endMarker);
+ assertTrue(first != -1);
+ assertTrue(last != -1);
+ assertTrue(last > first);
+ return packString(allLines.subList(first + 1, last));
+ }
+
+ private String packString(Collection list) {
+ final StringBuilder sb = new StringBuilder();
+ for (String s : list) {
+ sb.append(s);
+ sb.append("\n");
+ }
+ return sb.toString();
+ }
+
+}
diff --git a/test/nonreg/graphml/component/GML0000_Test.java b/test/nonreg/graphml/component/GML0000_Test.java
new file mode 100644
index 000000000..1defb06cb
--- /dev/null
+++ b/test/nonreg/graphml/component/GML0000_Test.java
@@ -0,0 +1,44 @@
+package nonreg.graphml.component;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.io.IOException;
+
+import org.junit.jupiter.api.Test;
+
+import nonreg.graphml.GraphmlTest;
+
+/*
+
+Test diagram MUST be put between triple quotes
+
+"""
+@startuml
+component comp1
+@enduml
+"""
+
+Expected result MUST be put between triple brackets
+
+{{{
+
+
+
+
+
+}}}
+
+ */
+public class GML0000_Test extends GraphmlTest {
+
+ @Test
+ void testSimple() throws IOException {
+ final String xml = getXmlAndCheckXmlAndDescription("(1 entities)");
+
+ // Those tests are ULGY: please improve them!
+ assertTrue(xml.contains(""));
+ assertTrue(xml.contains(""));
+ }
+
+}
diff --git a/test/nonreg/graphml/component/GML0001_Test.java b/test/nonreg/graphml/component/GML0001_Test.java
new file mode 100644
index 000000000..d139f9d8c
--- /dev/null
+++ b/test/nonreg/graphml/component/GML0001_Test.java
@@ -0,0 +1,47 @@
+package nonreg.graphml.component;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.io.IOException;
+
+import org.junit.jupiter.api.Test;
+
+import nonreg.graphml.GraphmlTest;
+
+/*
+
+Test diagram MUST be put between triple quotes
+
+"""
+@startuml
+component comp1
+component comp2
+@enduml
+"""
+
+Expected result MUST be put between triple brackets
+
+{{{
+
+
+
+
+
+
+}}}
+
+ */
+public class GML0001_Test extends GraphmlTest {
+
+ @Test
+ void testSimple() throws IOException {
+ final String xml = getXmlAndCheckXmlAndDescription("(2 entities)");
+
+ // Those tests are ULGY: please improve them!
+ assertTrue(xml.contains(""));
+ assertTrue(xml.contains(""));
+ assertTrue(xml.contains(""));
+ }
+
+}
diff --git a/test/nonreg/xmi/XmiTest.java b/test/nonreg/xmi/XmiTest.java
new file mode 100644
index 000000000..8af2e0f10
--- /dev/null
+++ b/test/nonreg/xmi/XmiTest.java
@@ -0,0 +1,112 @@
+package nonreg.xmi;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import net.sourceforge.plantuml.FileFormat;
+import net.sourceforge.plantuml.FileFormatOption;
+import net.sourceforge.plantuml.SourceStringReader;
+import net.sourceforge.plantuml.core.DiagramDescription;
+
+public class XmiTest {
+
+ private static final String TRIPLE_QUOTE = "\"\"\"";
+
+ protected void checkXmlAndDescription(final String expectedDescription)
+ throws IOException, UnsupportedEncodingException {
+ final String star = runPlantUML(expectedDescription, FileFormat.XMI_STAR);
+ final String startExpected = readStringFromSourceFile(getDiagramFile(), "{{{star", "}}}star");
+
+ // This is really a hack. Since XML generation does not guarantee the order of
+ // attributes, we make an easy to do check by sorting characters.
+ // Of course, this is really incomplete: a faulty String may match the expected
+ // result if, for example, an attribute is moved from a node to another.
+ // However, we consider that it is a good start.
+ if (sortString(star).equals(sortString(startExpected)) == false) {
+ assertEquals(startExpected, star, "XmiStar: Generated GraphML is not ok");
+ }
+
+ final String argo = runPlantUML(expectedDescription, FileFormat.XMI_ARGO);
+ final String argoExpected = readStringFromSourceFile(getDiagramFile(), "{{{argo", "}}}argo");
+
+ if (sortString(argo).equals(sortString(argoExpected)) == false) {
+ assertEquals(argoExpected, argo, "XmiArgo: Generated GraphML is not ok");
+ }
+
+ }
+
+ private String sortString(String s) {
+ final Map map = new TreeMap<>();
+ for (int i = 0; i < s.length(); i++) {
+ final char ch = s.charAt(i);
+ // We ignore non writable characters
+ if (ch <= ' ')
+ continue;
+
+ AtomicInteger count = map.get(ch);
+ if (count == null)
+ map.put(ch, new AtomicInteger(1));
+ else
+ count.addAndGet(1);
+ }
+ return map.toString();
+ }
+
+ private String getLocalFolder() {
+ return "test/" + getPackageName().replace(".", "/");
+ }
+
+ private String getPackageName() {
+ return getClass().getPackage().getName();
+ }
+
+ private Path getDiagramFile() {
+ return Paths.get(getLocalFolder(), getClass().getSimpleName() + ".java");
+ }
+
+ private String runPlantUML(String expectedDescription, FileFormat format)
+ throws IOException, UnsupportedEncodingException {
+ final String diagramText = readStringFromSourceFile(getDiagramFile(), TRIPLE_QUOTE, TRIPLE_QUOTE);
+ final SourceStringReader ssr = new SourceStringReader(diagramText, UTF_8);
+ final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ final DiagramDescription diagramDescription = ssr.outputImage(baos, 0, new FileFormatOption(format));
+ assertEquals(expectedDescription, diagramDescription.getDescription(), "Bad description");
+
+ return new String(baos.toByteArray(), UTF_8);
+ }
+
+ private String readStringFromSourceFile(Path path, String startMarker, String endMarker) throws IOException {
+ assertTrue(Files.exists(path), "Cannot find " + path);
+ assertTrue(Files.isReadable(path), "Cannot read " + path);
+ final List allLines = Files.readAllLines(path, UTF_8);
+ final int first = allLines.indexOf(startMarker);
+ final int last = allLines.lastIndexOf(endMarker);
+ assertTrue(first != -1);
+ assertTrue(last != -1);
+ assertTrue(last > first);
+ return packString(allLines.subList(first + 1, last));
+ }
+
+ private String packString(Collection list) {
+ final StringBuilder sb = new StringBuilder();
+ for (String s : list) {
+ sb.append(s);
+ sb.append("\n");
+ }
+ return sb.toString();
+ }
+
+}
diff --git a/test/nonreg/xmi/clazz/XMI0000_Test.java b/test/nonreg/xmi/clazz/XMI0000_Test.java
new file mode 100644
index 000000000..ae186bcfe
--- /dev/null
+++ b/test/nonreg/xmi/clazz/XMI0000_Test.java
@@ -0,0 +1,74 @@
+package nonreg.xmi.clazz;
+
+import java.io.IOException;
+
+import org.junit.jupiter.api.Test;
+
+import nonreg.xmi.XmiTest;
+
+/*
+
+
+https://forum.plantuml.net/12644/class-access-modifiers-not-in-xmi-export
+
+Test diagram MUST be put between triple quotes
+
+"""
+@startuml
+-class foo{
+ # field1 : type
+}
+@enduml
+"""
+
+Expected result MUST be put between triple brackets
+
+{{{star
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+}}}star
+
+{{{argo
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+}}}argo
+
+ */
+public class XMI0000_Test extends XmiTest {
+
+ @Test
+ void testSimple() throws IOException {
+ checkXmlAndDescription("(1 entities)");
+ }
+
+}
diff --git a/test/nonreg/xmi/clazz/XMI0002_Test.java b/test/nonreg/xmi/clazz/XMI0002_Test.java
new file mode 100644
index 000000000..98d43ebd3
--- /dev/null
+++ b/test/nonreg/xmi/clazz/XMI0002_Test.java
@@ -0,0 +1,101 @@
+package nonreg.xmi.clazz;
+
+import java.io.IOException;
+
+import org.junit.jupiter.api.Test;
+
+import nonreg.xmi.XmiTest;
+
+/*
+
+
+https://forum.plantuml.net/12972/only-the-first-line-any-component-description-exported-file
+
+
+Test diagram MUST be put between triple quotes
+
+"""
+@startuml
+class A {
+}
+
+class B{
+}
+
+A -->B
+@enduml
+"""
+
+Expected result MUST be put between triple brackets
+
+{{{star
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+}}}star
+
+{{{argo
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+}}}argo
+
+ */
+public class XMI0002_Test extends XmiTest {
+
+ @Test
+ void testSimple() throws IOException {
+ checkXmlAndDescription("(2 entities)");
+ }
+
+}
diff --git a/test/nonreg/xmi/clazz/XMI0003_Test.java b/test/nonreg/xmi/clazz/XMI0003_Test.java
new file mode 100644
index 000000000..f1a372139
--- /dev/null
+++ b/test/nonreg/xmi/clazz/XMI0003_Test.java
@@ -0,0 +1,91 @@
+package nonreg.xmi.clazz;
+
+import java.io.IOException;
+
+import org.junit.jupiter.api.Test;
+
+import nonreg.xmi.XmiTest;
+
+/*
+
+
+
+
+Test diagram MUST be put between triple quotes
+
+"""
+@startuml
+class A {
+ {method}{abstract}{static} + method
+}
+
+abstract class B{
+}
+
+static class C{
+}
+
+@enduml
+"""
+
+Expected result MUST be put between triple brackets
+
+{{{star
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+}}}star
+
+{{{argo
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+}}}argo
+
+ */
+public class XMI0003_Test extends XmiTest {
+
+ @Test
+ void testSimple() throws IOException {
+ checkXmlAndDescription("(3 entities)");
+ }
+
+}
diff --git a/test/nonreg/xmi/component/XMI0001_Test.java b/test/nonreg/xmi/component/XMI0001_Test.java
new file mode 100644
index 000000000..3c9362385
--- /dev/null
+++ b/test/nonreg/xmi/component/XMI0001_Test.java
@@ -0,0 +1,124 @@
+package nonreg.xmi.component;
+
+import java.io.IOException;
+
+import org.junit.jupiter.api.Test;
+
+import nonreg.xmi.XmiTest;
+
+/*
+
+
+https://forum.plantuml.net/12972/only-the-first-line-any-component-description-exported-file
+
+
+Test diagram MUST be put between triple quotes
+
+"""
+@startuml
+component test
+note top of test: first line1\nsecond line2
+note bottom of test
+ first line3
+ second line4
+end note
+@enduml
+"""
+
+Expected result MUST be put between triple brackets
+
+{{{star
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+}}}star
+
+{{{argo
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+}}}argo
+
+ */
+public class XMI0001_Test extends XmiTest {
+
+ @Test
+ void testSimple() throws IOException {
+ checkXmlAndDescription("(3 entities)");
+ }
+
+}