net.sourceforge.plantuml.abel.Entity Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of plantuml-epl Show documentation
Show all versions of plantuml-epl Show documentation
PlantUML is a component that allows to quickly write diagrams from text.
// THIS FILE HAS BEEN GENERATED BY A PREPROCESSOR.
/* +=======================================================================
* |
* | 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/liberapay (only 1€ per month!)
* https://plantuml.com/paypal
*
*
* PlantUML is free software; you can redistribute it and/or modify it
* under the terms of the Eclipse Public License.
*
* THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC
* LICENSE ("AGREEMENT"). [Eclipse Public License - v 1.0]
*
* ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES
* RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
*
* You may obtain a copy of the License at
*
* http://www.eclipse.org/legal/epl-v10.html
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* PlantUML can occasionally display sponsored or advertising messages. Those
* messages are usually generated on welcome or error images and never on
* functional diagrams.
* See https://plantuml.com/professional if you want to remove them
*
* Images (whatever their format : PNG, SVG, EPS...) generated by running PlantUML
* are owned by the author of their corresponding sources code (that is, their
* textual description in PlantUML language). Those images are not covered by
* this EPL license.
*
* The generated images can then be used without any reference to the EPL license.
* It is not even necessary to stipulate that they have been generated with PlantUML,
* although this will be appreciated by the PlantUML team.
*
* There is an exception : if the textual description in PlantUML language is also covered
* by any license, then the generated images are logically covered
* by the very same license.
*
* This is the IGY distribution (Install GraphViz by Yourself).
* You have to install GraphViz and to setup the GRAPHVIZ_DOT environment variable
* (see https://plantuml.com/graphviz-dot )
*
* Icons provided by OpenIconic : https://useiconic.com/open
* Archimate sprites provided by Archi : http://www.archimatetool.com
* Stdlib AWS provided by https://github.com/milo-minderbinder/AWS-PlantUML
* Stdlib Icons provided https://github.com/tupadr3/plantuml-icon-font-sprites
* ASCIIMathML (c) Peter Jipsen http://www.chapman.edu/~jipsen
* ASCIIMathML (c) David Lippman http://www.pierce.ctc.edu/dlippman
* CafeUndZopfli ported by Eugene Klyuchnikov https://github.com/eustas/CafeUndZopfli
* Brotli (c) by the Brotli Authors https://github.com/google/brotli
* Themes (c) by Brett Schwarz https://github.com/bschwarz/puml-themes
* Twemoji (c) by Twitter at https://twemoji.twitter.com/
*
*/
package net.sourceforge.plantuml.abel;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import net.atmp.CucaDiagram;
import net.sourceforge.plantuml.StringUtils;
import net.sourceforge.plantuml.cucadiagram.Bodier;
import net.sourceforge.plantuml.decoration.symbol.USymbol;
import net.sourceforge.plantuml.decoration.symbol.USymbols;
import net.sourceforge.plantuml.dot.Neighborhood;
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.Display;
import net.sourceforge.plantuml.klimt.font.FontConfiguration;
import net.sourceforge.plantuml.klimt.font.FontParam;
import net.sourceforge.plantuml.klimt.font.UFont;
import net.sourceforge.plantuml.klimt.geom.HorizontalAlignment;
import net.sourceforge.plantuml.klimt.shape.TextBlock;
import net.sourceforge.plantuml.klimt.shape.TextBlockEmpty;
import net.sourceforge.plantuml.plasma.Quark;
import net.sourceforge.plantuml.skin.VisibilityModifier;
import net.sourceforge.plantuml.stereo.Stereostyles;
import net.sourceforge.plantuml.stereo.Stereotag;
import net.sourceforge.plantuml.stereo.Stereotype;
import net.sourceforge.plantuml.style.ISkinParam;
import net.sourceforge.plantuml.style.Style;
import net.sourceforge.plantuml.svek.IEntityImage;
import net.sourceforge.plantuml.svek.Kal;
import net.sourceforge.plantuml.svek.Margins;
import net.sourceforge.plantuml.svek.PackageStyle;
import net.sourceforge.plantuml.svek.SingleStrategy;
import net.sourceforge.plantuml.svek.image.EntityImageStateCommon;
import net.sourceforge.plantuml.text.Guillemet;
import net.sourceforge.plantuml.url.Url;
import net.sourceforge.plantuml.utils.Direction;
import net.sourceforge.plantuml.utils.LineLocation;
import net.sourceforge.plantuml.utils.Position;
final public class Entity implements SpecificBackcolorable, Hideable, Removeable, LineConfigurable, Bag {
private final CucaDiagram diagram;
private final Quark quark;
private Url url;
private final Bodier bodier;
private final String uid;
private Display display = Display.empty();
private DisplayPositioned legend = null;
private LeafType leafType;
private Stereotype stereotype;
private Stereostyles stereostyles = Stereostyles.NONE;
private String generic;
private GroupType groupType;
// Other
private Margins margins = Margins.NONE;
private final Collection portShortNames = new HashSet<>();
private int xposition;
private IEntityImage svekImage;
private USymbol symbol;
private final int rawLayout;
private char concurrentSeparator;
private LineLocation codeLine;
private Set tags = new LinkedHashSet<>();
private final List notesTop = new ArrayList<>();
private final List notesBottom = new ArrayList<>();
private Together together;
private boolean packed;
private boolean isStatic;
private final Map> kals = new EnumMap<>(Direction.class);
private VisibilityModifier visibility;
private Neighborhood neighborhood;
private Colors colors = Colors.empty();
private final Map tips = new LinkedHashMap();
//
public void addNote(Display note, Position position, Colors colors) {
if (position == Position.TOP)
notesTop.add(CucaNote.build(note, position, colors));
else if (position == Position.BOTTOM)
notesBottom.add(CucaNote.build(note, position, colors));
}
//
public List getNotes(Position position) {
if (position == Position.TOP)
return Collections.unmodifiableList(notesTop);
if (position == Position.BOTTOM)
return Collections.unmodifiableList(notesBottom);
throw new IllegalArgumentException();
}
public void addStereotag(Stereotag tag) {
this.tags.add(tag);
}
public Set stereotags() {
return Collections.unmodifiableSet(tags);
}
// Back to Entity
private Entity(Quark quark, CucaDiagram diagram, Bodier bodier, int rawLayout) {
this.quark = Objects.requireNonNull(quark);
this.diagram = diagram;
if (quark.isRoot())
this.uid = "clroot";
else
this.uid = StringUtils.getUid("cl", diagram.getUniqueSequence());
this.bodier = bodier;
this.rawLayout = rawLayout;
this.quark.setData(this);
}
public Entity(Quark quark, CucaDiagram diagram, Bodier bodier, LeafType leafType, int rawLayout) {
this(Objects.requireNonNull(quark), diagram, bodier, rawLayout);
this.leafType = leafType;
}
public Entity(Quark quark, CucaDiagram diagram, Bodier bodier, GroupType groupType, int rawLayout) {
this(Objects.requireNonNull(quark), diagram, bodier, rawLayout);
this.groupType = groupType;
}
public LeafType getLeafType() {
return leafType;
}
public void muteToType(LeafType newType) {
if (leafType == LeafType.CLASS && newType == LeafType.OBJECT)
bodier.muteClassToObject();
this.groupType = null;
this.leafType = newType;
}
public void muteToGroupType(GroupType newType) {
this.groupType = newType;
this.leafType = null;
}
public boolean muteToType(LeafType newType, USymbol newSymbol) {
// checkNotGroup();
Objects.requireNonNull(newType);
if (leafType != LeafType.STILL_UNKNOWN) {
if (newType == this.leafType)
return true;
if (leafType != LeafType.ANNOTATION && leafType != LeafType.ABSTRACT_CLASS && leafType != LeafType.CLASS
&& leafType != LeafType.ENUM && leafType != LeafType.INTERFACE) {
return false;
// throw new IllegalArgumentException("type=" + leafType);
}
if (newType != LeafType.ANNOTATION && newType != LeafType.ABSTRACT_CLASS && newType != LeafType.CLASS
&& newType != LeafType.ENUM && newType != LeafType.INTERFACE && newType != LeafType.OBJECT) {
return false;
// throw new IllegalArgumentException("newtype=" + newType);
}
}
if (leafType == LeafType.CLASS && newType == LeafType.OBJECT)
bodier.muteClassToObject();
this.leafType = newType;
this.symbol = newSymbol;
return true;
}
public Quark getQuark() {
return quark;
}
public Display getDisplay() {
return display;
}
public void setDisplay(Display display) {
this.display = display;
}
public String getUid() {
return uid;
}
public Stereotype getStereotype() {
return stereotype;
}
public final void setStereotype(Stereotype stereotype) {
this.stereotype = stereotype;
}
public String toString() {
return quark.toString() + " " + display + "(" + leafType + ")[" + groupType + "] " + getUid();
}
public final Url getUrl99() {
return url;
}
public boolean hasUrl() {
if (Display.isNull(display) == false && display.hasUrl())
return true;
if (bodier == null)
return false;
if (bodier.hasUrl())
return true;
return url != null;
}
public final void addUrl(Url url) {
this.url = url;
}
public final Margins getMargins() {
checkNotGroup();
return margins;
}
public final void ensureMargins(Margins newMargins) {
// checkNotGroup();
this.margins = this.margins.merge(newMargins);
}
public int getXposition() {
checkNotGroup();
return xposition;
}
public void setXposition(int pos) {
checkNotGroup();
xposition = pos;
}
public final IEntityImage getSvekImage() {
checkNotGroup();
return svekImage;
}
public final void setSvekImage(IEntityImage svekImage) {
checkNotGroup();
this.svekImage = svekImage;
}
public final void setGeneric(String generic) {
checkNotGroup();
this.generic = generic;
}
public final String getGeneric() {
checkNotGroup();
return generic;
}
public Bodier getBodier() {
return bodier;
}
public EntityPosition getEntityPosition() {
// if (leafType == LeafType.PORT)
// return EntityPosition.PORT;
if (leafType == LeafType.PORTIN)
return EntityPosition.PORTIN;
if (leafType == LeafType.PORTOUT)
return EntityPosition.PORTOUT;
if (leafType != LeafType.STATE)
return EntityPosition.NORMAL;
if (quark.isRoot())
return EntityPosition.NORMAL;
final Stereotype stereotype = getStereotype();
if (stereotype == null)
return EntityPosition.NORMAL;
return EntityPosition.fromStereotype(stereotype.getLabel(Guillemet.DOUBLE_COMPARATOR));
}
// ----------
private void checkGroup() {
if (isGroup() == false)
throw new UnsupportedOperationException();
}
private void checkNotGroup() {
if (isGroup())
throw new UnsupportedOperationException();
}
public GroupType getGroupType() {
checkGroup();
return groupType;
}
public PackageStyle getPackageStyle() {
checkGroup();
if (stereotype == null)
return null;
return stereotype.getPackageStyle();
}
public boolean isGroup() {
if (groupType != null && leafType != null)
throw new IllegalStateException();
assert groupType == null || leafType == null;
if (groupType != null)
return true;
if (leafType != null)
return false;
throw new IllegalStateException();
}
// ---- other
public void overrideImage(IEntityImage img, LeafType leafType) {
checkGroup();
this.svekImage = img;
this.url = null;
for (final Link link : new ArrayList<>(this.diagram.getLinks()))
if (EntityUtils.isPureInnerLink12(this, link))
this.diagram.removeLink(link);
this.groupType = null;
this.leafType = leafType;
}
public USymbol getUSymbol() {
if (getLeafType() == LeafType.CIRCLE)
return USymbols.INTERFACE;
return symbol;
}
public void setUSymbol(USymbol symbol) {
this.symbol = symbol;
}
public SingleStrategy getSingleStrategy() {
return SingleStrategy.SQUARE;
}
public boolean isHidden() {
if (isRoot())
return false;
if (getParentContainer() != null && getParentContainer().isHidden())
return true;
return isHiddenInternal();
}
private boolean isHiddenInternal() {
if (isRoot())
return false;
// if (isGroup()) {
// if (this.diagram.isHidden(this))
// return true;
//
// if (leafs().size() == 0)
// return false;
//
// for (Entity leaf : leafs())
// if (leaf.isHiddenInternal() == false)
// return false;
//
// for (Entity g : groups())
// if (g.isHiddenInternal() == false)
// return false;
//
// return true;
// }
return this.diagram.isHidden(this);
}
public boolean isRemoved() {
if (isRoot())
return false;
if (getParentContainer() != null && getParentContainer().isRemoved())
return true;
return isRemovedInternal();
}
private boolean isRemovedInternal() {
// if (isGroup()) {
// if (this.diagram.isRemoved(this))
// return true;
//
// if (leafs().size() == 0 && groups().size() == 0)
// return false;
//
// for (Entity leaf : leafs())
// if (leaf.isRemovedInternal() == false)
// return false;
//
// for (Entity g : groups())
// if (g.isRemovedInternal() == false)
// return false;
//
// return true;
// }
return this.diagram.isRemoved(this);
}
public boolean isAloneAndUnlinked() {
if (isGroup()) {
for (Quark quarkChild : getQuark().getChildren()) {
final Entity child = quarkChild.getData();
if (child.isAloneAndUnlinked() == false)
return false;
}
return true;
}
for (Link link : this.diagram.getLinks())
if (link.contains(this)) {
final Entity other = link.getOther(this);
final boolean removed = this.diagram.isRemovedIgnoreUnlinked(other);
if (removed == false && link.getType().isInvisible() == false)
return false;
}
return true;
}
private FontParam getTitleFontParam() {
return getGroupType() == GroupType.STATE ? FontParam.STATE : FontParam.PACKAGE;
}
public FontConfiguration getFontConfigurationForTitle(final ISkinParam skinParam) {
final FontParam fontParam = getTitleFontParam();
final HColor fontHtmlColor = skinParam.getFontHtmlColor(getStereotype(), fontParam, FontParam.PACKAGE);
final UFont font = skinParam.getFont(getStereotype(), true, fontParam, FontParam.PACKAGE);
final FontConfiguration fontConfiguration = FontConfiguration.create(font, fontHtmlColor,
skinParam.getHyperlinkColor(), skinParam.useUnderlineForHyperlink(), skinParam.getTabSize());
return fontConfiguration;
}
public final int getRawLayout() {
return rawLayout;
}
public char getConcurrentSeparator() {
return concurrentSeparator;
}
public void setConcurrentSeparator(char separator) {
this.concurrentSeparator = separator;
}
public void setNeighborhood(Neighborhood neighborhood) {
this.neighborhood = neighborhood;
}
public Neighborhood getNeighborhood() {
return neighborhood;
}
public void putTip(String member, Display display) {
tips.put(member, display);
}
public Map getTips() {
return Collections.unmodifiableMap(tips);
}
public Colors getColors() {
return colors;
}
public void setColors(Colors colors) {
this.colors = colors;
}
public void setSpecificColorTOBEREMOVED(ColorType type, HColor color) {
if (color != null)
this.colors = colors.add(type, color);
}
public Collection getPortShortNames() {
checkNotGroup();
return Collections.unmodifiableCollection(portShortNames);
}
public void addPortShortName(String portShortName) {
portShortNames.add(portShortName);
}
public void setVisibilityModifier(VisibilityModifier visibility) {
this.visibility = visibility;
}
public VisibilityModifier getVisibilityModifier() {
return visibility;
}
public void setLegend(DisplayPositioned legend) {
checkGroup();
this.legend = legend;
}
public DisplayPositioned getLegend() {
return legend;
}
public String getCodeLine() {
if (this.codeLine == null)
return null;
return "" + this.codeLine.getPosition();
}
public void setCodeLine(LineLocation codeLine) {
this.codeLine = codeLine;
}
public void setStereostyle(String stereo) {
this.stereostyles = Stereostyles.build(stereo);
}
public Stereostyles getStereostyles() {
return stereostyles;
}
public void addKal(Kal kal) {
final Direction position = kal.getPosition();
List list = kals.get(position);
if (list == null) {
list = new ArrayList<>();
kals.put(position, list);
}
list.add(kal);
}
public List getKals(Direction position) {
final List result = kals.get(position);
if (result == null)
return Collections.emptyList();
return Collections.unmodifiableList(result);
}
public CucaDiagram getDiagram() {
return diagram;
}
public void setStatic(boolean isStatic) {
this.isStatic = isStatic;
}
public boolean isStatic() {
return isStatic;
}
// For group
public TextBlock getStateHeader(ISkinParam skinParam) {
checkGroup();
final Style style = EntityImageStateCommon.getStyleStateHeader(this, skinParam);
final List details = getBodier().getRawBody();
if (details.size() == 0)
return new TextBlockEmpty();
if (style == null)
throw new IllegalArgumentException();
final FontConfiguration fontConfiguration = FontConfiguration.create(skinParam, style);
Display display = null;
for (CharSequence s : details)
if (display == null)
display = Display.getWithNewlines(s.toString());
else
display = display.addAll(Display.getWithNewlines(s.toString()));
return display.create(fontConfiguration, HorizontalAlignment.LEFT, skinParam);
}
public void setTogether(Together together) {
this.together = together;
}
public Together getTogether() {
return this.together;
}
public Entity getParentContainer() {
if (quark.isRoot())
return null;
return quark.getParent().getData();
}
public Collection leafs() {
final List result = new ArrayList<>();
for (Quark child : quark.getChildren()) {
final Entity data = child.getData();
if (data != null && data.isGroup() == false)
result.add(data);
}
return Collections.unmodifiableCollection(result);
}
public Collection groups() {
final List result = new ArrayList<>();
for (Quark child : quark.getChildren()) {
final Entity data = child.getData();
if (data != null && data.isGroup())
result.add(data);
}
return Collections.unmodifiableCollection(result);
}
public int countChildren() {
return getQuark().countChildren();
}
public boolean isRoot() {
return getQuark().isRoot();
}
final public boolean isEmpty() {
for (Quark quarkChild : getQuark().getChildren()) {
final Entity child = quarkChild.getData();
if (this.diagram.isRemoved(child) == false)
return false;
}
return true;
}
public String getName() {
return getQuark().getName();
}
public boolean isAutarkic() {
if (getGroupType() == GroupType.PACKAGE)
return false;
if (getGroupType() == GroupType.INNER_ACTIVITY)
return true;
if (getGroupType() == GroupType.CONCURRENT_ACTIVITY)
return true;
if (getGroupType() == GroupType.CONCURRENT_STATE)
return true;
// if (diag.getChildrenGroups(this).size() > 0)
// return false;
for (Link link : this.diagram.getLinks())
if (EntityUtils.isPureInnerLink3(this, link) == false)
return false;
for (Entity leaf : leafs())
if (leaf.getEntityPosition() != EntityPosition.NORMAL)
return false;
return true;
}
public boolean canBePacked() {
if (isPacked())
return false;
if (countChildren() != 1)
return false;
if (leafs().size() != 0)
return false;
for (Link link : this.diagram.getLinks())
if (link.contains(this))
return false;
final Entity child = groups().iterator().next();
if (child.countChildren() == 0)
return false;
return true;
}
public final void setPacked(boolean packed) {
this.packed = true;
}
public final boolean isPacked() {
return packed;
}
}