From 96785da1c76a6e31b4b61414892e54caa5b1e734 Mon Sep 17 00:00:00 2001 From: Benjamin Davies Date: Thu, 16 Nov 2023 18:42:47 +1300 Subject: [PATCH] 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(); + } + +}