mirror of
https://github.com/octoleo/plantuml.git
synced 2024-11-25 14:27:33 +00:00
Merge pull request #1718 from Benjamin-Davies/cheneer
Implement Chen Notation for ER-diagrams
This commit is contained in:
commit
4afe3ef7fe
@ -48,6 +48,7 @@ import net.sourceforge.plantuml.activitydiagram3.ActivityDiagramFactory3;
|
|||||||
import net.sourceforge.plantuml.api.PSystemFactory;
|
import net.sourceforge.plantuml.api.PSystemFactory;
|
||||||
import net.sourceforge.plantuml.board.BoardDiagramFactory;
|
import net.sourceforge.plantuml.board.BoardDiagramFactory;
|
||||||
import net.sourceforge.plantuml.bpm.BpmDiagramFactory;
|
import net.sourceforge.plantuml.bpm.BpmDiagramFactory;
|
||||||
|
import net.sourceforge.plantuml.cheneer.ChenEerDiagramFactory;
|
||||||
import net.sourceforge.plantuml.chronology.ChronologyDiagramFactory;
|
import net.sourceforge.plantuml.chronology.ChronologyDiagramFactory;
|
||||||
import net.sourceforge.plantuml.classdiagram.ClassDiagramFactory;
|
import net.sourceforge.plantuml.classdiagram.ClassDiagramFactory;
|
||||||
import net.sourceforge.plantuml.core.Diagram;
|
import net.sourceforge.plantuml.core.Diagram;
|
||||||
@ -277,6 +278,8 @@ public class PSystemBuilder {
|
|||||||
factories.add(new HclDiagramFactory());
|
factories.add(new HclDiagramFactory());
|
||||||
factories.add(new PSystemEbnfFactory());
|
factories.add(new PSystemEbnfFactory());
|
||||||
factories.add(new PSystemRegexFactory());
|
factories.add(new PSystemRegexFactory());
|
||||||
|
|
||||||
|
factories.add(new ChenEerDiagramFactory());
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isOk(Diagram ps) {
|
private boolean isOk(Diagram ps) {
|
||||||
|
@ -62,6 +62,8 @@ public enum LeafType {
|
|||||||
|
|
||||||
PORTIN, PORTOUT,
|
PORTIN, PORTOUT,
|
||||||
|
|
||||||
|
CHEN_ENTITY, CHEN_RELATIONSHIP, CHEN_ATTRIBUTE, CHEN_CIRCLE,
|
||||||
|
|
||||||
STILL_UNKNOWN;
|
STILL_UNKNOWN;
|
||||||
|
|
||||||
public static LeafType getLeafType(String type) {
|
public static LeafType getLeafType(String type) {
|
||||||
|
95
src/net/sourceforge/plantuml/cheneer/ChenEerDiagram.java
Normal file
95
src/net/sourceforge/plantuml/cheneer/ChenEerDiagram.java
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
/* ========================================================================
|
||||||
|
* 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.Map;
|
||||||
|
import java.util.Stack;
|
||||||
|
|
||||||
|
import net.sourceforge.plantuml.abel.Entity;
|
||||||
|
import net.sourceforge.plantuml.classdiagram.AbstractEntityDiagram;
|
||||||
|
import net.sourceforge.plantuml.core.UmlSource;
|
||||||
|
import net.sourceforge.plantuml.skin.UmlDiagramType;
|
||||||
|
|
||||||
|
public class ChenEerDiagram extends AbstractEntityDiagram {
|
||||||
|
|
||||||
|
public ChenEerDiagram(UmlSource source, Map<String, String> skinParam) {
|
||||||
|
super(source, UmlDiagramType.CHEN_EER, skinParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Stack<Entity> ownerStack = new Stack<Entity>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
ownerStack.pop();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the owner of the current attribute.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
return ownerStack.peek();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,78 @@
|
|||||||
|
/* ========================================================================
|
||||||
|
* 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.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;
|
||||||
|
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<Command> cmds) {
|
||||||
|
CommonCommands.addTitleCommands(cmds);
|
||||||
|
CommonCommands.addCommonCommands2(cmds);
|
||||||
|
|
||||||
|
cmds.add(new CommandCreateEntity());
|
||||||
|
cmds.add(new CommandCreateAttribute());
|
||||||
|
cmds.add(new CommandAssociate());
|
||||||
|
cmds.add(new CommandEndGroup());
|
||||||
|
cmds.add(new CommandSimpleSubclass());
|
||||||
|
cmds.add(new CommandMultiSubclass());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AbstractPSystem createEmptyDiagram(UmlSource source, Map<String, String> skinParam) {
|
||||||
|
return new ChenEerDiagram(source, skinParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,108 @@
|
|||||||
|
/* ========================================================================
|
||||||
|
* 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.RegexOptional;
|
||||||
|
import net.sourceforge.plantuml.regex.RegexResult;
|
||||||
|
import net.sourceforge.plantuml.utils.LineLocation;
|
||||||
|
|
||||||
|
public class CommandAssociate extends SingleLineCommand2<ChenEerDiagram> {
|
||||||
|
|
||||||
|
public CommandAssociate() {
|
||||||
|
super(getRegexConcat());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected 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);
|
||||||
|
|
||||||
|
final Quark<Entity> quark1 = diagram.quarkInContext(true, name1);
|
||||||
|
final Entity entity1 = quark1.getData();
|
||||||
|
if (entity1 == null) {
|
||||||
|
return CommandExecutionResult.error("No such entity: " + name1);
|
||||||
|
}
|
||||||
|
|
||||||
|
final Quark<Entity> 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);
|
||||||
|
|
||||||
|
return CommandExecutionResult.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,126 @@
|
|||||||
|
/* ========================================================================
|
||||||
|
* 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.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.RegexOptional;
|
||||||
|
import net.sourceforge.plantuml.regex.RegexResult;
|
||||||
|
import net.sourceforge.plantuml.stereo.Stereotype;
|
||||||
|
import net.sourceforge.plantuml.utils.LineLocation;
|
||||||
|
|
||||||
|
public class CommandCreateAttribute extends SingleLineCommand2<ChenEerDiagram> {
|
||||||
|
|
||||||
|
public CommandCreateAttribute() {
|
||||||
|
super(getRegexConcat());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected 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");
|
||||||
|
}
|
||||||
|
|
||||||
|
final LeafType type = LeafType.CHEN_ATTRIBUTE;
|
||||||
|
final String idShort = diagram.cleanId(arg.get("CODE", 0).trim());
|
||||||
|
final String id = owner.getName() + "/" + idShort;
|
||||||
|
final Quark<Entity> quark = diagram.quarkInContext(true, id);
|
||||||
|
String displayText = arg.get("DISPLAY", 0);
|
||||||
|
if (displayText == null)
|
||||||
|
displayText = idShort;
|
||||||
|
|
||||||
|
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(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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
return CommandExecutionResult.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,123 @@
|
|||||||
|
/* ========================================================================
|
||||||
|
* 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.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<ChenEerDiagram> {
|
||||||
|
|
||||||
|
public CommandCreateEntity() {
|
||||||
|
super(getRegexConcat());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
final String idShort = arg.get("CODE", 0);
|
||||||
|
final Quark<Entity> quark = diagram.quarkInContext(true, diagram.cleanId(idShort));
|
||||||
|
String displayText = arg.get("DISPLAY", 0);
|
||||||
|
if (displayText == null)
|
||||||
|
displayText = quark.getName();
|
||||||
|
|
||||||
|
final String stereo = arg.get("STEREO", 0);
|
||||||
|
|
||||||
|
Entity entity = quark.getData();
|
||||||
|
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stereo != null) {
|
||||||
|
entity.setStereotype(Stereotype.build(stereo));
|
||||||
|
entity.setStereostyle(stereo);
|
||||||
|
}
|
||||||
|
|
||||||
|
diagram.pushOwner(entity);
|
||||||
|
|
||||||
|
return CommandExecutionResult.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,67 @@
|
|||||||
|
/* ========================================================================
|
||||||
|
* 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<ChenEerDiagram> {
|
||||||
|
|
||||||
|
public CommandEndGroup() {
|
||||||
|
super(getRegexConcat());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected 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) {
|
||||||
|
if (!diagram.popOwner()) {
|
||||||
|
return CommandExecutionResult.error("Unbalanced brackets");
|
||||||
|
}
|
||||||
|
return CommandExecutionResult.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,138 @@
|
|||||||
|
/* ========================================================================
|
||||||
|
* 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<ChenEerDiagram> {
|
||||||
|
|
||||||
|
public CommandMultiSubclass() {
|
||||||
|
super(getRegexConcat());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected 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<String> 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<Entity> centerQuark = diagram.quarkInContext(false, superclass + "/" + symbol + subclasses + "/center");
|
||||||
|
final Entity centerEntity = diagram.reallyCreateLeaf(centerQuark, Display.create(symbol), LeafType.CHEN_CIRCLE, null);
|
||||||
|
|
||||||
|
final Quark<Entity> 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<Entity> 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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<ChenEerDiagram> {
|
||||||
|
|
||||||
|
public CommandSimpleSubclass() {
|
||||||
|
super(getRegexConcat());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected 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<Entity> quark1 = diagram.quarkInContext(true, name1);
|
||||||
|
final Entity entity1 = quark1.getData();
|
||||||
|
if (entity1 == null) {
|
||||||
|
return CommandExecutionResult.error("No such entity: " + name1);
|
||||||
|
}
|
||||||
|
|
||||||
|
final Quark<Entity> 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -40,7 +40,7 @@ import net.sourceforge.plantuml.utils.StartUtils;
|
|||||||
public enum DiagramType {
|
public enum DiagramType {
|
||||||
// ::remove folder when __HAXE__
|
// ::remove folder when __HAXE__
|
||||||
UML, BPM, DITAA, DOT, PROJECT, JCCKIT, SALT, FLOW, CREOLE, MATH, LATEX, DEFINITION, GANTT, CHRONOLOGY, NW, MINDMAP,
|
UML, BPM, DITAA, DOT, PROJECT, JCCKIT, SALT, FLOW, CREOLE, MATH, LATEX, DEFINITION, GANTT, CHRONOLOGY, NW, MINDMAP,
|
||||||
WBS, WIRE, JSON, GIT, BOARD, YAML, HCL, EBNF, REGEX, FILES, UNKNOWN;
|
WBS, WIRE, JSON, GIT, BOARD, YAML, HCL, EBNF, REGEX, FILES, CHEN_EER, UNKNOWN;
|
||||||
|
|
||||||
static public DiagramType getTypeFromArobaseStart(String s) {
|
static public DiagramType getTypeFromArobaseStart(String s) {
|
||||||
s = s.toLowerCase();
|
s = s.toLowerCase();
|
||||||
@ -130,6 +130,9 @@ public enum DiagramType {
|
|||||||
if (StartUtils.startsWithSymbolAnd("startchronology", s))
|
if (StartUtils.startsWithSymbolAnd("startchronology", s))
|
||||||
return CHRONOLOGY;
|
return CHRONOLOGY;
|
||||||
|
|
||||||
|
if (StartUtils.startsWithSymbolAnd("startchen", s))
|
||||||
|
return CHEN_EER;
|
||||||
|
|
||||||
return UNKNOWN;
|
return UNKNOWN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,10 +40,11 @@ import net.sourceforge.plantuml.svek.extremity.MiddleCircleCircledMode;
|
|||||||
import net.sourceforge.plantuml.svek.extremity.MiddleFactory;
|
import net.sourceforge.plantuml.svek.extremity.MiddleFactory;
|
||||||
import net.sourceforge.plantuml.svek.extremity.MiddleFactoryCircle;
|
import net.sourceforge.plantuml.svek.extremity.MiddleFactoryCircle;
|
||||||
import net.sourceforge.plantuml.svek.extremity.MiddleFactoryCircleCircled;
|
import net.sourceforge.plantuml.svek.extremity.MiddleFactoryCircleCircled;
|
||||||
|
import net.sourceforge.plantuml.svek.extremity.MiddleFactorySubset;
|
||||||
|
|
||||||
public enum LinkMiddleDecor {
|
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) {
|
public MiddleFactory getMiddleFactory(HColor backColor, HColor diagramBackColor) {
|
||||||
if (this == CIRCLE)
|
if (this == CIRCLE)
|
||||||
@ -58,6 +59,12 @@ public enum LinkMiddleDecor {
|
|||||||
if (this == CIRCLE_CIRCLED2)
|
if (this == CIRCLE_CIRCLED2)
|
||||||
return new MiddleFactoryCircleCircled(MiddleCircleCircledMode.MODE2, backColor, diagramBackColor);
|
return new MiddleFactoryCircleCircled(MiddleCircleCircledMode.MODE2, backColor, diagramBackColor);
|
||||||
|
|
||||||
|
if (this == SUBSET)
|
||||||
|
return new MiddleFactorySubset(false);
|
||||||
|
|
||||||
|
if (this == SUPERSET)
|
||||||
|
return new MiddleFactorySubset(true);
|
||||||
|
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,6 +148,14 @@ public class LinkType {
|
|||||||
return new LinkType(decor1, decor2, LinkMiddleDecor.CIRCLE_CIRCLED2, linkStyle);
|
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() {
|
public LinkType getInvisible() {
|
||||||
return new LinkType(decor1, decor2, middleDecor, LinkStyle.INVISIBLE());
|
return new LinkType(decor1, decor2, middleDecor, LinkStyle.INVISIBLE());
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,7 @@ import net.sourceforge.plantuml.style.SName;
|
|||||||
|
|
||||||
public enum UmlDiagramType {
|
public enum UmlDiagramType {
|
||||||
SEQUENCE, STATE, CLASS, OBJECT, ACTIVITY, DESCRIPTION, COMPOSITE, FLOW, TIMING, BPM, NWDIAG, MINDMAP, WBS, WIRE,
|
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, CHRONOLOGY;
|
HELP, GANTT, SALT, JSON, GIT, BOARD, YAML, HCL, EBNF, REGEX, FILES, CHRONOLOGY, CHEN_EER;
|
||||||
|
|
||||||
public SName getStyleName() {
|
public SName getStyleName() {
|
||||||
if (this == SEQUENCE)
|
if (this == SEQUENCE)
|
||||||
|
@ -64,6 +64,10 @@ public enum SName {
|
|||||||
component, //
|
component, //
|
||||||
composite, //
|
composite, //
|
||||||
robust, //
|
robust, //
|
||||||
|
chenAttribute, //
|
||||||
|
chenEerDiagram, //
|
||||||
|
chenEntity, //
|
||||||
|
chenRelationship, //
|
||||||
concise, //
|
concise, //
|
||||||
clock, //
|
clock, //
|
||||||
componentDiagram, //
|
componentDiagram, //
|
||||||
|
@ -99,6 +99,10 @@ import net.sourceforge.plantuml.svek.image.EntityImageArcCircle;
|
|||||||
import net.sourceforge.plantuml.svek.image.EntityImageAssociation;
|
import net.sourceforge.plantuml.svek.image.EntityImageAssociation;
|
||||||
import net.sourceforge.plantuml.svek.image.EntityImageAssociationPoint;
|
import net.sourceforge.plantuml.svek.image.EntityImageAssociationPoint;
|
||||||
import net.sourceforge.plantuml.svek.image.EntityImageBranch;
|
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;
|
import net.sourceforge.plantuml.svek.image.EntityImageCircleEnd;
|
||||||
import net.sourceforge.plantuml.svek.image.EntityImageCircleStart;
|
import net.sourceforge.plantuml.svek.image.EntityImageCircleStart;
|
||||||
import net.sourceforge.plantuml.svek.image.EntityImageClass;
|
import net.sourceforge.plantuml.svek.image.EntityImageClass;
|
||||||
@ -254,6 +258,18 @@ public final class GeneralImageBuilder {
|
|||||||
if (leaf.getLeafType() == LeafType.TIPS)
|
if (leaf.getLeafType() == LeafType.TIPS)
|
||||||
return new EntityImageTips(leaf, skinParam, bibliotekon, umlDiagramType);
|
return new EntityImageTips(leaf, skinParam, bibliotekon, umlDiagramType);
|
||||||
|
|
||||||
|
if (leaf.getLeafType() == LeafType.CHEN_ENTITY)
|
||||||
|
return new EntityImageChenEntity(leaf, skinParam);
|
||||||
|
|
||||||
|
if (leaf.getLeafType() == LeafType.CHEN_RELATIONSHIP)
|
||||||
|
return new EntityImageChenRelationship(leaf, skinParam);
|
||||||
|
|
||||||
|
if (leaf.getLeafType() == LeafType.CHEN_ATTRIBUTE)
|
||||||
|
return new EntityImageChenAttribute(leaf, skinParam);
|
||||||
|
|
||||||
|
if (leaf.getLeafType() == LeafType.CHEN_CIRCLE)
|
||||||
|
return new EntityImageChenCircle(leaf, skinParam);
|
||||||
|
|
||||||
// TODO Clean
|
// TODO Clean
|
||||||
if (leaf.getLeafType() == LeafType.DOMAIN && leaf.getStereotype() != null
|
if (leaf.getLeafType() == LeafType.DOMAIN && leaf.getStereotype() != null
|
||||||
&& leaf.getStereotype().isMachineOrSpecification())
|
&& leaf.getStereotype().isMachineOrSpecification())
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,177 @@
|
|||||||
|
/* ========================================================================
|
||||||
|
* 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 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);
|
||||||
|
|
||||||
|
isKey = hasStereotype("<<key>>");
|
||||||
|
isMulti = hasStereotype("<<multi>>");
|
||||||
|
isDerived = hasStereotype("<<derived>>");
|
||||||
|
|
||||||
|
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.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());
|
||||||
|
|
||||||
|
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;
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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("<<key>>");
|
||||||
|
isMulti = hasStereotype("<<multi>>");
|
||||||
|
isDerived = hasStereotype("<<derived>>");
|
||||||
|
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,162 @@
|
|||||||
|
/* ========================================================================
|
||||||
|
* 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 boolean isWeak;
|
||||||
|
|
||||||
|
final private TextBlock title;
|
||||||
|
final private Url url;
|
||||||
|
|
||||||
|
public EntityImageChenEntity(Entity entity, ISkinParam skinParam) {
|
||||||
|
super(entity, skinParam);
|
||||||
|
|
||||||
|
isWeak = hasStereotype("<<weak>>");
|
||||||
|
|
||||||
|
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 boolean hasStereotype(String stereotype) {
|
||||||
|
return getEntity().getStereotype() != null && getEntity().getStereotype().toString().contains(stereotype);
|
||||||
|
}
|
||||||
|
|
||||||
|
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));
|
||||||
|
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;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,178 @@
|
|||||||
|
/* ========================================================================
|
||||||
|
* 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.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 boolean isIdentifying;
|
||||||
|
|
||||||
|
final private TextBlock title;
|
||||||
|
final private Url url;
|
||||||
|
|
||||||
|
public EntityImageChenRelationship(Entity entity, ISkinParam skinParam) {
|
||||||
|
super(entity, skinParam);
|
||||||
|
|
||||||
|
isIdentifying = hasStereotype("<<identifying>>");
|
||||||
|
|
||||||
|
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 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.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));
|
||||||
|
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;
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,126 @@
|
|||||||
|
package net.sourceforge.plantuml.cheneer.command;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
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<ChenEerDiagram> command = new CommandAssociate();
|
||||||
|
|
||||||
|
private final ChenEerDiagram diagram = new ChenEerDiagram(UmlSource.create(new ArrayList<>(), 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]");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,173 @@
|
|||||||
|
package net.sourceforge.plantuml.cheneer.command;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
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<ChenEerDiagram> command = new CommandCreateAttribute();
|
||||||
|
|
||||||
|
private final ChenEerDiagram diagram = new ChenEerDiagram(UmlSource.create(new ArrayList<>(), 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<<red>>");
|
||||||
|
|
||||||
|
assertThat(matcher).isNotNull();
|
||||||
|
assertThat(matcher.get("DISPLAY", 0)).isNull();
|
||||||
|
assertThat(matcher.get("CODE", 0)).isEqualTo("attr");
|
||||||
|
assertThat(matcher.get("STEREO", 0)).isEqualTo("<<red>>");
|
||||||
|
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<<stereo>>");
|
||||||
|
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("<<stereo>>");
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,123 @@
|
|||||||
|
package net.sourceforge.plantuml.cheneer.command;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
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<ChenEerDiagram> command = new CommandCreateEntity();
|
||||||
|
|
||||||
|
private final ChenEerDiagram diagram = new ChenEerDiagram(UmlSource.create(new ArrayList<>(), 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 <<red>> {");
|
||||||
|
|
||||||
|
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("<<red>>");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void test_parseEntityWithDisplayName() {
|
||||||
|
IRegex regex = CommandCreateEntity.getRegexConcat();
|
||||||
|
RegexResult matcher = regex.matcher("entity \"Red Bus :)\" as Bus_123 <<red>> {");
|
||||||
|
|
||||||
|
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("<<red>>");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void test_executeWithEntity() throws NoSuchColorException {
|
||||||
|
BlocLines lines = BlocLines.singleString("entity \"display\" as code <<stereo>> {");
|
||||||
|
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("<<stereo>>");
|
||||||
|
|
||||||
|
assertThat(diagram.peekOwner()).isSameAs(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void test_executeWithRelationship() throws NoSuchColorException {
|
||||||
|
BlocLines lines = BlocLines.singleString("relationship \"display\" as code <<stereo>> {");
|
||||||
|
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("<<stereo>>");
|
||||||
|
|
||||||
|
assertThat(diagram.peekOwner()).isSameAs(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void test_executeWithEntityWhenAlreadyExists() throws NoSuchColorException {
|
||||||
|
BlocLines lines = BlocLines.singleString("entity \"display\" as code <<stereo>> {");
|
||||||
|
command.execute(diagram, lines);
|
||||||
|
|
||||||
|
CommandExecutionResult result = command.execute(diagram, lines);
|
||||||
|
|
||||||
|
assertThat(result).matches(CommandExecutionResult::isOk);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
package net.sourceforge.plantuml.cheneer.command;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
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<ChenEerDiagram> command = new CommandEndGroup();
|
||||||
|
|
||||||
|
@Spy
|
||||||
|
private final ChenEerDiagram diagram = new ChenEerDiagram(UmlSource.create(new ArrayList<>(), 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();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,213 @@
|
|||||||
|
package net.sourceforge.plantuml.cheneer.command;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
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 CommandMultiSubclassTest {
|
||||||
|
|
||||||
|
private final Command<ChenEerDiagram> command = new CommandMultiSubclass();
|
||||||
|
|
||||||
|
private final ChenEerDiagram diagram = new ChenEerDiagram(UmlSource.create(new ArrayList<>(), 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);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,112 @@
|
|||||||
|
package net.sourceforge.plantuml.cheneer.command;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
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<ChenEerDiagram> command = new CommandSimpleSubclass();
|
||||||
|
|
||||||
|
private final ChenEerDiagram diagram = new ChenEerDiagram(UmlSource.create(new ArrayList<>(), 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);
|
||||||
|
}
|
||||||
|
}
|
94
test/nonreg/simple/ChenMovieAlias_Test.java
Normal file
94
test/nonreg/simple/ChenMovieAlias_Test.java
Normal file
@ -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 <<key>>
|
||||||
|
Name {
|
||||||
|
Fname
|
||||||
|
Lname
|
||||||
|
}
|
||||||
|
Born : DATE
|
||||||
|
Died
|
||||||
|
Age
|
||||||
|
}
|
||||||
|
|
||||||
|
entity "Customer" as CUSTOMER {
|
||||||
|
Number <<key>>
|
||||||
|
Bonus <<derived>>
|
||||||
|
Name <<multi>>
|
||||||
|
}
|
||||||
|
|
||||||
|
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 <<weak>> {
|
||||||
|
Name <<key>>
|
||||||
|
}
|
||||||
|
|
||||||
|
relationship "is-parent-of" as PARENT_OF <<identifying>> {
|
||||||
|
}
|
||||||
|
|
||||||
|
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)");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
1077
test/nonreg/simple/ChenMovieAlias_TestResult.java
Normal file
1077
test/nonreg/simple/ChenMovieAlias_TestResult.java
Normal file
File diff suppressed because it is too large
Load Diff
94
test/nonreg/simple/ChenMovieExtended_Test.java
Normal file
94
test/nonreg/simple/ChenMovieExtended_Test.java
Normal file
@ -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 <<key>>
|
||||||
|
Name {
|
||||||
|
Fname
|
||||||
|
Lname
|
||||||
|
}
|
||||||
|
Born : DATE
|
||||||
|
Died
|
||||||
|
Age
|
||||||
|
}
|
||||||
|
|
||||||
|
entity CUSTOMER {
|
||||||
|
Number <<key>>
|
||||||
|
Bonus <<derived>>
|
||||||
|
Name <<multi>>
|
||||||
|
}
|
||||||
|
|
||||||
|
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 <<weak>> {
|
||||||
|
Name <<key>>
|
||||||
|
}
|
||||||
|
|
||||||
|
relationship PARENT_OF <<identifying>> {
|
||||||
|
}
|
||||||
|
|
||||||
|
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)");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
1073
test/nonreg/simple/ChenMovieExtended_TestResult.java
Normal file
1073
test/nonreg/simple/ChenMovieExtended_TestResult.java
Normal file
File diff suppressed because it is too large
Load Diff
56
test/nonreg/simple/ChenMovie_Test.java
Normal file
56
test/nonreg/simple/ChenMovie_Test.java
Normal file
@ -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 <<key>>
|
||||||
|
Name {
|
||||||
|
Fname
|
||||||
|
Lname
|
||||||
|
}
|
||||||
|
Born : DATE
|
||||||
|
Died
|
||||||
|
Age
|
||||||
|
}
|
||||||
|
|
||||||
|
entity CUSTOMER {
|
||||||
|
Number <<key>>
|
||||||
|
Bonus <<derived>>
|
||||||
|
Name <<multi>>
|
||||||
|
}
|
||||||
|
|
||||||
|
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)");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
555
test/nonreg/simple/ChenMovie_TestResult.java
Normal file
555
test/nonreg/simple/ChenMovie_TestResult.java
Normal file
@ -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
|
||||||
|
|
||||||
|
"""
|
||||||
|
*/
|
Loading…
Reference in New Issue
Block a user