summaryrefslogtreecommitdiff
path: root/src/net/sourceforge/plantuml/statediagram
diff options
context:
space:
mode:
Diffstat (limited to 'src/net/sourceforge/plantuml/statediagram')
-rw-r--r--src/net/sourceforge/plantuml/statediagram/StateDiagram.java216
-rw-r--r--src/net/sourceforge/plantuml/statediagram/StateDiagramFactory.java145
-rw-r--r--src/net/sourceforge/plantuml/statediagram/command/CommandAddField.java74
-rw-r--r--src/net/sourceforge/plantuml/statediagram/command/CommandConcurrentState.java57
-rw-r--r--src/net/sourceforge/plantuml/statediagram/command/CommandCreatePackageState.java115
-rw-r--r--src/net/sourceforge/plantuml/statediagram/command/CommandCreateState.java141
-rw-r--r--src/net/sourceforge/plantuml/statediagram/command/CommandEndState.java60
-rw-r--r--src/net/sourceforge/plantuml/statediagram/command/CommandHideEmptyDescription.java55
-rw-r--r--src/net/sourceforge/plantuml/statediagram/command/CommandLinkState.java219
9 files changed, 1082 insertions, 0 deletions
diff --git a/src/net/sourceforge/plantuml/statediagram/StateDiagram.java b/src/net/sourceforge/plantuml/statediagram/StateDiagram.java
new file mode 100644
index 0000000..6d147af
--- /dev/null
+++ b/src/net/sourceforge/plantuml/statediagram/StateDiagram.java
@@ -0,0 +1,216 @@
+/* ========================================================================
+ * PlantUML : a free UML diagram generator
+ * ========================================================================
+ *
+ * (C) Copyright 2009-2014, Arnaud Roques
+ *
+ * Project Info: http://plantuml.sourceforge.net
+ *
+ * This file is part of PlantUML.
+ *
+ * Licensed under The MIT License (Massachusetts Institute of Technology License)
+ *
+ * See http://opensource.org/licenses/MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+ * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *
+ * Original Author: Arnaud Roques
+ */
+package net.sourceforge.plantuml.statediagram;
+
+import net.sourceforge.plantuml.UmlDiagramType;
+import net.sourceforge.plantuml.classdiagram.AbstractEntityDiagram;
+import net.sourceforge.plantuml.cucadiagram.Code;
+import net.sourceforge.plantuml.cucadiagram.Display;
+import net.sourceforge.plantuml.cucadiagram.EntityUtils;
+import net.sourceforge.plantuml.cucadiagram.GroupType;
+import net.sourceforge.plantuml.cucadiagram.IEntity;
+import net.sourceforge.plantuml.cucadiagram.IGroup;
+import net.sourceforge.plantuml.cucadiagram.LeafType;
+import net.sourceforge.plantuml.cucadiagram.Rankdir;
+import net.sourceforge.plantuml.graphic.USymbol;
+import net.sourceforge.plantuml.utils.UniqueSequence;
+
+public class StateDiagram extends AbstractEntityDiagram {
+
+ public boolean checkConcurrentStateOk(Code code) {
+ if (leafExist(code) == false) {
+ return true;
+ }
+ final IEntity existing = this.getLeafsget(code);
+ if (getCurrentGroup().getGroupType() == GroupType.CONCURRENT_STATE
+ && getCurrentGroup() != existing.getParentContainer()) {
+ return false;
+ }
+ if (existing.getParentContainer().getGroupType() == GroupType.CONCURRENT_STATE
+ && getCurrentGroup() != existing.getParentContainer()) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public IEntity getOrCreateLeaf(Code code, LeafType type, USymbol symbol) {
+ if (checkConcurrentStateOk(code) == false) {
+ throw new IllegalStateException("Concurrent State " + code);
+ }
+ if (type == null) {
+ if (code.getFullName().startsWith("[*]")) {
+ throw new IllegalArgumentException();
+ }
+ if (isGroup(code)) {
+ return getGroup(code);
+ }
+ return getOrCreateLeafDefault(code, LeafType.STATE, null);
+ }
+ return getOrCreateLeafDefault(code, type, symbol);
+ }
+
+ public IEntity getStart() {
+ final IGroup g = getCurrentGroup();
+ if (EntityUtils.groupRoot(g)) {
+ return getOrCreateLeaf(Code.of("*start"), LeafType.CIRCLE_START, null);
+ }
+ return getOrCreateLeaf(Code.of("*start*" + g.getCode().getFullName()), LeafType.CIRCLE_START, null);
+ }
+
+ public IEntity getEnd() {
+ final IGroup p = getCurrentGroup();
+ if (EntityUtils.groupRoot(p)) {
+ return getOrCreateLeaf(Code.of("*end"), LeafType.CIRCLE_END, null);
+ }
+ return getOrCreateLeaf(Code.of("*end*" + p.getCode().getFullName()), LeafType.CIRCLE_END, null);
+ }
+
+ public IEntity getHistorical() {
+ final IGroup g = getCurrentGroup();
+ if (EntityUtils.groupRoot(g)) {
+ return getOrCreateLeaf(Code.of("*historical"), LeafType.PSEUDO_STATE, null);
+ }
+ return getOrCreateLeaf(Code.of("*historical*" + g.getCode().getFullName()), LeafType.PSEUDO_STATE, null);
+ }
+
+ public IEntity getHistorical(Code codeGroup) {
+ final IEntity g = getOrCreateGroup(codeGroup, Display.getWithNewlines(codeGroup), GroupType.STATE,
+ getRootGroup());
+ final IEntity result = getOrCreateLeaf(Code.of("*historical*" + g.getCode().getFullName()),
+ LeafType.PSEUDO_STATE, null);
+ endGroup();
+ return result;
+ }
+
+ public boolean concurrentState(char direction) {
+ final IGroup cur = getCurrentGroup();
+ // printlink("BEFORE");
+ if (EntityUtils.groupRoot(cur) == false && cur.getGroupType() == GroupType.CONCURRENT_STATE) {
+ super.endGroup();
+ }
+ getCurrentGroup().setConcurrentSeparator(direction);
+ final IGroup conc1 = getOrCreateGroup(UniqueSequence.getCode("CONC"), Display.create(""),
+ GroupType.CONCURRENT_STATE, getCurrentGroup());
+ if (EntityUtils.groupRoot(cur) == false && cur.getGroupType() == GroupType.STATE) {
+ cur.moveEntitiesTo(conc1);
+ super.endGroup();
+ getOrCreateGroup(UniqueSequence.getCode("CONC"), Display.create(""), GroupType.CONCURRENT_STATE,
+ getCurrentGroup());
+ }
+ // printlink("AFTER");
+ return true;
+ }
+
+ // private void printlink(String comment) {
+ // Log.println("COMMENT="+comment);
+ // for (Link l : getLinks()) {
+ // Log.println(l);
+ // }
+ // }
+
+ @Override
+ public void endGroup() {
+ final IGroup cur = getCurrentGroup();
+ if (EntityUtils.groupRoot(cur) == false && cur.getGroupType() == GroupType.CONCURRENT_STATE) {
+ super.endGroup();
+ }
+ super.endGroup();
+ }
+
+ @Override
+ public UmlDiagramType getUmlDiagramType() {
+ return UmlDiagramType.STATE;
+ }
+
+ private boolean hideEmptyDescription = false;
+
+ public final void setHideEmptyDescription(boolean hideEmptyDescription) {
+ this.hideEmptyDescription = hideEmptyDescription;
+ }
+
+ public final boolean isHideEmptyDescriptionForState() {
+ return hideEmptyDescription;
+ }
+
+ // public Link isEntryPoint(IEntity ent) {
+ // final Stereotype stereotype = ent.getStereotype();
+ // if (stereotype == null) {
+ // return null;
+ // }
+ // final String label = stereotype.getLabel();
+ // if ("<<entrypoint>>".equalsIgnoreCase(label) == false) {
+ // return null;
+ // }
+ // Link inLink = null;
+ // Link outLink = null;
+ // for (Link link : getLinks()) {
+ // if (link.getEntity1() == ent) {
+ // if (outLink != null) {
+ // return null;
+ // }
+ // outLink = link;
+ // }
+ // if (link.getEntity2() == ent) {
+ // if (inLink != null) {
+ // return null;
+ // }
+ // inLink = link;
+ // }
+ // }
+ // if (inLink == null || outLink == null) {
+ // return null;
+ // }
+ // final Link result = Link.mergeForEntryPoint(inLink, outLink);
+ // result.setEntryPoint(ent.getContainer());
+ // return result;
+ // }
+ //
+ // public void manageExitAndEntryPoints() {
+ // for (IEntity ent : getEntities().values()) {
+ // final Link entryPointLink = isEntryPoint(ent);
+ // if (entryPointLink != null) {
+ // addLink(entryPointLink);
+ // for (Link link : new ArrayList<Link>(getLinks())) {
+ // if (link.contains(ent)) {
+ // removeLink(link);
+ // }
+ // }
+ // }
+ // }
+ //
+ // }
+
+}
diff --git a/src/net/sourceforge/plantuml/statediagram/StateDiagramFactory.java b/src/net/sourceforge/plantuml/statediagram/StateDiagramFactory.java
new file mode 100644
index 0000000..cb5e85e
--- /dev/null
+++ b/src/net/sourceforge/plantuml/statediagram/StateDiagramFactory.java
@@ -0,0 +1,145 @@
+/* ========================================================================
+ * PlantUML : a free UML diagram generator
+ * ========================================================================
+ *
+ * (C) Copyright 2009-2014, Arnaud Roques
+ *
+ * Project Info: http://plantuml.sourceforge.net
+ *
+ * This file is part of PlantUML.
+ *
+ * Licensed under The MIT License (Massachusetts Institute of Technology License)
+ *
+ * See http://opensource.org/licenses/MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+ * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *
+ * Original Author: Arnaud Roques
+ */
+package net.sourceforge.plantuml.statediagram;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import net.sourceforge.plantuml.AbstractPSystem;
+import net.sourceforge.plantuml.classdiagram.command.CommandUrl;
+import net.sourceforge.plantuml.command.Command;
+import net.sourceforge.plantuml.command.CommandFootboxIgnored;
+import net.sourceforge.plantuml.command.CommandRankDir;
+import net.sourceforge.plantuml.command.UmlDiagramFactory;
+import net.sourceforge.plantuml.command.note.FactoryNoteCommand;
+import net.sourceforge.plantuml.command.note.FactoryNoteOnEntityCommand;
+import net.sourceforge.plantuml.command.note.FactoryNoteOnLinkCommand;
+import net.sourceforge.plantuml.command.regex.RegexLeaf;
+import net.sourceforge.plantuml.command.regex.RegexOr;
+import net.sourceforge.plantuml.cucadiagram.GroupType;
+import net.sourceforge.plantuml.cucadiagram.IEntity;
+import net.sourceforge.plantuml.cucadiagram.IGroup;
+import net.sourceforge.plantuml.cucadiagram.Link;
+import net.sourceforge.plantuml.statediagram.command.CommandAddField;
+import net.sourceforge.plantuml.statediagram.command.CommandConcurrentState;
+import net.sourceforge.plantuml.statediagram.command.CommandCreatePackageState;
+import net.sourceforge.plantuml.statediagram.command.CommandCreateState;
+import net.sourceforge.plantuml.statediagram.command.CommandEndState;
+import net.sourceforge.plantuml.statediagram.command.CommandHideEmptyDescription;
+import net.sourceforge.plantuml.statediagram.command.CommandLinkState;
+
+public class StateDiagramFactory extends UmlDiagramFactory {
+
+ @Override
+ public StateDiagram createEmptyDiagram() {
+ return new StateDiagram();
+ }
+
+ @Override
+ protected List<Command> createCommands() {
+ final List<Command> cmds = new ArrayList<Command>();
+ cmds.add(new CommandFootboxIgnored());
+ cmds.add(new CommandRankDir());
+ cmds.add(new CommandCreateState());
+ // addCommand(new CommandLinkState());
+ cmds.add(new CommandLinkState());
+ cmds.add(new CommandCreatePackageState());
+ cmds.add(new CommandEndState());
+ cmds.add(new CommandAddField());
+ cmds.add(new CommandConcurrentState());
+
+ final FactoryNoteOnEntityCommand factoryNoteOnEntityCommand = new FactoryNoteOnEntityCommand(new RegexOr(
+ "ENTITY", new RegexLeaf("[\\p{L}0-9_.]+"), //
+ new RegexLeaf("[%g][^%g]+[%g]") //
+ ));
+ cmds.add(factoryNoteOnEntityCommand.createMultiLine());
+
+ cmds.add(new CommandHideEmptyDescription());
+
+ cmds.add(factoryNoteOnEntityCommand.createSingleLine());
+ final FactoryNoteOnLinkCommand factoryNoteOnLinkCommand = new FactoryNoteOnLinkCommand();
+ cmds.add(factoryNoteOnLinkCommand.createSingleLine());
+ cmds.add(factoryNoteOnLinkCommand.createMultiLine());
+ cmds.add(new CommandUrl());
+
+ final FactoryNoteCommand factoryNoteCommand = new FactoryNoteCommand();
+ cmds.add(factoryNoteCommand.createSingleLine());
+ cmds.add(factoryNoteCommand.createMultiLine());
+
+ addCommonCommands(cmds);
+
+ return cmds;
+ }
+
+ @Override
+ public String checkFinalError(AbstractPSystem sys) {
+ final StateDiagram system = (StateDiagram) sys;
+
+ for (Link link : system.getLinks()) {
+ final IGroup parent1 = getGroupParentIfItIsConcurrentState(link.getEntity1());
+ final IGroup parent2 = getGroupParentIfItIsConcurrentState(link.getEntity2());
+ if (isCompatible(parent1, parent2) == false) {
+ return "State within concurrent state cannot be linked out of this concurrent state (between "
+ + link.getEntity1().getCode().getFullName() + " and "
+ + link.getEntity2().getCode().getFullName() + ")";
+ }
+ }
+ return super.checkFinalError(system);
+ }
+
+ private boolean isCompatible(IGroup parent1, IGroup parent2) {
+ if (parent1 == null && parent2 == null) {
+ return true;
+ }
+ if (parent1 != null ^ parent2 != null) {
+ return false;
+ }
+ assert parent1 != null && parent2 != null;
+ return parent1 == parent2;
+ }
+
+ private IGroup getGroupParentIfItIsConcurrentState(IEntity ent) {
+ IGroup parent = ent.getParentContainer();
+ while (parent != null) {
+ if (parent.getGroupType() == GroupType.CONCURRENT_STATE) {
+ return parent;
+ }
+ parent = parent.getParentContainer();
+ }
+ return null;
+
+ }
+
+}
diff --git a/src/net/sourceforge/plantuml/statediagram/command/CommandAddField.java b/src/net/sourceforge/plantuml/statediagram/command/CommandAddField.java
new file mode 100644
index 0000000..71cc0a5
--- /dev/null
+++ b/src/net/sourceforge/plantuml/statediagram/command/CommandAddField.java
@@ -0,0 +1,74 @@
+/* ========================================================================
+ * PlantUML : a free UML diagram generator
+ * ========================================================================
+ *
+ * (C) Copyright 2009-2014, Arnaud Roques
+ *
+ * Project Info: http://plantuml.sourceforge.net
+ *
+ * This file is part of PlantUML.
+ *
+ * Licensed under The MIT License (Massachusetts Institute of Technology License)
+ *
+ * See http://opensource.org/licenses/MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+ * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *
+ * Original Author: Arnaud Roques
+ */
+package net.sourceforge.plantuml.statediagram.command;
+
+import net.sourceforge.plantuml.command.CommandExecutionResult;
+import net.sourceforge.plantuml.command.SingleLineCommand2;
+import net.sourceforge.plantuml.command.regex.RegexConcat;
+import net.sourceforge.plantuml.command.regex.RegexLeaf;
+import net.sourceforge.plantuml.command.regex.RegexOr;
+import net.sourceforge.plantuml.command.regex.RegexResult;
+import net.sourceforge.plantuml.cucadiagram.Code;
+import net.sourceforge.plantuml.cucadiagram.IEntity;
+import net.sourceforge.plantuml.statediagram.StateDiagram;
+
+public class CommandAddField extends SingleLineCommand2<StateDiagram> {
+
+ public CommandAddField() {
+ super(getRegexConcat());
+ }
+
+ private static RegexConcat getRegexConcat() {
+ return new RegexConcat(new RegexLeaf("^"), //
+ new RegexOr( //
+ new RegexLeaf("CODE3", "([\\p{L}0-9_.]+)"), //
+ new RegexLeaf("CODE4", "[%g]([^%g]+)[%g]")), //
+ new RegexLeaf("[%s]*:[%s]*"), //
+ new RegexLeaf("FIELD", "(.*)"), //
+ new RegexLeaf("$"));
+ }
+
+ @Override
+ protected CommandExecutionResult executeArg(StateDiagram diagram, RegexResult arg) {
+ final String code = arg.getLazzy("CODE", 0);
+ final String field = arg.get("FIELD", 0);
+
+ final IEntity entity = diagram.getOrCreateLeaf(Code.of(code), null, null);
+
+ entity.addFieldOrMethod(field);
+ return CommandExecutionResult.ok();
+ }
+
+}
diff --git a/src/net/sourceforge/plantuml/statediagram/command/CommandConcurrentState.java b/src/net/sourceforge/plantuml/statediagram/command/CommandConcurrentState.java
new file mode 100644
index 0000000..79fb65c
--- /dev/null
+++ b/src/net/sourceforge/plantuml/statediagram/command/CommandConcurrentState.java
@@ -0,0 +1,57 @@
+/* ========================================================================
+ * PlantUML : a free UML diagram generator
+ * ========================================================================
+ *
+ * (C) Copyright 2009-2014, Arnaud Roques
+ *
+ * Project Info: http://plantuml.sourceforge.net
+ *
+ * This file is part of PlantUML.
+ *
+ * Licensed under The MIT License (Massachusetts Institute of Technology License)
+ *
+ * See http://opensource.org/licenses/MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+ * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *
+ * Original Author: Arnaud Roques
+ */
+package net.sourceforge.plantuml.statediagram.command;
+
+import java.util.List;
+
+import net.sourceforge.plantuml.command.CommandExecutionResult;
+import net.sourceforge.plantuml.command.SingleLineCommand;
+import net.sourceforge.plantuml.statediagram.StateDiagram;
+
+public class CommandConcurrentState extends SingleLineCommand<StateDiagram> {
+
+ public CommandConcurrentState() {
+ super("(?i)^(--+|\\|\\|+)$");
+ }
+
+ @Override
+ protected CommandExecutionResult executeArg(StateDiagram diagram, List<String> arg) {
+ if (diagram.concurrentState(arg.get(0).charAt(0))) {
+ return CommandExecutionResult.ok();
+ }
+ return CommandExecutionResult.error("Error 42");
+ }
+
+}
diff --git a/src/net/sourceforge/plantuml/statediagram/command/CommandCreatePackageState.java b/src/net/sourceforge/plantuml/statediagram/command/CommandCreatePackageState.java
new file mode 100644
index 0000000..e785453
--- /dev/null
+++ b/src/net/sourceforge/plantuml/statediagram/command/CommandCreatePackageState.java
@@ -0,0 +1,115 @@
+/* ========================================================================
+ * PlantUML : a free UML diagram generator
+ * ========================================================================
+ *
+ * (C) Copyright 2009-2014, Arnaud Roques
+ *
+ * Project Info: http://plantuml.sourceforge.net
+ *
+ * This file is part of PlantUML.
+ *
+ * Licensed under The MIT License (Massachusetts Institute of Technology License)
+ *
+ * See http://opensource.org/licenses/MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+ * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *
+ * Original Author: Arnaud Roques
+ */
+package net.sourceforge.plantuml.statediagram.command;
+
+import net.sourceforge.plantuml.Url;
+import net.sourceforge.plantuml.UrlBuilder;
+import net.sourceforge.plantuml.UrlBuilder.ModeUrl;
+import net.sourceforge.plantuml.classdiagram.command.CommandCreateClassMultilines;
+import net.sourceforge.plantuml.command.CommandExecutionResult;
+import net.sourceforge.plantuml.command.SingleLineCommand2;
+import net.sourceforge.plantuml.command.regex.RegexConcat;
+import net.sourceforge.plantuml.command.regex.RegexLeaf;
+import net.sourceforge.plantuml.command.regex.RegexOr;
+import net.sourceforge.plantuml.command.regex.RegexResult;
+import net.sourceforge.plantuml.cucadiagram.Code;
+import net.sourceforge.plantuml.cucadiagram.Display;
+import net.sourceforge.plantuml.cucadiagram.GroupType;
+import net.sourceforge.plantuml.cucadiagram.IEntity;
+import net.sourceforge.plantuml.cucadiagram.IGroup;
+import net.sourceforge.plantuml.cucadiagram.Stereotype;
+import net.sourceforge.plantuml.graphic.HtmlColorUtils;
+import net.sourceforge.plantuml.statediagram.StateDiagram;
+
+public class CommandCreatePackageState extends SingleLineCommand2<StateDiagram> {
+
+ public CommandCreatePackageState() {
+ super(getRegexConcat());
+ }
+
+ private static RegexConcat getRegexConcat() {
+ return new RegexConcat(new RegexLeaf("^state[%s]+"), //
+ new RegexOr(//
+ new RegexConcat(//
+ new RegexLeaf("CODE1", "([\\p{L}0-9_.]+)[%s]+"), //
+ new RegexLeaf("DISPLAY1", "as[%s]+[%g]([^%g]+)[%g]")), //
+ new RegexConcat(//
+ new RegexLeaf("DISPLAY2", "(?:[%g]([^%g]+)[%g][%s]+as[%s]+)?"), //
+ new RegexLeaf("CODE2", "([\\p{L}0-9_.]+)"))), //
+ new RegexLeaf("[%s]*"), //
+ new RegexLeaf("STEREOTYPE", "(\\<\\<.*\\>\\>)?"), //
+ new RegexLeaf("[%s]*"), //
+ new RegexLeaf("URL", "(" + UrlBuilder.getRegexp() + ")?"), //
+ new RegexLeaf("[%s]*"), //
+ new RegexLeaf("COLOR", "(" + HtmlColorUtils.COLOR_REGEXP + ")?"), //
+ new RegexLeaf("[%s]*"), //
+ new RegexLeaf("LINECOLOR", "(?:##(?:\\[(dotted|dashed|bold)\\])?(\\w+)?)?"), //
+ new RegexLeaf("(?:[%s]*\\{|[%s]+begin)$"));
+ }
+
+ private String getNotNull(RegexResult arg, String v1, String v2) {
+ if (arg.get(v1, 0) == null) {
+ return arg.get(v2, 0);
+ }
+ return arg.get(v1, 0);
+ }
+
+ @Override
+ protected CommandExecutionResult executeArg(StateDiagram diagram, RegexResult arg) {
+ final IGroup currentPackage = diagram.getCurrentGroup();
+ final Code code = Code.of(getNotNull(arg, "CODE1", "CODE2"));
+ String display = getNotNull(arg, "DISPLAY1", "DISPLAY2");
+ if (display == null) {
+ display = code.getFullName();
+ }
+ final IEntity p = diagram.getOrCreateGroup(code, Display.getWithNewlines(display), GroupType.STATE,
+ currentPackage);
+ final String stereotype = arg.get("STEREOTYPE", 0);
+ if (stereotype != null) {
+ p.setStereotype(new Stereotype(stereotype));
+ }
+ final String urlString = arg.get("URL", 0);
+ if (urlString != null) {
+ final UrlBuilder urlBuilder = new UrlBuilder(diagram.getSkinParam().getValue("topurl"), ModeUrl.STRICT);
+ final Url url = urlBuilder.getUrl(urlString);
+ p.addUrl(url);
+ }
+ p.setSpecificBackcolor(diagram.getSkinParam().getIHtmlColorSet().getColorIfValid(arg.get("COLOR", 0)));
+ p.setSpecificLineColor(diagram.getSkinParam().getIHtmlColorSet().getColorIfValid(arg.get("LINECOLOR", 1)));
+ CommandCreateClassMultilines.applyStroke(p, arg.get("LINECOLOR", 0));
+ return CommandExecutionResult.ok();
+ }
+
+}
diff --git a/src/net/sourceforge/plantuml/statediagram/command/CommandCreateState.java b/src/net/sourceforge/plantuml/statediagram/command/CommandCreateState.java
new file mode 100644
index 0000000..ef288d3
--- /dev/null
+++ b/src/net/sourceforge/plantuml/statediagram/command/CommandCreateState.java
@@ -0,0 +1,141 @@
+/* ========================================================================
+ * PlantUML : a free UML diagram generator
+ * ========================================================================
+ *
+ * (C) Copyright 2009-2014, Arnaud Roques
+ *
+ * Project Info: http://plantuml.sourceforge.net
+ *
+ * This file is part of PlantUML.
+ *
+ * Licensed under The MIT License (Massachusetts Institute of Technology License)
+ *
+ * See http://opensource.org/licenses/MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+ * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *
+ * Original Author: Arnaud Roques
+ */
+package net.sourceforge.plantuml.statediagram.command;
+
+import net.sourceforge.plantuml.Url;
+import net.sourceforge.plantuml.UrlBuilder;
+import net.sourceforge.plantuml.UrlBuilder.ModeUrl;
+import net.sourceforge.plantuml.classdiagram.command.CommandCreateClassMultilines;
+import net.sourceforge.plantuml.command.CommandExecutionResult;
+import net.sourceforge.plantuml.command.SingleLineCommand2;
+import net.sourceforge.plantuml.command.regex.RegexConcat;
+import net.sourceforge.plantuml.command.regex.RegexLeaf;
+import net.sourceforge.plantuml.command.regex.RegexOr;
+import net.sourceforge.plantuml.command.regex.RegexResult;
+import net.sourceforge.plantuml.cucadiagram.Code;
+import net.sourceforge.plantuml.cucadiagram.Display;
+import net.sourceforge.plantuml.cucadiagram.IEntity;
+import net.sourceforge.plantuml.cucadiagram.LeafType;
+import net.sourceforge.plantuml.cucadiagram.Stereotype;
+import net.sourceforge.plantuml.graphic.HtmlColorUtils;
+import net.sourceforge.plantuml.statediagram.StateDiagram;
+
+public class CommandCreateState extends SingleLineCommand2<StateDiagram> {
+
+ public CommandCreateState() {
+ super(getRegexConcat());
+ }
+
+ private static RegexConcat getRegexConcat() {
+ return new RegexConcat(new RegexLeaf("^"), //
+ new RegexLeaf("(?:state[%s]+)"), //
+ new RegexOr(//
+ new RegexConcat(//
+ new RegexLeaf("CODE1", "([\\p{L}0-9_.]+)"), //
+ new RegexLeaf("[%s]+as[%s]+"), //
+ new RegexLeaf("DISPLAY1", "[%g]([^%g]+)[%g]")), //
+ new RegexConcat(//
+ new RegexLeaf("DISPLAY2", "[%g]([^%g]+)[%g]"), //
+ new RegexLeaf("[%s]+as[%s]+"), //
+ new RegexLeaf("CODE2", "([\\p{L}0-9_.]+)")), //
+ new RegexLeaf("CODE3", "([\\p{L}0-9_.]+)"), //
+ new RegexLeaf("CODE4", "[%g]([^%g]+)[%g]")), //
+
+ new RegexLeaf("[%s]*"), //
+ new RegexLeaf("STEREOTYPE", "(\\<\\<.*\\>\\>)?"), //
+ new RegexLeaf("[%s]*"), //
+ new RegexLeaf("URL", "(" + UrlBuilder.getRegexp() + ")?"), //
+ new RegexLeaf("[%s]*"), //
+ new RegexLeaf("COLOR", "(" + HtmlColorUtils.COLOR_REGEXP + ")?"), //
+ new RegexLeaf("[%s]*"), //
+ new RegexLeaf("LINECOLOR", "(?:##(?:\\[(dotted|dashed|bold)\\])?(\\w+)?)?"), //
+ new RegexLeaf("[%s]*"), //
+ new RegexLeaf("ADDFIELD", "(?::[%s]*(.*))?"), //
+ new RegexLeaf("$"));
+ }
+
+ @Override
+ protected CommandExecutionResult executeArg(StateDiagram diagram, RegexResult arg) {
+ final Code code = Code.of(arg.getLazzy("CODE", 0));
+ String display = arg.getLazzy("DISPLAY", 0);
+ if (display == null) {
+ display = code.getFullName();
+ }
+ final String stereotype = arg.get("STEREOTYPE", 0);
+ final LeafType type = getTypeFromStereotype(stereotype);
+ if (diagram.checkConcurrentStateOk(code) == false) {
+ return CommandExecutionResult.error("The state " + code.getFullName()
+ + " has been created in a concurrent state : it cannot be used here.");
+ }
+ final IEntity ent = diagram.getOrCreateLeaf(code, type, null);
+ ent.setDisplay(Display.getWithNewlines(display));
+
+ if (stereotype != null) {
+ ent.setStereotype(new Stereotype(stereotype));
+ }
+ final String urlString = arg.get("URL", 0);
+ if (urlString != null) {
+ final UrlBuilder urlBuilder = new UrlBuilder(diagram.getSkinParam().getValue("topurl"), ModeUrl.STRICT);
+ final Url url = urlBuilder.getUrl(urlString);
+ ent.addUrl(url);
+ }
+ ent.setSpecificBackcolor(diagram.getSkinParam().getIHtmlColorSet().getColorIfValid(arg.get("COLOR", 0)));
+ ent.setSpecificLineColor(diagram.getSkinParam().getIHtmlColorSet().getColorIfValid(arg.get("LINECOLOR", 1)));
+ CommandCreateClassMultilines.applyStroke(ent, arg.get("LINECOLOR", 0));
+
+ final String addFields = arg.get("ADDFIELD", 0);
+ if (addFields != null) {
+ ent.addFieldOrMethod(addFields);
+ }
+ return CommandExecutionResult.ok();
+ }
+
+ private LeafType getTypeFromStereotype(String stereotype) {
+ if ("<<choice>>".equalsIgnoreCase(stereotype)) {
+ return LeafType.STATE_CHOICE;
+ }
+ if ("<<fork>>".equalsIgnoreCase(stereotype)) {
+ return LeafType.STATE_FORK_JOIN;
+ }
+ if ("<<join>>".equalsIgnoreCase(stereotype)) {
+ return LeafType.STATE_FORK_JOIN;
+ }
+ if ("<<end>>".equalsIgnoreCase(stereotype)) {
+ return LeafType.CIRCLE_END;
+ }
+ return null;
+ }
+
+}
diff --git a/src/net/sourceforge/plantuml/statediagram/command/CommandEndState.java b/src/net/sourceforge/plantuml/statediagram/command/CommandEndState.java
new file mode 100644
index 0000000..edae33f
--- /dev/null
+++ b/src/net/sourceforge/plantuml/statediagram/command/CommandEndState.java
@@ -0,0 +1,60 @@
+/* ========================================================================
+ * PlantUML : a free UML diagram generator
+ * ========================================================================
+ *
+ * (C) Copyright 2009-2014, Arnaud Roques
+ *
+ * Project Info: http://plantuml.sourceforge.net
+ *
+ * This file is part of PlantUML.
+ *
+ * Licensed under The MIT License (Massachusetts Institute of Technology License)
+ *
+ * See http://opensource.org/licenses/MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+ * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *
+ * Original Author: Arnaud Roques
+ */
+package net.sourceforge.plantuml.statediagram.command;
+
+import java.util.List;
+
+import net.sourceforge.plantuml.command.CommandExecutionResult;
+import net.sourceforge.plantuml.command.SingleLineCommand;
+import net.sourceforge.plantuml.cucadiagram.IEntity;
+import net.sourceforge.plantuml.statediagram.StateDiagram;
+
+public class CommandEndState extends SingleLineCommand<StateDiagram> {
+
+ public CommandEndState() {
+ super("(?i)^(end[%s]?state|\\})$");
+ }
+
+ @Override
+ protected CommandExecutionResult executeArg(StateDiagram diagram, List<String> arg) {
+ final IEntity currentPackage = diagram.getCurrentGroup();
+ if (currentPackage == null) {
+ return CommandExecutionResult.error("No inner state defined");
+ }
+ diagram.endGroup();
+ return CommandExecutionResult.ok();
+ }
+
+}
diff --git a/src/net/sourceforge/plantuml/statediagram/command/CommandHideEmptyDescription.java b/src/net/sourceforge/plantuml/statediagram/command/CommandHideEmptyDescription.java
new file mode 100644
index 0000000..ea895c1
--- /dev/null
+++ b/src/net/sourceforge/plantuml/statediagram/command/CommandHideEmptyDescription.java
@@ -0,0 +1,55 @@
+/* ========================================================================
+ * PlantUML : a free UML diagram generator
+ * ========================================================================
+ *
+ * (C) Copyright 2009-2014, Arnaud Roques
+ *
+ * Project Info: http://plantuml.sourceforge.net
+ *
+ * This file is part of PlantUML.
+ *
+ * Licensed under The MIT License (Massachusetts Institute of Technology License)
+ *
+ * See http://opensource.org/licenses/MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+ * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *
+ * Original Author: Arnaud Roques
+ */
+package net.sourceforge.plantuml.statediagram.command;
+
+import java.util.List;
+
+import net.sourceforge.plantuml.command.CommandExecutionResult;
+import net.sourceforge.plantuml.command.SingleLineCommand;
+import net.sourceforge.plantuml.statediagram.StateDiagram;
+
+public class CommandHideEmptyDescription extends SingleLineCommand<StateDiagram> {
+
+ public CommandHideEmptyDescription() {
+ super("(?i)^(hide|show)[%s]+empty[%s]+description$");
+ }
+
+ @Override
+ protected CommandExecutionResult executeArg(StateDiagram diagram, List<String> arg) {
+ diagram.setHideEmptyDescription(arg.get(0).equalsIgnoreCase("hide"));
+ return CommandExecutionResult.ok();
+ }
+
+}
diff --git a/src/net/sourceforge/plantuml/statediagram/command/CommandLinkState.java b/src/net/sourceforge/plantuml/statediagram/command/CommandLinkState.java
new file mode 100644
index 0000000..414cbf4
--- /dev/null
+++ b/src/net/sourceforge/plantuml/statediagram/command/CommandLinkState.java
@@ -0,0 +1,219 @@
+/* ========================================================================
+ * PlantUML : a free UML diagram generator
+ * ========================================================================
+ *
+ * (C) Copyright 2009-2014, Arnaud Roques
+ *
+ * Project Info: http://plantuml.sourceforge.net
+ *
+ * This file is part of PlantUML.
+ *
+ * Licensed under The MIT License (Massachusetts Institute of Technology License)
+ *
+ * See http://opensource.org/licenses/MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+ * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *
+ * Original Author: Arnaud Roques
+ */
+package net.sourceforge.plantuml.statediagram.command;
+
+import net.sourceforge.plantuml.Direction;
+import net.sourceforge.plantuml.classdiagram.command.CommandLinkClass;
+import net.sourceforge.plantuml.command.CommandExecutionResult;
+import net.sourceforge.plantuml.command.SingleLineCommand2;
+import net.sourceforge.plantuml.command.regex.RegexConcat;
+import net.sourceforge.plantuml.command.regex.RegexLeaf;
+import net.sourceforge.plantuml.command.regex.RegexResult;
+import net.sourceforge.plantuml.cucadiagram.Code;
+import net.sourceforge.plantuml.cucadiagram.Display;
+import net.sourceforge.plantuml.cucadiagram.IEntity;
+import net.sourceforge.plantuml.cucadiagram.LeafType;
+import net.sourceforge.plantuml.cucadiagram.Link;
+import net.sourceforge.plantuml.cucadiagram.LinkDecor;
+import net.sourceforge.plantuml.cucadiagram.LinkType;
+import net.sourceforge.plantuml.cucadiagram.Stereotype;
+import net.sourceforge.plantuml.statediagram.StateDiagram;
+import net.sourceforge.plantuml.StringUtils;
+
+public class CommandLinkState extends SingleLineCommand2<StateDiagram> {
+
+ public CommandLinkState() {
+ super(getRegex());
+ }
+
+ static RegexConcat getRegex() {
+ return new RegexConcat(new RegexLeaf("^"), //
+ getStatePattern("ENT1"), //
+ new RegexLeaf("[%s]*"), //
+ new RegexConcat(
+ //
+ new RegexLeaf("ARROW_CROSS_START", "(x)?"), //
+ new RegexLeaf("ARROW_BODY1", "(-+)"), //
+ new RegexLeaf("ARROW_STYLE1",
+ "(?:\\[((?:#\\w+|dotted|dashed|bold|hidden)(?:,#\\w+|,dotted|,dashed|,bold|,hidden)*)\\])?"), //
+ new RegexLeaf("ARROW_DIRECTION", "(left|right|up|down|le?|ri?|up?|do?)?"), //
+ new RegexLeaf("ARROW_STYLE2",
+ "(?:\\[((?:#\\w+|dotted|dashed|bold|hidden)(?:,#\\w+|,dotted|,dashed|,bold|,hidden)*)\\])?"), //
+ new RegexLeaf("ARROW_BODY2", "(-*)"), //
+ new RegexLeaf("\\>"), //
+ new RegexLeaf("ARROW_CIRCLE_END", "(o[%s]+)?")), //
+ new RegexLeaf("[%s]*"), //
+ getStatePattern("ENT2"), //
+ new RegexLeaf("[%s]*"), //
+ new RegexLeaf("LABEL", "(?::[%s]*([^%g]+))?"), //
+ new RegexLeaf("$"));
+ }
+
+ private static RegexLeaf getStatePattern(String name) {
+ return new RegexLeaf(
+ name,
+ "([\\p{L}0-9_.]+|[\\p{L}0-9_.]+\\[H\\]|\\[\\*\\]|\\[H\\]|(?:==+)(?:[\\p{L}0-9_.]+)(?:==+))[%s]*(\\<\\<.*\\>\\>)?[%s]*(#\\w+)?");
+ }
+
+ @Override
+ protected CommandExecutionResult executeArg(StateDiagram diagram, RegexResult arg) {
+ final String ent1 = arg.get("ENT1", 0);
+ final String ent2 = arg.get("ENT2", 0);
+
+ final IEntity cl1 = getEntityStart(diagram, ent1);
+ if (cl1 == null) {
+ return CommandExecutionResult.error("The state " + ent1
+ + " has been created in a concurrent state : it cannot be used here.");
+ }
+ final IEntity cl2 = getEntityEnd(diagram, ent2);
+ if (cl2 == null) {
+ return CommandExecutionResult.error("The state " + ent2
+ + " has been created in a concurrent state : it cannot be used here.");
+ }
+
+ if (arg.get("ENT1", 1) != null) {
+ cl1.setStereotype(new Stereotype(arg.get("ENT1", 1)));
+ }
+ if (arg.get("ENT1", 2) != null) {
+ cl1.setSpecificBackcolor(diagram.getSkinParam().getIHtmlColorSet().getColorIfValid(arg.get("ENT1", 2)));
+ }
+ if (arg.get("ENT2", 1) != null) {
+ cl2.setStereotype(new Stereotype(arg.get("ENT2", 1)));
+ }
+ if (arg.get("ENT2", 2) != null) {
+ cl2.setSpecificBackcolor(diagram.getSkinParam().getIHtmlColorSet().getColorIfValid(arg.get("ENT2", 2)));
+ }
+
+ String queue = arg.get("ARROW_BODY1", 0) + arg.get("ARROW_BODY2", 0);
+ final Direction dir = getDirection(arg);
+
+ if (dir == Direction.LEFT || dir == Direction.RIGHT) {
+ queue = "-";
+ }
+
+ final int lenght = queue.length();
+
+ final boolean crossStart = arg.get("ARROW_CROSS_START", 0) != null;
+ final boolean circleEnd = arg.get("ARROW_CIRCLE_END", 0) != null;
+ final LinkType linkType = new LinkType(circleEnd ? LinkDecor.ARROW_AND_CIRCLE : LinkDecor.ARROW,
+ crossStart ? LinkDecor.CIRCLE_CROSS : LinkDecor.NONE);
+
+ Link link = new Link(cl1, cl2, linkType, Display.getWithNewlines(arg.get("LABEL", 0)), lenght);
+ if (dir == Direction.LEFT || dir == Direction.UP) {
+ link = link.getInv();
+ }
+ CommandLinkClass.applyStyle(arg.getLazzy("ARROW_STYLE", 0), link);
+ diagram.addLink(link);
+
+ return CommandExecutionResult.ok();
+ }
+
+ // public static void applyStyle(String arrowStyle, Link link) {
+ // if (arrowStyle == null) {
+ // return;
+ // }
+ // final StringTokenizer st = new StringTokenizer(arrowStyle, ",");
+ // while (st.hasMoreTokens()) {
+ // final String s = st.nextToken();
+ // if (s.equalsIgnoreCase("dashed")) {
+ // link.goDashed();
+ // } else if (s.equalsIgnoreCase("bold")) {
+ // link.goBold();
+ // } else if (s.equalsIgnoreCase("dotted")) {
+ // link.goDotted();
+ // } else if (s.equalsIgnoreCase("hidden")) {
+ // link.goHidden();
+ // } else {
+ // link.setSpecificColor(s);
+ // }
+ // }
+ // }
+
+ private Direction getDirection(RegexResult arg) {
+ final String arrowDirection = arg.get("ARROW_DIRECTION", 0);
+ if (arrowDirection != null) {
+ return StringUtils.getQueueDirection(arrowDirection);
+ }
+ return null;
+ }
+
+ private IEntity getEntityStart(StateDiagram system, String code) {
+ if (code.startsWith("[*]")) {
+ return system.getStart();
+ }
+ if (code.equalsIgnoreCase("[H]")) {
+ return system.getHistorical();
+ }
+ if (code.endsWith("[H]")) {
+ return system.getHistorical(Code.of(code.substring(0, code.length() - 3)));
+ }
+ if (code.startsWith("=") && code.endsWith("=")) {
+ code = removeEquals(code);
+ return system.getOrCreateLeaf(Code.of(code), LeafType.SYNCHRO_BAR, null);
+ }
+ if (system.checkConcurrentStateOk(Code.of(code)) == false) {
+ return null;
+ }
+ return system.getOrCreateLeaf(Code.of(code), null, null);
+ }
+
+ private String removeEquals(String code) {
+ while (code.startsWith("=")) {
+ code = code.substring(1);
+ }
+ while (code.endsWith("=")) {
+ code = code.substring(0, code.length() - 1);
+ }
+ return code;
+ }
+
+ private IEntity getEntityEnd(StateDiagram system, String code) {
+ if (code.startsWith("[*]")) {
+ return system.getEnd();
+ }
+ if (code.endsWith("[H]")) {
+ return system.getHistorical(Code.of(code.substring(0, code.length() - 3)));
+ }
+ if (code.startsWith("=") && code.endsWith("=")) {
+ code = removeEquals(code);
+ return system.getOrCreateLeaf(Code.of(code), LeafType.SYNCHRO_BAR, null);
+ }
+ if (system.checkConcurrentStateOk(Code.of(code)) == false) {
+ return null;
+ }
+ return system.getOrCreateLeaf(Code.of(code), null, null);
+ }
+
+}