From 4e3d8c94f6b81dd7d65821f1957721477f8f86cb Mon Sep 17 00:00:00 2001 From: Benjamin Davies Date: Sat, 26 Aug 2023 18:54:16 +1200 Subject: [PATCH 01/23] Parse Chen EER diagrams --- .../sourceforge/plantuml/PSystemBuilder.java | 3 + .../plantuml/cheneer/ChenEerDiagram.java | 93 ++++++++++++++++++ .../cheneer/ChenEerDiagramFactory.java | 76 +++++++++++++++ .../command/CommandAssociateRelationship.java | 76 +++++++++++++++ .../command/CommandCreateAttribute.java | 96 +++++++++++++++++++ .../cheneer/command/CommandCreateEntity.java | 74 ++++++++++++++ .../command/CommandCreateRelationship.java | 74 ++++++++++++++ .../cheneer/command/CommandEndGroup.java | 65 +++++++++++++ .../plantuml/core/DiagramType.java | 5 +- .../plantuml/skin/UmlDiagramType.java | 2 +- 10 files changed, 562 insertions(+), 2 deletions(-) create mode 100644 src/net/sourceforge/plantuml/cheneer/ChenEerDiagram.java create mode 100644 src/net/sourceforge/plantuml/cheneer/ChenEerDiagramFactory.java create mode 100644 src/net/sourceforge/plantuml/cheneer/command/CommandAssociateRelationship.java create mode 100644 src/net/sourceforge/plantuml/cheneer/command/CommandCreateAttribute.java create mode 100644 src/net/sourceforge/plantuml/cheneer/command/CommandCreateEntity.java create mode 100644 src/net/sourceforge/plantuml/cheneer/command/CommandCreateRelationship.java create mode 100644 src/net/sourceforge/plantuml/cheneer/command/CommandEndGroup.java diff --git a/src/net/sourceforge/plantuml/PSystemBuilder.java b/src/net/sourceforge/plantuml/PSystemBuilder.java index 0a58f6492..8faf8df5d 100644 --- a/src/net/sourceforge/plantuml/PSystemBuilder.java +++ b/src/net/sourceforge/plantuml/PSystemBuilder.java @@ -48,6 +48,7 @@ import net.sourceforge.plantuml.activitydiagram3.ActivityDiagramFactory3; import net.sourceforge.plantuml.api.PSystemFactory; import net.sourceforge.plantuml.board.BoardDiagramFactory; import net.sourceforge.plantuml.bpm.BpmDiagramFactory; +import net.sourceforge.plantuml.cheneer.ChenEerDiagramFactory; import net.sourceforge.plantuml.classdiagram.ClassDiagramFactory; import net.sourceforge.plantuml.core.Diagram; import net.sourceforge.plantuml.core.DiagramType; @@ -258,6 +259,8 @@ public class PSystemBuilder { factories.add(new HclDiagramFactory()); factories.add(new PSystemEbnfFactory()); factories.add(new PSystemRegexFactory()); + + factories.add(new ChenEerDiagramFactory()); } private boolean isOk(Diagram ps) { diff --git a/src/net/sourceforge/plantuml/cheneer/ChenEerDiagram.java b/src/net/sourceforge/plantuml/cheneer/ChenEerDiagram.java new file mode 100644 index 000000000..f307b952d --- /dev/null +++ b/src/net/sourceforge/plantuml/cheneer/ChenEerDiagram.java @@ -0,0 +1,93 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2024, Arnaud Roques + * + * Project Info: https://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * https://plantuml.com/patreon (only 1$ per month!) + * https://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.cheneer; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Stack; + +import net.sourceforge.plantuml.FileFormatOption; +import net.sourceforge.plantuml.TitledDiagram; +import net.sourceforge.plantuml.abel.Entity; +import net.sourceforge.plantuml.core.DiagramDescription; +import net.sourceforge.plantuml.core.ImageData; +import net.sourceforge.plantuml.core.UmlSource; +import net.sourceforge.plantuml.klimt.drawing.UGraphic; +import net.sourceforge.plantuml.klimt.font.StringBounder; +import net.sourceforge.plantuml.klimt.geom.XDimension2D; +import net.sourceforge.plantuml.klimt.shape.AbstractTextBlock; +import net.sourceforge.plantuml.klimt.shape.TextBlock; +import net.sourceforge.plantuml.klimt.shape.TextBlockUtils; +import net.sourceforge.plantuml.skin.UmlDiagramType; + +public class ChenEerDiagram extends TitledDiagram { + + public ChenEerDiagram(UmlSource source, Map skinParam) { + super(source, UmlDiagramType.CHEN_EER, skinParam); + // TODO + } + + @Override + public DiagramDescription getDescription() { + return new DiagramDescription("(Chen EER)"); + } + + @Override + protected ImageData exportDiagramNow(OutputStream os, int index, FileFormatOption fileFormatOption) + throws IOException { + return createImageBuilder(fileFormatOption).drawable(getTextBlock()).write(os); + } + + private void drawInternal(UGraphic ug) { + // TODO + } + + @Override + protected TextBlock getTextBlock() { + return new AbstractTextBlock() { + public void drawU(UGraphic ug) { + drawInternal(ug); + } + + public XDimension2D calculateDimension(StringBounder stringBounder) { + return TextBlockUtils.getMinMax(getTextBlock(), stringBounder, true).getDimension(); + } + }; + } + +} diff --git a/src/net/sourceforge/plantuml/cheneer/ChenEerDiagramFactory.java b/src/net/sourceforge/plantuml/cheneer/ChenEerDiagramFactory.java new file mode 100644 index 000000000..5c23db469 --- /dev/null +++ b/src/net/sourceforge/plantuml/cheneer/ChenEerDiagramFactory.java @@ -0,0 +1,76 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2024, Arnaud Roques + * + * Project Info: https://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * https://plantuml.com/patreon (only 1$ per month!) + * https://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.cheneer; + +import java.util.List; +import java.util.Map; + +import net.sourceforge.plantuml.AbstractPSystem; +import net.sourceforge.plantuml.cheneer.command.CommandAssociateRelationship; +import net.sourceforge.plantuml.cheneer.command.CommandCreateAttribute; +import net.sourceforge.plantuml.cheneer.command.CommandCreateEntity; +import net.sourceforge.plantuml.cheneer.command.CommandCreateRelationship; +import net.sourceforge.plantuml.cheneer.command.CommandEndGroup; +import net.sourceforge.plantuml.command.Command; +import net.sourceforge.plantuml.command.CommonCommands; +import net.sourceforge.plantuml.command.PSystemCommandFactory; +import net.sourceforge.plantuml.core.DiagramType; +import net.sourceforge.plantuml.core.UmlSource; + +public class ChenEerDiagramFactory extends PSystemCommandFactory { + + public ChenEerDiagramFactory() { + super(DiagramType.CHEN_EER); + } + + @Override + protected void initCommandsList(List cmds) { + cmds.add(new CommandCreateEntity()); + cmds.add(new CommandCreateAttribute()); + cmds.add(new CommandCreateRelationship()); + cmds.add(new CommandAssociateRelationship()); + cmds.add(new CommandEndGroup()); + + CommonCommands.addTitleCommands(cmds); + CommonCommands.addCommonCommands2(cmds); + } + + @Override + public AbstractPSystem createEmptyDiagram(UmlSource source, Map skinParam) { + return new ChenEerDiagram(source, skinParam); + } + +} diff --git a/src/net/sourceforge/plantuml/cheneer/command/CommandAssociateRelationship.java b/src/net/sourceforge/plantuml/cheneer/command/CommandAssociateRelationship.java new file mode 100644 index 000000000..01d2b1e24 --- /dev/null +++ b/src/net/sourceforge/plantuml/cheneer/command/CommandAssociateRelationship.java @@ -0,0 +1,76 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2024, Arnaud Roques + * + * Project Info: https://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * https://plantuml.com/patreon (only 1$ per month!) + * https://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.cheneer.command; + +import net.sourceforge.plantuml.cheneer.ChenEerDiagram; +import net.sourceforge.plantuml.command.CommandExecutionResult; +import net.sourceforge.plantuml.command.SingleLineCommand2; +import net.sourceforge.plantuml.klimt.color.NoSuchColorException; +import net.sourceforge.plantuml.regex.IRegex; +import net.sourceforge.plantuml.regex.RegexConcat; +import net.sourceforge.plantuml.regex.RegexLeaf; +import net.sourceforge.plantuml.regex.RegexOptional; +import net.sourceforge.plantuml.regex.RegexResult; +import net.sourceforge.plantuml.utils.LineLocation; + +public class CommandAssociateRelationship extends SingleLineCommand2 { + + public CommandAssociateRelationship() { + super(getRegexConcat()); + } + + private static IRegex getRegexConcat() { + return RegexConcat.build(CommandCreateEntity.class.getName(), RegexLeaf.start(), // + RegexLeaf.spaceZeroOrMore(), // + new RegexLeaf("PARTICIPATION", "([-=])"), // + new RegexOptional( // + new RegexLeaf("CARDINALITY", "(\\w+|\\(\\w+,[%s]*\\w+\\))")), // + RegexLeaf.spaceOneOrMore(), // + new RegexLeaf("NAME", "([\\w-]+)"), // + RegexLeaf.end()); + } + + @Override + protected CommandExecutionResult executeArg(ChenEerDiagram system, LineLocation location, RegexResult arg) + throws NoSuchColorException { + final String name = arg.get("NAME", 0); + + System.out.println("- " + name); + + return CommandExecutionResult.ok(); + } + +} diff --git a/src/net/sourceforge/plantuml/cheneer/command/CommandCreateAttribute.java b/src/net/sourceforge/plantuml/cheneer/command/CommandCreateAttribute.java new file mode 100644 index 000000000..68b6dff5e --- /dev/null +++ b/src/net/sourceforge/plantuml/cheneer/command/CommandCreateAttribute.java @@ -0,0 +1,96 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2024, Arnaud Roques + * + * Project Info: https://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * https://plantuml.com/patreon (only 1$ per month!) + * https://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.cheneer.command; + +import net.sourceforge.plantuml.cheneer.ChenEerDiagram; +import net.sourceforge.plantuml.command.CommandExecutionResult; +import net.sourceforge.plantuml.command.SingleLineCommand2; +import net.sourceforge.plantuml.klimt.color.NoSuchColorException; +import net.sourceforge.plantuml.regex.IRegex; +import net.sourceforge.plantuml.regex.RegexConcat; +import net.sourceforge.plantuml.regex.RegexLeaf; +import net.sourceforge.plantuml.regex.RegexOptional; +import net.sourceforge.plantuml.regex.RegexResult; +import net.sourceforge.plantuml.utils.LineLocation; + +public class CommandCreateAttribute extends SingleLineCommand2 { + + public CommandCreateAttribute() { + super(getRegexConcat()); + } + + private static IRegex getRegexConcat() { + return RegexConcat.build(CommandCreateEntity.class.getName(), RegexLeaf.start(), // + RegexLeaf.spaceZeroOrMore(), + new RegexOptional( // + new RegexConcat( // + new RegexLeaf("MULTI", "multi"), // + RegexLeaf.spaceOneOrMore())), // + new RegexOptional( // + new RegexConcat( // + new RegexLeaf("DERIVED", "derived"), // + RegexLeaf.spaceOneOrMore())), // + new RegexOptional( // + new RegexConcat( // + new RegexOptional( // + new RegexConcat( // + new RegexLeaf("PARTIAL", "partial"), // + RegexLeaf.spaceOneOrMore())), + new RegexLeaf("KEY", "key"), // + RegexLeaf.spaceOneOrMore())), // + new RegexOptional( // + new RegexConcat( // + new RegexLeaf("attr(:?ibute)?"), // + RegexLeaf.spaceOneOrMore())), // + new RegexLeaf("NAME", "(\\w+)"), // + new RegexOptional(// + new RegexConcat( // + RegexLeaf.spaceZeroOrMore(), // + new RegexLeaf("COMPOSITE", "\\{"))), // + RegexLeaf.end()); + } + + @Override + protected CommandExecutionResult executeArg(ChenEerDiagram system, LineLocation location, RegexResult arg) + throws NoSuchColorException { + final String name = arg.get("NAME", 0); + + System.out.println("attribute " + name); + + return CommandExecutionResult.ok(); + } + +} diff --git a/src/net/sourceforge/plantuml/cheneer/command/CommandCreateEntity.java b/src/net/sourceforge/plantuml/cheneer/command/CommandCreateEntity.java new file mode 100644 index 000000000..52ca57e76 --- /dev/null +++ b/src/net/sourceforge/plantuml/cheneer/command/CommandCreateEntity.java @@ -0,0 +1,74 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2024, Arnaud Roques + * + * Project Info: https://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * https://plantuml.com/patreon (only 1$ per month!) + * https://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.cheneer.command; + +import net.sourceforge.plantuml.cheneer.ChenEerDiagram; +import net.sourceforge.plantuml.command.CommandExecutionResult; +import net.sourceforge.plantuml.command.SingleLineCommand2; +import net.sourceforge.plantuml.klimt.color.NoSuchColorException; +import net.sourceforge.plantuml.regex.IRegex; +import net.sourceforge.plantuml.regex.RegexConcat; +import net.sourceforge.plantuml.regex.RegexLeaf; +import net.sourceforge.plantuml.regex.RegexResult; +import net.sourceforge.plantuml.utils.LineLocation; + +public class CommandCreateEntity extends SingleLineCommand2 { + + public CommandCreateEntity() { + super(getRegexConcat()); + } + + private static IRegex getRegexConcat() { + return RegexConcat.build(CommandCreateEntity.class.getName(), RegexLeaf.start(), // + new RegexLeaf("entity"), // + RegexLeaf.spaceOneOrMore(), // + new RegexLeaf("NAME", "(\\w+)"), // + RegexLeaf.spaceZeroOrMore(), // + new RegexLeaf("\\{"), // + RegexLeaf.end()); + } + + @Override + protected CommandExecutionResult executeArg(ChenEerDiagram system, LineLocation location, RegexResult arg) + throws NoSuchColorException { + final String name = arg.get("NAME", 0); + + System.out.println("entity " + name); + + return CommandExecutionResult.ok(); + } + +} diff --git a/src/net/sourceforge/plantuml/cheneer/command/CommandCreateRelationship.java b/src/net/sourceforge/plantuml/cheneer/command/CommandCreateRelationship.java new file mode 100644 index 000000000..bd1c219ec --- /dev/null +++ b/src/net/sourceforge/plantuml/cheneer/command/CommandCreateRelationship.java @@ -0,0 +1,74 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2024, Arnaud Roques + * + * Project Info: https://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * https://plantuml.com/patreon (only 1$ per month!) + * https://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.cheneer.command; + +import net.sourceforge.plantuml.cheneer.ChenEerDiagram; +import net.sourceforge.plantuml.command.CommandExecutionResult; +import net.sourceforge.plantuml.command.SingleLineCommand2; +import net.sourceforge.plantuml.klimt.color.NoSuchColorException; +import net.sourceforge.plantuml.regex.IRegex; +import net.sourceforge.plantuml.regex.RegexConcat; +import net.sourceforge.plantuml.regex.RegexLeaf; +import net.sourceforge.plantuml.regex.RegexResult; +import net.sourceforge.plantuml.utils.LineLocation; + +public class CommandCreateRelationship extends SingleLineCommand2 { + + public CommandCreateRelationship() { + super(getRegexConcat()); + } + + private static IRegex getRegexConcat() { + return RegexConcat.build(CommandCreateEntity.class.getName(), RegexLeaf.start(), // + new RegexLeaf("relationship"), // + RegexLeaf.spaceOneOrMore(), // + new RegexLeaf("NAME", "(\\w+)"), // + RegexLeaf.spaceZeroOrMore(), // + new RegexLeaf("\\{"), // + RegexLeaf.end()); + } + + @Override + protected CommandExecutionResult executeArg(ChenEerDiagram system, LineLocation location, RegexResult arg) + throws NoSuchColorException { + final String name = arg.get("NAME", 0); + + System.out.println("relationship " + name); + + return CommandExecutionResult.ok(); + } + +} diff --git a/src/net/sourceforge/plantuml/cheneer/command/CommandEndGroup.java b/src/net/sourceforge/plantuml/cheneer/command/CommandEndGroup.java new file mode 100644 index 000000000..7eaada17c --- /dev/null +++ b/src/net/sourceforge/plantuml/cheneer/command/CommandEndGroup.java @@ -0,0 +1,65 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2024, Arnaud Roques + * + * Project Info: https://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * https://plantuml.com/patreon (only 1$ per month!) + * https://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.cheneer.command; + +import net.sourceforge.plantuml.cheneer.ChenEerDiagram; +import net.sourceforge.plantuml.command.CommandExecutionResult; +import net.sourceforge.plantuml.command.SingleLineCommand2; +import net.sourceforge.plantuml.regex.IRegex; +import net.sourceforge.plantuml.regex.RegexConcat; +import net.sourceforge.plantuml.regex.RegexLeaf; +import net.sourceforge.plantuml.regex.RegexResult; +import net.sourceforge.plantuml.utils.LineLocation; + +public class CommandEndGroup extends SingleLineCommand2 { + + public CommandEndGroup() { + super(getRegexConcat()); + } + + static IRegex getRegexConcat() { + return RegexConcat.build(CommandEndGroup.class.getName(), RegexLeaf.start(), // + new RegexLeaf("\\}"), // + RegexLeaf.end()); // + } + + @Override + protected CommandExecutionResult executeArg(ChenEerDiagram diagram, LineLocation location, RegexResult arg) { + // TODO + return CommandExecutionResult.ok(); + } + +} diff --git a/src/net/sourceforge/plantuml/core/DiagramType.java b/src/net/sourceforge/plantuml/core/DiagramType.java index 2b0e4a4e7..463f70b28 100644 --- a/src/net/sourceforge/plantuml/core/DiagramType.java +++ b/src/net/sourceforge/plantuml/core/DiagramType.java @@ -40,7 +40,7 @@ import net.sourceforge.plantuml.utils.StartUtils; public enum DiagramType { // ::remove folder when __HAXE__ UML, BPM, DITAA, DOT, PROJECT, JCCKIT, SALT, FLOW, CREOLE, JUNGLE, CUTE, MATH, LATEX, DEFINITION, GANTT, NW, - MINDMAP, WBS, WIRE, JSON, GIT, BOARD, YAML, HCL, EBNF, REGEX, FILES, UNKNOWN; + MINDMAP, WBS, WIRE, JSON, GIT, BOARD, YAML, HCL, EBNF, REGEX, FILES, CHEN_EER, UNKNOWN; static public DiagramType getTypeFromArobaseStart(String s) { s = s.toLowerCase(); @@ -128,6 +128,9 @@ public enum DiagramType { if (StartUtils.startsWithSymbolAnd("startfiles", s)) return FILES; + if (StartUtils.startsWithSymbolAnd("startchen", s)) + return CHEN_EER; + return UNKNOWN; } } diff --git a/src/net/sourceforge/plantuml/skin/UmlDiagramType.java b/src/net/sourceforge/plantuml/skin/UmlDiagramType.java index 3beaf0691..f30c09913 100644 --- a/src/net/sourceforge/plantuml/skin/UmlDiagramType.java +++ b/src/net/sourceforge/plantuml/skin/UmlDiagramType.java @@ -39,7 +39,7 @@ import net.sourceforge.plantuml.style.SName; public enum UmlDiagramType { SEQUENCE, STATE, CLASS, OBJECT, ACTIVITY, DESCRIPTION, COMPOSITE, FLOW, TIMING, BPM, NWDIAG, MINDMAP, WBS, WIRE, - HELP, GANTT, SALT, JSON, GIT, BOARD, YAML, HCL, EBNF, REGEX, FILES; + HELP, GANTT, SALT, JSON, GIT, BOARD, YAML, HCL, EBNF, REGEX, FILES, CHEN_EER; public SName getStyleName() { if (this == SEQUENCE) From 07b25de38a98411f5ddb5dd8eaacaec07a431a95 Mon Sep 17 00:00:00 2001 From: Benjamin Davies Date: Sat, 26 Aug 2023 23:02:11 +1200 Subject: [PATCH 02/23] Add entities, attributes and relations to graph --- .../plantuml/cheneer/ChenEerDiagram.java | 51 ++++++++----------- .../command/CommandCreateAttribute.java | 25 +++++++-- .../cheneer/command/CommandCreateEntity.java | 22 ++++++-- .../command/CommandCreateRelationship.java | 22 ++++++-- .../cheneer/command/CommandEndGroup.java | 4 +- 5 files changed, 85 insertions(+), 39 deletions(-) diff --git a/src/net/sourceforge/plantuml/cheneer/ChenEerDiagram.java b/src/net/sourceforge/plantuml/cheneer/ChenEerDiagram.java index f307b952d..aa1e843cc 100644 --- a/src/net/sourceforge/plantuml/cheneer/ChenEerDiagram.java +++ b/src/net/sourceforge/plantuml/cheneer/ChenEerDiagram.java @@ -34,32 +34,21 @@ */ package net.sourceforge.plantuml.cheneer; -import java.io.IOException; -import java.io.OutputStream; -import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Stack; -import net.sourceforge.plantuml.FileFormatOption; -import net.sourceforge.plantuml.TitledDiagram; +import net.atmp.CucaDiagram; import net.sourceforge.plantuml.abel.Entity; import net.sourceforge.plantuml.core.DiagramDescription; -import net.sourceforge.plantuml.core.ImageData; import net.sourceforge.plantuml.core.UmlSource; -import net.sourceforge.plantuml.klimt.drawing.UGraphic; -import net.sourceforge.plantuml.klimt.font.StringBounder; -import net.sourceforge.plantuml.klimt.geom.XDimension2D; -import net.sourceforge.plantuml.klimt.shape.AbstractTextBlock; -import net.sourceforge.plantuml.klimt.shape.TextBlock; -import net.sourceforge.plantuml.klimt.shape.TextBlockUtils; import net.sourceforge.plantuml.skin.UmlDiagramType; -public class ChenEerDiagram extends TitledDiagram { +public class ChenEerDiagram extends CucaDiagram { public ChenEerDiagram(UmlSource source, Map skinParam) { super(source, UmlDiagramType.CHEN_EER, skinParam); - // TODO } @Override @@ -68,26 +57,30 @@ public class ChenEerDiagram extends TitledDiagram { } @Override - protected ImageData exportDiagramNow(OutputStream os, int index, FileFormatOption fileFormatOption) - throws IOException { - return createImageBuilder(fileFormatOption).drawable(getTextBlock()).write(os); + protected final List getDotStrings() { + return Arrays.asList("nodesep=.20;", "ranksep=0.4;", "edge [fontsize=11,labelfontsize=11];", + "node [fontsize=11];"); } - private void drawInternal(UGraphic ug) { - // TODO + private final Stack ownerStack = new Stack(); + + public void pushOwner(Entity group) { + ownerStack.push(group); } - @Override - protected TextBlock getTextBlock() { - return new AbstractTextBlock() { - public void drawU(UGraphic ug) { - drawInternal(ug); - } + public boolean popOwner() { + if (ownerStack.isEmpty()) { + return false; + } + ownerStack.pop(); + return true; + } - public XDimension2D calculateDimension(StringBounder stringBounder) { - return TextBlockUtils.getMinMax(getTextBlock(), stringBounder, true).getDimension(); - } - }; + public Entity peekOwner() { + if (ownerStack.isEmpty()) { + return null; + } + return ownerStack.peek(); } } diff --git a/src/net/sourceforge/plantuml/cheneer/command/CommandCreateAttribute.java b/src/net/sourceforge/plantuml/cheneer/command/CommandCreateAttribute.java index 68b6dff5e..6db4cb0bb 100644 --- a/src/net/sourceforge/plantuml/cheneer/command/CommandCreateAttribute.java +++ b/src/net/sourceforge/plantuml/cheneer/command/CommandCreateAttribute.java @@ -35,10 +35,14 @@ */ package net.sourceforge.plantuml.cheneer.command; +import net.sourceforge.plantuml.abel.Entity; +import net.sourceforge.plantuml.abel.LeafType; import net.sourceforge.plantuml.cheneer.ChenEerDiagram; import net.sourceforge.plantuml.command.CommandExecutionResult; import net.sourceforge.plantuml.command.SingleLineCommand2; import net.sourceforge.plantuml.klimt.color.NoSuchColorException; +import net.sourceforge.plantuml.klimt.creole.Display; +import net.sourceforge.plantuml.plasma.Quark; import net.sourceforge.plantuml.regex.IRegex; import net.sourceforge.plantuml.regex.RegexConcat; import net.sourceforge.plantuml.regex.RegexLeaf; @@ -84,11 +88,26 @@ public class CommandCreateAttribute extends SingleLineCommand2 { } @Override - protected CommandExecutionResult executeArg(ChenEerDiagram system, LineLocation location, RegexResult arg) + protected CommandExecutionResult executeArg(ChenEerDiagram diagram, LineLocation location, RegexResult arg) throws NoSuchColorException { - final String name = arg.get("NAME", 0); + final LeafType type = LeafType.OBJECT; + final String name = diagram.cleanId(arg.get("NAME", 0)); + final boolean composite = arg.get("COMPOSITE") != null; - System.out.println("attribute " + name); + final Quark quark = diagram.quarkInContext(true, name); + Entity entity = quark.getData(); + + if (entity == null) { + Display display = Display.getWithNewlines(name); + entity = diagram.reallyCreateLeaf(quark, display, type, null); + } else { + if (entity.muteToType(type, null) == false) + return CommandExecutionResult.error("Bad name"); + } + + if (composite) { + diagram.pushOwner(entity); + } return CommandExecutionResult.ok(); } diff --git a/src/net/sourceforge/plantuml/cheneer/command/CommandCreateEntity.java b/src/net/sourceforge/plantuml/cheneer/command/CommandCreateEntity.java index 52ca57e76..011da23a1 100644 --- a/src/net/sourceforge/plantuml/cheneer/command/CommandCreateEntity.java +++ b/src/net/sourceforge/plantuml/cheneer/command/CommandCreateEntity.java @@ -35,10 +35,14 @@ */ package net.sourceforge.plantuml.cheneer.command; +import net.sourceforge.plantuml.abel.Entity; +import net.sourceforge.plantuml.abel.LeafType; import net.sourceforge.plantuml.cheneer.ChenEerDiagram; import net.sourceforge.plantuml.command.CommandExecutionResult; import net.sourceforge.plantuml.command.SingleLineCommand2; import net.sourceforge.plantuml.klimt.color.NoSuchColorException; +import net.sourceforge.plantuml.klimt.creole.Display; +import net.sourceforge.plantuml.plasma.Quark; import net.sourceforge.plantuml.regex.IRegex; import net.sourceforge.plantuml.regex.RegexConcat; import net.sourceforge.plantuml.regex.RegexLeaf; @@ -62,11 +66,23 @@ public class CommandCreateEntity extends SingleLineCommand2 { } @Override - protected CommandExecutionResult executeArg(ChenEerDiagram system, LineLocation location, RegexResult arg) + protected CommandExecutionResult executeArg(ChenEerDiagram diagram, LineLocation location, RegexResult arg) throws NoSuchColorException { - final String name = arg.get("NAME", 0); + final LeafType type = LeafType.OBJECT; + final String name = diagram.cleanId(arg.get("NAME", 0)); - System.out.println("entity " + name); + final Quark quark = diagram.quarkInContext(true, name); + Entity entity = quark.getData(); + + if (entity == null) { + Display display = Display.getWithNewlines(name); + entity = diagram.reallyCreateLeaf(quark, display, type, null); + } else { + if (entity.muteToType(type, null) == false) + return CommandExecutionResult.error("Bad name"); + } + + diagram.pushOwner(entity); return CommandExecutionResult.ok(); } diff --git a/src/net/sourceforge/plantuml/cheneer/command/CommandCreateRelationship.java b/src/net/sourceforge/plantuml/cheneer/command/CommandCreateRelationship.java index bd1c219ec..84c378085 100644 --- a/src/net/sourceforge/plantuml/cheneer/command/CommandCreateRelationship.java +++ b/src/net/sourceforge/plantuml/cheneer/command/CommandCreateRelationship.java @@ -35,10 +35,14 @@ */ package net.sourceforge.plantuml.cheneer.command; +import net.sourceforge.plantuml.abel.Entity; +import net.sourceforge.plantuml.abel.LeafType; import net.sourceforge.plantuml.cheneer.ChenEerDiagram; import net.sourceforge.plantuml.command.CommandExecutionResult; import net.sourceforge.plantuml.command.SingleLineCommand2; import net.sourceforge.plantuml.klimt.color.NoSuchColorException; +import net.sourceforge.plantuml.klimt.creole.Display; +import net.sourceforge.plantuml.plasma.Quark; import net.sourceforge.plantuml.regex.IRegex; import net.sourceforge.plantuml.regex.RegexConcat; import net.sourceforge.plantuml.regex.RegexLeaf; @@ -62,11 +66,23 @@ public class CommandCreateRelationship extends SingleLineCommand2 quark = diagram.quarkInContext(true, name); + Entity entity = quark.getData(); + + if (entity == null) { + Display display = Display.getWithNewlines(name); + entity = diagram.reallyCreateLeaf(quark, display, type, null); + } else { + if (entity.muteToType(type, null) == false) + return CommandExecutionResult.error("Bad name"); + } + + diagram.pushOwner(entity); return CommandExecutionResult.ok(); } diff --git a/src/net/sourceforge/plantuml/cheneer/command/CommandEndGroup.java b/src/net/sourceforge/plantuml/cheneer/command/CommandEndGroup.java index 7eaada17c..37c195495 100644 --- a/src/net/sourceforge/plantuml/cheneer/command/CommandEndGroup.java +++ b/src/net/sourceforge/plantuml/cheneer/command/CommandEndGroup.java @@ -58,7 +58,9 @@ public class CommandEndGroup extends SingleLineCommand2 { @Override protected CommandExecutionResult executeArg(ChenEerDiagram diagram, LineLocation location, RegexResult arg) { - // TODO + if (!diagram.popOwner()) { + return CommandExecutionResult.error("Unbalanced brackets"); + } return CommandExecutionResult.ok(); } From d4110d5cebfeb1812411569e84cda98e1061e5d4 Mon Sep 17 00:00:00 2001 From: Benjamin Davies Date: Sun, 27 Aug 2023 00:03:40 +1200 Subject: [PATCH 03/23] Add associations between entities --- .../command/CommandAssociateRelationship.java | 29 ++++++++++++++++-- .../command/CommandCreateAttribute.java | 30 ++++++++++++++----- 2 files changed, 48 insertions(+), 11 deletions(-) diff --git a/src/net/sourceforge/plantuml/cheneer/command/CommandAssociateRelationship.java b/src/net/sourceforge/plantuml/cheneer/command/CommandAssociateRelationship.java index 01d2b1e24..9272b0d0b 100644 --- a/src/net/sourceforge/plantuml/cheneer/command/CommandAssociateRelationship.java +++ b/src/net/sourceforge/plantuml/cheneer/command/CommandAssociateRelationship.java @@ -35,10 +35,17 @@ */ package net.sourceforge.plantuml.cheneer.command; +import net.sourceforge.plantuml.abel.Entity; +import net.sourceforge.plantuml.abel.Link; +import net.sourceforge.plantuml.abel.LinkArg; import net.sourceforge.plantuml.cheneer.ChenEerDiagram; import net.sourceforge.plantuml.command.CommandExecutionResult; import net.sourceforge.plantuml.command.SingleLineCommand2; +import net.sourceforge.plantuml.decoration.LinkDecor; +import net.sourceforge.plantuml.decoration.LinkType; import net.sourceforge.plantuml.klimt.color.NoSuchColorException; +import net.sourceforge.plantuml.klimt.creole.Display; +import net.sourceforge.plantuml.plasma.Quark; import net.sourceforge.plantuml.regex.IRegex; import net.sourceforge.plantuml.regex.RegexConcat; import net.sourceforge.plantuml.regex.RegexLeaf; @@ -64,11 +71,27 @@ public class CommandAssociateRelationship extends SingleLineCommand2 entityQuark = diagram.quarkInContext(true, entityName); + final Entity entity = entityQuark.getData(); + if (entity == null) { + return CommandExecutionResult.error("No such entity: " + entityName); + } + + final LinkType linkType = new LinkType(LinkDecor.NONE, LinkDecor.NONE); + final Link link = new Link(diagram.getEntityFactory(), diagram.getCurrentStyleBuilder(), relationship, entity, + linkType, + // TODO: Cardinality + LinkArg.build(Display.NULL, 1)); + diagram.addLink(link); return CommandExecutionResult.ok(); } diff --git a/src/net/sourceforge/plantuml/cheneer/command/CommandCreateAttribute.java b/src/net/sourceforge/plantuml/cheneer/command/CommandCreateAttribute.java index 6db4cb0bb..9981fcf1e 100644 --- a/src/net/sourceforge/plantuml/cheneer/command/CommandCreateAttribute.java +++ b/src/net/sourceforge/plantuml/cheneer/command/CommandCreateAttribute.java @@ -37,9 +37,13 @@ package net.sourceforge.plantuml.cheneer.command; import net.sourceforge.plantuml.abel.Entity; import net.sourceforge.plantuml.abel.LeafType; +import net.sourceforge.plantuml.abel.Link; +import net.sourceforge.plantuml.abel.LinkArg; import net.sourceforge.plantuml.cheneer.ChenEerDiagram; import net.sourceforge.plantuml.command.CommandExecutionResult; import net.sourceforge.plantuml.command.SingleLineCommand2; +import net.sourceforge.plantuml.decoration.LinkDecor; +import net.sourceforge.plantuml.decoration.LinkType; import net.sourceforge.plantuml.klimt.color.NoSuchColorException; import net.sourceforge.plantuml.klimt.creole.Display; import net.sourceforge.plantuml.plasma.Quark; @@ -83,28 +87,38 @@ public class CommandCreateAttribute extends SingleLineCommand2 { new RegexOptional(// new RegexConcat( // RegexLeaf.spaceZeroOrMore(), // - new RegexLeaf("COMPOSITE", "\\{"))), // + new RegexLeaf("COMPOSITE", "(\\{)"))), // RegexLeaf.end()); } @Override protected CommandExecutionResult executeArg(ChenEerDiagram diagram, LineLocation location, RegexResult arg) throws NoSuchColorException { - final LeafType type = LeafType.OBJECT; + final Entity owner = diagram.peekOwner(); + if (owner == null) { + return CommandExecutionResult.error("Attribute must be inside an entity, relationship or another attribute"); + } + + final LeafType type = LeafType.USECASE; final String name = diagram.cleanId(arg.get("NAME", 0)); - final boolean composite = arg.get("COMPOSITE") != null; + final String id = owner.getName() + "/" + name; + final boolean composite = arg.get("COMPOSITE", 0) != null; + + final Quark quark = diagram.quarkInContext(true, id); - final Quark quark = diagram.quarkInContext(true, name); Entity entity = quark.getData(); - if (entity == null) { - Display display = Display.getWithNewlines(name); + final Display display = Display.getWithNewlines(name); entity = diagram.reallyCreateLeaf(quark, display, type, null); } else { - if (entity.muteToType(type, null) == false) - return CommandExecutionResult.error("Bad name"); + return CommandExecutionResult.error("Attribute already exists"); } + final LinkType linkType = new LinkType(LinkDecor.NONE, LinkDecor.NONE); + final Link link = new Link(diagram.getEntityFactory(), diagram.getCurrentStyleBuilder(), entity, owner, linkType, + LinkArg.build(Display.NULL, 1)); + diagram.addLink(link); + if (composite) { diagram.pushOwner(entity); } From c91b5e20157eb38a1f4c0fa536d1fce2309f74f8 Mon Sep 17 00:00:00 2001 From: Benjamin Davies Date: Sun, 27 Aug 2023 12:28:32 +1200 Subject: [PATCH 04/23] Fix diagram layout not working --- .../plantuml/cheneer/ChenEerDiagram.java | 18 ++---------------- .../command/CommandAssociateRelationship.java | 3 ++- .../command/CommandCreateAttribute.java | 2 +- 3 files changed, 5 insertions(+), 18 deletions(-) diff --git a/src/net/sourceforge/plantuml/cheneer/ChenEerDiagram.java b/src/net/sourceforge/plantuml/cheneer/ChenEerDiagram.java index aa1e843cc..94f447d6f 100644 --- a/src/net/sourceforge/plantuml/cheneer/ChenEerDiagram.java +++ b/src/net/sourceforge/plantuml/cheneer/ChenEerDiagram.java @@ -34,34 +34,20 @@ */ package net.sourceforge.plantuml.cheneer; -import java.util.Arrays; -import java.util.List; import java.util.Map; import java.util.Stack; -import net.atmp.CucaDiagram; import net.sourceforge.plantuml.abel.Entity; -import net.sourceforge.plantuml.core.DiagramDescription; +import net.sourceforge.plantuml.classdiagram.AbstractEntityDiagram; import net.sourceforge.plantuml.core.UmlSource; import net.sourceforge.plantuml.skin.UmlDiagramType; -public class ChenEerDiagram extends CucaDiagram { +public class ChenEerDiagram extends AbstractEntityDiagram { public ChenEerDiagram(UmlSource source, Map skinParam) { super(source, UmlDiagramType.CHEN_EER, skinParam); } - @Override - public DiagramDescription getDescription() { - return new DiagramDescription("(Chen EER)"); - } - - @Override - protected final List getDotStrings() { - return Arrays.asList("nodesep=.20;", "ranksep=0.4;", "edge [fontsize=11,labelfontsize=11];", - "node [fontsize=11];"); - } - private final Stack ownerStack = new Stack(); public void pushOwner(Entity group) { diff --git a/src/net/sourceforge/plantuml/cheneer/command/CommandAssociateRelationship.java b/src/net/sourceforge/plantuml/cheneer/command/CommandAssociateRelationship.java index 9272b0d0b..4a030d358 100644 --- a/src/net/sourceforge/plantuml/cheneer/command/CommandAssociateRelationship.java +++ b/src/net/sourceforge/plantuml/cheneer/command/CommandAssociateRelationship.java @@ -90,7 +90,8 @@ public class CommandAssociateRelationship extends SingleLineCommand2 { final LinkType linkType = new LinkType(LinkDecor.NONE, LinkDecor.NONE); final Link link = new Link(diagram.getEntityFactory(), diagram.getCurrentStyleBuilder(), entity, owner, linkType, - LinkArg.build(Display.NULL, 1)); + LinkArg.build(Display.NULL, 2)); diagram.addLink(link); if (composite) { From e26ccf756af91083b6febbbd3477741f792649f7 Mon Sep 17 00:00:00 2001 From: Benjamin Davies Date: Thu, 16 Nov 2023 09:43:54 +1300 Subject: [PATCH 05/23] Tweak Chen EER syntax to be more consistent with existing diagram types --- .../cheneer/ChenEerDiagramFactory.java | 2 +- .../command/CommandAssociateRelationship.java | 30 +++++++++++-------- .../command/CommandCreateAttribute.java | 28 +++++------------ 3 files changed, 25 insertions(+), 35 deletions(-) diff --git a/src/net/sourceforge/plantuml/cheneer/ChenEerDiagramFactory.java b/src/net/sourceforge/plantuml/cheneer/ChenEerDiagramFactory.java index 5c23db469..f7a31bc29 100644 --- a/src/net/sourceforge/plantuml/cheneer/ChenEerDiagramFactory.java +++ b/src/net/sourceforge/plantuml/cheneer/ChenEerDiagramFactory.java @@ -59,8 +59,8 @@ public class ChenEerDiagramFactory extends PSystemCommandFactory { @Override protected void initCommandsList(List cmds) { cmds.add(new CommandCreateEntity()); - cmds.add(new CommandCreateAttribute()); cmds.add(new CommandCreateRelationship()); + cmds.add(new CommandCreateAttribute()); cmds.add(new CommandAssociateRelationship()); cmds.add(new CommandEndGroup()); diff --git a/src/net/sourceforge/plantuml/cheneer/command/CommandAssociateRelationship.java b/src/net/sourceforge/plantuml/cheneer/command/CommandAssociateRelationship.java index 4a030d358..6b8362c2a 100644 --- a/src/net/sourceforge/plantuml/cheneer/command/CommandAssociateRelationship.java +++ b/src/net/sourceforge/plantuml/cheneer/command/CommandAssociateRelationship.java @@ -61,37 +61,41 @@ public class CommandAssociateRelationship extends SingleLineCommand2 quark1 = diagram.quarkInContext(true, name1); + final Entity entity1 = quark1.getData(); + if (entity1 == null) { + return CommandExecutionResult.error("No such entity: " + name1); } - final String entityName = diagram.cleanId(arg.get("NAME", 0)); - - final Quark entityQuark = diagram.quarkInContext(true, entityName); - final Entity entity = entityQuark.getData(); - if (entity == null) { - return CommandExecutionResult.error("No such entity: " + entityName); + final Quark quark2 = diagram.quarkInContext(true, name2); + final Entity entity2 = quark2.getData(); + if (entity2 == null) { + return CommandExecutionResult.error("No such entity: " + name2); } final LinkType linkType = new LinkType(LinkDecor.NONE, LinkDecor.NONE); - final Link link = new Link(diagram.getEntityFactory(), diagram.getCurrentStyleBuilder(), relationship, entity, + final Link link = new Link(diagram.getEntityFactory(), diagram.getCurrentStyleBuilder(), entity1, entity2, linkType, // TODO: Cardinality LinkArg.build(Display.NULL, 3)); - link.setPortMembers(diagram.getPortId(relationship.getName()), diagram.getPortId(entity.getName())); + link.setPortMembers(diagram.getPortId(entity1.getName()), diagram.getPortId(entity2.getName())); diagram.addLink(link); return CommandExecutionResult.ok(); diff --git a/src/net/sourceforge/plantuml/cheneer/command/CommandCreateAttribute.java b/src/net/sourceforge/plantuml/cheneer/command/CommandCreateAttribute.java index 206760d11..481ad58ae 100644 --- a/src/net/sourceforge/plantuml/cheneer/command/CommandCreateAttribute.java +++ b/src/net/sourceforge/plantuml/cheneer/command/CommandCreateAttribute.java @@ -63,27 +63,11 @@ public class CommandCreateAttribute extends SingleLineCommand2 { private static IRegex getRegexConcat() { return RegexConcat.build(CommandCreateEntity.class.getName(), RegexLeaf.start(), // RegexLeaf.spaceZeroOrMore(), - new RegexOptional( // - new RegexConcat( // - new RegexLeaf("MULTI", "multi"), // - RegexLeaf.spaceOneOrMore())), // - new RegexOptional( // - new RegexConcat( // - new RegexLeaf("DERIVED", "derived"), // - RegexLeaf.spaceOneOrMore())), // - new RegexOptional( // - new RegexConcat( // - new RegexOptional( // - new RegexConcat( // - new RegexLeaf("PARTIAL", "partial"), // - RegexLeaf.spaceOneOrMore())), - new RegexLeaf("KEY", "key"), // - RegexLeaf.spaceOneOrMore())), // - new RegexOptional( // - new RegexConcat( // - new RegexLeaf("attr(:?ibute)?"), // - RegexLeaf.spaceOneOrMore())), // - new RegexLeaf("NAME", "(\\w+)"), // + new RegexLeaf("NAME", "([^<>{}-]+)"), // + new RegexOptional(// + new RegexConcat( + RegexLeaf.spaceZeroOrMore(), // + new RegexLeaf("STEREOTYPE", "(<<.+>>)"))), // new RegexOptional(// new RegexConcat( // RegexLeaf.spaceZeroOrMore(), // @@ -104,6 +88,8 @@ public class CommandCreateAttribute extends SingleLineCommand2 { final String id = owner.getName() + "/" + name; final boolean composite = arg.get("COMPOSITE", 0) != null; + // TODO: stereotypes: multi, derived, key, partial key + final Quark quark = diagram.quarkInContext(true, id); Entity entity = quark.getData(); From 4d01e6fd6c2b5034fe50a2f78fa5ecb37c298ac2 Mon Sep 17 00:00:00 2001 From: Benjamin Davies Date: Thu, 16 Nov 2023 09:49:18 +1300 Subject: [PATCH 06/23] Merge entity and relationship commands --- .../cheneer/ChenEerDiagramFactory.java | 6 +- ...elationship.java => CommandAssociate.java} | 4 +- .../cheneer/command/CommandCreateEntity.java | 2 +- .../command/CommandCreateRelationship.java | 90 ------------------- 4 files changed, 5 insertions(+), 97 deletions(-) rename src/net/sourceforge/plantuml/cheneer/command/{CommandAssociateRelationship.java => CommandAssociate.java} (96%) delete mode 100644 src/net/sourceforge/plantuml/cheneer/command/CommandCreateRelationship.java diff --git a/src/net/sourceforge/plantuml/cheneer/ChenEerDiagramFactory.java b/src/net/sourceforge/plantuml/cheneer/ChenEerDiagramFactory.java index f7a31bc29..76ce3d03f 100644 --- a/src/net/sourceforge/plantuml/cheneer/ChenEerDiagramFactory.java +++ b/src/net/sourceforge/plantuml/cheneer/ChenEerDiagramFactory.java @@ -39,10 +39,9 @@ import java.util.List; import java.util.Map; import net.sourceforge.plantuml.AbstractPSystem; -import net.sourceforge.plantuml.cheneer.command.CommandAssociateRelationship; +import net.sourceforge.plantuml.cheneer.command.CommandAssociate; import net.sourceforge.plantuml.cheneer.command.CommandCreateAttribute; import net.sourceforge.plantuml.cheneer.command.CommandCreateEntity; -import net.sourceforge.plantuml.cheneer.command.CommandCreateRelationship; import net.sourceforge.plantuml.cheneer.command.CommandEndGroup; import net.sourceforge.plantuml.command.Command; import net.sourceforge.plantuml.command.CommonCommands; @@ -59,9 +58,8 @@ public class ChenEerDiagramFactory extends PSystemCommandFactory { @Override protected void initCommandsList(List cmds) { cmds.add(new CommandCreateEntity()); - cmds.add(new CommandCreateRelationship()); cmds.add(new CommandCreateAttribute()); - cmds.add(new CommandAssociateRelationship()); + cmds.add(new CommandAssociate()); cmds.add(new CommandEndGroup()); CommonCommands.addTitleCommands(cmds); diff --git a/src/net/sourceforge/plantuml/cheneer/command/CommandAssociateRelationship.java b/src/net/sourceforge/plantuml/cheneer/command/CommandAssociate.java similarity index 96% rename from src/net/sourceforge/plantuml/cheneer/command/CommandAssociateRelationship.java rename to src/net/sourceforge/plantuml/cheneer/command/CommandAssociate.java index 6b8362c2a..9c96bd6eb 100644 --- a/src/net/sourceforge/plantuml/cheneer/command/CommandAssociateRelationship.java +++ b/src/net/sourceforge/plantuml/cheneer/command/CommandAssociate.java @@ -53,9 +53,9 @@ import net.sourceforge.plantuml.regex.RegexOptional; import net.sourceforge.plantuml.regex.RegexResult; import net.sourceforge.plantuml.utils.LineLocation; -public class CommandAssociateRelationship extends SingleLineCommand2 { +public class CommandAssociate extends SingleLineCommand2 { - public CommandAssociateRelationship() { + public CommandAssociate() { super(getRegexConcat()); } diff --git a/src/net/sourceforge/plantuml/cheneer/command/CommandCreateEntity.java b/src/net/sourceforge/plantuml/cheneer/command/CommandCreateEntity.java index 011da23a1..3f4d93bc6 100644 --- a/src/net/sourceforge/plantuml/cheneer/command/CommandCreateEntity.java +++ b/src/net/sourceforge/plantuml/cheneer/command/CommandCreateEntity.java @@ -57,7 +57,7 @@ public class CommandCreateEntity extends SingleLineCommand2 { private static IRegex getRegexConcat() { return RegexConcat.build(CommandCreateEntity.class.getName(), RegexLeaf.start(), // - new RegexLeaf("entity"), // + new RegexLeaf("TYPE", "(entity|relationship)"), // RegexLeaf.spaceOneOrMore(), // new RegexLeaf("NAME", "(\\w+)"), // RegexLeaf.spaceZeroOrMore(), // diff --git a/src/net/sourceforge/plantuml/cheneer/command/CommandCreateRelationship.java b/src/net/sourceforge/plantuml/cheneer/command/CommandCreateRelationship.java deleted file mode 100644 index 84c378085..000000000 --- a/src/net/sourceforge/plantuml/cheneer/command/CommandCreateRelationship.java +++ /dev/null @@ -1,90 +0,0 @@ -/* ======================================================================== - * PlantUML : a free UML diagram generator - * ======================================================================== - * - * (C) Copyright 2009-2024, Arnaud Roques - * - * Project Info: https://plantuml.com - * - * If you like this project or if you find it useful, you can support us at: - * - * https://plantuml.com/patreon (only 1$ per month!) - * https://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.cheneer.command; - -import net.sourceforge.plantuml.abel.Entity; -import net.sourceforge.plantuml.abel.LeafType; -import net.sourceforge.plantuml.cheneer.ChenEerDiagram; -import net.sourceforge.plantuml.command.CommandExecutionResult; -import net.sourceforge.plantuml.command.SingleLineCommand2; -import net.sourceforge.plantuml.klimt.color.NoSuchColorException; -import net.sourceforge.plantuml.klimt.creole.Display; -import net.sourceforge.plantuml.plasma.Quark; -import net.sourceforge.plantuml.regex.IRegex; -import net.sourceforge.plantuml.regex.RegexConcat; -import net.sourceforge.plantuml.regex.RegexLeaf; -import net.sourceforge.plantuml.regex.RegexResult; -import net.sourceforge.plantuml.utils.LineLocation; - -public class CommandCreateRelationship extends SingleLineCommand2 { - - public CommandCreateRelationship() { - super(getRegexConcat()); - } - - private static IRegex getRegexConcat() { - return RegexConcat.build(CommandCreateEntity.class.getName(), RegexLeaf.start(), // - new RegexLeaf("relationship"), // - RegexLeaf.spaceOneOrMore(), // - new RegexLeaf("NAME", "(\\w+)"), // - RegexLeaf.spaceZeroOrMore(), // - new RegexLeaf("\\{"), // - RegexLeaf.end()); - } - - @Override - protected CommandExecutionResult executeArg(ChenEerDiagram diagram, LineLocation location, RegexResult arg) - throws NoSuchColorException { - final LeafType type = LeafType.OBJECT; - final String name = diagram.cleanId(arg.get("NAME", 0)); - - final Quark quark = diagram.quarkInContext(true, name); - Entity entity = quark.getData(); - - if (entity == null) { - Display display = Display.getWithNewlines(name); - entity = diagram.reallyCreateLeaf(quark, display, type, null); - } else { - if (entity.muteToType(type, null) == false) - return CommandExecutionResult.error("Bad name"); - } - - diagram.pushOwner(entity); - - return CommandExecutionResult.ok(); - } - -} From 153b96af3e3ab60d738ef3e9751d9338d272cc16 Mon Sep 17 00:00:00 2001 From: Benjamin Davies Date: Thu, 16 Nov 2023 10:03:30 +1300 Subject: [PATCH 07/23] Fix stereotype handling --- .../plantuml/cheneer/command/CommandCreateAttribute.java | 2 +- .../plantuml/cheneer/command/CommandCreateEntity.java | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/net/sourceforge/plantuml/cheneer/command/CommandCreateAttribute.java b/src/net/sourceforge/plantuml/cheneer/command/CommandCreateAttribute.java index 481ad58ae..a01dc2c3a 100644 --- a/src/net/sourceforge/plantuml/cheneer/command/CommandCreateAttribute.java +++ b/src/net/sourceforge/plantuml/cheneer/command/CommandCreateAttribute.java @@ -84,7 +84,7 @@ public class CommandCreateAttribute extends SingleLineCommand2 { } final LeafType type = LeafType.USECASE; - final String name = diagram.cleanId(arg.get("NAME", 0)); + final String name = diagram.cleanId(arg.get("NAME", 0).trim()); final String id = owner.getName() + "/" + name; final boolean composite = arg.get("COMPOSITE", 0) != null; diff --git a/src/net/sourceforge/plantuml/cheneer/command/CommandCreateEntity.java b/src/net/sourceforge/plantuml/cheneer/command/CommandCreateEntity.java index 3f4d93bc6..9ca195110 100644 --- a/src/net/sourceforge/plantuml/cheneer/command/CommandCreateEntity.java +++ b/src/net/sourceforge/plantuml/cheneer/command/CommandCreateEntity.java @@ -46,6 +46,7 @@ import net.sourceforge.plantuml.plasma.Quark; import net.sourceforge.plantuml.regex.IRegex; import net.sourceforge.plantuml.regex.RegexConcat; import net.sourceforge.plantuml.regex.RegexLeaf; +import net.sourceforge.plantuml.regex.RegexOptional; import net.sourceforge.plantuml.regex.RegexResult; import net.sourceforge.plantuml.utils.LineLocation; @@ -59,7 +60,11 @@ public class CommandCreateEntity extends SingleLineCommand2 { return RegexConcat.build(CommandCreateEntity.class.getName(), RegexLeaf.start(), // new RegexLeaf("TYPE", "(entity|relationship)"), // RegexLeaf.spaceOneOrMore(), // - new RegexLeaf("NAME", "(\\w+)"), // + new RegexLeaf("NAME", "([^<>{}]+)"), // + new RegexOptional(// + new RegexConcat( + RegexLeaf.spaceZeroOrMore(), // + new RegexLeaf("STEREOTYPE", "(<<.+>>)"))), // RegexLeaf.spaceZeroOrMore(), // new RegexLeaf("\\{"), // RegexLeaf.end()); @@ -69,7 +74,7 @@ public class CommandCreateEntity extends SingleLineCommand2 { protected CommandExecutionResult executeArg(ChenEerDiagram diagram, LineLocation location, RegexResult arg) throws NoSuchColorException { final LeafType type = LeafType.OBJECT; - final String name = diagram.cleanId(arg.get("NAME", 0)); + final String name = diagram.cleanId(arg.get("NAME", 0).trim()); final Quark quark = diagram.quarkInContext(true, name); Entity entity = quark.getData(); From 6361f826be340e5fba209c841e960ebf4363e571 Mon Sep 17 00:00:00 2001 From: Benjamin Davies Date: Thu, 16 Nov 2023 11:29:37 +1300 Subject: [PATCH 08/23] Add new leaf types --- .../sourceforge/plantuml/abel/LeafType.java | 2 + .../command/CommandCreateAttribute.java | 2 +- .../cheneer/command/CommandCreateEntity.java | 13 +- src/net/sourceforge/plantuml/style/SName.java | 4 + .../plantuml/svek/GeneralImageBuilder.java | 12 ++ .../svek/image/EntityImageChenAttribute.java | 155 ++++++++++++++++++ .../svek/image/EntityImageChenEntity.java | 151 +++++++++++++++++ 7 files changed, 337 insertions(+), 2 deletions(-) create mode 100644 src/net/sourceforge/plantuml/svek/image/EntityImageChenAttribute.java create mode 100644 src/net/sourceforge/plantuml/svek/image/EntityImageChenEntity.java diff --git a/src/net/sourceforge/plantuml/abel/LeafType.java b/src/net/sourceforge/plantuml/abel/LeafType.java index ce9b751e1..4c67360de 100644 --- a/src/net/sourceforge/plantuml/abel/LeafType.java +++ b/src/net/sourceforge/plantuml/abel/LeafType.java @@ -62,6 +62,8 @@ public enum LeafType { PORTIN, PORTOUT, + CHEN_ENTITY, CHEN_RELATIONSHIP, CHEN_ATTRIBUTE, + STILL_UNKNOWN; public static LeafType getLeafType(String type) { diff --git a/src/net/sourceforge/plantuml/cheneer/command/CommandCreateAttribute.java b/src/net/sourceforge/plantuml/cheneer/command/CommandCreateAttribute.java index a01dc2c3a..e7a98e8a1 100644 --- a/src/net/sourceforge/plantuml/cheneer/command/CommandCreateAttribute.java +++ b/src/net/sourceforge/plantuml/cheneer/command/CommandCreateAttribute.java @@ -83,7 +83,7 @@ public class CommandCreateAttribute extends SingleLineCommand2 { return CommandExecutionResult.error("Attribute must be inside an entity, relationship or another attribute"); } - final LeafType type = LeafType.USECASE; + final LeafType type = LeafType.CHEN_ATTRIBUTE; final String name = diagram.cleanId(arg.get("NAME", 0).trim()); final String id = owner.getName() + "/" + name; final boolean composite = arg.get("COMPOSITE", 0) != null; diff --git a/src/net/sourceforge/plantuml/cheneer/command/CommandCreateEntity.java b/src/net/sourceforge/plantuml/cheneer/command/CommandCreateEntity.java index 9ca195110..ceb5e7c38 100644 --- a/src/net/sourceforge/plantuml/cheneer/command/CommandCreateEntity.java +++ b/src/net/sourceforge/plantuml/cheneer/command/CommandCreateEntity.java @@ -73,7 +73,18 @@ public class CommandCreateEntity extends SingleLineCommand2 { @Override protected CommandExecutionResult executeArg(ChenEerDiagram diagram, LineLocation location, RegexResult arg) throws NoSuchColorException { - final LeafType type = LeafType.OBJECT; + LeafType type; + switch (arg.get("TYPE", 0)) { + case "entity": + type = LeafType.CHEN_ENTITY; + break; + case "relationship": + type = LeafType.CHEN_RELATIONSHIP; + break; + default: + throw new IllegalStateException(); + } + final String name = diagram.cleanId(arg.get("NAME", 0).trim()); final Quark quark = diagram.quarkInContext(true, name); diff --git a/src/net/sourceforge/plantuml/style/SName.java b/src/net/sourceforge/plantuml/style/SName.java index aa74331bb..451a65036 100644 --- a/src/net/sourceforge/plantuml/style/SName.java +++ b/src/net/sourceforge/plantuml/style/SName.java @@ -63,6 +63,10 @@ public enum SName { component, // composite, // robust, // + chenAttribute, // + chenEerDiagram, // + chenEntity, // + chenRelationship, // concise, // clock, // componentDiagram, // diff --git a/src/net/sourceforge/plantuml/svek/GeneralImageBuilder.java b/src/net/sourceforge/plantuml/svek/GeneralImageBuilder.java index 2b76371b5..4a8f317a1 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.svek.image.EntityImageArcCircle; import net.sourceforge.plantuml.svek.image.EntityImageAssociation; import net.sourceforge.plantuml.svek.image.EntityImageAssociationPoint; import net.sourceforge.plantuml.svek.image.EntityImageBranch; +import net.sourceforge.plantuml.svek.image.EntityImageChenAttribute; +import net.sourceforge.plantuml.svek.image.EntityImageChenEntity; import net.sourceforge.plantuml.svek.image.EntityImageCircleEnd; import net.sourceforge.plantuml.svek.image.EntityImageCircleStart; import net.sourceforge.plantuml.svek.image.EntityImageClass; @@ -254,6 +256,16 @@ public final class GeneralImageBuilder { if (leaf.getLeafType() == LeafType.TIPS) return new EntityImageTips(leaf, skinParam, bibliotekon, umlDiagramType); + if (leaf.getLeafType() == LeafType.CHEN_ENTITY) + return new EntityImageChenEntity(leaf, skinParam); + + if (leaf.getLeafType() == LeafType.CHEN_RELATIONSHIP) + // TODO: custom image type + return new EntityImageChenEntity(leaf, skinParam); + + if (leaf.getLeafType() == LeafType.CHEN_ATTRIBUTE) + return new EntityImageChenAttribute(leaf, skinParam); + // TODO Clean if (leaf.getLeafType() == LeafType.DOMAIN && leaf.getStereotype() != null && leaf.getStereotype().isMachineOrSpecification()) diff --git a/src/net/sourceforge/plantuml/svek/image/EntityImageChenAttribute.java b/src/net/sourceforge/plantuml/svek/image/EntityImageChenAttribute.java new file mode 100644 index 000000000..609377531 --- /dev/null +++ b/src/net/sourceforge/plantuml/svek/image/EntityImageChenAttribute.java @@ -0,0 +1,155 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2024, Arnaud Roques + * + * Project Info: https://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * https://plantuml.com/patreon (only 1$ per month!) + * https://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.svek.image; + +import java.util.Collections; + +import net.sourceforge.plantuml.abel.Entity; +import net.sourceforge.plantuml.klimt.UGroupType; +import net.sourceforge.plantuml.klimt.UShape; +import net.sourceforge.plantuml.klimt.UStroke; +import net.sourceforge.plantuml.klimt.UTranslate; +import net.sourceforge.plantuml.klimt.color.ColorType; +import net.sourceforge.plantuml.klimt.color.Colors; +import net.sourceforge.plantuml.klimt.color.HColor; +import net.sourceforge.plantuml.klimt.creole.CreoleMode; +import net.sourceforge.plantuml.klimt.drawing.UGraphic; +import net.sourceforge.plantuml.klimt.font.FontConfiguration; +import net.sourceforge.plantuml.klimt.font.StringBounder; +import net.sourceforge.plantuml.klimt.geom.HorizontalAlignment; +import net.sourceforge.plantuml.klimt.geom.XDimension2D; +import net.sourceforge.plantuml.klimt.shape.TextBlock; +import net.sourceforge.plantuml.klimt.shape.TextBlockInEllipse; +import net.sourceforge.plantuml.klimt.shape.UEllipse; +import net.sourceforge.plantuml.style.ISkinParam; +import net.sourceforge.plantuml.style.PName; +import net.sourceforge.plantuml.style.SName; +import net.sourceforge.plantuml.style.Style; +import net.sourceforge.plantuml.style.StyleSignatureBasic; +import net.sourceforge.plantuml.svek.AbstractEntityImage; +import net.sourceforge.plantuml.svek.ShapeType; +import net.sourceforge.plantuml.url.Url; + +public class EntityImageChenAttribute extends AbstractEntityImage { + + final static private int MARGIN = 6; + + final private TextBlock title; + final private Url url; + + public EntityImageChenAttribute(Entity entity, ISkinParam skinParam) { + super(entity, skinParam); + + final FontConfiguration titleFontConfiguration = getStyleTitle(entity, skinParam) + .getFontConfiguration(getSkinParam().getIHtmlColorSet(), entity.getColors()); + + title = entity.getDisplay().create8(titleFontConfiguration, HorizontalAlignment.CENTER, skinParam, CreoleMode.FULL, + getStyle().wrapWidth()); + + url = entity.getUrl99(); + } + + private Style getStyle() { + return getStyle(getEntity(), getSkinParam()); + } + + private static Style getStyle(Entity group, ISkinParam skinParam) { + return StyleSignatureBasic.of(SName.root, SName.element, SName.chenEerDiagram, SName.chenAttribute) + .withTOBECHANGED(group.getStereotype()).getMergedStyle(skinParam.getCurrentStyleBuilder()); + } + + private static Style getStyleTitle(Entity group, ISkinParam skinParam) { + return StyleSignatureBasic.of(SName.root, SName.element, SName.chenEerDiagram, SName.chenAttribute, SName.title) + .withTOBECHANGED(group.getStereotype()).getMergedStyle(skinParam.getCurrentStyleBuilder()); + } + + @Override + public ShapeType getShapeType() { + return ShapeType.OVAL; + } + + @Override + public XDimension2D calculateDimension(StringBounder stringBounder) { + final TextBlockInEllipse ellipse = new TextBlockInEllipse(title, stringBounder); + + return ellipse.calculateDimension(stringBounder); + } + + @Override + public void drawU(UGraphic ug) { + ug.startGroup(Collections.singletonMap(UGroupType.ID, getEntity().getQuark().toStringPoint())); + if (url != null) + ug.startUrl(url); + + final XDimension2D dimTotal = calculateDimension(ug.getStringBounder()); + final XDimension2D dimTitle = title.calculateDimension(ug.getStringBounder()); + + final UStroke stroke = getStyle().getStroke(getEntity().getColors()); + ug = applyColor(ug); + ug = ug.apply(stroke); + ug.draw(getShape(dimTotal)); + + final double xTitle = (dimTotal.getWidth() - dimTitle.getWidth()) / 2; + final double yTitle = MARGIN; + title.drawU(ug.apply(new UTranslate(xTitle, yTitle))); + + if (url != null) + ug.closeUrl(); + + ug.closeGroup(); + } + + final protected UGraphic applyColor(UGraphic ug) { + Colors colors = getEntity().getColors(); + + HColor border = colors.getColor(ColorType.LINE); + if (border == null) + border = getStyle().value(PName.LineColor).asColor(getSkinParam().getIHtmlColorSet()); + ug = ug.apply(border); + + HColor backcolor = colors.getColor(ColorType.BACK); + if (backcolor == null) + backcolor = getStyle().value(PName.BackGroundColor).asColor(getSkinParam().getIHtmlColorSet()); + ug = ug.apply(backcolor.bg()); + + return ug; + } + + private UShape getShape(XDimension2D dimTotal) { + return UEllipse.build(dimTotal.getWidth(), dimTotal.getHeight()); + } + +} diff --git a/src/net/sourceforge/plantuml/svek/image/EntityImageChenEntity.java b/src/net/sourceforge/plantuml/svek/image/EntityImageChenEntity.java new file mode 100644 index 000000000..766b6fbab --- /dev/null +++ b/src/net/sourceforge/plantuml/svek/image/EntityImageChenEntity.java @@ -0,0 +1,151 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2024, Arnaud Roques + * + * Project Info: https://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * https://plantuml.com/patreon (only 1$ per month!) + * https://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.svek.image; + +import java.util.Collections; + +import net.sourceforge.plantuml.abel.Entity; +import net.sourceforge.plantuml.klimt.UGroupType; +import net.sourceforge.plantuml.klimt.UStroke; +import net.sourceforge.plantuml.klimt.UTranslate; +import net.sourceforge.plantuml.klimt.color.ColorType; +import net.sourceforge.plantuml.klimt.color.Colors; +import net.sourceforge.plantuml.klimt.color.HColor; +import net.sourceforge.plantuml.klimt.creole.CreoleMode; +import net.sourceforge.plantuml.klimt.drawing.UGraphic; +import net.sourceforge.plantuml.klimt.font.FontConfiguration; +import net.sourceforge.plantuml.klimt.font.StringBounder; +import net.sourceforge.plantuml.klimt.geom.HorizontalAlignment; +import net.sourceforge.plantuml.klimt.geom.XDimension2D; +import net.sourceforge.plantuml.klimt.shape.TextBlock; +import net.sourceforge.plantuml.klimt.shape.URectangle; +import net.sourceforge.plantuml.style.ISkinParam; +import net.sourceforge.plantuml.style.PName; +import net.sourceforge.plantuml.style.SName; +import net.sourceforge.plantuml.style.Style; +import net.sourceforge.plantuml.style.StyleSignatureBasic; +import net.sourceforge.plantuml.svek.AbstractEntityImage; +import net.sourceforge.plantuml.svek.ShapeType; +import net.sourceforge.plantuml.url.Url; + +public class EntityImageChenEntity extends AbstractEntityImage { + + final private TextBlock title; + final private Url url; + + public EntityImageChenEntity(Entity entity, ISkinParam skinParam) { + super(entity, skinParam); + + final FontConfiguration titleFontConfiguration = getStyleStateTitle(entity, skinParam) + .getFontConfiguration(getSkinParam().getIHtmlColorSet(), entity.getColors()); + + title = entity.getDisplay().create8(titleFontConfiguration, HorizontalAlignment.CENTER, skinParam, CreoleMode.FULL, + getStyleState().wrapWidth()); + + url = entity.getUrl99(); + } + + private Style getStyleState() { + return getStyleState(getEntity(), getSkinParam()); + } + + private static Style getStyleState(Entity group, ISkinParam skinParam) { + return StyleSignatureBasic.of(SName.root, SName.element, SName.chenEerDiagram, SName.chenEntity) + .withTOBECHANGED(group.getStereotype()).getMergedStyle(skinParam.getCurrentStyleBuilder()); + } + + private static Style getStyleStateTitle(Entity group, ISkinParam skinParam) { + return StyleSignatureBasic.of(SName.root, SName.element, SName.chenEerDiagram, SName.chenEntity, SName.title) + .withTOBECHANGED(group.getStereotype()).getMergedStyle(skinParam.getCurrentStyleBuilder()); + } + + @Override + public ShapeType getShapeType() { + return ShapeType.RECTANGLE; + } + + @Override + public XDimension2D calculateDimension(StringBounder stringBounder) { + final XDimension2D dim = title.calculateDimension(stringBounder); + + return dim.delta(MARGIN * 2 + 2 * MARGIN_LINE); + } + + @Override + public void drawU(UGraphic ug) { + ug.startGroup(Collections.singletonMap(UGroupType.ID, getEntity().getQuark().toStringPoint())); + if (url != null) + ug.startUrl(url); + + final XDimension2D dimTotal = calculateDimension(ug.getStringBounder()); + final XDimension2D dimTitle = title.calculateDimension(ug.getStringBounder()); + + final UStroke stroke = getStyleState().getStroke(getEntity().getColors()); + ug = applyColor(ug); + ug = ug.apply(stroke); + ug.draw(getShape(dimTotal)); + + final double xTitle = (dimTotal.getWidth() - dimTitle.getWidth()) / 2; + final double yTitle = MARGIN + MARGIN_LINE; + title.drawU(ug.apply(new UTranslate(xTitle, yTitle))); + + if (url != null) + ug.closeUrl(); + + ug.closeGroup(); + } + + final protected UGraphic applyColor(UGraphic ug) { + Colors colors = getEntity().getColors(); + + HColor border = colors.getColor(ColorType.LINE); + if (border == null) + border = getStyleState().value(PName.LineColor).asColor(getSkinParam().getIHtmlColorSet()); + ug = ug.apply(border); + + HColor backcolor = colors.getColor(ColorType.BACK); + if (backcolor == null) + backcolor = getStyleState().value(PName.BackGroundColor).asColor(getSkinParam().getIHtmlColorSet()); + ug = ug.apply(backcolor.bg()); + + return ug; + } + + private URectangle getShape(XDimension2D dimTotal) { + return URectangle.build(dimTotal); + } + +} From c6bd537509af0e0532db63f7eb6b593b93fcbc17 Mon Sep 17 00:00:00 2001 From: Benjamin Davies Date: Thu, 16 Nov 2023 12:16:35 +1300 Subject: [PATCH 09/23] Draw relationships as diamonds --- .../plantuml/svek/GeneralImageBuilder.java | 4 +- .../image/EntityImageChenRelationship.java | 168 ++++++++++++++++++ 2 files changed, 170 insertions(+), 2 deletions(-) create mode 100644 src/net/sourceforge/plantuml/svek/image/EntityImageChenRelationship.java diff --git a/src/net/sourceforge/plantuml/svek/GeneralImageBuilder.java b/src/net/sourceforge/plantuml/svek/GeneralImageBuilder.java index 4a8f317a1..4a18f2783 100644 --- a/src/net/sourceforge/plantuml/svek/GeneralImageBuilder.java +++ b/src/net/sourceforge/plantuml/svek/GeneralImageBuilder.java @@ -101,6 +101,7 @@ import net.sourceforge.plantuml.svek.image.EntityImageAssociationPoint; import net.sourceforge.plantuml.svek.image.EntityImageBranch; import net.sourceforge.plantuml.svek.image.EntityImageChenAttribute; import net.sourceforge.plantuml.svek.image.EntityImageChenEntity; +import net.sourceforge.plantuml.svek.image.EntityImageChenRelationship; import net.sourceforge.plantuml.svek.image.EntityImageCircleEnd; import net.sourceforge.plantuml.svek.image.EntityImageCircleStart; import net.sourceforge.plantuml.svek.image.EntityImageClass; @@ -260,8 +261,7 @@ public final class GeneralImageBuilder { return new EntityImageChenEntity(leaf, skinParam); if (leaf.getLeafType() == LeafType.CHEN_RELATIONSHIP) - // TODO: custom image type - return new EntityImageChenEntity(leaf, skinParam); + return new EntityImageChenRelationship(leaf, skinParam); if (leaf.getLeafType() == LeafType.CHEN_ATTRIBUTE) return new EntityImageChenAttribute(leaf, skinParam); diff --git a/src/net/sourceforge/plantuml/svek/image/EntityImageChenRelationship.java b/src/net/sourceforge/plantuml/svek/image/EntityImageChenRelationship.java new file mode 100644 index 000000000..6b72bb2b5 --- /dev/null +++ b/src/net/sourceforge/plantuml/svek/image/EntityImageChenRelationship.java @@ -0,0 +1,168 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2024, Arnaud Roques + * + * Project Info: https://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * https://plantuml.com/patreon (only 1$ per month!) + * https://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.svek.image; + +import java.util.Arrays; +import java.util.Collections; + +import net.sourceforge.plantuml.abel.Entity; +import net.sourceforge.plantuml.klimt.UGroupType; +import net.sourceforge.plantuml.klimt.UShape; +import net.sourceforge.plantuml.klimt.UStroke; +import net.sourceforge.plantuml.klimt.UTranslate; +import net.sourceforge.plantuml.klimt.color.ColorType; +import net.sourceforge.plantuml.klimt.color.Colors; +import net.sourceforge.plantuml.klimt.color.HColor; +import net.sourceforge.plantuml.klimt.creole.CreoleMode; +import net.sourceforge.plantuml.klimt.drawing.UGraphic; +import net.sourceforge.plantuml.klimt.font.FontConfiguration; +import net.sourceforge.plantuml.klimt.font.StringBounder; +import net.sourceforge.plantuml.klimt.geom.HorizontalAlignment; +import net.sourceforge.plantuml.klimt.geom.XDimension2D; +import net.sourceforge.plantuml.klimt.geom.XPoint2D; +import net.sourceforge.plantuml.klimt.shape.TextBlock; +import net.sourceforge.plantuml.klimt.shape.TextBlockInEllipse; +import net.sourceforge.plantuml.klimt.shape.UPolygon; +import net.sourceforge.plantuml.style.ISkinParam; +import net.sourceforge.plantuml.style.PName; +import net.sourceforge.plantuml.style.SName; +import net.sourceforge.plantuml.style.Style; +import net.sourceforge.plantuml.style.StyleSignatureBasic; +import net.sourceforge.plantuml.svek.AbstractEntityImage; +import net.sourceforge.plantuml.svek.ShapeType; +import net.sourceforge.plantuml.url.Url; + +public class EntityImageChenRelationship extends AbstractEntityImage { + + final private TextBlock title; + final private Url url; + + public EntityImageChenRelationship(Entity entity, ISkinParam skinParam) { + super(entity, skinParam); + + final FontConfiguration titleFontConfiguration = getStyleTitle(entity, skinParam) + .getFontConfiguration(getSkinParam().getIHtmlColorSet(), entity.getColors()); + + title = entity.getDisplay().create8(titleFontConfiguration, HorizontalAlignment.CENTER, skinParam, CreoleMode.FULL, + getStyle().wrapWidth()); + + url = entity.getUrl99(); + } + + private Style getStyle() { + return getStyle(getEntity(), getSkinParam()); + } + + private static Style getStyle(Entity group, ISkinParam skinParam) { + return StyleSignatureBasic.of(SName.root, SName.element, SName.chenEerDiagram, SName.chenRelationship) + .withTOBECHANGED(group.getStereotype()).getMergedStyle(skinParam.getCurrentStyleBuilder()); + } + + private static Style getStyleTitle(Entity group, ISkinParam skinParam) { + return StyleSignatureBasic.of(SName.root, SName.element, SName.chenEerDiagram, SName.chenRelationship, SName.title) + .withTOBECHANGED(group.getStereotype()).getMergedStyle(skinParam.getCurrentStyleBuilder()); + } + + @Override + public ShapeType getShapeType() { + return ShapeType.DIAMOND; + } + + @Override + public XDimension2D calculateDimension(StringBounder stringBounder) { + final XDimension2D dimTitle = title.calculateDimension(stringBounder); + + // Fit a diamond with aspect ratio 2 around the text + // diagonal = dimTitle dot ([1, 2] / sqrt(5)) + 2 * MARGIN + // dimTotal = diagonal * [sqrt(5), sqrt(5) / 2] + + final double diagonal = (dimTitle.getWidth() + 2 * dimTitle.getHeight()) / Math.sqrt(5) + 2 * MARGIN; + return new XDimension2D(diagonal * Math.sqrt(5), diagonal * Math.sqrt(5) / 2); + } + + @Override + public void drawU(UGraphic ug) { + ug.startGroup(Collections.singletonMap(UGroupType.ID, getEntity().getQuark().toStringPoint())); + if (url != null) + ug.startUrl(url); + + final XDimension2D dimTotal = calculateDimension(ug.getStringBounder()); + final XDimension2D dimTitle = title.calculateDimension(ug.getStringBounder()); + + final UStroke stroke = getStyle().getStroke(getEntity().getColors()); + ug = applyColor(ug); + ug = ug.apply(stroke); + ug.draw(getShape(dimTotal)); + + final double xTitle = (dimTotal.getWidth() - dimTitle.getWidth()) / 2; + final double yTitle = (dimTotal.getHeight() - dimTitle.getHeight()) / 2; + title.drawU(ug.apply(new UTranslate(xTitle, yTitle))); + + if (url != null) + ug.closeUrl(); + + ug.closeGroup(); + } + + final protected UGraphic applyColor(UGraphic ug) { + Colors colors = getEntity().getColors(); + + HColor border = colors.getColor(ColorType.LINE); + if (border == null) + border = getStyle().value(PName.LineColor).asColor(getSkinParam().getIHtmlColorSet()); + ug = ug.apply(border); + + HColor backcolor = colors.getColor(ColorType.BACK); + if (backcolor == null) + backcolor = getStyle().value(PName.BackGroundColor).asColor(getSkinParam().getIHtmlColorSet()); + ug = ug.apply(backcolor.bg()); + + return ug; + } + + private UShape getShape(XDimension2D dimTotal) { + final double width = dimTotal.getWidth(); + final double height = dimTotal.getHeight(); + + final XPoint2D p1 = new XPoint2D(0, height / 2); + final XPoint2D p2 = new XPoint2D(width / 2, 0); + final XPoint2D p3 = new XPoint2D(width, height / 2); + final XPoint2D p4 = new XPoint2D(width / 2, height); + + return new UPolygon(Arrays.asList(p1, p2, p3, p4)); + } + +} From de74e7fae9d971ece7729a26053e86bba6b1b840 Mon Sep 17 00:00:00 2001 From: Benjamin Davies Date: Thu, 16 Nov 2023 13:24:12 +1300 Subject: [PATCH 10/23] Change leaf style based on stereotype --- .../command/CommandCreateAttribute.java | 24 +++++++-------- .../cheneer/command/CommandCreateEntity.java | 30 +++++++++++-------- .../svek/image/EntityImageChenAttribute.java | 26 ++++++++++++++-- .../svek/image/EntityImageChenEntity.java | 11 +++++++ .../image/EntityImageChenRelationship.java | 12 +++++++- 5 files changed, 75 insertions(+), 28 deletions(-) diff --git a/src/net/sourceforge/plantuml/cheneer/command/CommandCreateAttribute.java b/src/net/sourceforge/plantuml/cheneer/command/CommandCreateAttribute.java index e7a98e8a1..af29e951e 100644 --- a/src/net/sourceforge/plantuml/cheneer/command/CommandCreateAttribute.java +++ b/src/net/sourceforge/plantuml/cheneer/command/CommandCreateAttribute.java @@ -50,8 +50,8 @@ import net.sourceforge.plantuml.plasma.Quark; import net.sourceforge.plantuml.regex.IRegex; import net.sourceforge.plantuml.regex.RegexConcat; import net.sourceforge.plantuml.regex.RegexLeaf; -import net.sourceforge.plantuml.regex.RegexOptional; import net.sourceforge.plantuml.regex.RegexResult; +import net.sourceforge.plantuml.stereo.Stereotype; import net.sourceforge.plantuml.utils.LineLocation; public class CommandCreateAttribute extends SingleLineCommand2 { @@ -63,15 +63,11 @@ public class CommandCreateAttribute extends SingleLineCommand2 { private static IRegex getRegexConcat() { return RegexConcat.build(CommandCreateEntity.class.getName(), RegexLeaf.start(), // RegexLeaf.spaceZeroOrMore(), - new RegexLeaf("NAME", "([^<>{}-]+)"), // - new RegexOptional(// - new RegexConcat( - RegexLeaf.spaceZeroOrMore(), // - new RegexLeaf("STEREOTYPE", "(<<.+>>)"))), // - new RegexOptional(// - new RegexConcat( // - RegexLeaf.spaceZeroOrMore(), // - new RegexLeaf("COMPOSITE", "(\\{)"))), // + new RegexLeaf("NAME", "([^<>{}=-]+)"), // + RegexLeaf.spaceZeroOrMore(), // + new RegexLeaf("STEREO", "(<<.*>>)?"), // + RegexLeaf.spaceZeroOrMore(), // + new RegexLeaf("COMPOSITE", "(\\{)?"), // RegexLeaf.end()); } @@ -86,10 +82,9 @@ public class CommandCreateAttribute extends SingleLineCommand2 { final LeafType type = LeafType.CHEN_ATTRIBUTE; final String name = diagram.cleanId(arg.get("NAME", 0).trim()); final String id = owner.getName() + "/" + name; + final String stereo = arg.get("STEREO", 0); final boolean composite = arg.get("COMPOSITE", 0) != null; - // TODO: stereotypes: multi, derived, key, partial key - final Quark quark = diagram.quarkInContext(true, id); Entity entity = quark.getData(); @@ -100,6 +95,11 @@ public class CommandCreateAttribute extends SingleLineCommand2 { return CommandExecutionResult.error("Attribute already exists"); } + if (stereo != null) { + entity.setStereotype(Stereotype.build(stereo)); + entity.setStereostyle(stereo); + } + final LinkType linkType = new LinkType(LinkDecor.NONE, LinkDecor.NONE); final Link link = new Link(diagram.getEntityFactory(), diagram.getCurrentStyleBuilder(), entity, owner, linkType, LinkArg.build(Display.NULL, 2)); diff --git a/src/net/sourceforge/plantuml/cheneer/command/CommandCreateEntity.java b/src/net/sourceforge/plantuml/cheneer/command/CommandCreateEntity.java index ceb5e7c38..3fbb090d1 100644 --- a/src/net/sourceforge/plantuml/cheneer/command/CommandCreateEntity.java +++ b/src/net/sourceforge/plantuml/cheneer/command/CommandCreateEntity.java @@ -46,8 +46,8 @@ import net.sourceforge.plantuml.plasma.Quark; import net.sourceforge.plantuml.regex.IRegex; import net.sourceforge.plantuml.regex.RegexConcat; import net.sourceforge.plantuml.regex.RegexLeaf; -import net.sourceforge.plantuml.regex.RegexOptional; import net.sourceforge.plantuml.regex.RegexResult; +import net.sourceforge.plantuml.stereo.Stereotype; import net.sourceforge.plantuml.utils.LineLocation; public class CommandCreateEntity extends SingleLineCommand2 { @@ -61,10 +61,8 @@ public class CommandCreateEntity extends SingleLineCommand2 { new RegexLeaf("TYPE", "(entity|relationship)"), // RegexLeaf.spaceOneOrMore(), // new RegexLeaf("NAME", "([^<>{}]+)"), // - new RegexOptional(// - new RegexConcat( - RegexLeaf.spaceZeroOrMore(), // - new RegexLeaf("STEREOTYPE", "(<<.+>>)"))), // + RegexLeaf.spaceZeroOrMore(), // + new RegexLeaf("STEREO", "(<<.+>>)?"), // RegexLeaf.spaceZeroOrMore(), // new RegexLeaf("\\{"), // RegexLeaf.end()); @@ -75,17 +73,18 @@ public class CommandCreateEntity extends SingleLineCommand2 { throws NoSuchColorException { LeafType type; switch (arg.get("TYPE", 0)) { - case "entity": - type = LeafType.CHEN_ENTITY; - break; - case "relationship": - type = LeafType.CHEN_RELATIONSHIP; - break; - default: - throw new IllegalStateException(); + case "entity": + type = LeafType.CHEN_ENTITY; + break; + case "relationship": + type = LeafType.CHEN_RELATIONSHIP; + break; + default: + throw new IllegalStateException(); } final String name = diagram.cleanId(arg.get("NAME", 0).trim()); + final String stereo = arg.get("STEREO", 0); final Quark quark = diagram.quarkInContext(true, name); Entity entity = quark.getData(); @@ -98,6 +97,11 @@ public class CommandCreateEntity extends SingleLineCommand2 { return CommandExecutionResult.error("Bad name"); } + if (stereo != null) { + entity.setStereotype(Stereotype.build(stereo)); + entity.setStereostyle(stereo); + } + diagram.pushOwner(entity); return CommandExecutionResult.ok(); diff --git a/src/net/sourceforge/plantuml/svek/image/EntityImageChenAttribute.java b/src/net/sourceforge/plantuml/svek/image/EntityImageChenAttribute.java index 609377531..b69ba154b 100644 --- a/src/net/sourceforge/plantuml/svek/image/EntityImageChenAttribute.java +++ b/src/net/sourceforge/plantuml/svek/image/EntityImageChenAttribute.java @@ -67,14 +67,25 @@ public class EntityImageChenAttribute extends AbstractEntityImage { final static private int MARGIN = 6; + final private boolean isKey; + final private boolean isMulti; + final private boolean isDerived; + final private TextBlock title; final private Url url; public EntityImageChenAttribute(Entity entity, ISkinParam skinParam) { super(entity, skinParam); - final FontConfiguration titleFontConfiguration = getStyleTitle(entity, skinParam) + isKey = hasStereotype("<>"); + isMulti = hasStereotype("<>"); + isDerived = hasStereotype("<>"); + + FontConfiguration titleFontConfiguration = getStyleTitle(entity, skinParam) .getFontConfiguration(getSkinParam().getIHtmlColorSet(), entity.getColors()); + if (isKey) { + titleFontConfiguration = titleFontConfiguration.underline(); + } title = entity.getDisplay().create8(titleFontConfiguration, HorizontalAlignment.CENTER, skinParam, CreoleMode.FULL, getStyle().wrapWidth()); @@ -82,6 +93,10 @@ public class EntityImageChenAttribute extends AbstractEntityImage { url = entity.getUrl99(); } + private boolean hasStereotype(String stereotype) { + return getEntity().getStereotype() != null && getEntity().getStereotype().toString().contains(stereotype); + } + private Style getStyle() { return getStyle(getEntity(), getSkinParam()); } @@ -117,10 +132,17 @@ public class EntityImageChenAttribute extends AbstractEntityImage { final XDimension2D dimTotal = calculateDimension(ug.getStringBounder()); final XDimension2D dimTitle = title.calculateDimension(ug.getStringBounder()); - final UStroke stroke = getStyle().getStroke(getEntity().getColors()); + UStroke stroke = getStyle().getStroke(getEntity().getColors()); + if (isDerived) { + stroke = new UStroke(10, 10, stroke.getThickness()); + } + ug = applyColor(ug); ug = ug.apply(stroke); ug.draw(getShape(dimTotal)); + if (isMulti) { + ug.apply(new UTranslate(3, 3)).draw(getShape(dimTotal.delta(-6))); + } final double xTitle = (dimTotal.getWidth() - dimTitle.getWidth()) / 2; final double yTitle = MARGIN; diff --git a/src/net/sourceforge/plantuml/svek/image/EntityImageChenEntity.java b/src/net/sourceforge/plantuml/svek/image/EntityImageChenEntity.java index 766b6fbab..a86b97676 100644 --- a/src/net/sourceforge/plantuml/svek/image/EntityImageChenEntity.java +++ b/src/net/sourceforge/plantuml/svek/image/EntityImageChenEntity.java @@ -63,12 +63,16 @@ import net.sourceforge.plantuml.url.Url; public class EntityImageChenEntity extends AbstractEntityImage { + final private boolean isWeak; + final private TextBlock title; final private Url url; public EntityImageChenEntity(Entity entity, ISkinParam skinParam) { super(entity, skinParam); + isWeak = hasStereotype("<>"); + final FontConfiguration titleFontConfiguration = getStyleStateTitle(entity, skinParam) .getFontConfiguration(getSkinParam().getIHtmlColorSet(), entity.getColors()); @@ -78,6 +82,10 @@ public class EntityImageChenEntity extends AbstractEntityImage { url = entity.getUrl99(); } + private boolean hasStereotype(String stereotype) { + return getEntity().getStereotype() != null && getEntity().getStereotype().toString().contains(stereotype); + } + private Style getStyleState() { return getStyleState(getEntity(), getSkinParam()); } @@ -117,6 +125,9 @@ public class EntityImageChenEntity extends AbstractEntityImage { ug = applyColor(ug); ug = ug.apply(stroke); ug.draw(getShape(dimTotal)); + if (isWeak) { + ug.apply(new UTranslate(3, 3)).draw(getShape(dimTotal.delta(-6))); + } final double xTitle = (dimTotal.getWidth() - dimTitle.getWidth()) / 2; final double yTitle = MARGIN + MARGIN_LINE; diff --git a/src/net/sourceforge/plantuml/svek/image/EntityImageChenRelationship.java b/src/net/sourceforge/plantuml/svek/image/EntityImageChenRelationship.java index 6b72bb2b5..8bf58c962 100644 --- a/src/net/sourceforge/plantuml/svek/image/EntityImageChenRelationship.java +++ b/src/net/sourceforge/plantuml/svek/image/EntityImageChenRelationship.java @@ -54,7 +54,6 @@ import net.sourceforge.plantuml.klimt.geom.HorizontalAlignment; import net.sourceforge.plantuml.klimt.geom.XDimension2D; import net.sourceforge.plantuml.klimt.geom.XPoint2D; import net.sourceforge.plantuml.klimt.shape.TextBlock; -import net.sourceforge.plantuml.klimt.shape.TextBlockInEllipse; import net.sourceforge.plantuml.klimt.shape.UPolygon; import net.sourceforge.plantuml.style.ISkinParam; import net.sourceforge.plantuml.style.PName; @@ -67,12 +66,16 @@ import net.sourceforge.plantuml.url.Url; public class EntityImageChenRelationship extends AbstractEntityImage { + final private boolean isIdentifying; + final private TextBlock title; final private Url url; public EntityImageChenRelationship(Entity entity, ISkinParam skinParam) { super(entity, skinParam); + isIdentifying = hasStereotype("<>"); + final FontConfiguration titleFontConfiguration = getStyleTitle(entity, skinParam) .getFontConfiguration(getSkinParam().getIHtmlColorSet(), entity.getColors()); @@ -82,6 +85,10 @@ public class EntityImageChenRelationship extends AbstractEntityImage { url = entity.getUrl99(); } + private boolean hasStereotype(String stereotype) { + return getEntity().getStereotype() != null && getEntity().getStereotype().toString().contains(stereotype); + } + private Style getStyle() { return getStyle(getEntity(), getSkinParam()); } @@ -126,6 +133,9 @@ public class EntityImageChenRelationship extends AbstractEntityImage { ug = applyColor(ug); ug = ug.apply(stroke); ug.draw(getShape(dimTotal)); + if (isIdentifying) { + ug.apply(new UTranslate(10, 5)).draw(getShape(dimTotal.delta(-20, -10))); + } final double xTitle = (dimTotal.getWidth() - dimTitle.getWidth()) / 2; final double yTitle = (dimTotal.getHeight() - dimTitle.getHeight()) / 2; From 37344654416e2de28e0385ff2304c3c8bb458ef3 Mon Sep 17 00:00:00 2001 From: Benjamin Davies Date: Thu, 16 Nov 2023 13:36:34 +1300 Subject: [PATCH 11/23] Style associations --- .../plantuml/cheneer/command/CommandAssociate.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/net/sourceforge/plantuml/cheneer/command/CommandAssociate.java b/src/net/sourceforge/plantuml/cheneer/command/CommandAssociate.java index 9c96bd6eb..a43da9d3c 100644 --- a/src/net/sourceforge/plantuml/cheneer/command/CommandAssociate.java +++ b/src/net/sourceforge/plantuml/cheneer/command/CommandAssociate.java @@ -42,6 +42,8 @@ import net.sourceforge.plantuml.cheneer.ChenEerDiagram; import net.sourceforge.plantuml.command.CommandExecutionResult; import net.sourceforge.plantuml.command.SingleLineCommand2; import net.sourceforge.plantuml.decoration.LinkDecor; +import net.sourceforge.plantuml.decoration.LinkMiddleDecor; +import net.sourceforge.plantuml.decoration.LinkStyle; import net.sourceforge.plantuml.decoration.LinkType; import net.sourceforge.plantuml.klimt.color.NoSuchColorException; import net.sourceforge.plantuml.klimt.creole.Display; @@ -77,6 +79,8 @@ public class CommandAssociate extends SingleLineCommand2 { throws NoSuchColorException { final String name1 = diagram.cleanId(arg.get("NAME1", 0)); final String name2 = diagram.cleanId(arg.get("NAME2", 0)); + final boolean isDouble = arg.get("PARTICIPATION", 0).equals("="); + final String cardinality = arg.get("CARDINALITY", 0); final Quark quark1 = diagram.quarkInContext(true, name1); final Entity entity1 = quark1.getData(); @@ -90,11 +94,13 @@ public class CommandAssociate extends SingleLineCommand2 { return CommandExecutionResult.error("No such entity: " + name2); } - final LinkType linkType = new LinkType(LinkDecor.NONE, LinkDecor.NONE); + LinkType linkType = new LinkType(LinkDecor.NONE, LinkDecor.NONE); + if (isDouble) { + linkType = linkType.goBold(); + } final Link link = new Link(diagram.getEntityFactory(), diagram.getCurrentStyleBuilder(), entity1, entity2, linkType, - // TODO: Cardinality - LinkArg.build(Display.NULL, 3)); + LinkArg.build(Display.getWithNewlines(cardinality), 3)); link.setPortMembers(diagram.getPortId(entity1.getName()), diagram.getPortId(entity2.getName())); diagram.addLink(link); From 9e8a313681c88bd24f71a913fd48e773e141c564 Mon Sep 17 00:00:00 2001 From: Benjamin Davies Date: Thu, 16 Nov 2023 17:41:11 +1300 Subject: [PATCH 12/23] Add subset associations --- .../cheneer/ChenEerDiagramFactory.java | 8 +- .../cheneer/command/CommandAssociate.java | 2 - .../command/CommandSimpleSubclass.java | 111 ++++++++++++++++++ .../plantuml/decoration/LinkMiddleDecor.java | 9 +- .../plantuml/decoration/LinkType.java | 8 ++ .../svek/extremity/MiddleFactorySubset.java | 52 ++++++++ .../plantuml/svek/extremity/MiddleSubset.java | 82 +++++++++++++ 7 files changed, 266 insertions(+), 6 deletions(-) create mode 100644 src/net/sourceforge/plantuml/cheneer/command/CommandSimpleSubclass.java create mode 100644 src/net/sourceforge/plantuml/svek/extremity/MiddleFactorySubset.java create mode 100644 src/net/sourceforge/plantuml/svek/extremity/MiddleSubset.java diff --git a/src/net/sourceforge/plantuml/cheneer/ChenEerDiagramFactory.java b/src/net/sourceforge/plantuml/cheneer/ChenEerDiagramFactory.java index 76ce3d03f..105fa9632 100644 --- a/src/net/sourceforge/plantuml/cheneer/ChenEerDiagramFactory.java +++ b/src/net/sourceforge/plantuml/cheneer/ChenEerDiagramFactory.java @@ -43,6 +43,7 @@ import net.sourceforge.plantuml.cheneer.command.CommandAssociate; import net.sourceforge.plantuml.cheneer.command.CommandCreateAttribute; import net.sourceforge.plantuml.cheneer.command.CommandCreateEntity; import net.sourceforge.plantuml.cheneer.command.CommandEndGroup; +import net.sourceforge.plantuml.cheneer.command.CommandSimpleSubclass; import net.sourceforge.plantuml.command.Command; import net.sourceforge.plantuml.command.CommonCommands; import net.sourceforge.plantuml.command.PSystemCommandFactory; @@ -57,13 +58,14 @@ public class ChenEerDiagramFactory extends PSystemCommandFactory { @Override protected void initCommandsList(List cmds) { + CommonCommands.addTitleCommands(cmds); + CommonCommands.addCommonCommands2(cmds); + cmds.add(new CommandCreateEntity()); cmds.add(new CommandCreateAttribute()); cmds.add(new CommandAssociate()); cmds.add(new CommandEndGroup()); - - CommonCommands.addTitleCommands(cmds); - CommonCommands.addCommonCommands2(cmds); + cmds.add(new CommandSimpleSubclass()); } @Override diff --git a/src/net/sourceforge/plantuml/cheneer/command/CommandAssociate.java b/src/net/sourceforge/plantuml/cheneer/command/CommandAssociate.java index a43da9d3c..116eaf514 100644 --- a/src/net/sourceforge/plantuml/cheneer/command/CommandAssociate.java +++ b/src/net/sourceforge/plantuml/cheneer/command/CommandAssociate.java @@ -42,8 +42,6 @@ import net.sourceforge.plantuml.cheneer.ChenEerDiagram; import net.sourceforge.plantuml.command.CommandExecutionResult; import net.sourceforge.plantuml.command.SingleLineCommand2; import net.sourceforge.plantuml.decoration.LinkDecor; -import net.sourceforge.plantuml.decoration.LinkMiddleDecor; -import net.sourceforge.plantuml.decoration.LinkStyle; import net.sourceforge.plantuml.decoration.LinkType; import net.sourceforge.plantuml.klimt.color.NoSuchColorException; import net.sourceforge.plantuml.klimt.creole.Display; diff --git a/src/net/sourceforge/plantuml/cheneer/command/CommandSimpleSubclass.java b/src/net/sourceforge/plantuml/cheneer/command/CommandSimpleSubclass.java new file mode 100644 index 000000000..2c8e3c1c4 --- /dev/null +++ b/src/net/sourceforge/plantuml/cheneer/command/CommandSimpleSubclass.java @@ -0,0 +1,111 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2024, Arnaud Roques + * + * Project Info: https://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * https://plantuml.com/patreon (only 1$ per month!) + * https://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.cheneer.command; + +import net.sourceforge.plantuml.abel.Entity; +import net.sourceforge.plantuml.abel.Link; +import net.sourceforge.plantuml.abel.LinkArg; +import net.sourceforge.plantuml.cheneer.ChenEerDiagram; +import net.sourceforge.plantuml.command.CommandExecutionResult; +import net.sourceforge.plantuml.command.SingleLineCommand2; +import net.sourceforge.plantuml.decoration.LinkDecor; +import net.sourceforge.plantuml.decoration.LinkType; +import net.sourceforge.plantuml.klimt.color.NoSuchColorException; +import net.sourceforge.plantuml.klimt.creole.Display; +import net.sourceforge.plantuml.plasma.Quark; +import net.sourceforge.plantuml.regex.IRegex; +import net.sourceforge.plantuml.regex.RegexConcat; +import net.sourceforge.plantuml.regex.RegexLeaf; +import net.sourceforge.plantuml.regex.RegexResult; +import net.sourceforge.plantuml.utils.LineLocation; + +public class CommandSimpleSubclass extends SingleLineCommand2 { + + public CommandSimpleSubclass() { + super(getRegexConcat()); + } + + private static IRegex getRegexConcat() { + return RegexConcat.build(CommandCreateEntity.class.getName(), RegexLeaf.start(), // + new RegexLeaf("NAME1", "([\\w-]+)"), // + RegexLeaf.spaceZeroOrMore(), // + new RegexLeaf("PARTICIPATION", "([-=])"), // + new RegexLeaf("DIRECTION", "([<>])"), // + new RegexLeaf("PARTICIPATION2", "([-=])"), // + RegexLeaf.spaceZeroOrMore(), // + new RegexLeaf("NAME2", "([\\w-]+)"), // + RegexLeaf.end()); + } + + @Override + protected CommandExecutionResult executeArg(ChenEerDiagram diagram, LineLocation location, RegexResult arg) + throws NoSuchColorException { + String name1 = diagram.cleanId(arg.get("NAME1", 0)); + String name2 = diagram.cleanId(arg.get("NAME2", 0)); + final boolean isDouble = arg.get("PARTICIPATION", 0).equals("="); + final boolean isSuperset = arg.get("DIRECTION", 0).equals(">"); + + final Quark quark1 = diagram.quarkInContext(true, name1); + final Entity entity1 = quark1.getData(); + if (entity1 == null) { + return CommandExecutionResult.error("No such entity: " + name1); + } + + final Quark quark2 = diagram.quarkInContext(true, name2); + final Entity entity2 = quark2.getData(); + if (entity2 == null) { + return CommandExecutionResult.error("No such entity: " + name2); + } + + LinkType linkType = new LinkType(LinkDecor.NONE, LinkDecor.NONE); + if (isDouble) { + linkType = linkType.goBold(); + } + if (isSuperset) { + linkType = linkType.withMiddleSuperset(); + } else { + linkType = linkType.withMiddleSubset(); + } + final Link link = new Link(diagram.getEntityFactory(), diagram.getCurrentStyleBuilder(), entity1, entity2, + linkType, + LinkArg.build(Display.NULL, 3)); + link.setPortMembers(diagram.getPortId(entity1.getName()), diagram.getPortId(entity2.getName())); + diagram.addLink(link); + + return CommandExecutionResult.ok(); + } + +} diff --git a/src/net/sourceforge/plantuml/decoration/LinkMiddleDecor.java b/src/net/sourceforge/plantuml/decoration/LinkMiddleDecor.java index e2afe1f26..262d05f22 100644 --- a/src/net/sourceforge/plantuml/decoration/LinkMiddleDecor.java +++ b/src/net/sourceforge/plantuml/decoration/LinkMiddleDecor.java @@ -40,10 +40,11 @@ import net.sourceforge.plantuml.svek.extremity.MiddleCircleCircledMode; import net.sourceforge.plantuml.svek.extremity.MiddleFactory; import net.sourceforge.plantuml.svek.extremity.MiddleFactoryCircle; import net.sourceforge.plantuml.svek.extremity.MiddleFactoryCircleCircled; +import net.sourceforge.plantuml.svek.extremity.MiddleFactorySubset; public enum LinkMiddleDecor { - NONE, CIRCLE, CIRCLE_CIRCLED, CIRCLE_CIRCLED1, CIRCLE_CIRCLED2; + NONE, CIRCLE, CIRCLE_CIRCLED, CIRCLE_CIRCLED1, CIRCLE_CIRCLED2, SUBSET, SUPERSET; public MiddleFactory getMiddleFactory(HColor backColor, HColor diagramBackColor) { if (this == CIRCLE) @@ -57,6 +58,12 @@ public enum LinkMiddleDecor { if (this == CIRCLE_CIRCLED2) return new MiddleFactoryCircleCircled(MiddleCircleCircledMode.MODE2, backColor, diagramBackColor); + + if (this == SUBSET) + return new MiddleFactorySubset(false); + + if (this == SUPERSET) + return new MiddleFactorySubset(true); throw new UnsupportedOperationException(); } diff --git a/src/net/sourceforge/plantuml/decoration/LinkType.java b/src/net/sourceforge/plantuml/decoration/LinkType.java index 6a6710684..482004431 100644 --- a/src/net/sourceforge/plantuml/decoration/LinkType.java +++ b/src/net/sourceforge/plantuml/decoration/LinkType.java @@ -148,6 +148,14 @@ public class LinkType { return new LinkType(decor1, decor2, LinkMiddleDecor.CIRCLE_CIRCLED2, linkStyle); } + public LinkType withMiddleSubset() { + return new LinkType(decor1, decor2, LinkMiddleDecor.SUBSET, linkStyle); + } + + public LinkType withMiddleSuperset() { + return new LinkType(decor1, decor2, LinkMiddleDecor.SUPERSET, linkStyle); + } + public LinkType getInvisible() { return new LinkType(decor1, decor2, middleDecor, LinkStyle.INVISIBLE()); } diff --git a/src/net/sourceforge/plantuml/svek/extremity/MiddleFactorySubset.java b/src/net/sourceforge/plantuml/svek/extremity/MiddleFactorySubset.java new file mode 100644 index 000000000..37a2b067c --- /dev/null +++ b/src/net/sourceforge/plantuml/svek/extremity/MiddleFactorySubset.java @@ -0,0 +1,52 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2024, Arnaud Roques + * + * Project Info: https://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * https://plantuml.com/patreon (only 1$ per month!) + * https://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.svek.extremity; + +import net.sourceforge.plantuml.klimt.shape.UDrawable; + +public class MiddleFactorySubset implements MiddleFactory { + + private final boolean reverse; + + public MiddleFactorySubset(boolean reverse) { + this.reverse = reverse; + } + + public UDrawable createUDrawable(double angle) { + return new MiddleSubset(angle, reverse); + } + +} diff --git a/src/net/sourceforge/plantuml/svek/extremity/MiddleSubset.java b/src/net/sourceforge/plantuml/svek/extremity/MiddleSubset.java new file mode 100644 index 000000000..00acf5e0c --- /dev/null +++ b/src/net/sourceforge/plantuml/svek/extremity/MiddleSubset.java @@ -0,0 +1,82 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2024, Arnaud Roques + * + * Project Info: https://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * https://plantuml.com/patreon (only 1$ per month!) + * https://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.svek.extremity; + +import net.sourceforge.plantuml.klimt.UStroke; +import net.sourceforge.plantuml.klimt.UTranslate; +import net.sourceforge.plantuml.klimt.drawing.UGraphic; +import net.sourceforge.plantuml.klimt.geom.XPoint2D; +import net.sourceforge.plantuml.klimt.shape.UEllipse; +import net.sourceforge.plantuml.klimt.shape.ULine; + +class MiddleSubset extends Extremity { + + private final double radius = 6; + private final double length = 10; + + private final double angle; + private final boolean reverse; + + public MiddleSubset(double angle, boolean reverse) { + this.angle = angle; + this.reverse = reverse; + } + + @Override + public XPoint2D somePoint() { + return null; + } + + public void drawU(UGraphic ug) { + ug = ug.apply(UStroke.withThickness(1.5)); + + final double rotate = reverse ? -45 : 135; + + ug.apply(new UTranslate(-radius, -radius)).draw(new UEllipse(2 * radius, 2 * radius, angle + rotate, 180)); + + final double sin = Math.sin(Math.toRadians(angle + rotate)); + final double cos = Math.cos(Math.toRadians(angle + rotate)); + + ug.apply(new UTranslate(radius * cos, radius * -sin)).draw(new ULine(length * sin, length * cos)); + ug.apply(new UTranslate(radius * -cos, radius * sin)).draw(new ULine(length * sin, length * cos)); + } + + @Override + public double getDecorationLength() { + return radius; + } + +} From 96785da1c76a6e31b4b61414892e54caa5b1e734 Mon Sep 17 00:00:00 2001 From: Benjamin Davies Date: Thu, 16 Nov 2023 18:42:47 +1300 Subject: [PATCH 13/23] Add multiple subclasses command --- .../cheneer/ChenEerDiagramFactory.java | 2 + .../cheneer/command/CommandMultiSubclass.java | 139 ++++++++++++++++++ 2 files changed, 141 insertions(+) create mode 100644 src/net/sourceforge/plantuml/cheneer/command/CommandMultiSubclass.java diff --git a/src/net/sourceforge/plantuml/cheneer/ChenEerDiagramFactory.java b/src/net/sourceforge/plantuml/cheneer/ChenEerDiagramFactory.java index 105fa9632..5712b5f99 100644 --- a/src/net/sourceforge/plantuml/cheneer/ChenEerDiagramFactory.java +++ b/src/net/sourceforge/plantuml/cheneer/ChenEerDiagramFactory.java @@ -43,6 +43,7 @@ import net.sourceforge.plantuml.cheneer.command.CommandAssociate; import net.sourceforge.plantuml.cheneer.command.CommandCreateAttribute; import net.sourceforge.plantuml.cheneer.command.CommandCreateEntity; import net.sourceforge.plantuml.cheneer.command.CommandEndGroup; +import net.sourceforge.plantuml.cheneer.command.CommandMultiSubclass; import net.sourceforge.plantuml.cheneer.command.CommandSimpleSubclass; import net.sourceforge.plantuml.command.Command; import net.sourceforge.plantuml.command.CommonCommands; @@ -66,6 +67,7 @@ public class ChenEerDiagramFactory extends PSystemCommandFactory { cmds.add(new CommandAssociate()); cmds.add(new CommandEndGroup()); cmds.add(new CommandSimpleSubclass()); + cmds.add(new CommandMultiSubclass()); } @Override diff --git a/src/net/sourceforge/plantuml/cheneer/command/CommandMultiSubclass.java b/src/net/sourceforge/plantuml/cheneer/command/CommandMultiSubclass.java new file mode 100644 index 000000000..d24e35d6e --- /dev/null +++ b/src/net/sourceforge/plantuml/cheneer/command/CommandMultiSubclass.java @@ -0,0 +1,139 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2024, Arnaud Roques + * + * Project Info: https://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * https://plantuml.com/patreon (only 1$ per month!) + * https://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.cheneer.command; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import net.sourceforge.plantuml.abel.Entity; +import net.sourceforge.plantuml.abel.LeafType; +import net.sourceforge.plantuml.abel.Link; +import net.sourceforge.plantuml.abel.LinkArg; +import net.sourceforge.plantuml.cheneer.ChenEerDiagram; +import net.sourceforge.plantuml.command.CommandExecutionResult; +import net.sourceforge.plantuml.command.SingleLineCommand2; +import net.sourceforge.plantuml.decoration.LinkDecor; +import net.sourceforge.plantuml.decoration.LinkType; +import net.sourceforge.plantuml.klimt.color.NoSuchColorException; +import net.sourceforge.plantuml.klimt.creole.Display; +import net.sourceforge.plantuml.plasma.Quark; +import net.sourceforge.plantuml.regex.IRegex; +import net.sourceforge.plantuml.regex.RegexConcat; +import net.sourceforge.plantuml.regex.RegexLeaf; +import net.sourceforge.plantuml.regex.RegexResult; +import net.sourceforge.plantuml.utils.LineLocation; + +public class CommandMultiSubclass extends SingleLineCommand2 { + + public CommandMultiSubclass() { + super(getRegexConcat()); + } + + private static IRegex getRegexConcat() { + return RegexConcat.build(CommandCreateEntity.class.getName(), RegexLeaf.start(), // + new RegexLeaf("SUPERCLASS", "([\\w-]+)"), // + RegexLeaf.spaceZeroOrMore(), // + new RegexLeaf("PARTICIPATION", "([-=])"), // + new RegexLeaf("(>)"), // + new RegexLeaf("PARTICIPATION2", "([-=])"), // + RegexLeaf.spaceZeroOrMore(), // + new RegexLeaf("SYMBOL", "([doU])"), // + RegexLeaf.spaceZeroOrMore(), // + new RegexLeaf("\\{"), // + new RegexLeaf("SUBCLASSES", "(.+)"), // + new RegexLeaf("\\}"), // + RegexLeaf.end()); + } + + @Override + protected CommandExecutionResult executeArg(ChenEerDiagram diagram, LineLocation location, RegexResult arg) + throws NoSuchColorException { + final String superclass = diagram.cleanId(arg.get("SUPERCLASS", 0)); + final String subclasses = arg.get("SUBCLASSES", 0); + final List subclassIds = Arrays.stream(subclasses.split(",")) + .map(String::trim) + .map(diagram::cleanId) + .collect(Collectors.toList()); + final boolean isDouble = arg.get("PARTICIPATION", 0).equals("="); + final String symbol = arg.get("SYMBOL", 0); + + final Quark centerQuark = diagram.quarkInContext(false, superclass + "/" + symbol + subclasses + "/center"); + // TODO: Custom LeafType + final Entity centerEntity = diagram.reallyCreateLeaf(centerQuark, Display.create(symbol), LeafType.USECASE, null); + + final Quark superclassQuark = diagram.quarkInContext(true, superclass); + final Entity superclassEntity = superclassQuark.getData(); + if (superclassEntity == null) { + return CommandExecutionResult.error("No such entity: " + superclass); + } + + LinkType linkType = new LinkType(LinkDecor.NONE, LinkDecor.NONE); + if (isDouble) { + linkType = linkType.goBold(); + } + if (symbol.equals("U")) { + linkType = linkType.withMiddleSuperset(); + } + final Link link = new Link(diagram.getEntityFactory(), diagram.getCurrentStyleBuilder(), superclassEntity, + centerEntity, + linkType, + LinkArg.build(Display.NULL, 2)); + link.setPortMembers(diagram.getPortId(superclassEntity.getName()), diagram.getPortId(centerEntity.getName())); + diagram.addLink(link); + + for (String subclass : subclassIds) { + final Quark subclassQuark = diagram.quarkInContext(true, subclass); + final Entity subclassEntity = subclassQuark.getData(); + if (subclassEntity == null) { + return CommandExecutionResult.error("No such entity: " + subclass); + } + + LinkType subclassLinkType = new LinkType(LinkDecor.NONE, LinkDecor.NONE); + if (!symbol.equals("U")) { + subclassLinkType = subclassLinkType.withMiddleSuperset(); + } + final Link subclassLink = new Link(diagram.getEntityFactory(), diagram.getCurrentStyleBuilder(), centerEntity, + subclassEntity, + subclassLinkType, + LinkArg.build(Display.NULL, 3)); + diagram.addLink(subclassLink); + } + + return CommandExecutionResult.ok(); + } + +} From 9ad84822fad038b42bfe70d0e59ff786034d5989 Mon Sep 17 00:00:00 2001 From: Benjamin Davies Date: Thu, 16 Nov 2023 18:49:00 +1300 Subject: [PATCH 14/23] Introduce CHEN_CIRCLE entity type --- .../sourceforge/plantuml/abel/LeafType.java | 2 +- .../cheneer/command/CommandMultiSubclass.java | 3 +- .../plantuml/svek/GeneralImageBuilder.java | 4 + .../svek/image/EntityImageChenCircle.java | 175 ++++++++++++++++++ 4 files changed, 181 insertions(+), 3 deletions(-) create mode 100644 src/net/sourceforge/plantuml/svek/image/EntityImageChenCircle.java diff --git a/src/net/sourceforge/plantuml/abel/LeafType.java b/src/net/sourceforge/plantuml/abel/LeafType.java index 4c67360de..34c7a2de4 100644 --- a/src/net/sourceforge/plantuml/abel/LeafType.java +++ b/src/net/sourceforge/plantuml/abel/LeafType.java @@ -62,7 +62,7 @@ public enum LeafType { PORTIN, PORTOUT, - CHEN_ENTITY, CHEN_RELATIONSHIP, CHEN_ATTRIBUTE, + CHEN_ENTITY, CHEN_RELATIONSHIP, CHEN_ATTRIBUTE, CHEN_CIRCLE, STILL_UNKNOWN; diff --git a/src/net/sourceforge/plantuml/cheneer/command/CommandMultiSubclass.java b/src/net/sourceforge/plantuml/cheneer/command/CommandMultiSubclass.java index d24e35d6e..b05ece9ff 100644 --- a/src/net/sourceforge/plantuml/cheneer/command/CommandMultiSubclass.java +++ b/src/net/sourceforge/plantuml/cheneer/command/CommandMultiSubclass.java @@ -92,8 +92,7 @@ public class CommandMultiSubclass extends SingleLineCommand2 { final String symbol = arg.get("SYMBOL", 0); final Quark centerQuark = diagram.quarkInContext(false, superclass + "/" + symbol + subclasses + "/center"); - // TODO: Custom LeafType - final Entity centerEntity = diagram.reallyCreateLeaf(centerQuark, Display.create(symbol), LeafType.USECASE, null); + final Entity centerEntity = diagram.reallyCreateLeaf(centerQuark, Display.create(symbol), LeafType.CHEN_CIRCLE, null); final Quark superclassQuark = diagram.quarkInContext(true, superclass); final Entity superclassEntity = superclassQuark.getData(); diff --git a/src/net/sourceforge/plantuml/svek/GeneralImageBuilder.java b/src/net/sourceforge/plantuml/svek/GeneralImageBuilder.java index 4a18f2783..175478e73 100644 --- a/src/net/sourceforge/plantuml/svek/GeneralImageBuilder.java +++ b/src/net/sourceforge/plantuml/svek/GeneralImageBuilder.java @@ -100,6 +100,7 @@ import net.sourceforge.plantuml.svek.image.EntityImageAssociation; import net.sourceforge.plantuml.svek.image.EntityImageAssociationPoint; import net.sourceforge.plantuml.svek.image.EntityImageBranch; import net.sourceforge.plantuml.svek.image.EntityImageChenAttribute; +import net.sourceforge.plantuml.svek.image.EntityImageChenCircle; import net.sourceforge.plantuml.svek.image.EntityImageChenEntity; import net.sourceforge.plantuml.svek.image.EntityImageChenRelationship; import net.sourceforge.plantuml.svek.image.EntityImageCircleEnd; @@ -266,6 +267,9 @@ public final class GeneralImageBuilder { if (leaf.getLeafType() == LeafType.CHEN_ATTRIBUTE) return new EntityImageChenAttribute(leaf, skinParam); + if (leaf.getLeafType() == LeafType.CHEN_CIRCLE) + return new EntityImageChenCircle(leaf, skinParam); + // TODO Clean if (leaf.getLeafType() == LeafType.DOMAIN && leaf.getStereotype() != null && leaf.getStereotype().isMachineOrSpecification()) diff --git a/src/net/sourceforge/plantuml/svek/image/EntityImageChenCircle.java b/src/net/sourceforge/plantuml/svek/image/EntityImageChenCircle.java new file mode 100644 index 000000000..0badab72e --- /dev/null +++ b/src/net/sourceforge/plantuml/svek/image/EntityImageChenCircle.java @@ -0,0 +1,175 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2024, Arnaud Roques + * + * Project Info: https://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * https://plantuml.com/patreon (only 1$ per month!) + * https://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.svek.image; + +import java.util.Collections; + +import net.sourceforge.plantuml.abel.Entity; +import net.sourceforge.plantuml.klimt.UGroupType; +import net.sourceforge.plantuml.klimt.UShape; +import net.sourceforge.plantuml.klimt.UStroke; +import net.sourceforge.plantuml.klimt.UTranslate; +import net.sourceforge.plantuml.klimt.color.ColorType; +import net.sourceforge.plantuml.klimt.color.Colors; +import net.sourceforge.plantuml.klimt.color.HColor; +import net.sourceforge.plantuml.klimt.creole.CreoleMode; +import net.sourceforge.plantuml.klimt.drawing.UGraphic; +import net.sourceforge.plantuml.klimt.font.FontConfiguration; +import net.sourceforge.plantuml.klimt.font.StringBounder; +import net.sourceforge.plantuml.klimt.geom.HorizontalAlignment; +import net.sourceforge.plantuml.klimt.geom.XDimension2D; +import net.sourceforge.plantuml.klimt.shape.TextBlock; +import net.sourceforge.plantuml.klimt.shape.TextBlockInEllipse; +import net.sourceforge.plantuml.klimt.shape.UEllipse; +import net.sourceforge.plantuml.style.ISkinParam; +import net.sourceforge.plantuml.style.PName; +import net.sourceforge.plantuml.style.SName; +import net.sourceforge.plantuml.style.Style; +import net.sourceforge.plantuml.style.StyleSignatureBasic; +import net.sourceforge.plantuml.svek.AbstractEntityImage; +import net.sourceforge.plantuml.svek.ShapeType; +import net.sourceforge.plantuml.url.Url; + +public class EntityImageChenCircle extends AbstractEntityImage { + + final static private int MARGIN = 6; + + final private boolean isKey; + final private boolean isMulti; + final private boolean isDerived; + + final private TextBlock title; + final private Url url; + + public EntityImageChenCircle(Entity entity, ISkinParam skinParam) { + super(entity, skinParam); + + isKey = hasStereotype("<>"); + isMulti = hasStereotype("<>"); + isDerived = hasStereotype("<>"); + + FontConfiguration titleFontConfiguration = getStyleTitle(entity, skinParam) + .getFontConfiguration(getSkinParam().getIHtmlColorSet(), entity.getColors()); + if (isKey) { + titleFontConfiguration = titleFontConfiguration.underline(); + } + + title = entity.getDisplay().create8(titleFontConfiguration, HorizontalAlignment.CENTER, skinParam, CreoleMode.FULL, + getStyle().wrapWidth()); + + url = entity.getUrl99(); + } + + private boolean hasStereotype(String stereotype) { + return getEntity().getStereotype() != null && getEntity().getStereotype().toString().contains(stereotype); + } + + private Style getStyle() { + return getStyle(getEntity(), getSkinParam()); + } + + private static Style getStyle(Entity group, ISkinParam skinParam) { + return StyleSignatureBasic.of(SName.root, SName.element, SName.chenEerDiagram, SName.circle) + .withTOBECHANGED(group.getStereotype()).getMergedStyle(skinParam.getCurrentStyleBuilder()); + } + + private static Style getStyleTitle(Entity group, ISkinParam skinParam) { + return StyleSignatureBasic.of(SName.root, SName.element, SName.chenEerDiagram, SName.circle, SName.title) + .withTOBECHANGED(group.getStereotype()).getMergedStyle(skinParam.getCurrentStyleBuilder()); + } + + @Override + public ShapeType getShapeType() { + return ShapeType.OVAL; + } + + @Override + public XDimension2D calculateDimension(StringBounder stringBounder) { + return new XDimension2D(25, 25); + } + + @Override + public void drawU(UGraphic ug) { + ug.startGroup(Collections.singletonMap(UGroupType.ID, getEntity().getQuark().toStringPoint())); + if (url != null) + ug.startUrl(url); + + final XDimension2D dimTotal = calculateDimension(ug.getStringBounder()); + final XDimension2D dimTitle = title.calculateDimension(ug.getStringBounder()); + + UStroke stroke = getStyle().getStroke(getEntity().getColors()); + if (isDerived) { + stroke = new UStroke(10, 10, stroke.getThickness()); + } + + ug = applyColor(ug); + ug = ug.apply(stroke); + ug.draw(getShape(dimTotal)); + if (isMulti) { + ug.apply(new UTranslate(3, 3)).draw(getShape(dimTotal.delta(-6))); + } + + final double xTitle = (dimTotal.getWidth() - dimTitle.getWidth()) / 2; + final double yTitle = (dimTotal.getHeight() - dimTitle.getHeight()) / 2; + title.drawU(ug.apply(new UTranslate(xTitle, yTitle))); + + if (url != null) + ug.closeUrl(); + + ug.closeGroup(); + } + + final protected UGraphic applyColor(UGraphic ug) { + Colors colors = getEntity().getColors(); + + HColor border = colors.getColor(ColorType.LINE); + if (border == null) + border = getStyle().value(PName.LineColor).asColor(getSkinParam().getIHtmlColorSet()); + ug = ug.apply(border); + + HColor backcolor = colors.getColor(ColorType.BACK); + if (backcolor == null) + backcolor = getStyle().value(PName.BackGroundColor).asColor(getSkinParam().getIHtmlColorSet()); + ug = ug.apply(backcolor.bg()); + + return ug; + } + + private UShape getShape(XDimension2D dimTotal) { + return UEllipse.build(dimTotal.getWidth(), dimTotal.getHeight()); + } + +} From 273f8b4bf12cebe13558624d01527e515ab3e1c5 Mon Sep 17 00:00:00 2001 From: Benjamin Davies Date: Thu, 16 Nov 2023 20:32:18 +1300 Subject: [PATCH 15/23] Add tests --- .../nonreg/simple/ChenMovieExtended_Test.java | 94 ++ .../simple/ChenMovieExtended_TestResult.java | 1073 +++++++++++++++++ test/nonreg/simple/ChenMovie_Test.java | 56 + test/nonreg/simple/ChenMovie_TestResult.java | 555 +++++++++ 4 files changed, 1778 insertions(+) create mode 100644 test/nonreg/simple/ChenMovieExtended_Test.java create mode 100644 test/nonreg/simple/ChenMovieExtended_TestResult.java create mode 100644 test/nonreg/simple/ChenMovie_Test.java create mode 100644 test/nonreg/simple/ChenMovie_TestResult.java diff --git a/test/nonreg/simple/ChenMovieExtended_Test.java b/test/nonreg/simple/ChenMovieExtended_Test.java new file mode 100644 index 000000000..d26d61e0d --- /dev/null +++ b/test/nonreg/simple/ChenMovieExtended_Test.java @@ -0,0 +1,94 @@ +package nonreg.simple; + +import java.io.IOException; + +import org.junit.jupiter.api.Test; + +import nonreg.BasicTest; + +/* + +Test diagram MUST be put between triple quotes + +""" +@startchen movies + +entity DIRECTOR { + Number <> + Name { + Fname + Lname + } + Born : DATE + Died + Age +} + +entity CUSTOMER { + Number <> + Bonus <> + Name <> +} + +entity MOVIE { + Code +} + +relationship RENTED_TO { + Date +} + +RENTED_TO -1- CUSTOMER +RENTED_TO -N- MOVIE +RENTED_TO -(N,M)- DIRECTOR + +entity PARENT { +} + +entity MEMBER { +} + +CUSTOMER ->- PARENT +MEMBER -<- CUSTOMER + +entity CHILD <> { + Name <> +} + +relationship PARENT_OF <> { +} + +PARENT_OF -1- PARENT +PARENT_OF =N= CHILD + +entity TODDLER { + FavoriteToy +} + +entity PRIMARY_AGE { + FavoriteColor +} + +entity TEEN { + Hobby +} + +CHILD =>= d { TODDLER, PRIMARY_AGE, TEEN } + +entity PERSON { +} + +PERSON ->- U { CUSTOMER, DIRECTOR } + +@endchen +""" + + */ +public class ChenMovieExtended_Test extends BasicTest { + + @Test + void testSimple() throws IOException { + checkImage("(30 entities)"); + } + +} diff --git a/test/nonreg/simple/ChenMovieExtended_TestResult.java b/test/nonreg/simple/ChenMovieExtended_TestResult.java new file mode 100644 index 000000000..6219b35af --- /dev/null +++ b/test/nonreg/simple/ChenMovieExtended_TestResult.java @@ -0,0 +1,1073 @@ +package nonreg.simple; + +public class ChenMovieExtended_TestResult { +} +/* +""" +DPI: 96 +dimension: [ 1611.3106 ; 720.0000 ] +scaleFactor: 1.0000 +seed: -7760046765121812191 +svgLinkTarget: _top +hoverPathColorRGB: null +preserveAspectRatio: none + +RECTANGLE: + pt1: [ 298.5000 ; 310.0000 ] + pt2: [ 413.4536 ; 344.0000 ] + xCorner: 0 + yCorner: 0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: DIRECTOR + position: [ 308.5000 ; 330.8889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +ELLIPSE: + pt1: [ 200.5000 ; 217.0000 ] + pt2: [ 319.7119 ; 245.6424 ] + start: 0.0 + extend: 0.0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: Number + position: [ 215.6174 ; 233.8889 ] + orientation: 0 + font: SansSerif.plain/14 [UNDERLINE] + color: ff000000 + extendedColor: NULL_COLOR + +ELLIPSE: + pt1: [ 82.0000 ; 218.5000 ] + pt2: [ 182.4750 ; 244.2990 ] + start: 0.0 + extend: 0.0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: Name + position: [ 98.8355 ; 235.3889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +ELLIPSE: + pt1: [ 24.5000 ; 115.5000 ] + pt2: [ 117.5753 ; 141.2990 ] + start: 0.0 + extend: 0.0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: Fname + position: [ 40.2519 ; 132.3889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +ELLIPSE: + pt1: [ 136.0000 ; 114.5000 ] + pt2: [ 250.0711 ; 142.1142 ] + start: 0.0 + extend: 0.0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: Lname + position: [ 151.8671 ; 131.3889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +ELLIPSE: + pt1: [ 434.0000 ; 211.0000 ] + pt2: [ 613.7951 ; 251.7590 ] + start: 0.0 + extend: 0.0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: Born : DATE + position: [ 444.3602 ; 227.8889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +ELLIPSE: + pt1: [ 632.0000 ; 218.5000 ] + pt2: [ 705.9416 ; 244.2990 ] + start: 0.0 + extend: 0.0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: Died + position: [ 644.9498 ; 235.3889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +ELLIPSE: + pt1: [ 6.0000 ; 218.5000 ] + pt2: [ 64.3515 ; 244.2990 ] + start: 0.0 + extend: 0.0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: Age + position: [ 16.6667 ; 235.3889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +RECTANGLE: + pt1: [ 1158.0000 ; 310.0000 ] + pt2: [ 1290.4781 ; 344.0000 ] + xCorner: 0 + yCorner: 0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: CUSTOMER + position: [ 1168.0000 ; 330.8889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +ELLIPSE: + pt1: [ 966.5000 ; 217.0000 ] + pt2: [ 1085.7119 ; 245.6424 ] + start: 0.0 + extend: 0.0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: Number + position: [ 981.6174 ; 233.8889 ] + orientation: 0 + font: SansSerif.plain/14 [UNDERLINE] + color: ff000000 + extendedColor: NULL_COLOR + +ELLIPSE: + pt1: [ 1103.5000 ; 217.5000 ] + pt2: [ 1218.1275 ; 245.2255 ] + start: 0.0 + extend: 0.0 + stroke: 10.0-10.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: Bonus + position: [ 1119.2808 ; 234.3889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +ELLIPSE: + pt1: [ 1237.0000 ; 218.5000 ] + pt2: [ 1337.4750 ; 244.2990 ] + start: 0.0 + extend: 0.0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +ELLIPSE: + pt1: [ 1240.0000 ; 221.5000 ] + pt2: [ 1334.4750 ; 241.2990 ] + start: 0.0 + extend: 0.0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: Name + position: [ 1253.8355 ; 235.3889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +RECTANGLE: + pt1: [ 759.0000 ; 310.0000 ] + pt2: [ 837.2949 ; 344.0000 ] + xCorner: 0 + yCorner: 0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: MOVIE + position: [ 769.0000 ; 330.8889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +ELLIPSE: + pt1: [ 810.5000 ; 218.5000 ] + pt2: [ 899.6043 ; 244.2990 ] + start: 0.0 + extend: 0.0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: Code + position: [ 825.6703 ; 235.3889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +POLYGON: + points: + - [ 651.5000 ; 128.3553 ] + - [ 742.2105 ; 83.0000 ] + - [ 832.9210 ; 128.3553 ] + - [ 742.2105 ; 173.7105 ] + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: RENTED_TO + position: [ 676.6803 ; 132.2441 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +ELLIPSE: + pt1: [ 700.0000 ; 16.0000 ] + pt2: [ 783.5211 ; 41.7990 ] + start: 0.0 + extend: 0.0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: Date + position: [ 714.3527 ; 32.8889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +RECTANGLE: + pt1: [ 1229.5000 ; 465.0000 ] + pt2: [ 1354.0571 ; 499.0000 ] + xCorner: 0 + yCorner: 0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: PARENT + position: [ 1239.5000 ; 485.8889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +RECTANGLE: + pt1: [ 1346.0000 ; 111.5000 ] + pt2: [ 1460.3033 ; 145.5000 ] + xCorner: 0 + yCorner: 0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: MEMBER + position: [ 1356.0000 ; 132.3889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +RECTANGLE: + pt1: [ 1395.0000 ; 465.0000 ] + pt2: [ 1488.9311 ; 499.0000 ] + xCorner: 0 + yCorner: 0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +RECTANGLE: + pt1: [ 1398.0000 ; 468.0000 ] + pt2: [ 1485.9311 ; 496.0000 ] + xCorner: 0 + yCorner: 0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: CHILD + position: [ 1405.0000 ; 485.8889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +ELLIPSE: + pt1: [ 1414.0000 ; 402.0000 ] + pt2: [ 1514.4750 ; 427.7990 ] + start: 0.0 + extend: 0.0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: Name + position: [ 1430.8355 ; 418.8889 ] + orientation: 0 + font: SansSerif.plain/14 [UNDERLINE] + color: ff000000 + extendedColor: NULL_COLOR + +POLYGON: + points: + - [ 1308.0000 ; 327.0569 ] + - [ 1384.1139 ; 289.0000 ] + - [ 1460.2278 ; 327.0569 ] + - [ 1384.1139 ; 365.1139 ] + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +POLYGON: + points: + - [ 1318.0000 ; 327.0569 ] + - [ 1384.1139 ; 294.0000 ] + - [ 1450.2278 ; 327.0569 ] + - [ 1384.1139 ; 360.1139 ] + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: PARENT_OF + position: [ 1333.1803 ; 330.9458 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +RECTANGLE: + pt1: [ 1054.5000 ; 681.0000 ] + pt2: [ 1181.8526 ; 715.0000 ] + xCorner: 0 + yCorner: 0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: TODDLER + position: [ 1064.5000 ; 701.8889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +ELLIPSE: + pt1: [ 948.5000 ; 598.0000 ] + pt2: [ 1155.2015 ; 644.1403 ] + start: 0.0 + extend: 0.0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: FavoriteToy + position: [ 957.8014 ; 614.8889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +RECTANGLE: + pt1: [ 1267.5000 ; 681.0000 ] + pt2: [ 1456.6987 ; 715.0000 ] + xCorner: 0 + yCorner: 0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: PRIMARY_AGE + position: [ 1277.5000 ; 701.8889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +ELLIPSE: + pt1: [ 1212.0000 ; 598.5000 ] + pt2: [ 1414.3804 ; 643.7761 ] + start: 0.0 + extend: 0.0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: FavoriteColor + position: [ 1221.4497 ; 615.3889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +RECTANGLE: + pt1: [ 1523.0000 ; 681.0000 ] + pt2: [ 1589.1122 ; 715.0000 ] + xCorner: 0 + yCorner: 0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: TEEN + position: [ 1533.0000 ; 701.8889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +ELLIPSE: + pt1: [ 1470.5000 ; 608.0000 ] + pt2: [ 1577.1381 ; 634.1276 ] + start: 0.0 + extend: 0.0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: Hobby + position: [ 1487.6665 ; 624.8889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +ELLIPSE: + pt1: [ 1429.5000 ; 536.0000 ] + pt2: [ 1454.5000 ; 561.0000 ] + start: 0.0 + extend: 0.0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: d + position: [ 1435.3082 ; 552.3889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +RECTANGLE: + pt1: [ 867.0000 ; 12.0000 ] + pt2: [ 957.4807 ; 46.0000 ] + xCorner: 0 + yCorner: 0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: PERSON + position: [ 877.0000 ; 32.8889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +ELLIPSE: + pt1: [ 899.5000 ; 116.0000 ] + pt2: [ 924.5000 ; 141.0000 ] + start: 0.0 + extend: 0.0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: U + position: [ 905.3048 ; 132.3889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 268.1651 ; 240.2962 ] + - type: SEG_CUBICTO + pt1: [ 285.5853 ; 257.2628 ] + pt2: [ 315.1026 ; 286.0114 ] + pt3: [ 333.5209 ; 303.9500 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 154.8255 ; 238.5321 ] + - type: SEG_CUBICTO + pt1: [ 194.7642 ; 255.2029 ] + pt2: [ 267.0296 ; 285.3673 ] + pt3: [ 311.5348 ; 303.9442 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 72.4798 ; 135.8846 ] + - type: SEG_CUBICTO + pt1: [ 84.2510 ; 155.3746 ] + pt2: [ 106.9591 ; 192.9732 ] + pt3: [ 118.6496 ; 212.3296 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 179.0253 ; 136.7040 ] + - type: SEG_CUBICTO + pt1: [ 167.1409 ; 156.3814 ] + pt2: [ 144.9474 ; 193.1281 ] + pt3: [ 133.4036 ; 212.2416 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 482.7817 ; 246.1007 ] + - type: SEG_CUBICTO + pt1: [ 451.8961 ; 263.2900 ] + pt2: [ 407.5456 ; 287.9731 ] + pt3: [ 378.7542 ; 303.9969 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 635.9871 ; 238.6440 ] + - type: SEG_CUBICTO + pt1: [ 629.8072 ; 241.2278 ] + pt2: [ 623.2244 ; 243.8286 ] + pt3: [ 617.0000 ; 246.0000 ] + - type: SEG_CUBICTO + pt1: [ 546.0356 ; 270.7566 ] + pt2: [ 462.2325 ; 292.8599 ] + pt3: [ 407.6991 ; 306.3262 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 50.7303 ; 238.6785 ] + - type: SEG_CUBICTO + pt1: [ 55.9588 ; 241.3192 ] + pt2: [ 61.5971 ; 243.9358 ] + pt3: [ 67.0000 ; 246.0000 ] + - type: SEG_CUBICTO + pt1: [ 142.9032 ; 274.9989 ] + pt2: [ 234.4743 ; 296.6554 ] + pt3: [ 292.4787 ; 308.8199 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 1048.7909 ; 240.0957 ] + - type: SEG_CUBICTO + pt1: [ 1084.6142 ; 257.0123 ] + pt2: [ 1145.7067 ; 285.8615 ] + pt3: [ 1183.8552 ; 303.8761 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 1163.7599 ; 239.5008 ] + - type: SEG_CUBICTO + pt1: [ 1175.1200 ; 256.3607 ] + pt2: [ 1194.9292 ; 285.7601 ] + pt3: [ 1207.2057 ; 303.9799 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 1272.7639 ; 238.7235 ] + - type: SEG_CUBICTO + pt1: [ 1261.5571 ; 255.3557 ] + pt2: [ 1241.4744 ; 285.1610 ] + pt3: [ 1228.9918 ; 303.6868 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 841.5482 ; 238.7235 ] + - type: SEG_CUBICTO + pt1: [ 831.4088 ; 255.3557 ] + pt2: [ 813.2388 ; 285.1610 ] + pt3: [ 801.9449 ; 303.6868 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 736.0000 ; 36.3484 ] + - type: SEG_CUBICTO + pt1: [ 736.0000 ; 46.5968 ] + pt2: [ 736.0000 ; 61.8318 ] + pt3: [ 736.0000 ; 76.5937 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 826.7636 ; 160.0422 ] + - type: SEG_CUBICTO + pt1: [ 852.5824 ; 172.4484 ] + pt2: [ 879.9325 ; 187.6334 ] + pt3: [ 903.0000 ; 205.0000 ] + - type: SEG_CUBICTO + pt1: [ 922.6093 ; 219.7630 ] + pt2: [ 919.0540 ; 233.2041 ] + pt3: [ 940.0000 ; 246.0000 ] + - type: SEG_CUBICTO + pt1: [ 1005.5294 ; 286.0319 ] + pt2: [ 1092.6223 ; 304.6706 ] + pt3: [ 1151.7405 ; 313.1735 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +EMPTY: + pt1: [ 946.0000 ; 225.0000 ] + pt2: [ 958.3969 ; 238.0000 ] + +TEXT: + text: 1 + position: [ 947.0000 ; 234.5556 ] + orientation: 0 + font: SansSerif.plain/11 [] + color: ff000000 + extendedColor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 748.7073 ; 168.0889 ] + - type: SEG_CUBICTO + pt1: [ 761.0345 ; 211.3442 ] + pt2: [ 779.0663 ; 274.6167 ] + pt3: [ 787.4284 ; 303.9587 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +EMPTY: + pt1: [ 776.0000 ; 225.0000 ] + pt2: [ 788.5088 ; 238.0000 ] + +TEXT: + text: N + position: [ 777.0000 ; 234.5556 ] + orientation: 0 + font: SansSerif.plain/11 [] + color: ff000000 + extendedColor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 645.2131 ; 130.8428 ] + - type: SEG_CUBICTO + pt1: [ 545.9048 ; 140.9068 ] + pt2: [ 395.8949 ; 162.7634 ] + pt3: [ 359.0000 ; 205.0000 ] + - type: SEG_CUBICTO + pt1: [ 335.0217 ; 232.4498 ] + pt2: [ 340.5887 ; 278.9941 ] + pt3: [ 345.8106 ; 303.6089 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +EMPTY: + pt1: [ 365.0000 ; 225.0000 ] + pt2: [ 425.5178 ; 238.0000 ] + +TEXT: + text: (N,M) + position: [ 366.0000 ; 234.5556 ] + orientation: 0 + font: SansSerif.plain/11 [] + color: ff000000 + extendedColor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 1225.1487 ; 338.0845 ] + - type: SEG_CUBICTO + pt1: [ 1238.1745 ; 367.3927 ] + pt2: [ 1265.6366 ; 429.1824 ] + pt3: [ 1278.7424 ; 458.6705 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 1399.4767 ; 139.5548 ] + - type: SEG_CUBICTO + pt1: [ 1402.9872 ; 168.6950 ] + pt2: [ 1405.7433 ; 230.4632 ] + pt3: [ 1373.0000 ; 265.0000 ] + - type: SEG_CUBICTO + pt1: [ 1347.9258 ; 291.4477 ] + pt2: [ 1327.3605 ; 270.8529 ] + pt3: [ 1293.0000 ; 283.0000 ] + - type: SEG_CUBICTO + pt1: [ 1277.1209 ; 288.6136 ] + pt2: [ 1260.2330 ; 296.7368 ] + pt3: [ 1246.5110 ; 303.9427 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 1453.8620 ; 422.2260 ] + - type: SEG_CUBICTO + pt1: [ 1450.3768 ; 432.5231 ] + pt2: [ 1445.3615 ; 447.3410 ] + pt3: [ 1441.5320 ; 458.6555 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 1355.7294 ; 359.0370 ] + - type: SEG_CUBICTO + pt1: [ 1336.5849 ; 390.8751 ] + pt2: [ 1309.8892 ; 435.2712 ] + pt3: [ 1295.7259 ; 458.8254 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +EMPTY: + pt1: [ 1338.0000 ; 408.5000 ] + pt2: [ 1350.3969 ; 421.5000 ] + +TEXT: + text: 1 + position: [ 1339.0000 ; 418.0556 ] + orientation: 0 + font: SansSerif.plain/11 [] + color: ff000000 + extendedColor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 1375.7164 ; 359.0616 ] + - type: SEG_CUBICTO + pt1: [ 1375.8794 ; 378.5549 ] + pt2: [ 1378.2970 ; 402.4053 ] + pt3: [ 1387.0000 ; 422.0000 ] + - type: SEG_CUBICTO + pt1: [ 1393.3583 ; 436.3156 ] + pt2: [ 1405.1898 ; 449.2873 ] + pt3: [ 1415.6337 ; 458.8144 ] + stroke: 0.0-0.0-2.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +EMPTY: + pt1: [ 1393.0000 ; 408.5000 ] + pt2: [ 1405.5088 ; 421.5000 ] + +TEXT: + text: N + position: [ 1394.0000 ; 418.0556 ] + orientation: 0 + font: SansSerif.plain/11 [] + color: ff000000 + extendedColor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 1065.4452 ; 638.0968 ] + - type: SEG_CUBICTO + pt1: [ 1075.7878 ; 649.8497 ] + pt2: [ 1088.2804 ; 664.0459 ] + pt3: [ 1097.7196 ; 674.7723 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 1321.1728 ; 637.6931 ] + - type: SEG_CUBICTO + pt1: [ 1328.8608 ; 649.4605 ] + pt2: [ 1338.2095 ; 663.7696 ] + pt3: [ 1345.2846 ; 674.5989 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 1523.1414 ; 628.0500 ] + - type: SEG_CUBICTO + pt1: [ 1528.5475 ; 640.7208 ] + pt2: [ 1537.0854 ; 660.7313 ] + pt3: [ 1543.0805 ; 674.7824 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 1436.0000 ; 493.2761 ] + - type: SEG_CUBICTO + pt1: [ 1436.0000 ; 504.6212 ] + pt2: [ 1436.0000 ; 519.4948 ] + pt3: [ 1436.0000 ; 529.7072 ] + stroke: 0.0-0.0-2.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 1423.2771 ; 543.2072 ] + - type: SEG_CUBICTO + pt1: [ 1385.7609 ; 542.9125 ] + pt2: [ 1273.4289 ; 546.1572 ] + pt3: [ 1197.0000 ; 592.0000 ] + - type: SEG_CUBICTO + pt1: [ 1174.2590 ; 605.6403 ] + pt2: [ 1176.2443 ; 617.8544 ] + pt3: [ 1159.0000 ; 638.0000 ] + - type: SEG_CUBICTO + pt1: [ 1148.2836 ; 650.5194 ] + pt2: [ 1135.9085 ; 664.4539 ] + pt3: [ 1126.5474 ; 674.8919 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 1436.0189 ; 555.0998 ] + - type: SEG_CUBICTO + pt1: [ 1435.5583 ; 573.8059 ] + pt2: [ 1432.5689 ; 611.2406 ] + pt3: [ 1417.0000 ; 638.0000 ] + - type: SEG_CUBICTO + pt1: [ 1408.3927 ; 652.7940 ] + pt2: [ 1394.1355 ; 665.5244 ] + pt3: [ 1381.5681 ; 674.7981 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 1448.8860 ; 543.2582 ] + - type: SEG_CUBICTO + pt1: [ 1478.2165 ; 543.4959 ] + pt2: [ 1549.8255 ; 548.7005 ] + pt3: [ 1581.0000 ; 592.0000 ] + - type: SEG_CUBICTO + pt1: [ 1599.3106 ; 617.4323 ] + pt2: [ 1578.4090 ; 654.0281 ] + pt3: [ 1563.1402 ; 674.8629 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 906.0000 ; 40.1001 ] + - type: SEG_CUBICTO + pt1: [ 906.0000 ; 59.7879 ] + pt2: [ 906.0000 ; 92.6243 ] + pt3: [ 906.0000 ; 109.9627 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 918.8689 ; 123.8100 ] + - type: SEG_CUBICTO + pt1: [ 984.8556 ; 125.6932 ] + pt2: [ 1284.3167 ; 137.8868 ] + pt3: [ 1340.0000 ; 205.0000 ] + - type: SEG_CUBICTO + pt1: [ 1351.6354 ; 219.0238 ] + pt2: [ 1348.9399 ; 230.1215 ] + pt3: [ 1340.0000 ; 246.0000 ] + - type: SEG_CUBICTO + pt1: [ 1330.2773 ; 263.2689 ] + pt2: [ 1285.0517 ; 287.8579 ] + pt3: [ 1252.4998 ; 303.8713 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 893.3683 ; 131.4109 ] + - type: SEG_CUBICTO + pt1: [ 872.0927 ; 145.0407 ] + pt2: [ 828.2752 ; 174.4430 ] + pt3: [ 796.0000 ; 205.0000 ] + - type: SEG_CUBICTO + pt1: [ 778.8096 ; 221.2753 ] + pt2: [ 782.4478 ; 234.0717 ] + pt3: [ 762.0000 ; 246.0000 ] + - type: SEG_CUBICTO + pt1: [ 702.6802 ; 280.6044 ] + pt2: [ 506.3854 ; 304.4476 ] + pt3: [ 407.7005 ; 314.5578 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +""" +*/ \ No newline at end of file diff --git a/test/nonreg/simple/ChenMovie_Test.java b/test/nonreg/simple/ChenMovie_Test.java new file mode 100644 index 000000000..98e3dace5 --- /dev/null +++ b/test/nonreg/simple/ChenMovie_Test.java @@ -0,0 +1,56 @@ +package nonreg.simple; + +import java.io.IOException; + +import org.junit.jupiter.api.Test; + +import nonreg.BasicTest; + +/* + +Test diagram MUST be put between triple quotes + +""" +@startchen movies + +entity DIRECTOR { + Number <> + Name { + Fname + Lname + } + Born : DATE + Died + Age +} + +entity CUSTOMER { + Number <> + Bonus <> + Name <> +} + +entity MOVIE { + Code +} + +relationship RENTED_TO { + Date +} + +RENTED_TO -1- CUSTOMER +RENTED_TO -N- MOVIE +RENTED_TO -(N,M)- DIRECTOR + +@endchen +""" + + */ +public class ChenMovie_Test extends BasicTest { + + @Test + void testSimple() throws IOException { + checkImage("(16 entities)"); + } + +} diff --git a/test/nonreg/simple/ChenMovie_TestResult.java b/test/nonreg/simple/ChenMovie_TestResult.java new file mode 100644 index 000000000..73d81f756 --- /dev/null +++ b/test/nonreg/simple/ChenMovie_TestResult.java @@ -0,0 +1,555 @@ +package nonreg.simple; + +public class ChenMovie_TestResult { +} +/* +""" +DPI: 96 +dimension: [ 1357.2949 ; 320.0000 ] +scaleFactor: 1.0000 +seed: 1893551533522493087 +svgLinkTarget: _top +hoverPathColorRGB: null +preserveAspectRatio: none + +RECTANGLE: + pt1: [ 411.5000 ; 281.0000 ] + pt2: [ 526.4536 ; 315.0000 ] + xCorner: 0 + yCorner: 0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: DIRECTOR + position: [ 421.5000 ; 301.8889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +ELLIPSE: + pt1: [ 654.5000 ; 209.0000 ] + pt2: [ 773.7119 ; 237.6424 ] + start: 0.0 + extend: 0.0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: Number + position: [ 669.6174 ; 225.8889 ] + orientation: 0 + font: SansSerif.plain/14 [UNDERLINE] + color: ff000000 + extendedColor: NULL_COLOR + +ELLIPSE: + pt1: [ 74.0000 ; 210.5000 ] + pt2: [ 174.4750 ; 236.2990 ] + start: 0.0 + extend: 0.0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: Name + position: [ 90.8355 ; 227.3889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +ELLIPSE: + pt1: [ 138.5000 ; 107.5000 ] + pt2: [ 231.5753 ; 133.2990 ] + start: 0.0 + extend: 0.0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: Fname + position: [ 154.2519 ; 124.3889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +ELLIPSE: + pt1: [ 6.0000 ; 106.5000 ] + pt2: [ 120.0711 ; 134.1142 ] + start: 0.0 + extend: 0.0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: Lname + position: [ 21.8671 ; 123.3889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +ELLIPSE: + pt1: [ 192.0000 ; 203.0000 ] + pt2: [ 371.7951 ; 243.7590 ] + start: 0.0 + extend: 0.0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: Born : DATE + position: [ 202.3602 ; 219.8889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +ELLIPSE: + pt1: [ 390.0000 ; 210.5000 ] + pt2: [ 463.9416 ; 236.2990 ] + start: 0.0 + extend: 0.0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: Died + position: [ 402.9498 ; 227.3889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +ELLIPSE: + pt1: [ 482.0000 ; 210.5000 ] + pt2: [ 540.3515 ; 236.2990 ] + start: 0.0 + extend: 0.0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: Age + position: [ 492.6667 ; 227.3889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +RECTANGLE: + pt1: [ 917.0000 ; 281.0000 ] + pt2: [ 1049.4781 ; 315.0000 ] + xCorner: 0 + yCorner: 0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: CUSTOMER + position: [ 927.0000 ; 301.8889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +ELLIPSE: + pt1: [ 1091.5000 ; 209.0000 ] + pt2: [ 1210.7119 ; 237.6424 ] + start: 0.0 + extend: 0.0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: Number + position: [ 1106.6174 ; 225.8889 ] + orientation: 0 + font: SansSerif.plain/14 [UNDERLINE] + color: ff000000 + extendedColor: NULL_COLOR + +ELLIPSE: + pt1: [ 791.5000 ; 209.5000 ] + pt2: [ 906.1275 ; 237.2255 ] + start: 0.0 + extend: 0.0 + stroke: 10.0-10.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: Bonus + position: [ 807.2808 ; 226.3889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +ELLIPSE: + pt1: [ 973.0000 ; 210.5000 ] + pt2: [ 1073.4750 ; 236.2990 ] + start: 0.0 + extend: 0.0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +ELLIPSE: + pt1: [ 976.0000 ; 213.5000 ] + pt2: [ 1070.4750 ; 233.2990 ] + start: 0.0 + extend: 0.0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: Name + position: [ 989.8355 ; 227.3889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +RECTANGLE: + pt1: [ 1274.0000 ; 281.0000 ] + pt2: [ 1352.2949 ; 315.0000 ] + xCorner: 0 + yCorner: 0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: MOVIE + position: [ 1284.0000 ; 301.8889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +ELLIPSE: + pt1: [ 1228.5000 ; 210.5000 ] + pt2: [ 1317.6043 ; 236.2990 ] + start: 0.0 + extend: 0.0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: Code + position: [ 1243.6703 ; 227.3889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +POLYGON: + points: + - [ 852.5000 ; 120.3553 ] + - [ 943.2105 ; 75.0000 ] + - [ 1033.9210 ; 120.3553 ] + - [ 943.2105 ; 165.7105 ] + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: RENTED_TO + position: [ 877.6803 ; 124.2441 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +ELLIPSE: + pt1: [ 901.0000 ; 12.0000 ] + pt2: [ 984.5211 ; 37.7990 ] + start: 0.0 + extend: 0.0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: Date + position: [ 915.3527 ; 28.8889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 665.3328 ; 232.0606 ] + - type: SEG_CUBICTO + pt1: [ 641.4594 ; 239.5693 ] + pt2: [ 611.1286 ; 248.9786 ] + pt3: [ 584.0000 ; 257.0000 ] + - type: SEG_CUBICTO + pt1: [ 563.3889 ; 263.0943 ] + pt2: [ 540.7253 ; 269.5323 ] + pt3: [ 520.6400 ; 275.1474 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 151.7733 ; 230.5368 ] + - type: SEG_CUBICTO + pt1: [ 159.9663 ; 233.2134 ] + pt2: [ 168.7450 ; 235.8814 ] + pt3: [ 177.0000 ; 238.0000 ] + - type: SEG_CUBICTO + pt1: [ 255.1385 ; 258.0537 ] + pt2: [ 347.1264 ; 273.7179 ] + pt3: [ 405.2514 ; 282.6619 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 171.5202 ; 127.8846 ] + - type: SEG_CUBICTO + pt1: [ 159.7490 ; 147.3746 ] + pt2: [ 137.0409 ; 184.9732 ] + pt3: [ 125.3504 ; 204.3296 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 64.9747 ; 128.7040 ] + - type: SEG_CUBICTO + pt1: [ 76.8591 ; 148.3814 ] + pt2: [ 99.0526 ; 185.1281 ] + pt3: [ 110.5964 ; 204.2416 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 326.6049 ; 238.1195 ] + - type: SEG_CUBICTO + pt1: [ 356.3505 ; 249.6519 ] + pt2: [ 393.4909 ; 264.0513 ] + pt3: [ 421.5014 ; 274.9110 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 428.1247 ; 230.7986 ] + - type: SEG_CUBICTO + pt1: [ 435.1459 ; 242.9185 ] + pt2: [ 445.9126 ; 261.5039 ] + pt3: [ 453.6250 ; 274.8170 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 497.8753 ; 230.7986 ] + - type: SEG_CUBICTO + pt1: [ 490.8541 ; 242.9185 ] + pt2: [ 480.0874 ; 261.5039 ] + pt3: [ 472.3750 ; 274.8170 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 1113.4005 ; 232.1367 ] + - type: SEG_CUBICTO + pt1: [ 1085.2657 ; 244.2782 ] + pt2: [ 1044.0729 ; 262.0549 ] + pt3: [ 1014.3238 ; 274.8930 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 867.2664 ; 231.6292 ] + - type: SEG_CUBICTO + pt1: [ 889.7416 ; 243.7893 ] + pt2: [ 923.2277 ; 261.9068 ] + pt3: [ 947.2935 ; 274.9275 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 1010.2145 ; 230.7986 ] + - type: SEG_CUBICTO + pt1: [ 1003.5277 ; 242.9185 ] + pt2: [ 993.2737 ; 261.5039 ] + pt3: [ 985.9285 ; 274.8170 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 1273.7855 ; 230.7986 ] + - type: SEG_CUBICTO + pt1: [ 1280.4723 ; 242.9185 ] + pt2: [ 1290.7263 ; 261.5039 ] + pt3: [ 1298.0715 ; 274.8170 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 937.0000 ; 32.2235 ] + - type: SEG_CUBICTO + pt1: [ 937.0000 ; 41.6286 ] + pt2: [ 937.0000 ; 55.2460 ] + pt3: [ 937.0000 ; 68.6542 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 935.4608 ; 160.0549 ] + - type: SEG_CUBICTO + pt1: [ 935.8346 ; 183.6946 ] + pt2: [ 938.2163 ; 212.9522 ] + pt3: [ 946.0000 ; 238.0000 ] + - type: SEG_CUBICTO + pt1: [ 950.1123 ; 251.2335 ] + pt2: [ 958.0422 ; 264.6940 ] + pt3: [ 964.8519 ; 274.7384 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +EMPTY: + pt1: [ 952.0000 ; 217.0000 ] + pt2: [ 964.3969 ; 230.0000 ] + +TEXT: + text: 1 + position: [ 953.0000 ; 226.5556 ] + orientation: 0 + font: SansSerif.plain/11 [] + color: ff000000 + extendedColor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 1027.7972 ; 121.8769 ] + - type: SEG_CUBICTO + pt1: [ 1129.4735 ; 131.1293 ] + pt2: [ 1284.8054 ; 152.3173 ] + pt3: [ 1321.0000 ; 197.0000 ] + - type: SEG_CUBICTO + pt1: [ 1338.9667 ; 219.1802 ] + pt2: [ 1326.2568 ; 254.3104 ] + pt3: [ 1316.1265 ; 274.7586 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +EMPTY: + pt1: [ 1336.0000 ; 217.0000 ] + pt2: [ 1348.5088 ; 230.0000 ] + +TEXT: + text: N + position: [ 1337.0000 ; 226.5556 ] + orientation: 0 + font: SansSerif.plain/11 [] + color: ff000000 + extendedColor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 846.3294 ; 120.6490 ] + - type: SEG_CUBICTO + pt1: [ 770.3065 ; 128.4455 ] + pt2: [ 661.2914 ; 148.0025 ] + pt3: [ 579.0000 ; 197.0000 ] + - type: SEG_CUBICTO + pt1: [ 558.1640 ; 209.4060 ] + pt2: [ 561.2682 ; 222.0525 ] + pt3: [ 543.0000 ; 238.0000 ] + - type: SEG_CUBICTO + pt1: [ 527.0605 ; 251.9147 ] + pt2: [ 507.2472 ; 265.0672 ] + pt3: [ 491.3266 ; 274.7892 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +EMPTY: + pt1: [ 585.0000 ; 217.0000 ] + pt2: [ 645.5178 ; 230.0000 ] + +TEXT: + text: (N,M) + position: [ 586.0000 ; 226.5556 ] + orientation: 0 + font: SansSerif.plain/11 [] + color: ff000000 + extendedColor: NULL_COLOR + +""" +*/ \ No newline at end of file From 8312e8c22f840d934fee37a613f3fc9a24caea96 Mon Sep 17 00:00:00 2001 From: Benjamin Davies Date: Sat, 16 Mar 2024 17:38:41 +1300 Subject: [PATCH 16/23] Correctly detect cheneer diagrams --- src/net/sourceforge/plantuml/core/DiagramType.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/net/sourceforge/plantuml/core/DiagramType.java b/src/net/sourceforge/plantuml/core/DiagramType.java index 24a92b7e3..b01603de0 100644 --- a/src/net/sourceforge/plantuml/core/DiagramType.java +++ b/src/net/sourceforge/plantuml/core/DiagramType.java @@ -127,6 +127,9 @@ public enum DiagramType { if (StartUtils.startsWithSymbolAnd("startfiles", s)) return FILES; + if (StartUtils.startsWithSymbolAnd("startchen", s)) + return CHEN_EER; + return UNKNOWN; } } From 90a88ce4ee2f69191dac4d6281d7fb0bec204b19 Mon Sep 17 00:00:00 2001 From: Benjamin Davies Date: Sat, 16 Mar 2024 18:42:55 +1300 Subject: [PATCH 17/23] Support long name and alias in Chen-EER --- .../cheneer/command/CommandAssociate.java | 86 +++++------ .../command/CommandCreateAttribute.java | 111 ++++++++------- .../cheneer/command/CommandCreateEntity.java | 113 ++++++++------- .../cheneer/command/CommandMultiSubclass.java | 134 +++++++++--------- .../command/CommandSimpleSubclass.java | 94 ++++++------ 5 files changed, 281 insertions(+), 257 deletions(-) diff --git a/src/net/sourceforge/plantuml/cheneer/command/CommandAssociate.java b/src/net/sourceforge/plantuml/cheneer/command/CommandAssociate.java index 116eaf514..74fdaa9af 100644 --- a/src/net/sourceforge/plantuml/cheneer/command/CommandAssociate.java +++ b/src/net/sourceforge/plantuml/cheneer/command/CommandAssociate.java @@ -55,54 +55,54 @@ import net.sourceforge.plantuml.utils.LineLocation; public class CommandAssociate extends SingleLineCommand2 { - public CommandAssociate() { - super(getRegexConcat()); - } + public CommandAssociate() { + super(getRegexConcat()); + } - private static IRegex getRegexConcat() { - return RegexConcat.build(CommandCreateEntity.class.getName(), RegexLeaf.start(), // - new RegexLeaf("NAME1", "([\\w-]+)"), // - RegexLeaf.spaceZeroOrMore(), // - new RegexLeaf("PARTICIPATION", "([-=])"), // - new RegexOptional( // - new RegexLeaf("CARDINALITY", "(\\w+|\\(\\w+,[%s]*\\w+\\))")), // - new RegexLeaf("PARTICIPATION2", "([-=])"), // - RegexLeaf.spaceZeroOrMore(), // - new RegexLeaf("NAME2", "([\\w-]+)"), // - RegexLeaf.end()); - } + private static IRegex getRegexConcat() { + return RegexConcat.build(CommandCreateEntity.class.getName(), RegexLeaf.start(), // + new RegexLeaf("NAME1", "([\\w-]+)"), // + RegexLeaf.spaceZeroOrMore(), // + new RegexLeaf("PARTICIPATION", "([-=])"), // + new RegexOptional( // + new RegexLeaf("CARDINALITY", "(\\w+|\\(\\w+,[%s]*\\w+\\))")), // + new RegexLeaf("PARTICIPATION2", "([-=])"), // + RegexLeaf.spaceZeroOrMore(), // + new RegexLeaf("NAME2", "([\\w-]+)"), // + RegexLeaf.end()); + } - @Override - protected CommandExecutionResult executeArg(ChenEerDiagram diagram, LineLocation location, RegexResult arg) - throws NoSuchColorException { - final String name1 = diagram.cleanId(arg.get("NAME1", 0)); - final String name2 = diagram.cleanId(arg.get("NAME2", 0)); - final boolean isDouble = arg.get("PARTICIPATION", 0).equals("="); - final String cardinality = arg.get("CARDINALITY", 0); + @Override + protected CommandExecutionResult executeArg(ChenEerDiagram diagram, LineLocation location, RegexResult arg) + throws NoSuchColorException { + final String name1 = diagram.cleanId(arg.get("NAME1", 0)); + final String name2 = diagram.cleanId(arg.get("NAME2", 0)); + final boolean isDouble = arg.get("PARTICIPATION", 0).equals("="); + final String cardinality = arg.get("CARDINALITY", 0); - final Quark quark1 = diagram.quarkInContext(true, name1); - final Entity entity1 = quark1.getData(); - if (entity1 == null) { - return CommandExecutionResult.error("No such entity: " + name1); - } + final Quark quark1 = diagram.quarkInContext(true, name1); + final Entity entity1 = quark1.getData(); + if (entity1 == null) { + return CommandExecutionResult.error("No such entity: " + name1); + } - final Quark quark2 = diagram.quarkInContext(true, name2); - final Entity entity2 = quark2.getData(); - if (entity2 == null) { - return CommandExecutionResult.error("No such entity: " + name2); - } + final Quark quark2 = diagram.quarkInContext(true, name2); + final Entity entity2 = quark2.getData(); + if (entity2 == null) { + return CommandExecutionResult.error("No such entity: " + name2); + } - LinkType linkType = new LinkType(LinkDecor.NONE, LinkDecor.NONE); - if (isDouble) { - linkType = linkType.goBold(); - } - final Link link = new Link(diagram.getEntityFactory(), diagram.getCurrentStyleBuilder(), entity1, entity2, - linkType, - LinkArg.build(Display.getWithNewlines(cardinality), 3)); - link.setPortMembers(diagram.getPortId(entity1.getName()), diagram.getPortId(entity2.getName())); - diagram.addLink(link); + LinkType linkType = new LinkType(LinkDecor.NONE, LinkDecor.NONE); + if (isDouble) { + linkType = linkType.goBold(); + } + final Link link = new Link(diagram.getEntityFactory(), diagram.getCurrentStyleBuilder(), entity1, entity2, + linkType, + LinkArg.build(Display.getWithNewlines(cardinality), 3)); + link.setPortMembers(diagram.getPortId(entity1.getName()), diagram.getPortId(entity2.getName())); + diagram.addLink(link); - return CommandExecutionResult.ok(); - } + return CommandExecutionResult.ok(); + } } diff --git a/src/net/sourceforge/plantuml/cheneer/command/CommandCreateAttribute.java b/src/net/sourceforge/plantuml/cheneer/command/CommandCreateAttribute.java index af29e951e..027b23486 100644 --- a/src/net/sourceforge/plantuml/cheneer/command/CommandCreateAttribute.java +++ b/src/net/sourceforge/plantuml/cheneer/command/CommandCreateAttribute.java @@ -5,12 +5,12 @@ * (C) Copyright 2009-2024, Arnaud Roques * * Project Info: https://plantuml.com - * + * * If you like this project or if you find it useful, you can support us at: - * + * * https://plantuml.com/patreon (only 1$ per month!) * https://plantuml.com/paypal - * + * * This file is part of PlantUML. * * PlantUML is free software; you can redistribute it and/or modify it @@ -30,7 +30,7 @@ * * * Original Author: Arnaud Roques - * + * * */ package net.sourceforge.plantuml.cheneer.command; @@ -50,66 +50,77 @@ import net.sourceforge.plantuml.plasma.Quark; import net.sourceforge.plantuml.regex.IRegex; import net.sourceforge.plantuml.regex.RegexConcat; import net.sourceforge.plantuml.regex.RegexLeaf; +import net.sourceforge.plantuml.regex.RegexOptional; import net.sourceforge.plantuml.regex.RegexResult; import net.sourceforge.plantuml.stereo.Stereotype; import net.sourceforge.plantuml.utils.LineLocation; public class CommandCreateAttribute extends SingleLineCommand2 { - public CommandCreateAttribute() { - super(getRegexConcat()); - } + public CommandCreateAttribute() { + super(getRegexConcat()); + } - private static IRegex getRegexConcat() { - return RegexConcat.build(CommandCreateEntity.class.getName(), RegexLeaf.start(), // - RegexLeaf.spaceZeroOrMore(), - new RegexLeaf("NAME", "([^<>{}=-]+)"), // - RegexLeaf.spaceZeroOrMore(), // - new RegexLeaf("STEREO", "(<<.*>>)?"), // - RegexLeaf.spaceZeroOrMore(), // - new RegexLeaf("COMPOSITE", "(\\{)?"), // - RegexLeaf.end()); - } + private static IRegex getRegexConcat() { + return RegexConcat.build(CommandCreateEntity.class.getName(), RegexLeaf.start(), // + RegexLeaf.spaceZeroOrMore(), + new RegexOptional( // Copied from CommandCreatePackageBlock + new RegexConcat( // + new RegexLeaf("DISPLAY", "[%g]([^%g]+)[%g]"), // + RegexLeaf.spaceOneOrMore(), // + new RegexLeaf("as"), // + RegexLeaf.spaceOneOrMore() // + )), // + new RegexLeaf("CODE", "([%pLN%s_.:<>]+)"), // + RegexLeaf.spaceZeroOrMore(), // + new RegexLeaf("STEREO", "(<<.*>>)?"), // + RegexLeaf.spaceZeroOrMore(), // + new RegexLeaf("COMPOSITE", "(\\{)?"), // + RegexLeaf.end()); + } - @Override - protected CommandExecutionResult executeArg(ChenEerDiagram diagram, LineLocation location, RegexResult arg) - throws NoSuchColorException { - final Entity owner = diagram.peekOwner(); - if (owner == null) { - return CommandExecutionResult.error("Attribute must be inside an entity, relationship or another attribute"); - } + @Override + protected CommandExecutionResult executeArg(ChenEerDiagram diagram, LineLocation location, RegexResult arg) + throws NoSuchColorException { + final Entity owner = diagram.peekOwner(); + if (owner == null) { + return CommandExecutionResult.error("Attribute must be inside an entity, relationship or another attribute"); + } - final LeafType type = LeafType.CHEN_ATTRIBUTE; - final String name = diagram.cleanId(arg.get("NAME", 0).trim()); - final String id = owner.getName() + "/" + name; - final String stereo = arg.get("STEREO", 0); - final boolean composite = arg.get("COMPOSITE", 0) != null; + final LeafType type = LeafType.CHEN_ATTRIBUTE; + final String idShort = diagram.cleanId(arg.get("CODE", 0).trim()); + final String id = owner.getName() + "/" + idShort; + final Quark quark = diagram.quarkInContext(true, id); + String displayText = arg.get("DISPLAY", 0); + if (displayText == null) + displayText = quark.getName(); - final Quark quark = diagram.quarkInContext(true, id); + final String stereo = arg.get("STEREO", 0); + final boolean composite = arg.get("COMPOSITE", 0) != null; - Entity entity = quark.getData(); - if (entity == null) { - final Display display = Display.getWithNewlines(name); - entity = diagram.reallyCreateLeaf(quark, display, type, null); - } else { - return CommandExecutionResult.error("Attribute already exists"); - } + Entity entity = quark.getData(); + if (entity == null) { + final Display display = Display.getWithNewlines(displayText); + entity = diagram.reallyCreateLeaf(quark, display, type, null); + } else { + return CommandExecutionResult.error("Attribute already exists"); + } - if (stereo != null) { - entity.setStereotype(Stereotype.build(stereo)); - entity.setStereostyle(stereo); - } + if (stereo != null) { + entity.setStereotype(Stereotype.build(stereo)); + entity.setStereostyle(stereo); + } - final LinkType linkType = new LinkType(LinkDecor.NONE, LinkDecor.NONE); - final Link link = new Link(diagram.getEntityFactory(), diagram.getCurrentStyleBuilder(), entity, owner, linkType, - LinkArg.build(Display.NULL, 2)); - diagram.addLink(link); + final LinkType linkType = new LinkType(LinkDecor.NONE, LinkDecor.NONE); + final Link link = new Link(diagram.getEntityFactory(), diagram.getCurrentStyleBuilder(), entity, owner, linkType, + LinkArg.build(Display.NULL, 2)); + diagram.addLink(link); - if (composite) { - diagram.pushOwner(entity); - } + if (composite) { + diagram.pushOwner(entity); + } - return CommandExecutionResult.ok(); - } + return CommandExecutionResult.ok(); + } } diff --git a/src/net/sourceforge/plantuml/cheneer/command/CommandCreateEntity.java b/src/net/sourceforge/plantuml/cheneer/command/CommandCreateEntity.java index 3fbb090d1..7770be211 100644 --- a/src/net/sourceforge/plantuml/cheneer/command/CommandCreateEntity.java +++ b/src/net/sourceforge/plantuml/cheneer/command/CommandCreateEntity.java @@ -5,12 +5,12 @@ * (C) Copyright 2009-2024, Arnaud Roques * * Project Info: https://plantuml.com - * + * * If you like this project or if you find it useful, you can support us at: - * + * * https://plantuml.com/patreon (only 1$ per month!) * https://plantuml.com/paypal - * + * * This file is part of PlantUML. * * PlantUML is free software; you can redistribute it and/or modify it @@ -30,7 +30,7 @@ * * * Original Author: Arnaud Roques - * + * * */ package net.sourceforge.plantuml.cheneer.command; @@ -46,65 +46,78 @@ import net.sourceforge.plantuml.plasma.Quark; import net.sourceforge.plantuml.regex.IRegex; import net.sourceforge.plantuml.regex.RegexConcat; import net.sourceforge.plantuml.regex.RegexLeaf; +import net.sourceforge.plantuml.regex.RegexOptional; +import net.sourceforge.plantuml.regex.RegexOr; import net.sourceforge.plantuml.regex.RegexResult; import net.sourceforge.plantuml.stereo.Stereotype; import net.sourceforge.plantuml.utils.LineLocation; public class CommandCreateEntity extends SingleLineCommand2 { - public CommandCreateEntity() { - super(getRegexConcat()); - } + public CommandCreateEntity() { + super(getRegexConcat()); + } - private static IRegex getRegexConcat() { - return RegexConcat.build(CommandCreateEntity.class.getName(), RegexLeaf.start(), // - new RegexLeaf("TYPE", "(entity|relationship)"), // - RegexLeaf.spaceOneOrMore(), // - new RegexLeaf("NAME", "([^<>{}]+)"), // - RegexLeaf.spaceZeroOrMore(), // - new RegexLeaf("STEREO", "(<<.+>>)?"), // - RegexLeaf.spaceZeroOrMore(), // - new RegexLeaf("\\{"), // - RegexLeaf.end()); - } + private static IRegex getRegexConcat() { + return RegexConcat.build(CommandCreateEntity.class.getName(), RegexLeaf.start(), // + new RegexLeaf("TYPE", "(entity|relationship)"), // + RegexLeaf.spaceOneOrMore(), // + new RegexOptional( // Copied from CommandCreatePackageBlock + new RegexConcat( // + new RegexLeaf("DISPLAY", "[%g]([^%g]+)[%g]"), // + RegexLeaf.spaceOneOrMore(), // + new RegexLeaf("as"), // + RegexLeaf.spaceOneOrMore() // + )), // + new RegexLeaf("CODE", "([%pLN_.]+)"), // + RegexLeaf.spaceZeroOrMore(), // + new RegexLeaf("STEREO", "(<<.+>>)?"), // + RegexLeaf.spaceZeroOrMore(), // + new RegexLeaf("\\{"), // + RegexLeaf.end()); + } - @Override - protected CommandExecutionResult executeArg(ChenEerDiagram diagram, LineLocation location, RegexResult arg) - throws NoSuchColorException { - LeafType type; - switch (arg.get("TYPE", 0)) { - case "entity": - type = LeafType.CHEN_ENTITY; - break; - case "relationship": - type = LeafType.CHEN_RELATIONSHIP; - break; - default: - throw new IllegalStateException(); - } + @Override + protected CommandExecutionResult executeArg(ChenEerDiagram diagram, LineLocation location, RegexResult arg) + throws NoSuchColorException { + LeafType type; + switch (arg.get("TYPE", 0)) { + case "entity": + type = LeafType.CHEN_ENTITY; + break; + case "relationship": + type = LeafType.CHEN_RELATIONSHIP; + break; + default: + throw new IllegalStateException(); + } - final String name = diagram.cleanId(arg.get("NAME", 0).trim()); - final String stereo = arg.get("STEREO", 0); + final String idShort = arg.get("CODE", 0); + final Quark quark = diagram.quarkInContext(true, diagram.cleanId(idShort)); + String displayText = arg.get("DISPLAY", 0); + if (displayText == null) + displayText = quark.getName(); - final Quark quark = diagram.quarkInContext(true, name); - Entity entity = quark.getData(); + final String stereo = arg.get("STEREO", 0); - if (entity == null) { - Display display = Display.getWithNewlines(name); - entity = diagram.reallyCreateLeaf(quark, display, type, null); - } else { - if (entity.muteToType(type, null) == false) - return CommandExecutionResult.error("Bad name"); - } + Entity entity = quark.getData(); - if (stereo != null) { - entity.setStereotype(Stereotype.build(stereo)); - entity.setStereostyle(stereo); - } + if (entity == null) { + Display display = Display.getWithNewlines(displayText); + entity = diagram.reallyCreateLeaf(quark, display, type, null); + } else { + if (entity.muteToType(type, null) == false) + return CommandExecutionResult.error("Bad name"); + } - diagram.pushOwner(entity); + if (stereo != null) { + entity.setStereotype(Stereotype.build(stereo)); + entity.setStereostyle(stereo); + } - return CommandExecutionResult.ok(); - } + diagram.pushOwner(entity); + + return CommandExecutionResult.ok(); + } } diff --git a/src/net/sourceforge/plantuml/cheneer/command/CommandMultiSubclass.java b/src/net/sourceforge/plantuml/cheneer/command/CommandMultiSubclass.java index b05ece9ff..e23088aa1 100644 --- a/src/net/sourceforge/plantuml/cheneer/command/CommandMultiSubclass.java +++ b/src/net/sourceforge/plantuml/cheneer/command/CommandMultiSubclass.java @@ -59,80 +59,80 @@ import net.sourceforge.plantuml.utils.LineLocation; public class CommandMultiSubclass extends SingleLineCommand2 { - public CommandMultiSubclass() { - super(getRegexConcat()); - } + public CommandMultiSubclass() { + super(getRegexConcat()); + } - private static IRegex getRegexConcat() { - return RegexConcat.build(CommandCreateEntity.class.getName(), RegexLeaf.start(), // - new RegexLeaf("SUPERCLASS", "([\\w-]+)"), // - RegexLeaf.spaceZeroOrMore(), // - new RegexLeaf("PARTICIPATION", "([-=])"), // - new RegexLeaf("(>)"), // - new RegexLeaf("PARTICIPATION2", "([-=])"), // - RegexLeaf.spaceZeroOrMore(), // - new RegexLeaf("SYMBOL", "([doU])"), // - RegexLeaf.spaceZeroOrMore(), // - new RegexLeaf("\\{"), // - new RegexLeaf("SUBCLASSES", "(.+)"), // - new RegexLeaf("\\}"), // - RegexLeaf.end()); - } + private static IRegex getRegexConcat() { + return RegexConcat.build(CommandCreateEntity.class.getName(), RegexLeaf.start(), // + new RegexLeaf("SUPERCLASS", "([\\w-]+)"), // + RegexLeaf.spaceZeroOrMore(), // + new RegexLeaf("PARTICIPATION", "([-=])"), // + new RegexLeaf("(>)"), // + new RegexLeaf("PARTICIPATION2", "([-=])"), // + RegexLeaf.spaceZeroOrMore(), // + new RegexLeaf("SYMBOL", "([doU])"), // + RegexLeaf.spaceZeroOrMore(), // + new RegexLeaf("\\{"), // + new RegexLeaf("SUBCLASSES", "(.+)"), // + new RegexLeaf("\\}"), // + RegexLeaf.end()); + } - @Override - protected CommandExecutionResult executeArg(ChenEerDiagram diagram, LineLocation location, RegexResult arg) - throws NoSuchColorException { - final String superclass = diagram.cleanId(arg.get("SUPERCLASS", 0)); - final String subclasses = arg.get("SUBCLASSES", 0); - final List subclassIds = Arrays.stream(subclasses.split(",")) - .map(String::trim) - .map(diagram::cleanId) - .collect(Collectors.toList()); - final boolean isDouble = arg.get("PARTICIPATION", 0).equals("="); - final String symbol = arg.get("SYMBOL", 0); + @Override + protected CommandExecutionResult executeArg(ChenEerDiagram diagram, LineLocation location, RegexResult arg) + throws NoSuchColorException { + final String superclass = diagram.cleanId(arg.get("SUPERCLASS", 0)); + final String subclasses = arg.get("SUBCLASSES", 0); + final List subclassIds = Arrays.stream(subclasses.split(",")) + .map(String::trim) + .map(diagram::cleanId) + .collect(Collectors.toList()); + final boolean isDouble = arg.get("PARTICIPATION", 0).equals("="); + final String symbol = arg.get("SYMBOL", 0); - final Quark centerQuark = diagram.quarkInContext(false, superclass + "/" + symbol + subclasses + "/center"); - final Entity centerEntity = diagram.reallyCreateLeaf(centerQuark, Display.create(symbol), LeafType.CHEN_CIRCLE, null); + final Quark centerQuark = diagram.quarkInContext(false, superclass + "/" + symbol + subclasses + "/center"); + final Entity centerEntity = diagram.reallyCreateLeaf(centerQuark, Display.create(symbol), LeafType.CHEN_CIRCLE, null); - final Quark superclassQuark = diagram.quarkInContext(true, superclass); - final Entity superclassEntity = superclassQuark.getData(); - if (superclassEntity == null) { - return CommandExecutionResult.error("No such entity: " + superclass); - } + final Quark superclassQuark = diagram.quarkInContext(true, superclass); + final Entity superclassEntity = superclassQuark.getData(); + if (superclassEntity == null) { + return CommandExecutionResult.error("No such entity: " + superclass); + } - LinkType linkType = new LinkType(LinkDecor.NONE, LinkDecor.NONE); - if (isDouble) { - linkType = linkType.goBold(); - } - if (symbol.equals("U")) { - linkType = linkType.withMiddleSuperset(); - } - final Link link = new Link(diagram.getEntityFactory(), diagram.getCurrentStyleBuilder(), superclassEntity, - centerEntity, - linkType, - LinkArg.build(Display.NULL, 2)); - link.setPortMembers(diagram.getPortId(superclassEntity.getName()), diagram.getPortId(centerEntity.getName())); - diagram.addLink(link); + LinkType linkType = new LinkType(LinkDecor.NONE, LinkDecor.NONE); + if (isDouble) { + linkType = linkType.goBold(); + } + if (symbol.equals("U")) { + linkType = linkType.withMiddleSuperset(); + } + final Link link = new Link(diagram.getEntityFactory(), diagram.getCurrentStyleBuilder(), superclassEntity, + centerEntity, + linkType, + LinkArg.build(Display.NULL, 2)); + link.setPortMembers(diagram.getPortId(superclassEntity.getName()), diagram.getPortId(centerEntity.getName())); + diagram.addLink(link); - for (String subclass : subclassIds) { - final Quark subclassQuark = diagram.quarkInContext(true, subclass); - final Entity subclassEntity = subclassQuark.getData(); - if (subclassEntity == null) { - return CommandExecutionResult.error("No such entity: " + subclass); - } + for (String subclass : subclassIds) { + final Quark subclassQuark = diagram.quarkInContext(true, subclass); + final Entity subclassEntity = subclassQuark.getData(); + if (subclassEntity == null) { + return CommandExecutionResult.error("No such entity: " + subclass); + } - LinkType subclassLinkType = new LinkType(LinkDecor.NONE, LinkDecor.NONE); - if (!symbol.equals("U")) { - subclassLinkType = subclassLinkType.withMiddleSuperset(); - } - final Link subclassLink = new Link(diagram.getEntityFactory(), diagram.getCurrentStyleBuilder(), centerEntity, - subclassEntity, - subclassLinkType, - LinkArg.build(Display.NULL, 3)); - diagram.addLink(subclassLink); - } + LinkType subclassLinkType = new LinkType(LinkDecor.NONE, LinkDecor.NONE); + if (!symbol.equals("U")) { + subclassLinkType = subclassLinkType.withMiddleSuperset(); + } + final Link subclassLink = new Link(diagram.getEntityFactory(), diagram.getCurrentStyleBuilder(), centerEntity, + subclassEntity, + subclassLinkType, + LinkArg.build(Display.NULL, 3)); + diagram.addLink(subclassLink); + } - return CommandExecutionResult.ok(); - } + return CommandExecutionResult.ok(); + } } diff --git a/src/net/sourceforge/plantuml/cheneer/command/CommandSimpleSubclass.java b/src/net/sourceforge/plantuml/cheneer/command/CommandSimpleSubclass.java index 2c8e3c1c4..2f348fdfb 100644 --- a/src/net/sourceforge/plantuml/cheneer/command/CommandSimpleSubclass.java +++ b/src/net/sourceforge/plantuml/cheneer/command/CommandSimpleSubclass.java @@ -54,58 +54,58 @@ import net.sourceforge.plantuml.utils.LineLocation; public class CommandSimpleSubclass extends SingleLineCommand2 { - public CommandSimpleSubclass() { - super(getRegexConcat()); - } + public CommandSimpleSubclass() { + super(getRegexConcat()); + } - private static IRegex getRegexConcat() { - return RegexConcat.build(CommandCreateEntity.class.getName(), RegexLeaf.start(), // - new RegexLeaf("NAME1", "([\\w-]+)"), // - RegexLeaf.spaceZeroOrMore(), // - new RegexLeaf("PARTICIPATION", "([-=])"), // - new RegexLeaf("DIRECTION", "([<>])"), // - new RegexLeaf("PARTICIPATION2", "([-=])"), // - RegexLeaf.spaceZeroOrMore(), // - new RegexLeaf("NAME2", "([\\w-]+)"), // - RegexLeaf.end()); - } + private static IRegex getRegexConcat() { + return RegexConcat.build(CommandCreateEntity.class.getName(), RegexLeaf.start(), // + new RegexLeaf("NAME1", "([\\w-]+)"), // + RegexLeaf.spaceZeroOrMore(), // + new RegexLeaf("PARTICIPATION", "([-=])"), // + new RegexLeaf("DIRECTION", "([<>])"), // + new RegexLeaf("PARTICIPATION2", "([-=])"), // + RegexLeaf.spaceZeroOrMore(), // + new RegexLeaf("NAME2", "([\\w-]+)"), // + RegexLeaf.end()); + } - @Override - protected CommandExecutionResult executeArg(ChenEerDiagram diagram, LineLocation location, RegexResult arg) - throws NoSuchColorException { - String name1 = diagram.cleanId(arg.get("NAME1", 0)); - String name2 = diagram.cleanId(arg.get("NAME2", 0)); - final boolean isDouble = arg.get("PARTICIPATION", 0).equals("="); - final boolean isSuperset = arg.get("DIRECTION", 0).equals(">"); + @Override + protected CommandExecutionResult executeArg(ChenEerDiagram diagram, LineLocation location, RegexResult arg) + throws NoSuchColorException { + String name1 = diagram.cleanId(arg.get("NAME1", 0)); + String name2 = diagram.cleanId(arg.get("NAME2", 0)); + final boolean isDouble = arg.get("PARTICIPATION", 0).equals("="); + final boolean isSuperset = arg.get("DIRECTION", 0).equals(">"); - final Quark quark1 = diagram.quarkInContext(true, name1); - final Entity entity1 = quark1.getData(); - if (entity1 == null) { - return CommandExecutionResult.error("No such entity: " + name1); - } + final Quark quark1 = diagram.quarkInContext(true, name1); + final Entity entity1 = quark1.getData(); + if (entity1 == null) { + return CommandExecutionResult.error("No such entity: " + name1); + } - final Quark quark2 = diagram.quarkInContext(true, name2); - final Entity entity2 = quark2.getData(); - if (entity2 == null) { - return CommandExecutionResult.error("No such entity: " + name2); - } + final Quark quark2 = diagram.quarkInContext(true, name2); + final Entity entity2 = quark2.getData(); + if (entity2 == null) { + return CommandExecutionResult.error("No such entity: " + name2); + } - LinkType linkType = new LinkType(LinkDecor.NONE, LinkDecor.NONE); - if (isDouble) { - linkType = linkType.goBold(); - } - if (isSuperset) { - linkType = linkType.withMiddleSuperset(); - } else { - linkType = linkType.withMiddleSubset(); - } - final Link link = new Link(diagram.getEntityFactory(), diagram.getCurrentStyleBuilder(), entity1, entity2, - linkType, - LinkArg.build(Display.NULL, 3)); - link.setPortMembers(diagram.getPortId(entity1.getName()), diagram.getPortId(entity2.getName())); - diagram.addLink(link); + LinkType linkType = new LinkType(LinkDecor.NONE, LinkDecor.NONE); + if (isDouble) { + linkType = linkType.goBold(); + } + if (isSuperset) { + linkType = linkType.withMiddleSuperset(); + } else { + linkType = linkType.withMiddleSubset(); + } + final Link link = new Link(diagram.getEntityFactory(), diagram.getCurrentStyleBuilder(), entity1, entity2, + linkType, + LinkArg.build(Display.NULL, 3)); + link.setPortMembers(diagram.getPortId(entity1.getName()), diagram.getPortId(entity2.getName())); + diagram.addLink(link); - return CommandExecutionResult.ok(); - } + return CommandExecutionResult.ok(); + } } From 83255431f7bf2bcccfe59333a1f77ca71c3035e1 Mon Sep 17 00:00:00 2001 From: Benjamin Davies Date: Wed, 20 Mar 2024 16:08:43 +1300 Subject: [PATCH 18/23] Document purpose of shared methods --- .../plantuml/cheneer/ChenEerDiagram.java | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/net/sourceforge/plantuml/cheneer/ChenEerDiagram.java b/src/net/sourceforge/plantuml/cheneer/ChenEerDiagram.java index 94f447d6f..0decacbef 100644 --- a/src/net/sourceforge/plantuml/cheneer/ChenEerDiagram.java +++ b/src/net/sourceforge/plantuml/cheneer/ChenEerDiagram.java @@ -50,10 +50,22 @@ public class ChenEerDiagram extends AbstractEntityDiagram { private final Stack ownerStack = new Stack(); + /** + * Pushes the owner of the following attributes. + * + * @see #peekOwner() + * @param group the entity that owns the following attributes + */ public void pushOwner(Entity group) { ownerStack.push(group); } + /** + * Pops an attribute owner from the stack. See also {@link #peekOwner()}. + * + * @see #peekOwner() + * @return true if an owner was popped, false if the stack was empty + */ public boolean popOwner() { if (ownerStack.isEmpty()) { return false; @@ -62,6 +74,17 @@ public class ChenEerDiagram extends AbstractEntityDiagram { return true; } + /** + * Returns the owner of the current attribute. + * + *

+ * This is used to link attributes based on their lexical position (how they + * appear in sources) without nesting the entities (like how packages are + * done). It is for this reason that we can't use CucaDiagram.getCurrentGroup, + * as that method nests the entities. + * + * @return the owner of the current attribute, or null if there is no owner + */ public Entity peekOwner() { if (ownerStack.isEmpty()) { return null; From cbe84c240a5aae39a830ab66016256693bdd7bf1 Mon Sep 17 00:00:00 2001 From: Benjamin Davies Date: Wed, 20 Mar 2024 16:54:40 +1300 Subject: [PATCH 19/23] Fix attribute labels --- .../plantuml/cheneer/command/CommandCreateAttribute.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/net/sourceforge/plantuml/cheneer/command/CommandCreateAttribute.java b/src/net/sourceforge/plantuml/cheneer/command/CommandCreateAttribute.java index 027b23486..7d8d966d8 100644 --- a/src/net/sourceforge/plantuml/cheneer/command/CommandCreateAttribute.java +++ b/src/net/sourceforge/plantuml/cheneer/command/CommandCreateAttribute.java @@ -71,7 +71,7 @@ public class CommandCreateAttribute extends SingleLineCommand2 { new RegexLeaf("as"), // RegexLeaf.spaceOneOrMore() // )), // - new RegexLeaf("CODE", "([%pLN%s_.:<>]+)"), // + new RegexLeaf("CODE", "([%pLN%s_.:]+)"), // RegexLeaf.spaceZeroOrMore(), // new RegexLeaf("STEREO", "(<<.*>>)?"), // RegexLeaf.spaceZeroOrMore(), // @@ -93,7 +93,7 @@ public class CommandCreateAttribute extends SingleLineCommand2 { final Quark quark = diagram.quarkInContext(true, id); String displayText = arg.get("DISPLAY", 0); if (displayText == null) - displayText = quark.getName(); + displayText = idShort; final String stereo = arg.get("STEREO", 0); final boolean composite = arg.get("COMPOSITE", 0) != null; From d39bfbc3b5992e1a75433ca3cc90ce8349d74cbf Mon Sep 17 00:00:00 2001 From: Benjamin Davies Date: Wed, 20 Mar 2024 16:57:41 +1300 Subject: [PATCH 20/23] Add test for aliases --- test/nonreg/simple/ChenMovieAlias_Test.java | 94 ++ .../simple/ChenMovieAlias_TestResult.java | 1077 +++++++++++++++++ 2 files changed, 1171 insertions(+) create mode 100644 test/nonreg/simple/ChenMovieAlias_Test.java create mode 100644 test/nonreg/simple/ChenMovieAlias_TestResult.java diff --git a/test/nonreg/simple/ChenMovieAlias_Test.java b/test/nonreg/simple/ChenMovieAlias_Test.java new file mode 100644 index 000000000..38aeac532 --- /dev/null +++ b/test/nonreg/simple/ChenMovieAlias_Test.java @@ -0,0 +1,94 @@ +package nonreg.simple; + +import java.io.IOException; + +import org.junit.jupiter.api.Test; + +import nonreg.BasicTest; + +/* + +Test diagram MUST be put between triple quotes + +""" +@startchen movies + +entity "Director" as DIRECTOR { + "No." as Number <> + Name { + Fname + Lname + } + Born : DATE + Died + Age +} + +entity "Customer" as CUSTOMER { + Number <> + Bonus <> + Name <> +} + +entity "Movie" as MOVIE { + Code +} + +relationship "was-rented-to" as RENTED_TO { + Date +} + +RENTED_TO -1- CUSTOMER +RENTED_TO -N- MOVIE +RENTED_TO -(N,M)- DIRECTOR + +entity "Parent" as PARENT { +} + +entity "Member" as MEMBER { +} + +CUSTOMER ->- PARENT +MEMBER -<- CUSTOMER + +entity "Kid" as CHILD <> { + Name <> +} + +relationship "is-parent-of" as PARENT_OF <> { +} + +PARENT_OF -1- PARENT +PARENT_OF =N= CHILD + +entity "Little Kid" as TODDLER { + FavoriteToy +} + +entity "Primary-Aged Kid" as PRIMARY_AGE { + FavoriteColor +} + +entity "Teenager" as TEEN { + Hobby +} + +CHILD =>= d { TODDLER, PRIMARY_AGE, TEEN } + +entity "Human" as PERSON { +} + +PERSON ->- U { CUSTOMER, DIRECTOR } + +@endchen +""" + + */ +public class ChenMovieAlias_Test extends BasicTest { + + @Test + void testSimple() throws IOException { + checkImage("(30 entities)"); + } + +} diff --git a/test/nonreg/simple/ChenMovieAlias_TestResult.java b/test/nonreg/simple/ChenMovieAlias_TestResult.java new file mode 100644 index 000000000..70a5dd854 --- /dev/null +++ b/test/nonreg/simple/ChenMovieAlias_TestResult.java @@ -0,0 +1,1077 @@ +package nonreg.simple; + +public class ChenMovieAlias_TestResult { +} +/* +""" +DPI: 96 +dimension: [ 1600.7960 ; 777.0000 ] +scaleFactor: 1.0000 +seed: 8173768504811424439 +svgLinkTarget: _top +hoverPathColorRGB: null +preserveAspectRatio: none + +RECTANGLE: + pt1: [ 225.0000 ; 345.5000 ] + pt2: [ 371.0712 ; 379.5000 ] + xCorner: 0 + yCorner: 0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: Director + position: [ 235.0000 ; 366.3889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +ELLIPSE: + pt1: [ 200.5000 ; 232.5000 ] + pt2: [ 261.9272 ; 258.2990 ] + start: 0.0 + extend: 0.0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: No. + position: [ 211.6171 ; 249.3889 ] + orientation: 0 + font: SansSerif.plain/14 [UNDERLINE] + color: ff000000 + extendedColor: NULL_COLOR + +ELLIPSE: + pt1: [ 82.0000 ; 232.5000 ] + pt2: [ 182.4750 ; 258.2990 ] + start: 0.0 + extend: 0.0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: Name + position: [ 98.8355 ; 249.3889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +ELLIPSE: + pt1: [ 24.5000 ; 122.5000 ] + pt2: [ 117.5753 ; 148.2990 ] + start: 0.0 + extend: 0.0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: Fname + position: [ 40.2519 ; 139.3889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +ELLIPSE: + pt1: [ 136.0000 ; 121.5000 ] + pt2: [ 250.0711 ; 149.1142 ] + start: 0.0 + extend: 0.0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: Lname + position: [ 151.8671 ; 138.3889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +ELLIPSE: + pt1: [ 376.0000 ; 225.0000 ] + pt2: [ 555.7951 ; 265.7590 ] + start: 0.0 + extend: 0.0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: Born : DATE + position: [ 386.3602 ; 241.8889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +ELLIPSE: + pt1: [ 574.0000 ; 232.5000 ] + pt2: [ 647.9416 ; 258.2990 ] + start: 0.0 + extend: 0.0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: Died + position: [ 586.9498 ; 249.3889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +ELLIPSE: + pt1: [ 6.0000 ; 232.5000 ] + pt2: [ 64.3515 ; 258.2990 ] + start: 0.0 + extend: 0.0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: Age + position: [ 16.6667 ; 249.3889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +RECTANGLE: + pt1: [ 1102.0000 ; 345.5000 ] + pt2: [ 1229.6315 ; 379.5000 ] + xCorner: 0 + yCorner: 0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: Customer + position: [ 1112.0000 ; 366.3889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +ELLIPSE: + pt1: [ 908.5000 ; 231.0000 ] + pt2: [ 1027.7119 ; 259.6424 ] + start: 0.0 + extend: 0.0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: Number + position: [ 923.6174 ; 247.8889 ] + orientation: 0 + font: SansSerif.plain/14 [UNDERLINE] + color: ff000000 + extendedColor: NULL_COLOR + +ELLIPSE: + pt1: [ 1045.5000 ; 231.5000 ] + pt2: [ 1160.1275 ; 259.2255 ] + start: 0.0 + extend: 0.0 + stroke: 10.0-10.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: Bonus + position: [ 1061.2808 ; 248.3889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +ELLIPSE: + pt1: [ 1179.0000 ; 232.5000 ] + pt2: [ 1279.4750 ; 258.2990 ] + start: 0.0 + extend: 0.0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +ELLIPSE: + pt1: [ 1182.0000 ; 235.5000 ] + pt2: [ 1276.4750 ; 255.2990 ] + start: 0.0 + extend: 0.0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: Name + position: [ 1195.8355 ; 249.3889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +RECTANGLE: + pt1: [ 696.5000 ; 345.5000 ] + pt2: [ 783.3873 ; 379.5000 ] + xCorner: 0 + yCorner: 0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: Movie + position: [ 706.5000 ; 366.3889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +ELLIPSE: + pt1: [ 752.5000 ; 232.5000 ] + pt2: [ 841.6043 ; 258.2990 ] + start: 0.0 + extend: 0.0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: Code + position: [ 767.6703 ; 249.3889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +POLYGON: + points: + - [ 578.5000 ; 135.6745 ] + - [ 683.8491 ; 83.0000 ] + - [ 789.1982 ; 135.6745 ] + - [ 683.8491 ; 188.3491 ] + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: was-rented-to + position: [ 603.6803 ; 139.5634 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +ELLIPSE: + pt1: [ 642.0000 ; 16.0000 ] + pt2: [ 725.5211 ; 41.7990 ] + start: 0.0 + extend: 0.0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: Date + position: [ 656.3527 ; 32.8889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +RECTANGLE: + pt1: [ 1237.5000 ; 522.0000 ] + pt2: [ 1346.8250 ; 556.0000 ] + xCorner: 0 + yCorner: 0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: Parent + position: [ 1247.5000 ; 542.8889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +RECTANGLE: + pt1: [ 1298.0000 ; 118.5000 ] + pt2: [ 1392.0549 ; 152.5000 ] + xCorner: 0 + yCorner: 0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: Member + position: [ 1308.0000 ; 139.3889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +RECTANGLE: + pt1: [ 1391.0000 ; 522.0000 ] + pt2: [ 1448.6410 ; 556.0000 ] + xCorner: 0 + yCorner: 0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +RECTANGLE: + pt1: [ 1394.0000 ; 525.0000 ] + pt2: [ 1445.6410 ; 553.0000 ] + xCorner: 0 + yCorner: 0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: Kid + position: [ 1401.0000 ; 542.8889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +ELLIPSE: + pt1: [ 1397.0000 ; 459.0000 ] + pt2: [ 1497.4750 ; 484.7990 ] + start: 0.0 + extend: 0.0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: Name + position: [ 1413.8355 ; 475.8889 ] + orientation: 0 + font: SansSerif.plain/14 [UNDERLINE] + color: ff000000 + extendedColor: NULL_COLOR + +POLYGON: + points: + - [ 1248.0000 ; 362.5454 ] + - [ 1367.0907 ; 303.0000 ] + - [ 1486.1815 ; 362.5454 ] + - [ 1367.0907 ; 422.0907 ] + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +POLYGON: + points: + - [ 1258.0000 ; 362.5454 ] + - [ 1367.0907 ; 308.0000 ] + - [ 1476.1815 ; 362.5454 ] + - [ 1367.0907 ; 417.0907 ] + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: is-parent-of + position: [ 1273.1803 ; 366.4343 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +RECTANGLE: + pt1: [ 961.0000 ; 738.0000 ] + pt2: [ 1150.8871 ; 772.0000 ] + xCorner: 0 + yCorner: 0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: Little Kid + position: [ 971.0000 ; 758.8889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +ELLIPSE: + pt1: [ 926.5000 ; 655.0000 ] + pt2: [ 1133.2015 ; 701.1403 ] + start: 0.0 + extend: 0.0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: FavoriteToy + position: [ 935.8014 ; 671.8889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +RECTANGLE: + pt1: [ 1221.5000 ; 738.0000 ] + pt2: [ 1420.7716 ; 772.0000 ] + xCorner: 0 + yCorner: 0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: Primary-Aged Kid + position: [ 1231.5000 ; 758.8889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +ELLIPSE: + pt1: [ 1190.0000 ; 655.5000 ] + pt2: [ 1392.3804 ; 700.7761 ] + start: 0.0 + extend: 0.0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: FavoriteColor + position: [ 1199.4497 ; 672.3889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +RECTANGLE: + pt1: [ 1464.5000 ; 738.0000 ] + pt2: [ 1595.7960 ; 772.0000 ] + xCorner: 0 + yCorner: 0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: Teenager + position: [ 1474.5000 ; 758.8889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +ELLIPSE: + pt1: [ 1448.5000 ; 665.0000 ] + pt2: [ 1555.1381 ; 691.1276 ] + start: 0.0 + extend: 0.0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: Hobby + position: [ 1465.6665 ; 681.8889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +ELLIPSE: + pt1: [ 1407.5000 ; 593.0000 ] + pt2: [ 1432.5000 ; 618.0000 ] + start: 0.0 + extend: 0.0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: d + position: [ 1413.3082 ; 609.3889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +RECTANGLE: + pt1: [ 1003.0000 ; 12.0000 ] + pt2: [ 1082.9460 ; 46.0000 ] + xCorner: 0 + yCorner: 0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: Human + position: [ 1013.0000 ; 32.8889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +ELLIPSE: + pt1: [ 1030.5000 ; 123.0000 ] + pt2: [ 1055.5000 ; 148.0000 ] + start: 0.0 + extend: 0.0 + stroke: 0.0-0.0-0.5 + shadow: 0 + color: ff181818 + backcolor: fff1f1f1 + +TEXT: + text: U + position: [ 1036.3048 ; 139.3889 ] + orientation: 0 + font: SansSerif.plain/14 [] + color: ff000000 + extendedColor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 232.1702 ; 252.8070 ] + - type: SEG_CUBICTO + pt1: [ 244.3231 ; 273.6665 ] + pt2: [ 268.9649 ; 315.9622 ] + pt3: [ 282.5249 ; 339.2368 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 143.4512 ; 252.5897 ] + - type: SEG_CUBICTO + pt1: [ 173.5015 ; 273.4077 ] + pt2: [ 235.0250 ; 316.0294 ] + pt3: [ 268.7005 ; 339.3588 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 71.9975 ; 142.8890 ] + - type: SEG_CUBICTO + pt1: [ 83.7642 ; 163.7218 ] + pt2: [ 107.3724 ; 205.5201 ] + pt3: [ 119.0841 ; 226.2555 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 179.5202 ; 143.7429 ] + - type: SEG_CUBICTO + pt1: [ 167.5581 ; 164.9216 ] + pt2: [ 144.3016 ; 206.0972 ] + pt3: [ 132.7905 ; 226.4775 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 431.5011 ; 260.0082 ] + - type: SEG_CUBICTO + pt1: [ 398.8293 ; 282.3728 ] + pt2: [ 345.8814 ; 318.6169 ] + pt3: [ 315.4799 ; 339.4275 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 577.3751 ; 252.5142 ] + - type: SEG_CUBICTO + pt1: [ 571.3454 ; 255.0514 ] + pt2: [ 564.9792 ; 257.6656 ] + pt3: [ 559.0000 ; 260.0000 ] + - type: SEG_CUBICTO + pt1: [ 482.8743 ; 289.7213 ] + pt2: [ 393.2083 ; 321.0528 ] + pt3: [ 339.5708 ; 339.4093 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 51.7745 ; 252.5268 ] + - type: SEG_CUBICTO + pt1: [ 56.7584 ; 255.0632 ] + pt2: [ 62.0302 ; 257.6739 ] + pt3: [ 67.0000 ; 260.0000 ] + - type: SEG_CUBICTO + pt1: [ 130.8004 ; 289.8615 ] + pt2: [ 206.4657 ; 321.1514 ] + pt3: [ 251.7823 ; 339.4613 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 985.4907 ; 254.1436 ] + - type: SEG_CUBICTO + pt1: [ 1022.2659 ; 275.5029 ] + pt2: [ 1093.2657 ; 316.7402 ] + pt3: [ 1132.4153 ; 339.4786 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 1104.2269 ; 253.6920 ] + - type: SEG_CUBICTO + pt1: [ 1115.7976 ; 274.8131 ] + pt2: [ 1138.4553 ; 316.1723 ] + pt3: [ 1151.0385 ; 339.1416 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 1216.2579 ; 252.8070 ] + - type: SEG_CUBICTO + pt1: [ 1204.8305 ; 273.6665 ] + pt2: [ 1181.6598 ; 315.9622 ] + pt3: [ 1168.9094 ; 339.2368 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 784.9000 ; 252.8070 ] + - type: SEG_CUBICTO + pt1: [ 774.5609 ; 273.6665 ] + pt2: [ 753.5970 ; 315.9622 ] + pt3: [ 742.0609 ; 339.2368 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 678.0000 ; 36.3979 ] + - type: SEG_CUBICTO + pt1: [ 678.0000 ; 46.5620 ] + pt2: [ 678.0000 ; 61.6797 ] + pt3: [ 678.0000 ; 76.7427 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 783.9201 ; 179.4304 ] + - type: SEG_CUBICTO + pt1: [ 805.0022 ; 191.1245 ] + pt2: [ 826.3650 ; 204.4783 ] + pt3: [ 845.0000 ; 219.0000 ] + - type: SEG_CUBICTO + pt1: [ 864.3608 ; 234.0873 ] + pt2: [ 861.5196 ; 246.4714 ] + pt3: [ 882.0000 ; 260.0000 ] + - type: SEG_CUBICTO + pt1: [ 948.2135 ; 303.7382 ] + pt2: [ 1036.5592 ; 329.5771 ] + pt3: [ 1095.7197 ; 343.1239 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +EMPTY: + pt1: [ 888.0000 ; 239.0000 ] + pt2: [ 900.3969 ; 252.0000 ] + +TEXT: + text: 1 + position: [ 889.0000 ; 248.5556 ] + orientation: 0 + font: SansSerif.plain/11 [] + color: ff000000 + extendedColor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 690.8475 ; 182.1195 ] + - type: SEG_CUBICTO + pt1: [ 703.4411 ; 232.7188 ] + pt2: [ 721.8869 ; 306.8313 ] + pt3: [ 729.9624 ; 339.2776 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +EMPTY: + pt1: [ 716.0000 ; 239.0000 ] + pt2: [ 728.5088 ; 252.0000 ] + +TEXT: + text: N + position: [ 717.0000 ; 248.5556 ] + orientation: 0 + font: SansSerif.plain/11 [] + color: ff000000 + extendedColor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 572.4552 ; 141.3090 ] + - type: SEG_CUBICTO + pt1: [ 473.4806 ; 153.8082 ] + pt2: [ 335.6648 ; 178.0968 ] + pt3: [ 301.0000 ; 219.0000 ] + - type: SEG_CUBICTO + pt1: [ 271.9795 ; 253.2431 ] + pt2: [ 280.9041 ; 311.3247 ] + pt3: [ 287.5633 ; 339.3813 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +EMPTY: + pt1: [ 307.0000 ; 239.0000 ] + pt2: [ 367.5178 ; 252.0000 ] + +TEXT: + text: (N,M) + position: [ 308.0000 ; 248.5556 ] + orientation: 0 + font: SansSerif.plain/11 [] + color: ff000000 + extendedColor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 1171.6279 ; 373.6038 ] + - type: SEG_CUBICTO + pt1: [ 1195.6314 ; 406.8467 ] + pt2: [ 1250.4207 ; 482.7255 ] + pt3: [ 1274.4002 ; 515.9352 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 1336.5920 ; 146.6696 ] + - type: SEG_CUBICTO + pt1: [ 1332.2375 ; 172.2425 ] + pt2: [ 1321.3527 ; 222.9198 ] + pt3: [ 1299.0000 ; 260.0000 ] + - type: SEG_CUBICTO + pt1: [ 1281.6387 ; 288.8001 ] + pt2: [ 1262.1722 ; 280.2715 ] + pt3: [ 1233.0000 ; 297.0000 ] + - type: SEG_CUBICTO + pt1: [ 1212.1484 ; 308.9571 ] + pt2: [ 1191.0078 ; 326.6412 ] + pt3: [ 1176.8815 ; 339.4340 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 1435.9215 ; 479.2260 ] + - type: SEG_CUBICTO + pt1: [ 1431.6443 ; 489.5231 ] + pt2: [ 1425.4891 ; 504.3410 ] + pt3: [ 1420.7893 ; 515.6555 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 1335.8174 ; 416.0914 ] + - type: SEG_CUBICTO + pt1: [ 1320.7529 ; 451.1416 ] + pt2: [ 1302.7049 ; 493.1332 ] + pt3: [ 1293.0006 ; 515.7121 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +EMPTY: + pt1: [ 1325.0000 ; 465.5000 ] + pt2: [ 1337.3969 ; 478.5000 ] + +TEXT: + text: 1 + position: [ 1326.0000 ; 475.0556 ] + orientation: 0 + font: SansSerif.plain/11 [] + color: ff000000 + extendedColor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 1358.1384 ; 416.0133 ] + - type: SEG_CUBICTO + pt1: [ 1358.9834 ; 436.5538 ] + pt2: [ 1362.0875 ; 459.3842 ] + pt3: [ 1370.0000 ; 479.0000 ] + - type: SEG_CUBICTO + pt1: [ 1375.6368 ; 492.9743 ] + pt2: [ 1386.3839 ; 506.0318 ] + pt3: [ 1395.8452 ; 515.6898 ] + stroke: 0.0-0.0-2.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +EMPTY: + pt1: [ 1376.0000 ; 465.5000 ] + pt2: [ 1388.5088 ; 478.5000 ] + +TEXT: + text: N + position: [ 1377.0000 ; 475.0556 ] + orientation: 0 + font: SansSerif.plain/11 [] + color: ff000000 + extendedColor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 1031.6602 ; 695.0968 ] + - type: SEG_CUBICTO + pt1: [ 1035.7346 ; 706.8497 ] + pt2: [ 1040.6559 ; 721.0459 ] + pt3: [ 1044.3744 ; 731.7723 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 1293.6772 ; 694.6931 ] + - type: SEG_CUBICTO + pt1: [ 1298.3842 ; 706.4605 ] + pt2: [ 1304.1079 ; 720.7696 ] + pt3: [ 1308.4396 ; 731.5989 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 1500.4987 ; 685.0500 ] + - type: SEG_CUBICTO + pt1: [ 1505.2291 ; 697.7208 ] + pt2: [ 1512.6997 ; 717.7313 ] + pt3: [ 1517.9454 ; 731.7824 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 1414.0000 ; 550.2761 ] + - type: SEG_CUBICTO + pt1: [ 1414.0000 ; 561.6212 ] + pt2: [ 1414.0000 ; 576.4948 ] + pt3: [ 1414.0000 ; 586.7072 ] + stroke: 0.0-0.0-2.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 1401.2771 ; 600.2072 ] + - type: SEG_CUBICTO + pt1: [ 1363.7609 ; 599.9125 ] + pt2: [ 1251.4289 ; 603.1572 ] + pt3: [ 1175.0000 ; 649.0000 ] + - type: SEG_CUBICTO + pt1: [ 1152.2590 ; 662.6403 ] + pt2: [ 1157.0453 ; 677.6393 ] + pt3: [ 1137.0000 ; 695.0000 ] + - type: SEG_CUBICTO + pt1: [ 1120.2885 ; 709.4734 ] + pt2: [ 1099.1544 ; 722.4488 ] + pt3: [ 1081.9010 ; 731.9383 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 1414.4114 ; 612.0393 ] + - type: SEG_CUBICTO + pt1: [ 1414.5294 ; 630.9891 ] + pt2: [ 1412.3704 ; 669.1714 ] + pt3: [ 1395.0000 ; 695.0000 ] + - type: SEG_CUBICTO + pt1: [ 1384.3079 ; 710.8984 ] + pt2: [ 1367.0782 ; 723.2084 ] + pt3: [ 1351.3421 ; 731.9456 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 1426.8860 ; 600.2582 ] + - type: SEG_CUBICTO + pt1: [ 1456.2165 ; 600.4959 ] + pt2: [ 1527.8255 ; 605.7005 ] + pt3: [ 1559.0000 ; 649.0000 ] + - type: SEG_CUBICTO + pt1: [ 1577.5338 ; 674.7423 ] + pt2: [ 1554.7041 ; 711.2267 ] + pt3: [ 1538.1772 ; 731.9584 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 1037.0000 ; 40.3281 ] + - type: SEG_CUBICTO + pt1: [ 1037.0000 ; 61.5674 ] + pt2: [ 1037.0000 ; 98.1555 ] + pt3: [ 1037.0000 ; 116.8167 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 1049.5409 ; 130.4592 ] + - type: SEG_CUBICTO + pt1: [ 1091.2973 ; 131.0869 ] + pt2: [ 1226.1328 ; 139.4190 ] + pt3: [ 1282.0000 ; 219.0000 ] + - type: SEG_CUBICTO + pt1: [ 1292.4699 ; 233.9141 ] + pt2: [ 1290.1227 ; 243.6883 ] + pt3: [ 1282.0000 ; 260.0000 ] + - type: SEG_CUBICTO + pt1: [ 1269.8357 ; 284.4279 ] + pt2: [ 1254.5386 ; 280.2435 ] + pt3: [ 1233.0000 ; 297.0000 ] + - type: SEG_CUBICTO + pt1: [ 1214.7975 ; 311.1611 ] + pt2: [ 1194.3279 ; 327.6114 ] + pt3: [ 1179.7068 ; 339.4543 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +PATH: + - type: SEG_MOVETO + pt1: [ 1024.2296 ; 131.6209 ] + - type: SEG_CUBICTO + pt1: [ 980.6910 ; 135.9617 ] + pt2: [ 835.3843 ; 154.7622 ] + pt3: [ 738.0000 ; 219.0000 ] + - type: SEG_CUBICTO + pt1: [ 718.2392 ; 232.0348 ] + pt2: [ 724.1429 ; 247.5637 ] + pt3: [ 704.0000 ; 260.0000 ] + - type: SEG_CUBICTO + pt1: [ 598.1032 ; 325.3810 ] + pt2: [ 451.8207 ; 346.0494 ] + pt3: [ 365.0560 ; 352.5521 ] + stroke: 0.0-0.0-1.0 + shadow: 0 + color: ff181818 + backcolor: NULL_COLOR + +""" +*/ \ No newline at end of file From 234cb3adea19aea3ecfc33f541622cc3343db683 Mon Sep 17 00:00:00 2001 From: Benjamin Davies Date: Thu, 21 Mar 2024 17:55:42 +1300 Subject: [PATCH 21/23] Add tests for each new command --- .../cheneer/command/CommandAssociate.java | 10 +- .../command/CommandCreateAttribute.java | 2 +- .../cheneer/command/CommandCreateEntity.java | 2 +- .../cheneer/command/CommandEndGroup.java | 10 +- .../cheneer/command/CommandMultiSubclass.java | 10 +- .../command/CommandSimpleSubclass.java | 10 +- .../cheneer/command/CommandAssociateTest.java | 126 +++++++++++ .../command/CommandCreateAttributeTest.java | 173 ++++++++++++++ .../command/CommandCreateEntityTest.java | 123 ++++++++++ .../cheneer/command/CommandEndGroupTest.java | 49 ++++ .../command/CommandMultiSubclassTest.java | 214 ++++++++++++++++++ .../command/CommandSimpleSubclassTest.java | 112 +++++++++ 12 files changed, 819 insertions(+), 22 deletions(-) create mode 100644 test/net/sourceforge/plantuml/cheneer/command/CommandAssociateTest.java create mode 100644 test/net/sourceforge/plantuml/cheneer/command/CommandCreateAttributeTest.java create mode 100644 test/net/sourceforge/plantuml/cheneer/command/CommandCreateEntityTest.java create mode 100644 test/net/sourceforge/plantuml/cheneer/command/CommandEndGroupTest.java create mode 100644 test/net/sourceforge/plantuml/cheneer/command/CommandMultiSubclassTest.java create mode 100644 test/net/sourceforge/plantuml/cheneer/command/CommandSimpleSubclassTest.java diff --git a/src/net/sourceforge/plantuml/cheneer/command/CommandAssociate.java b/src/net/sourceforge/plantuml/cheneer/command/CommandAssociate.java index 74fdaa9af..0f799f01f 100644 --- a/src/net/sourceforge/plantuml/cheneer/command/CommandAssociate.java +++ b/src/net/sourceforge/plantuml/cheneer/command/CommandAssociate.java @@ -5,12 +5,12 @@ * (C) Copyright 2009-2024, Arnaud Roques * * Project Info: https://plantuml.com - * + * * If you like this project or if you find it useful, you can support us at: - * + * * https://plantuml.com/patreon (only 1$ per month!) * https://plantuml.com/paypal - * + * * This file is part of PlantUML. * * PlantUML is free software; you can redistribute it and/or modify it @@ -30,7 +30,7 @@ * * * Original Author: Arnaud Roques - * + * * */ package net.sourceforge.plantuml.cheneer.command; @@ -59,7 +59,7 @@ public class CommandAssociate extends SingleLineCommand2 { super(getRegexConcat()); } - private static IRegex getRegexConcat() { + protected static IRegex getRegexConcat() { return RegexConcat.build(CommandCreateEntity.class.getName(), RegexLeaf.start(), // new RegexLeaf("NAME1", "([\\w-]+)"), // RegexLeaf.spaceZeroOrMore(), // diff --git a/src/net/sourceforge/plantuml/cheneer/command/CommandCreateAttribute.java b/src/net/sourceforge/plantuml/cheneer/command/CommandCreateAttribute.java index 7d8d966d8..be8b8a78f 100644 --- a/src/net/sourceforge/plantuml/cheneer/command/CommandCreateAttribute.java +++ b/src/net/sourceforge/plantuml/cheneer/command/CommandCreateAttribute.java @@ -61,7 +61,7 @@ public class CommandCreateAttribute extends SingleLineCommand2 { super(getRegexConcat()); } - private static IRegex getRegexConcat() { + protected static IRegex getRegexConcat() { return RegexConcat.build(CommandCreateEntity.class.getName(), RegexLeaf.start(), // RegexLeaf.spaceZeroOrMore(), new RegexOptional( // Copied from CommandCreatePackageBlock diff --git a/src/net/sourceforge/plantuml/cheneer/command/CommandCreateEntity.java b/src/net/sourceforge/plantuml/cheneer/command/CommandCreateEntity.java index 7770be211..904e2c625 100644 --- a/src/net/sourceforge/plantuml/cheneer/command/CommandCreateEntity.java +++ b/src/net/sourceforge/plantuml/cheneer/command/CommandCreateEntity.java @@ -58,7 +58,7 @@ public class CommandCreateEntity extends SingleLineCommand2 { super(getRegexConcat()); } - private static IRegex getRegexConcat() { + protected static IRegex getRegexConcat() { return RegexConcat.build(CommandCreateEntity.class.getName(), RegexLeaf.start(), // new RegexLeaf("TYPE", "(entity|relationship)"), // RegexLeaf.spaceOneOrMore(), // diff --git a/src/net/sourceforge/plantuml/cheneer/command/CommandEndGroup.java b/src/net/sourceforge/plantuml/cheneer/command/CommandEndGroup.java index 37c195495..d3c4dcfc4 100644 --- a/src/net/sourceforge/plantuml/cheneer/command/CommandEndGroup.java +++ b/src/net/sourceforge/plantuml/cheneer/command/CommandEndGroup.java @@ -5,12 +5,12 @@ * (C) Copyright 2009-2024, Arnaud Roques * * Project Info: https://plantuml.com - * + * * If you like this project or if you find it useful, you can support us at: - * + * * https://plantuml.com/patreon (only 1$ per month!) * https://plantuml.com/paypal - * + * * This file is part of PlantUML. * * PlantUML is free software; you can redistribute it and/or modify it @@ -30,7 +30,7 @@ * * * Original Author: Arnaud Roques - * + * * */ package net.sourceforge.plantuml.cheneer.command; @@ -50,7 +50,7 @@ public class CommandEndGroup extends SingleLineCommand2 { super(getRegexConcat()); } - static IRegex getRegexConcat() { + protected static IRegex getRegexConcat() { return RegexConcat.build(CommandEndGroup.class.getName(), RegexLeaf.start(), // new RegexLeaf("\\}"), // RegexLeaf.end()); // diff --git a/src/net/sourceforge/plantuml/cheneer/command/CommandMultiSubclass.java b/src/net/sourceforge/plantuml/cheneer/command/CommandMultiSubclass.java index e23088aa1..5a8a2519b 100644 --- a/src/net/sourceforge/plantuml/cheneer/command/CommandMultiSubclass.java +++ b/src/net/sourceforge/plantuml/cheneer/command/CommandMultiSubclass.java @@ -5,12 +5,12 @@ * (C) Copyright 2009-2024, Arnaud Roques * * Project Info: https://plantuml.com - * + * * If you like this project or if you find it useful, you can support us at: - * + * * https://plantuml.com/patreon (only 1$ per month!) * https://plantuml.com/paypal - * + * * This file is part of PlantUML. * * PlantUML is free software; you can redistribute it and/or modify it @@ -30,7 +30,7 @@ * * * Original Author: Arnaud Roques - * + * * */ package net.sourceforge.plantuml.cheneer.command; @@ -63,7 +63,7 @@ public class CommandMultiSubclass extends SingleLineCommand2 { super(getRegexConcat()); } - private static IRegex getRegexConcat() { + protected static IRegex getRegexConcat() { return RegexConcat.build(CommandCreateEntity.class.getName(), RegexLeaf.start(), // new RegexLeaf("SUPERCLASS", "([\\w-]+)"), // RegexLeaf.spaceZeroOrMore(), // diff --git a/src/net/sourceforge/plantuml/cheneer/command/CommandSimpleSubclass.java b/src/net/sourceforge/plantuml/cheneer/command/CommandSimpleSubclass.java index 2f348fdfb..323ecd862 100644 --- a/src/net/sourceforge/plantuml/cheneer/command/CommandSimpleSubclass.java +++ b/src/net/sourceforge/plantuml/cheneer/command/CommandSimpleSubclass.java @@ -5,12 +5,12 @@ * (C) Copyright 2009-2024, Arnaud Roques * * Project Info: https://plantuml.com - * + * * If you like this project or if you find it useful, you can support us at: - * + * * https://plantuml.com/patreon (only 1$ per month!) * https://plantuml.com/paypal - * + * * This file is part of PlantUML. * * PlantUML is free software; you can redistribute it and/or modify it @@ -30,7 +30,7 @@ * * * Original Author: Arnaud Roques - * + * * */ package net.sourceforge.plantuml.cheneer.command; @@ -58,7 +58,7 @@ public class CommandSimpleSubclass extends SingleLineCommand2 { super(getRegexConcat()); } - private static IRegex getRegexConcat() { + protected static IRegex getRegexConcat() { return RegexConcat.build(CommandCreateEntity.class.getName(), RegexLeaf.start(), // new RegexLeaf("NAME1", "([\\w-]+)"), // RegexLeaf.spaceZeroOrMore(), // diff --git a/test/net/sourceforge/plantuml/cheneer/command/CommandAssociateTest.java b/test/net/sourceforge/plantuml/cheneer/command/CommandAssociateTest.java new file mode 100644 index 000000000..cb72a51fa --- /dev/null +++ b/test/net/sourceforge/plantuml/cheneer/command/CommandAssociateTest.java @@ -0,0 +1,126 @@ +package net.sourceforge.plantuml.cheneer.command; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.List; + +import org.junit.jupiter.api.Test; + +import net.sourceforge.plantuml.abel.Link; +import net.sourceforge.plantuml.cheneer.ChenEerDiagram; +import net.sourceforge.plantuml.command.Command; +import net.sourceforge.plantuml.command.CommandExecutionResult; +import net.sourceforge.plantuml.core.UmlSource; +import net.sourceforge.plantuml.klimt.color.NoSuchColorException; +import net.sourceforge.plantuml.regex.IRegex; +import net.sourceforge.plantuml.regex.RegexResult; +import net.sourceforge.plantuml.utils.BlocLines; + +public class CommandAssociateTest { + + private final Command command = new CommandAssociate(); + + private final ChenEerDiagram diagram = new ChenEerDiagram(UmlSource.create(List.of(), false), null); + + @Test + void test_parse() { + IRegex regex = CommandAssociate.getRegexConcat(); + RegexResult matcher = regex.matcher("E1 -- E2"); + + assertThat(matcher).isNotNull(); + assertThat(matcher.get("NAME1", 0)).isEqualTo("E1"); + assertThat(matcher.get("NAME2", 0)).isEqualTo("E2"); + assertThat(matcher.get("PARTICIPATION", 0)).isEqualTo("-"); + assertThat(matcher.get("CARDINALITY", 0)).isNull(); + } + + @Test + void test_parseWithCompulsoryParticipation() { + IRegex regex = CommandAssociate.getRegexConcat(); + RegexResult matcher = regex.matcher("E1 == E2"); + + assertThat(matcher).isNotNull(); + assertThat(matcher.get("NAME1", 0)).isEqualTo("E1"); + assertThat(matcher.get("NAME2", 0)).isEqualTo("E2"); + assertThat(matcher.get("PARTICIPATION", 0)).isEqualTo("="); + assertThat(matcher.get("CARDINALITY", 0)).isNull(); + } + + @Test + void test_parseWithCardinality() { + IRegex regex = CommandAssociate.getRegexConcat(); + RegexResult matcher = regex.matcher("E1 -N- E2"); + + assertThat(matcher).isNotNull(); + assertThat(matcher.get("NAME1", 0)).isEqualTo("E1"); + assertThat(matcher.get("NAME2", 0)).isEqualTo("E2"); + assertThat(matcher.get("PARTICIPATION", 0)).isEqualTo("-"); + assertThat(matcher.get("CARDINALITY", 0)).isEqualTo("N"); + } + + @Test + void test_parseCardinalityRange() { + IRegex regex = CommandAssociate.getRegexConcat(); + RegexResult matcher = regex.matcher("E1 -(1, n)- E2"); + + assertThat(matcher).isNotNull(); + assertThat(matcher.get("NAME1", 0)).isEqualTo("E1"); + assertThat(matcher.get("NAME2", 0)).isEqualTo("E2"); + assertThat(matcher.get("PARTICIPATION", 0)).isEqualTo("-"); + assertThat(matcher.get("CARDINALITY", 0)).isEqualTo("(1, n)"); + } + + @Test + void test_execute() throws NoSuchColorException { + new CommandCreateEntity().execute(diagram, BlocLines.singleString("entity E1 {")); + new CommandCreateEntity().execute(diagram, BlocLines.singleString("entity E2 {")); + + BlocLines lines = BlocLines.singleString("E1 -- E2"); + CommandExecutionResult result = command.execute(diagram, lines); + + assertThat(result).matches(CommandExecutionResult::isOk); + + assertThat(diagram.getLinks().size()).isEqualTo(1); + Link link = diagram.getLinks().get(0); + assertThat(link.getEntity1().getName()).isEqualTo("E1"); + assertThat(link.getEntity2().getName()).isEqualTo("E2"); + assertThat(link.getType().getStyle().getStroke3().getThickness()).isEqualTo(1); + assertThat(link.getLabel().toString()).isEqualTo("NULL"); + } + + @Test + void test_executeWithCompulsoryParticipation() throws NoSuchColorException { + new CommandCreateEntity().execute(diagram, BlocLines.singleString("entity E1 {")); + new CommandCreateEntity().execute(diagram, BlocLines.singleString("entity E2 {")); + + BlocLines lines = BlocLines.singleString("E1 == E2"); + CommandExecutionResult result = command.execute(diagram, lines); + + assertThat(result).matches(CommandExecutionResult::isOk); + + assertThat(diagram.getLinks().size()).isEqualTo(1); + Link link = diagram.getLinks().get(0); + assertThat(link.getEntity1().getName()).isEqualTo("E1"); + assertThat(link.getEntity2().getName()).isEqualTo("E2"); + assertThat(link.getType().getStyle().getStroke3().getThickness()).isEqualTo(2); + assertThat(link.getLabel().toString()).isEqualTo("NULL"); + } + + @Test + void test_executeWithCardinality() throws NoSuchColorException { + new CommandCreateEntity().execute(diagram, BlocLines.singleString("entity E1 {")); + new CommandCreateEntity().execute(diagram, BlocLines.singleString("entity E2 {")); + + BlocLines lines = BlocLines.singleString("E1 -N- E2"); + CommandExecutionResult result = command.execute(diagram, lines); + + assertThat(result).matches(CommandExecutionResult::isOk); + + assertThat(diagram.getLinks().size()).isEqualTo(1); + Link link = diagram.getLinks().get(0); + assertThat(link.getEntity1().getName()).isEqualTo("E1"); + assertThat(link.getEntity2().getName()).isEqualTo("E2"); + assertThat(link.getType().getStyle().getStroke3().getThickness()).isEqualTo(1); + assertThat(link.getLabel().toString()).isEqualTo("[N]"); + } +} diff --git a/test/net/sourceforge/plantuml/cheneer/command/CommandCreateAttributeTest.java b/test/net/sourceforge/plantuml/cheneer/command/CommandCreateAttributeTest.java new file mode 100644 index 000000000..08c2139f8 --- /dev/null +++ b/test/net/sourceforge/plantuml/cheneer/command/CommandCreateAttributeTest.java @@ -0,0 +1,173 @@ +package net.sourceforge.plantuml.cheneer.command; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.List; + +import org.junit.jupiter.api.Test; + +import net.sourceforge.plantuml.abel.Entity; +import net.sourceforge.plantuml.abel.Link; +import net.sourceforge.plantuml.cheneer.ChenEerDiagram; +import net.sourceforge.plantuml.command.Command; +import net.sourceforge.plantuml.command.CommandExecutionResult; +import net.sourceforge.plantuml.core.UmlSource; +import net.sourceforge.plantuml.klimt.color.NoSuchColorException; +import net.sourceforge.plantuml.regex.IRegex; +import net.sourceforge.plantuml.regex.RegexResult; +import net.sourceforge.plantuml.utils.BlocLines; + +public class CommandCreateAttributeTest { + + private final Command command = new CommandCreateAttribute(); + + private final ChenEerDiagram diagram = new ChenEerDiagram(UmlSource.create(List.of(), false), null); + + @Test + void test_parse() { + IRegex regex = CommandCreateAttribute.getRegexConcat(); + RegexResult matcher = regex.matcher("attr"); + + assertThat(matcher).isNotNull(); + assertThat(matcher.get("DISPLAY", 0)).isNull(); + assertThat(matcher.get("CODE", 0)).isEqualTo("attr"); + assertThat(matcher.get("STEREO", 0)).isNull(); + assertThat(matcher.get("COMPOSITE", 0)).isNull(); + } + + @Test + void test_parseWithType() { + IRegex regex = CommandCreateAttribute.getRegexConcat(); + RegexResult matcher = regex.matcher("attr : String"); + + assertThat(matcher).isNotNull(); + assertThat(matcher.get("DISPLAY", 0)).isNull(); + assertThat(matcher.get("CODE", 0)).isEqualTo("attr : String"); + assertThat(matcher.get("STEREO", 0)).isNull(); + assertThat(matcher.get("COMPOSITE", 0)).isNull(); + } + + @Test + void test_parseComposite() { + IRegex regex = CommandCreateAttribute.getRegexConcat(); + RegexResult matcher = regex.matcher("attr{"); + + assertThat(matcher).isNotNull(); + assertThat(matcher.get("DISPLAY", 0)).isNull(); + assertThat(matcher.get("CODE", 0)).isEqualTo("attr"); + assertThat(matcher.get("STEREO", 0)).isNull(); + assertThat(matcher.get("COMPOSITE", 0)).isNotNull(); + } + + @Test + void test_parseWithDisplay() { + IRegex regex = CommandCreateAttribute.getRegexConcat(); + RegexResult matcher = regex.matcher("\"My Attribute\" as attr"); + + assertThat(matcher).isNotNull(); + assertThat(matcher.get("DISPLAY", 0)).isEqualTo("My Attribute"); + assertThat(matcher.get("CODE", 0)).isEqualTo("attr"); + assertThat(matcher.get("STEREO", 0)).isNull(); + assertThat(matcher.get("COMPOSITE", 0)).isNull(); + } + + @Test + void test_parseWithStereo() { + IRegex regex = CommandCreateAttribute.getRegexConcat(); + RegexResult matcher = regex.matcher("attr<>"); + + assertThat(matcher).isNotNull(); + assertThat(matcher.get("DISPLAY", 0)).isNull(); + assertThat(matcher.get("CODE", 0)).isEqualTo("attr"); + assertThat(matcher.get("STEREO", 0)).isEqualTo("<>"); + assertThat(matcher.get("COMPOSITE", 0)).isNull(); + } + + @Test + void test_execute() throws NoSuchColorException { + new CommandCreateEntity().execute(diagram, BlocLines.singleString("entity E {")); + + BlocLines lines = BlocLines.singleString("\"Attribute\" as attr<>"); + CommandExecutionResult result = command.execute(diagram, lines); + + assertThat(result).matches(CommandExecutionResult::isOk); + + Entity entity = diagram.quarkInContext(true, "E").getData(); + assertThat(entity).isNotNull(); + + Entity attribute = diagram.quarkInContext(true, "E/attr").getData(); + assertThat(attribute).isNotNull(); + assertThat(attribute.getDisplay().toString()).isEqualTo("[Attribute]"); + assertThat(attribute.getStereotype().toString()).isEqualTo("<>"); + + assertThat(diagram.getLinks().size()).isEqualTo(1); + Link link = diagram.getLinks().get(0); + assertThat(link).isNotNull(); + assertThat(link.getEntity1()).isSameAs(attribute); + assertThat(link.getEntity2()).isSameAs(entity); + } + + @Test + void test_executeNested() throws NoSuchColorException { + new CommandCreateEntity().execute(diagram, BlocLines.singleString("entity E {")); + + CommandExecutionResult result1 = command.execute(diagram, BlocLines.singleString("attr1{")); + CommandExecutionResult result2 = command.execute(diagram, BlocLines.singleString("attr2")); + + assertThat(result1).matches(CommandExecutionResult::isOk); + assertThat(result2).matches(CommandExecutionResult::isOk); + + Entity entity = diagram.quarkInContext(true, "E").getData(); + assertThat(entity).isNotNull(); + + Entity attribute1 = diagram.quarkInContext(true, "E/attr1").getData(); + assertThat(attribute1).isNotNull(); + assertThat(attribute1.getDisplay().toString()).isEqualTo("[attr1]"); + + Entity attribute2 = diagram.quarkInContext(true, "E/attr1/attr2").getData(); + assertThat(attribute2).isNotNull(); + assertThat(attribute2.getDisplay().toString()).isEqualTo("[attr2]"); + + assertThat(diagram.getLinks().size()).isEqualTo(2); + Link link1 = diagram.getLinks().get(0); + assertThat(link1).isNotNull(); + assertThat(link1.getEntity1()).isSameAs(attribute1); + assertThat(link1.getEntity2()).isSameAs(entity); + Link link2 = diagram.getLinks().get(1); + assertThat(link2).isNotNull(); + assertThat(link2.getEntity1()).isSameAs(attribute2); + assertThat(link2.getEntity2()).isSameAs(attribute1); + } + + @Test + void test_executeNonNested() throws NoSuchColorException { + new CommandCreateEntity().execute(diagram, BlocLines.singleString("entity E {")); + + CommandExecutionResult result1 = command.execute(diagram, BlocLines.singleString("attr1")); + CommandExecutionResult result2 = command.execute(diagram, BlocLines.singleString("attr2")); + + assertThat(result1).matches(CommandExecutionResult::isOk); + assertThat(result2).matches(CommandExecutionResult::isOk); + + Entity entity = diagram.quarkInContext(true, "E").getData(); + assertThat(entity).isNotNull(); + + Entity attribute1 = diagram.quarkInContext(true, "E/attr1").getData(); + assertThat(attribute1).isNotNull(); + assertThat(attribute1.getDisplay().toString()).isEqualTo("[attr1]"); + + Entity attribute2 = diagram.quarkInContext(true, "E/attr2").getData(); + assertThat(attribute2).isNotNull(); + assertThat(attribute2.getDisplay().toString()).isEqualTo("[attr2]"); + + assertThat(diagram.getLinks().size()).isEqualTo(2); + Link link1 = diagram.getLinks().get(0); + assertThat(link1).isNotNull(); + assertThat(link1.getEntity1()).isSameAs(attribute1); + assertThat(link1.getEntity2()).isSameAs(entity); + Link link2 = diagram.getLinks().get(1); + assertThat(link2).isNotNull(); + assertThat(link2.getEntity1()).isSameAs(attribute2); + assertThat(link2.getEntity2()).isSameAs(entity); + } +} diff --git a/test/net/sourceforge/plantuml/cheneer/command/CommandCreateEntityTest.java b/test/net/sourceforge/plantuml/cheneer/command/CommandCreateEntityTest.java new file mode 100644 index 000000000..7226e5c5e --- /dev/null +++ b/test/net/sourceforge/plantuml/cheneer/command/CommandCreateEntityTest.java @@ -0,0 +1,123 @@ +package net.sourceforge.plantuml.cheneer.command; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.List; + +import org.junit.jupiter.api.Test; + +import net.sourceforge.plantuml.abel.Entity; +import net.sourceforge.plantuml.abel.LeafType; +import net.sourceforge.plantuml.cheneer.ChenEerDiagram; +import net.sourceforge.plantuml.command.Command; +import net.sourceforge.plantuml.command.CommandExecutionResult; +import net.sourceforge.plantuml.core.UmlSource; +import net.sourceforge.plantuml.klimt.color.NoSuchColorException; +import net.sourceforge.plantuml.regex.IRegex; +import net.sourceforge.plantuml.regex.RegexResult; +import net.sourceforge.plantuml.utils.BlocLines; + +public class CommandCreateEntityTest { + + private final Command command = new CommandCreateEntity(); + + private final ChenEerDiagram diagram = new ChenEerDiagram(UmlSource.create(List.of(), false), null); + + @Test + void test_parseEntity() { + IRegex regex = CommandCreateEntity.getRegexConcat(); + RegexResult matcher = regex.matcher("entity Bus_123 {"); + + assertThat(matcher).isNotNull(); + assertThat(matcher.get("TYPE", 0)).isEqualTo("entity"); + assertThat(matcher.get("DISPLAY", 0)).isNull(); + assertThat(matcher.get("CODE", 0)).isEqualTo("Bus_123"); + assertThat(matcher.get("STEREO", 0)).isNull(); + } + + @Test + void test_parseRelationship() { + IRegex regex = CommandCreateEntity.getRegexConcat(); + RegexResult matcher = regex.matcher("relationship Drives {"); + + assertThat(matcher).isNotNull(); + assertThat(matcher.get("TYPE", 0)).isEqualTo("relationship"); + assertThat(matcher.get("DISPLAY", 0)).isNull(); + assertThat(matcher.get("CODE", 0)).isEqualTo("Drives"); + assertThat(matcher.get("STEREO", 0)).isNull(); + } + + @Test + void test_parseInvalid() { + IRegex regex = CommandCreateEntity.getRegexConcat(); + RegexResult matcher = regex.matcher("class MyClass {"); + + assertThat(matcher).isNull(); + } + + @Test + void test_parseEntityWithStereo() { + IRegex regex = CommandCreateEntity.getRegexConcat(); + RegexResult matcher = regex.matcher("entity Bus_123 <> {"); + + assertThat(matcher).isNotNull(); + assertThat(matcher.get("TYPE", 0)).isEqualTo("entity"); + assertThat(matcher.get("DISPLAY", 0)).isNull(); + assertThat(matcher.get("CODE", 0)).isEqualTo("Bus_123"); + assertThat(matcher.get("STEREO", 0)).isEqualTo("<>"); + } + + @Test + void test_parseEntityWithDisplayName() { + IRegex regex = CommandCreateEntity.getRegexConcat(); + RegexResult matcher = regex.matcher("entity \"Red Bus :)\" as Bus_123 <> {"); + + assertThat(matcher).isNotNull(); + assertThat(matcher.get("TYPE", 0)).isEqualTo("entity"); + assertThat(matcher.get("DISPLAY", 0)).isEqualTo("Red Bus :)"); + assertThat(matcher.get("CODE", 0)).isEqualTo("Bus_123"); + assertThat(matcher.get("STEREO", 0)).isEqualTo("<>"); + } + + @Test + void test_executeWithEntity() throws NoSuchColorException { + BlocLines lines = BlocLines.singleString("entity \"display\" as code <> {"); + CommandExecutionResult result = command.execute(diagram, lines); + + assertThat(result).matches(CommandExecutionResult::isOk); + + Entity entity = diagram.quarkInContext(true, "code").getData(); + assertThat(entity).isNotNull(); + assertThat(entity.getLeafType()).isEqualTo(LeafType.CHEN_ENTITY); + assertThat(entity.getDisplay().toString()).isEqualTo("[display]"); + assertThat(entity.getStereotype().toString()).isEqualTo("<>"); + + assertThat(diagram.peekOwner()).isSameAs(entity); + } + + @Test + void test_executeWithRelationship() throws NoSuchColorException { + BlocLines lines = BlocLines.singleString("relationship \"display\" as code <> {"); + CommandExecutionResult result = command.execute(diagram, lines); + + assertThat(result).matches(CommandExecutionResult::isOk); + + Entity entity = diagram.quarkInContext(true, "code").getData(); + assertThat(entity).isNotNull(); + assertThat(entity.getLeafType()).isEqualTo(LeafType.CHEN_RELATIONSHIP); + assertThat(entity.getDisplay().toString()).isEqualTo("[display]"); + assertThat(entity.getStereotype().toString()).isEqualTo("<>"); + + assertThat(diagram.peekOwner()).isSameAs(entity); + } + + @Test + void test_executeWithEntityWhenAlreadyExists() throws NoSuchColorException { + BlocLines lines = BlocLines.singleString("entity \"display\" as code <> {"); + command.execute(diagram, lines); + + CommandExecutionResult result = command.execute(diagram, lines); + + assertThat(result).matches(CommandExecutionResult::isOk); + } +} diff --git a/test/net/sourceforge/plantuml/cheneer/command/CommandEndGroupTest.java b/test/net/sourceforge/plantuml/cheneer/command/CommandEndGroupTest.java new file mode 100644 index 000000000..dfa696234 --- /dev/null +++ b/test/net/sourceforge/plantuml/cheneer/command/CommandEndGroupTest.java @@ -0,0 +1,49 @@ +package net.sourceforge.plantuml.cheneer.command; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.List; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mockito; +import org.mockito.Spy; +import org.mockito.junit.jupiter.MockitoExtension; + +import net.sourceforge.plantuml.cheneer.ChenEerDiagram; +import net.sourceforge.plantuml.command.Command; +import net.sourceforge.plantuml.command.CommandExecutionResult; +import net.sourceforge.plantuml.core.UmlSource; +import net.sourceforge.plantuml.klimt.color.NoSuchColorException; +import net.sourceforge.plantuml.regex.IRegex; +import net.sourceforge.plantuml.regex.RegexResult; +import net.sourceforge.plantuml.utils.BlocLines; + +@ExtendWith(MockitoExtension.class) +public class CommandEndGroupTest { + + private final Command command = new CommandEndGroup(); + + @Spy + private final ChenEerDiagram diagram = new ChenEerDiagram(UmlSource.create(List.of(), false), null); + + @Test + void test_parse() { + IRegex regex = CommandEndGroup.getRegexConcat(); + RegexResult matcher = regex.matcher("}"); + + assertThat(matcher).isNotNull(); + } + + @Test + void test_execute() throws NoSuchColorException { + diagram.pushOwner(null); + + BlocLines lines = BlocLines.singleString("}"); + CommandExecutionResult result = command.execute(diagram, lines); + + assertThat(result).matches(CommandExecutionResult::isOk); + + Mockito.verify(diagram).popOwner(); + } +} diff --git a/test/net/sourceforge/plantuml/cheneer/command/CommandMultiSubclassTest.java b/test/net/sourceforge/plantuml/cheneer/command/CommandMultiSubclassTest.java new file mode 100644 index 000000000..d6b0c9168 --- /dev/null +++ b/test/net/sourceforge/plantuml/cheneer/command/CommandMultiSubclassTest.java @@ -0,0 +1,214 @@ +package net.sourceforge.plantuml.cheneer.command; + +import static org.assertj.core.api.Assertions.assertThat; + +import net.sourceforge.plantuml.core.UmlSource; + +import org.junit.jupiter.api.Test; + +import net.sourceforge.plantuml.abel.Link; +import net.sourceforge.plantuml.cheneer.ChenEerDiagram; +import net.sourceforge.plantuml.command.Command; +import net.sourceforge.plantuml.command.CommandExecutionResult; +import net.sourceforge.plantuml.decoration.LinkMiddleDecor; +import net.sourceforge.plantuml.klimt.color.NoSuchColorException; +import net.sourceforge.plantuml.regex.IRegex; +import net.sourceforge.plantuml.regex.RegexResult; +import net.sourceforge.plantuml.utils.BlocLines; + +import java.util.List; + +public class CommandMultiSubclassTest { + + private final Command command = new CommandMultiSubclass(); + + private final ChenEerDiagram diagram = new ChenEerDiagram(UmlSource.create(List.of(), false), null); + + @Test + void test_parse() { + IRegex regex = CommandMultiSubclass.getRegexConcat(); + RegexResult matcher = regex.matcher("E1 ->- d { E2, E3, E4 }"); + + assertThat(matcher).isNotNull(); + assertThat(matcher.get("SUPERCLASS", 0)).isEqualTo("E1"); + assertThat(matcher.get("SUBCLASSES", 0)).isEqualTo(" E2, E3, E4 "); + assertThat(matcher.get("PARTICIPATION", 0)).isEqualTo("-"); + assertThat(matcher.get("SYMBOL", 0)).isEqualTo("d"); + } + + @Test + void test_parseWithCompulsoryParticipation() { + IRegex regex = CommandMultiSubclass.getRegexConcat(); + RegexResult matcher = regex.matcher("E1 =>= d { E2, E3, E4 }"); + + assertThat(matcher).isNotNull(); + assertThat(matcher.get("SUPERCLASS", 0)).isEqualTo("E1"); + assertThat(matcher.get("SUBCLASSES", 0)).isEqualTo(" E2, E3, E4 "); + assertThat(matcher.get("PARTICIPATION", 0)).isEqualTo("="); + assertThat(matcher.get("SYMBOL", 0)).isEqualTo("d"); + } + + @Test + void test_parseOverlapping() { + IRegex regex = CommandMultiSubclass.getRegexConcat(); + RegexResult matcher = regex.matcher("E1 ->- o { E2, E3, E4 }"); + + assertThat(matcher).isNotNull(); + assertThat(matcher.get("SUPERCLASS", 0)).isEqualTo("E1"); + assertThat(matcher.get("SUBCLASSES", 0)).isEqualTo(" E2, E3, E4 "); + assertThat(matcher.get("PARTICIPATION", 0)).isEqualTo("-"); + assertThat(matcher.get("SYMBOL", 0)).isEqualTo("o"); + } + + @Test + void test_parseCategory() { + IRegex regex = CommandMultiSubclass.getRegexConcat(); + RegexResult matcher = regex.matcher("E1 ->- U { E2, E3, E4 }"); + + assertThat(matcher).isNotNull(); + assertThat(matcher.get("SUPERCLASS", 0)).isEqualTo("E1"); + assertThat(matcher.get("SUBCLASSES", 0)).isEqualTo(" E2, E3, E4 "); + assertThat(matcher.get("PARTICIPATION", 0)).isEqualTo("-"); + assertThat(matcher.get("SYMBOL", 0)).isEqualTo("U"); + } + + @Test + void test_executeOverlappingSubclasses() throws NoSuchColorException { + new CommandCreateEntity().execute(diagram, BlocLines.singleString("entity E1 {")); + new CommandCreateEntity().execute(diagram, BlocLines.singleString("entity E2 {")); + new CommandCreateEntity().execute(diagram, BlocLines.singleString("entity E3 {")); + new CommandCreateEntity().execute(diagram, BlocLines.singleString("entity E4 {")); + + BlocLines lines = BlocLines.singleString("E1 ->- o { E2, E3, E4 }"); + CommandExecutionResult result = command.execute(diagram, lines); + + assertThat(result).matches(CommandExecutionResult::isOk); + + assertThat(diagram.getLinks().size()).isEqualTo(4); + Link link1 = diagram.getLinks().get(0); + assertThat(link1.getEntity1().getName()).isEqualTo("E1"); + assertThat(link1.getEntity2().getName()).isEqualTo("E1/o E2, E3, E4 /center"); + assertThat(link1.getType().getStyle().getStroke3().getThickness()).isEqualTo(1); + assertThat(link1.getType().getMiddleDecor()).isEqualTo(LinkMiddleDecor.NONE); + Link link2 = diagram.getLinks().get(1); + assertThat(link2.getEntity1().getName()).isEqualTo("E1/o E2, E3, E4 /center"); + assertThat(link2.getEntity2().getName()).isEqualTo("E2"); + assertThat(link2.getType().getStyle().getStroke3().getThickness()).isEqualTo(1); + assertThat(link2.getType().getMiddleDecor()).isEqualTo(LinkMiddleDecor.SUPERSET); + Link link3 = diagram.getLinks().get(2); + assertThat(link3.getEntity1().getName()).isEqualTo("E1/o E2, E3, E4 /center"); + assertThat(link3.getEntity2().getName()).isEqualTo("E3"); + assertThat(link3.getType().getStyle().getStroke3().getThickness()).isEqualTo(1); + assertThat(link3.getType().getMiddleDecor()).isEqualTo(LinkMiddleDecor.SUPERSET); + Link link4 = diagram.getLinks().get(3); + assertThat(link4.getEntity1().getName()).isEqualTo("E1/o E2, E3, E4 /center"); + assertThat(link4.getEntity2().getName()).isEqualTo("E4"); + assertThat(link4.getType().getStyle().getStroke3().getThickness()).isEqualTo(1); + assertThat(link4.getType().getMiddleDecor()).isEqualTo(LinkMiddleDecor.SUPERSET); + } + + @Test + void test_executeOverlappingSubclassesWithCompulsaryParticipation() throws NoSuchColorException { + new CommandCreateEntity().execute(diagram, BlocLines.singleString("entity E1 {")); + new CommandCreateEntity().execute(diagram, BlocLines.singleString("entity E2 {")); + new CommandCreateEntity().execute(diagram, BlocLines.singleString("entity E3 {")); + new CommandCreateEntity().execute(diagram, BlocLines.singleString("entity E4 {")); + + BlocLines lines = BlocLines.singleString("E1 =>= o { E2, E3, E4 }"); + CommandExecutionResult result = command.execute(diagram, lines); + + assertThat(result).matches(CommandExecutionResult::isOk); + + assertThat(diagram.getLinks().size()).isEqualTo(4); + Link link1 = diagram.getLinks().get(0); + assertThat(link1.getEntity1().getName()).isEqualTo("E1"); + assertThat(link1.getEntity2().getName()).isEqualTo("E1/o E2, E3, E4 /center"); + assertThat(link1.getType().getStyle().getStroke3().getThickness()).isEqualTo(2); + assertThat(link1.getType().getMiddleDecor()).isEqualTo(LinkMiddleDecor.NONE); + Link link2 = diagram.getLinks().get(1); + assertThat(link2.getEntity1().getName()).isEqualTo("E1/o E2, E3, E4 /center"); + assertThat(link2.getEntity2().getName()).isEqualTo("E2"); + assertThat(link2.getType().getStyle().getStroke3().getThickness()).isEqualTo(1); + assertThat(link2.getType().getMiddleDecor()).isEqualTo(LinkMiddleDecor.SUPERSET); + Link link3 = diagram.getLinks().get(2); + assertThat(link3.getEntity1().getName()).isEqualTo("E1/o E2, E3, E4 /center"); + assertThat(link3.getEntity2().getName()).isEqualTo("E3"); + assertThat(link3.getType().getStyle().getStroke3().getThickness()).isEqualTo(1); + assertThat(link3.getType().getMiddleDecor()).isEqualTo(LinkMiddleDecor.SUPERSET); + Link link4 = diagram.getLinks().get(3); + assertThat(link4.getEntity1().getName()).isEqualTo("E1/o E2, E3, E4 /center"); + assertThat(link4.getEntity2().getName()).isEqualTo("E4"); + assertThat(link4.getType().getStyle().getStroke3().getThickness()).isEqualTo(1); + assertThat(link4.getType().getMiddleDecor()).isEqualTo(LinkMiddleDecor.SUPERSET); + } + + @Test + void test_executeCategories() throws NoSuchColorException { + new CommandCreateEntity().execute(diagram, BlocLines.singleString("entity E1 {")); + new CommandCreateEntity().execute(diagram, BlocLines.singleString("entity E2 {")); + new CommandCreateEntity().execute(diagram, BlocLines.singleString("entity E3 {")); + new CommandCreateEntity().execute(diagram, BlocLines.singleString("entity E4 {")); + + BlocLines lines = BlocLines.singleString("E1 ->- U { E2, E3, E4 }"); + CommandExecutionResult result = command.execute(diagram, lines); + + assertThat(result).matches(CommandExecutionResult::isOk); + + assertThat(diagram.getLinks().size()).isEqualTo(4); + Link link1 = diagram.getLinks().get(0); + assertThat(link1.getEntity1().getName()).isEqualTo("E1"); + assertThat(link1.getEntity2().getName()).isEqualTo("E1/U E2, E3, E4 /center"); + assertThat(link1.getType().getStyle().getStroke3().getThickness()).isEqualTo(1); + assertThat(link1.getType().getMiddleDecor()).isEqualTo(LinkMiddleDecor.SUPERSET); + Link link2 = diagram.getLinks().get(1); + assertThat(link2.getEntity1().getName()).isEqualTo("E1/U E2, E3, E4 /center"); + assertThat(link2.getEntity2().getName()).isEqualTo("E2"); + assertThat(link2.getType().getStyle().getStroke3().getThickness()).isEqualTo(1); + assertThat(link2.getType().getMiddleDecor()).isEqualTo(LinkMiddleDecor.NONE); + Link link3 = diagram.getLinks().get(2); + assertThat(link3.getEntity1().getName()).isEqualTo("E1/U E2, E3, E4 /center"); + assertThat(link3.getEntity2().getName()).isEqualTo("E3"); + assertThat(link3.getType().getStyle().getStroke3().getThickness()).isEqualTo(1); + assertThat(link3.getType().getMiddleDecor()).isEqualTo(LinkMiddleDecor.NONE); + Link link4 = diagram.getLinks().get(3); + assertThat(link4.getEntity1().getName()).isEqualTo("E1/U E2, E3, E4 /center"); + assertThat(link4.getEntity2().getName()).isEqualTo("E4"); + assertThat(link4.getType().getStyle().getStroke3().getThickness()).isEqualTo(1); + assertThat(link4.getType().getMiddleDecor()).isEqualTo(LinkMiddleDecor.NONE); + } + + @Test + void test_executeCategoriesWithCompulsaryParticipation() throws NoSuchColorException { + new CommandCreateEntity().execute(diagram, BlocLines.singleString("entity E1 {")); + new CommandCreateEntity().execute(diagram, BlocLines.singleString("entity E2 {")); + new CommandCreateEntity().execute(diagram, BlocLines.singleString("entity E3 {")); + new CommandCreateEntity().execute(diagram, BlocLines.singleString("entity E4 {")); + + BlocLines lines = BlocLines.singleString("E1 =>= U { E2, E3, E4 }"); + CommandExecutionResult result = command.execute(diagram, lines); + + assertThat(result).matches(CommandExecutionResult::isOk); + + assertThat(diagram.getLinks().size()).isEqualTo(4); + Link link1 = diagram.getLinks().get(0); + assertThat(link1.getEntity1().getName()).isEqualTo("E1"); + assertThat(link1.getEntity2().getName()).isEqualTo("E1/U E2, E3, E4 /center"); + assertThat(link1.getType().getStyle().getStroke3().getThickness()).isEqualTo(2); + assertThat(link1.getType().getMiddleDecor()).isEqualTo(LinkMiddleDecor.SUPERSET); + Link link2 = diagram.getLinks().get(1); + assertThat(link2.getEntity1().getName()).isEqualTo("E1/U E2, E3, E4 /center"); + assertThat(link2.getEntity2().getName()).isEqualTo("E2"); + assertThat(link2.getType().getStyle().getStroke3().getThickness()).isEqualTo(1); + assertThat(link2.getType().getMiddleDecor()).isEqualTo(LinkMiddleDecor.NONE); + Link link3 = diagram.getLinks().get(2); + assertThat(link3.getEntity1().getName()).isEqualTo("E1/U E2, E3, E4 /center"); + assertThat(link3.getEntity2().getName()).isEqualTo("E3"); + assertThat(link3.getType().getStyle().getStroke3().getThickness()).isEqualTo(1); + assertThat(link3.getType().getMiddleDecor()).isEqualTo(LinkMiddleDecor.NONE); + Link link4 = diagram.getLinks().get(3); + assertThat(link4.getEntity1().getName()).isEqualTo("E1/U E2, E3, E4 /center"); + assertThat(link4.getEntity2().getName()).isEqualTo("E4"); + assertThat(link4.getType().getStyle().getStroke3().getThickness()).isEqualTo(1); + assertThat(link4.getType().getMiddleDecor()).isEqualTo(LinkMiddleDecor.NONE); + } +} diff --git a/test/net/sourceforge/plantuml/cheneer/command/CommandSimpleSubclassTest.java b/test/net/sourceforge/plantuml/cheneer/command/CommandSimpleSubclassTest.java new file mode 100644 index 000000000..ed27ae6b5 --- /dev/null +++ b/test/net/sourceforge/plantuml/cheneer/command/CommandSimpleSubclassTest.java @@ -0,0 +1,112 @@ +package net.sourceforge.plantuml.cheneer.command; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.List; + +import org.junit.jupiter.api.Test; + +import net.sourceforge.plantuml.abel.Link; +import net.sourceforge.plantuml.cheneer.ChenEerDiagram; +import net.sourceforge.plantuml.command.Command; +import net.sourceforge.plantuml.command.CommandExecutionResult; +import net.sourceforge.plantuml.core.UmlSource; +import net.sourceforge.plantuml.decoration.LinkMiddleDecor; +import net.sourceforge.plantuml.klimt.color.NoSuchColorException; +import net.sourceforge.plantuml.regex.IRegex; +import net.sourceforge.plantuml.regex.RegexResult; +import net.sourceforge.plantuml.utils.BlocLines; + +public class CommandSimpleSubclassTest { + + private final Command command = new CommandSimpleSubclass(); + + private final ChenEerDiagram diagram = new ChenEerDiagram(UmlSource.create(List.of(), false), null); + + @Test + void test_parseSubset() { + IRegex regex = CommandSimpleSubclass.getRegexConcat(); + RegexResult matcher = regex.matcher("E1 -<- E2"); + + assertThat(matcher).isNotNull(); + assertThat(matcher.get("NAME1", 0)).isEqualTo("E1"); + assertThat(matcher.get("NAME2", 0)).isEqualTo("E2"); + assertThat(matcher.get("PARTICIPATION", 0)).isEqualTo("-"); + assertThat(matcher.get("DIRECTION", 0)).isEqualTo("<"); + } + + @Test + void test_parseSubsetWithCompulsoryParticipation() { + IRegex regex = CommandSimpleSubclass.getRegexConcat(); + RegexResult matcher = regex.matcher("E1 =<= E2"); + + assertThat(matcher).isNotNull(); + assertThat(matcher.get("NAME1", 0)).isEqualTo("E1"); + assertThat(matcher.get("NAME2", 0)).isEqualTo("E2"); + assertThat(matcher.get("PARTICIPATION", 0)).isEqualTo("="); + assertThat(matcher.get("DIRECTION", 0)).isEqualTo("<"); + } + + @Test + void test_parseSuperset() { + IRegex regex = CommandSimpleSubclass.getRegexConcat(); + RegexResult matcher = regex.matcher("E1 ->- E2"); + + assertThat(matcher).isNotNull(); + assertThat(matcher.get("NAME1", 0)).isEqualTo("E1"); + assertThat(matcher.get("NAME2", 0)).isEqualTo("E2"); + assertThat(matcher.get("PARTICIPATION", 0)).isEqualTo("-"); + assertThat(matcher.get("DIRECTION", 0)).isEqualTo(">"); + } + + @Test + void test_executeSubset() throws NoSuchColorException { + new CommandCreateEntity().execute(diagram, BlocLines.singleString("entity E1 {")); + new CommandCreateEntity().execute(diagram, BlocLines.singleString("entity E2 {")); + + BlocLines lines = BlocLines.singleString("E1 -<- E2"); + CommandExecutionResult result = command.execute(diagram, lines); + + assertThat(result).matches(CommandExecutionResult::isOk); + + Link link = diagram.getLinks().get(0); + assertThat(link.getEntity1().getName()).isEqualTo("E1"); + assertThat(link.getEntity2().getName()).isEqualTo("E2"); + assertThat(link.getType().getStyle().getStroke3().getThickness()).isEqualTo(1); + assertThat(link.getType().getMiddleDecor()).isEqualTo(LinkMiddleDecor.SUBSET); + } + + @Test + void test_executeSubsetWithCompulsoryParticipation() throws NoSuchColorException { + new CommandCreateEntity().execute(diagram, BlocLines.singleString("entity E1 {")); + new CommandCreateEntity().execute(diagram, BlocLines.singleString("entity E2 {")); + + BlocLines lines = BlocLines.singleString("E1 =<= E2"); + CommandExecutionResult result = command.execute(diagram, lines); + + assertThat(result).matches(CommandExecutionResult::isOk); + + Link link = diagram.getLinks().get(0); + assertThat(link.getEntity1().getName()).isEqualTo("E1"); + assertThat(link.getEntity2().getName()).isEqualTo("E2"); + assertThat(link.getType().getStyle().getStroke3().getThickness()).isEqualTo(2); + assertThat(link.getType().getMiddleDecor()).isEqualTo(LinkMiddleDecor.SUBSET); + } + + @Test + void test_executeSuperset() throws NoSuchColorException { + new CommandCreateEntity().execute(diagram, BlocLines.singleString("entity E1 {")); + new CommandCreateEntity().execute(diagram, BlocLines.singleString("entity E2 {")); + + BlocLines lines = BlocLines.singleString("E1 ->- E2"); + CommandExecutionResult result = command.execute(diagram, lines); + + assertThat(result).matches(CommandExecutionResult::isOk); + + Link link = diagram.getLinks().get(0); + assertThat(link.getEntity1().getName()).isEqualTo("E1"); + assertThat(link.getEntity2().getName()).isEqualTo("E2"); + assertThat(link.getType().getStyle().getStroke3().getThickness()).isEqualTo(1); + assertThat(link.getType().getMiddleDecor()).isEqualTo(LinkMiddleDecor.SUPERSET); + } +} From e14c8ef0a50bf094444c1f2ac47ff412e9292a09 Mon Sep 17 00:00:00 2001 From: Benjamin Davies Date: Thu, 21 Mar 2024 19:34:33 +1300 Subject: [PATCH 22/23] Re-add chronology diagram This was accidentally removed in a merge --- src/net/sourceforge/plantuml/core/DiagramType.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/net/sourceforge/plantuml/core/DiagramType.java b/src/net/sourceforge/plantuml/core/DiagramType.java index b01603de0..0105cbd83 100644 --- a/src/net/sourceforge/plantuml/core/DiagramType.java +++ b/src/net/sourceforge/plantuml/core/DiagramType.java @@ -5,12 +5,12 @@ * (C) Copyright 2009-2024, Arnaud Roques * * Project Info: https://plantuml.com - * + * * If you like this project or if you find it useful, you can support us at: - * + * * https://plantuml.com/patreon (only 1$ per month!) * https://plantuml.com/paypal - * + * * This file is part of PlantUML. * * PlantUML is free software; you can redistribute it and/or modify it @@ -127,8 +127,11 @@ public enum DiagramType { if (StartUtils.startsWithSymbolAnd("startfiles", s)) return FILES; + if (StartUtils.startsWithSymbolAnd("startchronology", s)) + return CHRONOLOGY; + if (StartUtils.startsWithSymbolAnd("startchen", s)) - return CHEN_EER; + return CHEN_EER; return UNKNOWN; } From 4b5bcd3bca2726ab8ded2f7ad1061d6cd489d4a0 Mon Sep 17 00:00:00 2001 From: Benjamin Davies Date: Thu, 21 Mar 2024 19:38:05 +1300 Subject: [PATCH 23/23] Fix compatibility with Java 8 --- .../plantuml/cheneer/command/CommandAssociateTest.java | 4 ++-- .../cheneer/command/CommandCreateAttributeTest.java | 4 ++-- .../plantuml/cheneer/command/CommandCreateEntityTest.java | 4 ++-- .../plantuml/cheneer/command/CommandEndGroupTest.java | 4 ++-- .../plantuml/cheneer/command/CommandMultiSubclassTest.java | 7 +++---- .../cheneer/command/CommandSimpleSubclassTest.java | 4 ++-- 6 files changed, 13 insertions(+), 14 deletions(-) diff --git a/test/net/sourceforge/plantuml/cheneer/command/CommandAssociateTest.java b/test/net/sourceforge/plantuml/cheneer/command/CommandAssociateTest.java index cb72a51fa..1012443b6 100644 --- a/test/net/sourceforge/plantuml/cheneer/command/CommandAssociateTest.java +++ b/test/net/sourceforge/plantuml/cheneer/command/CommandAssociateTest.java @@ -2,7 +2,7 @@ package net.sourceforge.plantuml.cheneer.command; import static org.assertj.core.api.Assertions.assertThat; -import java.util.List; +import java.util.ArrayList; import org.junit.jupiter.api.Test; @@ -20,7 +20,7 @@ public class CommandAssociateTest { private final Command command = new CommandAssociate(); - private final ChenEerDiagram diagram = new ChenEerDiagram(UmlSource.create(List.of(), false), null); + private final ChenEerDiagram diagram = new ChenEerDiagram(UmlSource.create(new ArrayList<>(), false), null); @Test void test_parse() { diff --git a/test/net/sourceforge/plantuml/cheneer/command/CommandCreateAttributeTest.java b/test/net/sourceforge/plantuml/cheneer/command/CommandCreateAttributeTest.java index 08c2139f8..d2735db5d 100644 --- a/test/net/sourceforge/plantuml/cheneer/command/CommandCreateAttributeTest.java +++ b/test/net/sourceforge/plantuml/cheneer/command/CommandCreateAttributeTest.java @@ -2,7 +2,7 @@ package net.sourceforge.plantuml.cheneer.command; import static org.assertj.core.api.Assertions.assertThat; -import java.util.List; +import java.util.ArrayList; import org.junit.jupiter.api.Test; @@ -21,7 +21,7 @@ public class CommandCreateAttributeTest { private final Command command = new CommandCreateAttribute(); - private final ChenEerDiagram diagram = new ChenEerDiagram(UmlSource.create(List.of(), false), null); + private final ChenEerDiagram diagram = new ChenEerDiagram(UmlSource.create(new ArrayList<>(), false), null); @Test void test_parse() { diff --git a/test/net/sourceforge/plantuml/cheneer/command/CommandCreateEntityTest.java b/test/net/sourceforge/plantuml/cheneer/command/CommandCreateEntityTest.java index 7226e5c5e..f9730f537 100644 --- a/test/net/sourceforge/plantuml/cheneer/command/CommandCreateEntityTest.java +++ b/test/net/sourceforge/plantuml/cheneer/command/CommandCreateEntityTest.java @@ -2,7 +2,7 @@ package net.sourceforge.plantuml.cheneer.command; import static org.assertj.core.api.Assertions.assertThat; -import java.util.List; +import java.util.ArrayList; import org.junit.jupiter.api.Test; @@ -21,7 +21,7 @@ public class CommandCreateEntityTest { private final Command command = new CommandCreateEntity(); - private final ChenEerDiagram diagram = new ChenEerDiagram(UmlSource.create(List.of(), false), null); + private final ChenEerDiagram diagram = new ChenEerDiagram(UmlSource.create(new ArrayList<>(), false), null); @Test void test_parseEntity() { diff --git a/test/net/sourceforge/plantuml/cheneer/command/CommandEndGroupTest.java b/test/net/sourceforge/plantuml/cheneer/command/CommandEndGroupTest.java index dfa696234..99f4a5591 100644 --- a/test/net/sourceforge/plantuml/cheneer/command/CommandEndGroupTest.java +++ b/test/net/sourceforge/plantuml/cheneer/command/CommandEndGroupTest.java @@ -2,7 +2,7 @@ package net.sourceforge.plantuml.cheneer.command; import static org.assertj.core.api.Assertions.assertThat; -import java.util.List; +import java.util.ArrayList; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -25,7 +25,7 @@ public class CommandEndGroupTest { private final Command command = new CommandEndGroup(); @Spy - private final ChenEerDiagram diagram = new ChenEerDiagram(UmlSource.create(List.of(), false), null); + private final ChenEerDiagram diagram = new ChenEerDiagram(UmlSource.create(new ArrayList<>(), false), null); @Test void test_parse() { diff --git a/test/net/sourceforge/plantuml/cheneer/command/CommandMultiSubclassTest.java b/test/net/sourceforge/plantuml/cheneer/command/CommandMultiSubclassTest.java index d6b0c9168..d1fc338ed 100644 --- a/test/net/sourceforge/plantuml/cheneer/command/CommandMultiSubclassTest.java +++ b/test/net/sourceforge/plantuml/cheneer/command/CommandMultiSubclassTest.java @@ -2,7 +2,7 @@ package net.sourceforge.plantuml.cheneer.command; import static org.assertj.core.api.Assertions.assertThat; -import net.sourceforge.plantuml.core.UmlSource; +import java.util.ArrayList; import org.junit.jupiter.api.Test; @@ -10,19 +10,18 @@ import net.sourceforge.plantuml.abel.Link; import net.sourceforge.plantuml.cheneer.ChenEerDiagram; import net.sourceforge.plantuml.command.Command; import net.sourceforge.plantuml.command.CommandExecutionResult; +import net.sourceforge.plantuml.core.UmlSource; import net.sourceforge.plantuml.decoration.LinkMiddleDecor; import net.sourceforge.plantuml.klimt.color.NoSuchColorException; import net.sourceforge.plantuml.regex.IRegex; import net.sourceforge.plantuml.regex.RegexResult; import net.sourceforge.plantuml.utils.BlocLines; -import java.util.List; - public class CommandMultiSubclassTest { private final Command command = new CommandMultiSubclass(); - private final ChenEerDiagram diagram = new ChenEerDiagram(UmlSource.create(List.of(), false), null); + private final ChenEerDiagram diagram = new ChenEerDiagram(UmlSource.create(new ArrayList<>(), false), null); @Test void test_parse() { diff --git a/test/net/sourceforge/plantuml/cheneer/command/CommandSimpleSubclassTest.java b/test/net/sourceforge/plantuml/cheneer/command/CommandSimpleSubclassTest.java index ed27ae6b5..22a33b2c5 100644 --- a/test/net/sourceforge/plantuml/cheneer/command/CommandSimpleSubclassTest.java +++ b/test/net/sourceforge/plantuml/cheneer/command/CommandSimpleSubclassTest.java @@ -2,7 +2,7 @@ package net.sourceforge.plantuml.cheneer.command; import static org.assertj.core.api.Assertions.assertThat; -import java.util.List; +import java.util.ArrayList; import org.junit.jupiter.api.Test; @@ -21,7 +21,7 @@ public class CommandSimpleSubclassTest { private final Command command = new CommandSimpleSubclass(); - private final ChenEerDiagram diagram = new ChenEerDiagram(UmlSource.create(List.of(), false), null); + private final ChenEerDiagram diagram = new ChenEerDiagram(UmlSource.create(new ArrayList<>(), false), null); @Test void test_parseSubset() {