summaryrefslogtreecommitdiff
path: root/src/net/sourceforge/plantuml/classdiagram/ClassDiagram.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/net/sourceforge/plantuml/classdiagram/ClassDiagram.java')
-rw-r--r--src/net/sourceforge/plantuml/classdiagram/ClassDiagram.java488
1 files changed, 252 insertions, 236 deletions
diff --git a/src/net/sourceforge/plantuml/classdiagram/ClassDiagram.java b/src/net/sourceforge/plantuml/classdiagram/ClassDiagram.java
index 9db21b3..40e4312 100644
--- a/src/net/sourceforge/plantuml/classdiagram/ClassDiagram.java
+++ b/src/net/sourceforge/plantuml/classdiagram/ClassDiagram.java
@@ -1,236 +1,252 @@
-/* ========================================================================
- * PlantUML : a free UML diagram generator
- * ========================================================================
- *
- * (C) Copyright 2009-2017, Arnaud Roques
- *
- * Project Info: http://plantuml.com
- *
- * This file is part of PlantUML.
- *
- * Licensed under The MIT License (Massachusetts Institute of Technology License)
- *
- * See http://opensource.org/licenses/MIT
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
- * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- *
- * Original Author: Arnaud Roques
- */
-package net.sourceforge.plantuml.classdiagram;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-import net.sourceforge.plantuml.FileFormatOption;
-import net.sourceforge.plantuml.UmlDiagramType;
-import net.sourceforge.plantuml.core.ImageData;
-import net.sourceforge.plantuml.creole.CreoleMode;
-import net.sourceforge.plantuml.cucadiagram.Code;
-import net.sourceforge.plantuml.cucadiagram.Display;
-import net.sourceforge.plantuml.cucadiagram.EntityUtils;
-import net.sourceforge.plantuml.cucadiagram.GroupType;
-import net.sourceforge.plantuml.cucadiagram.IGroup;
-import net.sourceforge.plantuml.cucadiagram.ILeaf;
-import net.sourceforge.plantuml.cucadiagram.LeafType;
-import net.sourceforge.plantuml.graphic.HtmlColorUtils;
-import net.sourceforge.plantuml.graphic.TextBlock;
-import net.sourceforge.plantuml.graphic.USymbol;
-import net.sourceforge.plantuml.objectdiagram.AbstractClassOrObjectDiagram;
-import net.sourceforge.plantuml.svek.image.EntityImageClass;
-import net.sourceforge.plantuml.ugraphic.ImageBuilder;
-
-public class ClassDiagram extends AbstractClassOrObjectDiagram {
-
- private String namespaceSeparator = ".";
-
- @Override
- public ILeaf getOrCreateLeaf(Code code, LeafType type, USymbol symbol) {
- if (namespaceSeparator != null) {
- code = code.withSeparator(namespaceSeparator);
- }
- if (type == null) {
- code = code.eventuallyRemoveStartingAndEndingDoubleQuote("\"([:");
- if (namespaceSeparator == null) {
- return getOrCreateLeafDefault(code, LeafType.CLASS, symbol);
- }
- code = code.getFullyQualifiedCode(getCurrentGroup());
- if (super.leafExist(code)) {
- return getOrCreateLeafDefault(code, LeafType.CLASS, symbol);
- }
- return createEntityWithNamespace(code, Display.getWithNewlines(code.getShortName(getLeafs())),
- LeafType.CLASS, symbol);
- }
- if (namespaceSeparator == null) {
- return getOrCreateLeafDefault(code, LeafType.CLASS, symbol);
- }
- code = code.getFullyQualifiedCode(getCurrentGroup());
- if (super.leafExist(code)) {
- return getOrCreateLeafDefault(code, type, symbol);
- }
- return createEntityWithNamespace(code, Display.getWithNewlines(code.getShortName(getLeafs())), type, symbol);
- }
-
- public IGroup getOrCreateNamespace(Code namespace, Display display, GroupType type, IGroup parent) {
- if (namespaceSeparator != null) {
- namespace = namespace.withSeparator(namespaceSeparator).getFullyQualifiedCode(getCurrentGroup());
- }
- final IGroup g = getOrCreateNamespaceInternal(namespace, display, type, parent);
- currentGroup = g;
- return g;
- }
-
- private IGroup getOrCreateNamespaceInternal(Code namespace, Display display, GroupType type, IGroup parent) {
- IGroup result = entityFactory.getGroups().get(namespace);
- if (result != null) {
- return result;
- }
- if (entityFactory.getLeafs().containsKey(namespace)) {
- result = entityFactory.muteToGroup(namespace, namespace, type, parent);
- result.setDisplay(display);
- } else {
- result = entityFactory.createGroup(namespace, display, namespace, type, parent, getHides(),
- getNamespaceSeparator());
- }
- entityFactory.addGroup(result);
- return result;
- }
-
- @Override
- public ILeaf createLeaf(Code code, Display display, LeafType type, USymbol symbol) {
- if (namespaceSeparator != null) {
- code = code.withSeparator(namespaceSeparator);
- }
- if (type != LeafType.ABSTRACT_CLASS && type != LeafType.ANNOTATION && type != LeafType.CLASS
- && type != LeafType.INTERFACE && type != LeafType.ENUM && type != LeafType.LOLLIPOP
- && type != LeafType.NOTE) {
- return super.createLeaf(code, display, type, symbol);
- }
- if (namespaceSeparator == null) {
- return super.createLeaf(code, display, type, symbol);
- }
- code = code.getFullyQualifiedCode(getCurrentGroup());
- if (super.leafExist(code)) {
- throw new IllegalArgumentException("Already known: " + code);
- }
- return createEntityWithNamespace(code, display, type, symbol);
- }
-
- private ILeaf createEntityWithNamespace(Code fullyCode, Display display, LeafType type, USymbol symbol) {
- IGroup group = getCurrentGroup();
- final String namespace = getNamespace(fullyCode);
- if (namespace != null
- && (EntityUtils.groupRoot(group) || group.getCode().getFullName().equals(namespace) == false)) {
- final Code namespace2 = Code.of(namespace);
- group = getOrCreateNamespaceInternal(namespace2, Display.getWithNewlines(namespace), GroupType.PACKAGE,
- getRootGroup());
- }
- return createLeafInternal(
- fullyCode,
- Display.isNull(display) ? Display.getWithNewlines(fullyCode.getShortName(getLeafs())).withCreoleMode(
- CreoleMode.SIMPLE_LINE) : display, type, group, symbol);
- }
-
- private final String getNamespace(Code fullyCode) {
- String name = fullyCode.getFullName();
- do {
- final int x = name.lastIndexOf(namespaceSeparator);
- if (x == -1) {
- return null;
- }
- name = name.substring(0, x);
- } while (getLeafs().containsKey(Code.of(name, namespaceSeparator)));
- return name;
- }
-
- @Override
- public final boolean leafExist(Code code) {
- if (namespaceSeparator == null) {
- return super.leafExist(code);
- }
- code = code.withSeparator(namespaceSeparator);
- return super.leafExist(code.getFullyQualifiedCode(getCurrentGroup()));
- }
-
- @Override
- public UmlDiagramType getUmlDiagramType() {
- return UmlDiagramType.CLASS;
- }
-
- public void setNamespaceSeparator(String namespaceSeparator) {
- this.namespaceSeparator = namespaceSeparator;
- }
-
- public String getNamespaceSeparator() {
- return namespaceSeparator;
- }
-
- private boolean allowMixing;
-
- public void setAllowMixing(boolean allowMixing) {
- this.allowMixing = allowMixing;
- }
-
- public boolean isAllowMixing() {
- return allowMixing;
- }
-
- private int useLayoutExplicit = 0;
-
- public void layoutNewLine() {
- useLayoutExplicit++;
- incRawLayout();
- }
-
- @Override
- final protected ImageData exportDiagramInternal(OutputStream os, int index, FileFormatOption fileFormatOption)
- throws IOException {
- if (useLayoutExplicit != 0) {
- return exportLayoutExplicit(os, index, fileFormatOption);
- }
- return super.exportDiagramInternal(os, index, fileFormatOption);
- }
-
- final protected ImageData exportLayoutExplicit(OutputStream os, int index, FileFormatOption fileFormatOption)
- throws IOException {
- final FullLayout fullLayout = new FullLayout();
- for (int i = 0; i <= useLayoutExplicit; i++) {
- final RowLayout rawLayout = getRawLayout(i);
- fullLayout.addRowLayout(rawLayout);
- }
- final ImageBuilder imageBuilder = new ImageBuilder(getSkinParam().getColorMapper(), 1, HtmlColorUtils.WHITE,
- null, null, 0, 10, null, getSkinParam().handwritten());
- imageBuilder.setUDrawable(fullLayout);
- return imageBuilder.writeImageTOBEMOVED(fileFormatOption, os);
- }
-
- private RowLayout getRawLayout(int raw) {
- final RowLayout rawLayout = new RowLayout();
- for (ILeaf leaf : getLeafs().values()) {
- if (leaf.getRawLayout() == raw) {
- rawLayout.addLeaf(getEntityImageClass(leaf));
- }
- }
- return rawLayout;
- }
-
- private TextBlock getEntityImageClass(ILeaf entity) {
- return new EntityImageClass(null, entity, getSkinParam(), this);
- }
-
-}
+/* ========================================================================
+ * PlantUML : a free UML diagram generator
+ * ========================================================================
+ *
+ * (C) Copyright 2009-2017, Arnaud Roques
+ *
+ * Project Info: http://plantuml.com
+ *
+ * If you like this project or if you find it useful, you can support us at:
+ *
+ * http://plantuml.com/patreon (only 1$ per month!)
+ * http://plantuml.com/paypal
+ *
+ * This file is part of PlantUML.
+ *
+ * PlantUML is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * PlantUML distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ *
+ *
+ * Original Author: Arnaud Roques
+ *
+ *
+ */
+package net.sourceforge.plantuml.classdiagram;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import net.sourceforge.plantuml.FileFormatOption;
+import net.sourceforge.plantuml.UmlDiagramType;
+import net.sourceforge.plantuml.core.ImageData;
+import net.sourceforge.plantuml.creole.CreoleMode;
+import net.sourceforge.plantuml.cucadiagram.Code;
+import net.sourceforge.plantuml.cucadiagram.Display;
+import net.sourceforge.plantuml.cucadiagram.EntityUtils;
+import net.sourceforge.plantuml.cucadiagram.GroupType;
+import net.sourceforge.plantuml.cucadiagram.IGroup;
+import net.sourceforge.plantuml.cucadiagram.ILeaf;
+import net.sourceforge.plantuml.cucadiagram.LeafType;
+import net.sourceforge.plantuml.cucadiagram.Link;
+import net.sourceforge.plantuml.graphic.TextBlock;
+import net.sourceforge.plantuml.graphic.USymbol;
+import net.sourceforge.plantuml.objectdiagram.AbstractClassOrObjectDiagram;
+import net.sourceforge.plantuml.svek.image.EntityImageClass;
+import net.sourceforge.plantuml.ugraphic.ImageBuilder;
+
+public class ClassDiagram extends AbstractClassOrObjectDiagram {
+
+ private String namespaceSeparator = ".";
+
+ @Override
+ public ILeaf getOrCreateLeaf(Code code, LeafType type, USymbol symbol) {
+ if (namespaceSeparator != null) {
+ code = code.withSeparator(namespaceSeparator);
+ }
+ if (type == null) {
+ code = code.eventuallyRemoveStartingAndEndingDoubleQuote("\"([:");
+ if (namespaceSeparator == null) {
+ return getOrCreateLeafDefault(code, LeafType.CLASS, symbol);
+ }
+ code = code.getFullyQualifiedCode(getCurrentGroup());
+ if (super.leafExist(code)) {
+ return getOrCreateLeafDefault(code, LeafType.CLASS, symbol);
+ }
+ return createEntityWithNamespace(code, Display.getWithNewlines(code.getShortName(getLeafs())),
+ LeafType.CLASS, symbol);
+ }
+ if (namespaceSeparator == null) {
+ return getOrCreateLeafDefault(code, LeafType.CLASS, symbol);
+ }
+ code = code.getFullyQualifiedCode(getCurrentGroup());
+ if (super.leafExist(code)) {
+ return getOrCreateLeafDefault(code, type, symbol);
+ }
+ return createEntityWithNamespace(code, Display.getWithNewlines(code.getShortName(getLeafs())), type, symbol);
+ }
+
+ public IGroup getOrCreateNamespace(Code namespace, Display display, GroupType type, IGroup parent) {
+ if (namespaceSeparator != null) {
+ namespace = namespace.withSeparator(namespaceSeparator).getFullyQualifiedCode(getCurrentGroup());
+ }
+ final IGroup g = getOrCreateNamespaceInternal(namespace, display, type, parent);
+ currentGroup = g;
+ return g;
+ }
+
+ private IGroup getOrCreateNamespaceInternal(Code namespace, Display display, GroupType type, IGroup parent) {
+ IGroup result = entityFactory.getGroups().get(namespace);
+ if (result != null) {
+ return result;
+ }
+ if (entityFactory.getLeafs().containsKey(namespace)) {
+ result = entityFactory.muteToGroup(namespace, namespace, type, parent);
+ result.setDisplay(display);
+ } else {
+ result = entityFactory.createGroup(namespace, display, namespace, type, parent, getHides(),
+ getNamespaceSeparator());
+ }
+ entityFactory.addGroup(result);
+ return result;
+ }
+
+ @Override
+ public ILeaf createLeaf(Code code, Display display, LeafType type, USymbol symbol) {
+ if (namespaceSeparator != null) {
+ code = code.withSeparator(namespaceSeparator);
+ }
+ if (type != LeafType.ABSTRACT_CLASS && type != LeafType.ANNOTATION && type != LeafType.CLASS
+ && type != LeafType.INTERFACE && type != LeafType.ENUM && type != LeafType.LOLLIPOP
+ && type != LeafType.NOTE) {
+ return super.createLeaf(code, display, type, symbol);
+ }
+ if (namespaceSeparator == null) {
+ return super.createLeaf(code, display, type, symbol);
+ }
+ code = code.getFullyQualifiedCode(getCurrentGroup());
+ if (super.leafExist(code)) {
+ throw new IllegalArgumentException("Already known: " + code);
+ }
+ return createEntityWithNamespace(code, display, type, symbol);
+ }
+
+ private ILeaf createEntityWithNamespace(Code fullyCode, Display display, LeafType type, USymbol symbol) {
+ IGroup group = getCurrentGroup();
+ final String namespace = getNamespace(fullyCode);
+ if (namespace != null
+ && (EntityUtils.groupRoot(group) || group.getCode().getFullName().equals(namespace) == false)) {
+ final Code namespace2 = Code.of(namespace);
+ group = getOrCreateNamespaceInternal(namespace2, Display.getWithNewlines(namespace), GroupType.PACKAGE,
+ getRootGroup());
+ }
+ return createLeafInternal(
+ fullyCode,
+ Display.isNull(display) ? Display.getWithNewlines(fullyCode.getShortName(getLeafs())).withCreoleMode(
+ CreoleMode.SIMPLE_LINE) : display, type, group, symbol);
+ }
+
+ private final String getNamespace(Code fullyCode) {
+ String name = fullyCode.getFullName();
+ do {
+ final int x = name.lastIndexOf(namespaceSeparator);
+ if (x == -1) {
+ return null;
+ }
+ name = name.substring(0, x);
+ } while (getLeafs().containsKey(Code.of(name, namespaceSeparator)));
+ return name;
+ }
+
+ @Override
+ public final boolean leafExist(Code code) {
+ if (namespaceSeparator == null) {
+ return super.leafExist(code);
+ }
+ code = code.withSeparator(namespaceSeparator);
+ return super.leafExist(code.getFullyQualifiedCode(getCurrentGroup()));
+ }
+
+ @Override
+ public UmlDiagramType getUmlDiagramType() {
+ return UmlDiagramType.CLASS;
+ }
+
+ public void setNamespaceSeparator(String namespaceSeparator) {
+ this.namespaceSeparator = namespaceSeparator;
+ }
+
+ public String getNamespaceSeparator() {
+ return namespaceSeparator;
+ }
+
+ private boolean allowMixing;
+
+ public void setAllowMixing(boolean allowMixing) {
+ this.allowMixing = allowMixing;
+ }
+
+ public boolean isAllowMixing() {
+ return allowMixing;
+ }
+
+ private int useLayoutExplicit = 0;
+
+ public void layoutNewLine() {
+ useLayoutExplicit++;
+ incRawLayout();
+ }
+
+ @Override
+ final protected ImageData exportDiagramInternal(OutputStream os, int index, FileFormatOption fileFormatOption)
+ throws IOException {
+ if (useLayoutExplicit != 0) {
+ return exportLayoutExplicit(os, index, fileFormatOption);
+ }
+ return super.exportDiagramInternal(os, index, fileFormatOption);
+ }
+
+ final protected ImageData exportLayoutExplicit(OutputStream os, int index, FileFormatOption fileFormatOption)
+ throws IOException {
+ final FullLayout fullLayout = new FullLayout();
+ for (int i = 0; i <= useLayoutExplicit; i++) {
+ final RowLayout rawLayout = getRawLayout(i);
+ fullLayout.addRowLayout(rawLayout);
+ }
+ final ImageBuilder imageBuilder = new ImageBuilder(getSkinParam(), 1, null, null, 0, 10, null);
+ imageBuilder.setUDrawable(fullLayout);
+ return imageBuilder.writeImageTOBEMOVED(fileFormatOption, seed(), os);
+ }
+
+ private RowLayout getRawLayout(int raw) {
+ final RowLayout rawLayout = new RowLayout();
+ for (ILeaf leaf : getLeafs().values()) {
+ if (leaf.getRawLayout() == raw) {
+ rawLayout.addLeaf(getEntityImageClass(leaf));
+ }
+ }
+ return rawLayout;
+ }
+
+ private TextBlock getEntityImageClass(ILeaf entity) {
+ return new EntityImageClass(null, entity, getSkinParam(), this);
+ }
+
+ @Override
+ public String checkFinalError() {
+ for (Link link : this.getLinks()) {
+ final int len = link.getLength();
+ if (len == 1) {
+ for (Link link2 : this.getLinks()) {
+ if (link2.sameConnections(link) && link2.getLength() != 1) {
+ link2.setLength(1);
+ }
+ }
+ }
+ }
+ this.applySingleStrategy();
+ return super.checkFinalError();
+ }
+
+}