mirror of
https://github.com/octoleo/plantuml.git
synced 2024-11-21 20:45:10 +00:00
wip
This commit is contained in:
parent
117102bb65
commit
80217d8c90
@ -85,6 +85,7 @@ import net.sourceforge.plantuml.openiconic.PSystemListOpenIconicFactory;
|
||||
import net.sourceforge.plantuml.openiconic.PSystemOpenIconicFactory;
|
||||
import net.sourceforge.plantuml.oregon.PSystemOregonFactory;
|
||||
import net.sourceforge.plantuml.project.GanttDiagramFactory;
|
||||
import net.sourceforge.plantuml.regex.PSystemRegexFactory;
|
||||
import net.sourceforge.plantuml.salt.PSystemSaltFactory2;
|
||||
import net.sourceforge.plantuml.security.SecurityProfile;
|
||||
import net.sourceforge.plantuml.security.SecurityUtils;
|
||||
@ -212,7 +213,6 @@ public class PSystemBuilder {
|
||||
factories.add(new PSystemXearthFactory());
|
||||
}
|
||||
factories.add(new GanttDiagramFactory(DiagramType.GANTT));
|
||||
// factories.add(new GanttDiagramFactory(DiagramType.UML));
|
||||
GanttDiagramFactory.clearCache();
|
||||
factories.add(new FlowDiagramFactory());
|
||||
// factories.add(new PSystemTreeFactory(DiagramType.JUNGLE));
|
||||
@ -227,6 +227,7 @@ public class PSystemBuilder {
|
||||
factories.add(new YamlDiagramFactory());
|
||||
factories.add(new HclDiagramFactory());
|
||||
factories.add(new PSystemEbnfFactory());
|
||||
factories.add(new PSystemRegexFactory());
|
||||
}
|
||||
|
||||
private boolean isOk(Diagram ps) {
|
||||
|
@ -41,12 +41,12 @@ abstract class ScaleProtected implements Scale {
|
||||
|
||||
final public double getScale(double width, double height) {
|
||||
final double result = getScaleInternal(width, height);
|
||||
if (result <= 0) {
|
||||
if (result <= 0)
|
||||
return 1;
|
||||
}
|
||||
if (result > 4) {
|
||||
|
||||
if (result > 4)
|
||||
return 4;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -39,7 +39,7 @@ import net.sourceforge.plantuml.style.SName;
|
||||
|
||||
public enum UmlDiagramType {
|
||||
SEQUENCE, STATE, CLASS, OBJECT, ACTIVITY, DESCRIPTION, COMPOSITE, FLOW, TIMING, BPM, NWDIAG, MINDMAP, WBS, WIRE,
|
||||
HELP, GANTT, SALT, JSON, GIT, BOARD, YAML, HCL, EBNF;
|
||||
HELP, GANTT, SALT, JSON, GIT, BOARD, YAML, HCL, EBNF, REGEX;
|
||||
|
||||
public SName getStyleName() {
|
||||
if (this == SEQUENCE)
|
||||
@ -93,6 +93,9 @@ public enum UmlDiagramType {
|
||||
if (this == EBNF)
|
||||
return SName.ebnf;
|
||||
|
||||
if (this == REGEX)
|
||||
return SName.regex;
|
||||
|
||||
return SName.activityDiagram;
|
||||
}
|
||||
}
|
||||
|
@ -67,14 +67,14 @@ public class CommandScale extends SingleLineCommand2<AbstractPSystem> {
|
||||
@Override
|
||||
protected CommandExecutionResult executeArg(AbstractPSystem diagram, LineLocation location, RegexResult arg) {
|
||||
double scale = Double.parseDouble(arg.get("SCALE", 0));
|
||||
if (scale == 0) {
|
||||
if (scale == 0)
|
||||
return CommandExecutionResult.error("Scale cannot be zero");
|
||||
}
|
||||
|
||||
if (arg.get("DIV", 0) != null) {
|
||||
final double div = Double.parseDouble(arg.get("DIV", 0));
|
||||
if (div == 0) {
|
||||
if (div == 0)
|
||||
return CommandExecutionResult.error("Scale cannot be zero");
|
||||
}
|
||||
|
||||
scale /= div;
|
||||
}
|
||||
diagram.setScale(new ScaleSimple(scale));
|
||||
|
@ -39,7 +39,7 @@ import net.sourceforge.plantuml.utils.StartUtils;
|
||||
|
||||
public enum DiagramType {
|
||||
UML, BPM, DITAA, DOT, PROJECT, JCCKIT, SALT, FLOW, CREOLE, JUNGLE, CUTE, MATH, LATEX, DEFINITION, GANTT, NW,
|
||||
MINDMAP, WBS, WIRE, JSON, GIT, BOARD, YAML, HCL, EBNF, UNKNOWN;
|
||||
MINDMAP, WBS, WIRE, JSON, GIT, BOARD, YAML, HCL, EBNF, REGEX, UNKNOWN;
|
||||
|
||||
static public DiagramType getTypeFromArobaseStart(String s) {
|
||||
s = s.toLowerCase();
|
||||
@ -121,6 +121,9 @@ public enum DiagramType {
|
||||
if (StartUtils.startsWithSymbolAnd("startebnf", s))
|
||||
return EBNF;
|
||||
|
||||
if (StartUtils.startsWithSymbolAnd("startregex", s))
|
||||
return REGEX;
|
||||
|
||||
return UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
@ -84,9 +84,9 @@ public class AtomImg extends AbstractAtom implements Atom {
|
||||
public static Atom createQrcode(String flash, double scale) {
|
||||
final FlashCodeUtils utils = FlashCodeFactory.getFlashCodeUtils();
|
||||
BufferedImage im = utils.exportFlashcode(flash, Color.BLACK, Color.WHITE);
|
||||
if (im == null) {
|
||||
if (im == null)
|
||||
im = new BufferedImage(10, 10, BufferedImage.TYPE_INT_RGB);
|
||||
}
|
||||
|
||||
return new AtomImg(
|
||||
new UImage(new PixelImage(im, AffineTransformType.TYPE_NEAREST_NEIGHBOR)).scale(scale).getImage(1), 1,
|
||||
null, null);
|
||||
@ -120,38 +120,38 @@ public class AtomImg extends AbstractAtom implements Atom {
|
||||
try {
|
||||
// Check if valid URL
|
||||
if (src.startsWith("http:") || src.startsWith("https:")) {
|
||||
if (src.endsWith(".svg"))
|
||||
if (src.endsWith(".svg"))
|
||||
return buildSvgFromUrl(src, fc, SURL.create(src), scale, url);
|
||||
|
||||
|
||||
return buildRasterFromUrl(src, fc, SURL.create(src), scale, url);
|
||||
}
|
||||
final SFile f = FileSystem.getInstance().getFile(src);
|
||||
if (f.exists() == false) {
|
||||
if (SecurityUtils.getSecurityProfile() == SecurityProfile.UNSECURE)
|
||||
if (SecurityUtils.getSecurityProfile() == SecurityProfile.UNSECURE)
|
||||
return AtomTextUtils.createLegacy("(File not found: " + f.getPrintablePath() + ")", fc);
|
||||
|
||||
|
||||
return AtomTextUtils.createLegacy("(Cannot decode)", fc);
|
||||
}
|
||||
if (f.getName().endsWith(".svg")) {
|
||||
final String tmp = FileUtils.readSvg(f);
|
||||
if (tmp == null)
|
||||
if (tmp == null)
|
||||
return AtomTextUtils.createLegacy("(Cannot decode)", fc);
|
||||
|
||||
|
||||
return new AtomImgSvg(new TileImageSvg(tmp, scale));
|
||||
}
|
||||
final BufferedImage read = f.readRasterImageFromFile();
|
||||
if (read == null) {
|
||||
if (SecurityUtils.getSecurityProfile() == SecurityProfile.UNSECURE)
|
||||
if (SecurityUtils.getSecurityProfile() == SecurityProfile.UNSECURE)
|
||||
return AtomTextUtils.createLegacy("(Cannot decode: " + f.getPrintablePath() + ")", fc);
|
||||
|
||||
|
||||
return AtomTextUtils.createLegacy("(Cannot decode)", fc);
|
||||
}
|
||||
return new AtomImg(f.readRasterImageFromFile(), scale, url, src);
|
||||
} catch (IOException e) {
|
||||
Logme.error(e);
|
||||
if (SecurityUtils.getSecurityProfile() == SecurityProfile.UNSECURE)
|
||||
if (SecurityUtils.getSecurityProfile() == SecurityProfile.UNSECURE)
|
||||
return AtomTextUtils.createLegacy("ERROR " + e.toString(), fc);
|
||||
|
||||
|
||||
return AtomTextUtils.createLegacy("ERROR", fc);
|
||||
}
|
||||
}
|
||||
@ -159,33 +159,33 @@ public class AtomImg extends AbstractAtom implements Atom {
|
||||
private static Atom buildRasterFromData(String source, final FontConfiguration fc, final byte[] data, double scale,
|
||||
Url url) throws IOException {
|
||||
final BufferedImage read = SImageIO.read(data);
|
||||
if (read == null) {
|
||||
if (read == null)
|
||||
return AtomTextUtils.createLegacy("(Cannot decode: " + source + ")", fc);
|
||||
}
|
||||
|
||||
return new AtomImg(read, scale, url, null);
|
||||
}
|
||||
|
||||
private static Atom buildRasterFromUrl(String text, final FontConfiguration fc, SURL source, double scale, Url url)
|
||||
throws IOException {
|
||||
if (source == null) {
|
||||
if (source == null)
|
||||
return AtomTextUtils.createLegacy("(Cannot decode: " + text + ")", fc);
|
||||
}
|
||||
|
||||
final BufferedImage read = source.readRasterImageFromURL();
|
||||
if (read == null) {
|
||||
if (read == null)
|
||||
return AtomTextUtils.createLegacy("(Cannot decode: " + text + ")", fc);
|
||||
}
|
||||
|
||||
return new AtomImg(read, scale, url, "http");
|
||||
}
|
||||
|
||||
private static Atom buildSvgFromUrl(String text, final FontConfiguration fc, SURL source, double scale, Url url)
|
||||
throws IOException {
|
||||
if (source == null) {
|
||||
if (source == null)
|
||||
return AtomTextUtils.createLegacy("(Cannot decode SVG: " + text + ")", fc);
|
||||
}
|
||||
|
||||
final byte[] read = source.getBytes();
|
||||
if (read == null) {
|
||||
if (read == null)
|
||||
return AtomTextUtils.createLegacy("(Cannot decode SVG: " + text + ")", fc);
|
||||
}
|
||||
|
||||
return new AtomImgSvg(new TileImageSvg(new String(read, UTF_8), scale));
|
||||
}
|
||||
|
||||
@ -200,14 +200,15 @@ public class AtomImg extends AbstractAtom implements Atom {
|
||||
}
|
||||
|
||||
public void drawU(UGraphic ug) {
|
||||
if (url != null) {
|
||||
if (url != null)
|
||||
ug.startUrl(url);
|
||||
}
|
||||
|
||||
ug.draw(new UImage(new PixelImage(image, AffineTransformType.TYPE_BILINEAR)).withRawFileName(rawFileName)
|
||||
.scale(scale));
|
||||
if (url != null) {
|
||||
|
||||
if (url != null)
|
||||
ug.closeUrl();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -35,7 +35,7 @@
|
||||
*/
|
||||
package net.sourceforge.plantuml.ebnf;
|
||||
|
||||
interface CharIterator {
|
||||
public interface CharIterator {
|
||||
char peek(int ahead);
|
||||
|
||||
void next();
|
||||
|
@ -37,7 +37,7 @@ package net.sourceforge.plantuml.ebnf;
|
||||
|
||||
import net.sourceforge.plantuml.command.BlocLines;
|
||||
|
||||
class CharIteratorImpl implements CharIterator {
|
||||
public class CharIteratorImpl implements CharIterator {
|
||||
|
||||
final private BlocLines data;
|
||||
private int line = 0;
|
||||
|
@ -42,6 +42,7 @@ import net.sourceforge.plantuml.awt.geom.XDimension2D;
|
||||
import net.sourceforge.plantuml.graphic.StringBounder;
|
||||
import net.sourceforge.plantuml.ugraphic.UGraphic;
|
||||
import net.sourceforge.plantuml.ugraphic.UTranslate;
|
||||
import net.sourceforge.plantuml.ugraphic.color.HColor;
|
||||
|
||||
public class ETileAlternation extends ETile {
|
||||
|
||||
|
@ -68,6 +68,10 @@ public class ETileBox extends ETile {
|
||||
private String commentAbove;
|
||||
private String commentBelow;
|
||||
|
||||
public ETileBox mergeWith(ETileBox other) {
|
||||
return new ETileBox(this.value + other.value, symbol, fc, style, colorSet, skinParam);
|
||||
}
|
||||
|
||||
public ETileBox(String value, Symbol symbol, FontConfiguration fc, Style style, HColorSet colorSet,
|
||||
ISkinParam skinParam) {
|
||||
this.symbol = symbol;
|
||||
@ -225,4 +229,8 @@ public class ETileBox extends ETile {
|
||||
return value;
|
||||
}
|
||||
|
||||
public final Symbol getSymbol() {
|
||||
return symbol;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -52,6 +52,10 @@ public class ETileConcatenation extends ETile {
|
||||
tiles.add(0, tile);
|
||||
}
|
||||
|
||||
public void overideFirst(ETile tile) {
|
||||
tiles.set(0, tile);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawU(UGraphic ug) {
|
||||
final StringBounder stringBounder = ug.getStringBounder();
|
||||
@ -104,4 +108,8 @@ public class ETileConcatenation extends ETile {
|
||||
return width;
|
||||
}
|
||||
|
||||
public ETile getFirst() {
|
||||
return tiles.get(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -39,15 +39,11 @@ import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import net.sourceforge.plantuml.Direction;
|
||||
import net.sourceforge.plantuml.ISkinParam;
|
||||
import net.sourceforge.plantuml.activitydiagram3.ftile.vcompact.FloatingNote;
|
||||
import net.sourceforge.plantuml.awt.geom.XDimension2D;
|
||||
import net.sourceforge.plantuml.awt.geom.XPoint2D;
|
||||
import net.sourceforge.plantuml.cucadiagram.Display;
|
||||
import net.sourceforge.plantuml.graphic.FontConfiguration;
|
||||
import net.sourceforge.plantuml.graphic.HorizontalAlignment;
|
||||
import net.sourceforge.plantuml.graphic.StringBounder;
|
||||
import net.sourceforge.plantuml.graphic.TextBlock;
|
||||
import net.sourceforge.plantuml.graphic.TextBlockUtils;
|
||||
import net.sourceforge.plantuml.style.PName;
|
||||
|
@ -85,9 +85,9 @@ public class PSystemWelcome extends PlainDiagram {
|
||||
}
|
||||
|
||||
public TextBlockBackcolored getGraphicStrings() {
|
||||
if (position != null) {
|
||||
if (position != null)
|
||||
return GraphicStrings.createBlackOnWhite(strings, PSystemVersion.getPlantumlImage(), position);
|
||||
}
|
||||
|
||||
return GraphicStrings.createBlackOnWhite(strings);
|
||||
}
|
||||
|
||||
|
@ -78,7 +78,7 @@ public class HclDiagramFactory extends PSystemAbstractFactory {
|
||||
} catch (Exception e) {
|
||||
Logme.error(e);
|
||||
}
|
||||
final JsonDiagram result = new JsonDiagram(source, UmlDiagramType.HCL, data, highlighted);
|
||||
final JsonDiagram result = new JsonDiagram(source, UmlDiagramType.HCL, data, highlighted, styleExtractor);
|
||||
// if (styleExtractor != null) {
|
||||
// styleExtractor.applyStyles(result.getSkinParam());
|
||||
// final String title = styleExtractor.getTitle();
|
||||
|
@ -49,6 +49,7 @@ import net.sourceforge.plantuml.json.JsonObject;
|
||||
import net.sourceforge.plantuml.json.JsonString;
|
||||
import net.sourceforge.plantuml.json.JsonValue;
|
||||
|
||||
// https://github.com/hashicorp/hcl
|
||||
public class HclParser {
|
||||
|
||||
private final List<HclTerm> terms = new ArrayList<HclTerm>();
|
||||
|
@ -39,6 +39,7 @@ import java.io.OutputStream;
|
||||
import java.util.List;
|
||||
|
||||
import net.sourceforge.plantuml.FileFormatOption;
|
||||
import net.sourceforge.plantuml.ScaleSimple;
|
||||
import net.sourceforge.plantuml.TitledDiagram;
|
||||
import net.sourceforge.plantuml.UmlDiagramType;
|
||||
import net.sourceforge.plantuml.awt.geom.XDimension2D;
|
||||
@ -60,14 +61,18 @@ import net.sourceforge.plantuml.ugraphic.MinMax;
|
||||
import net.sourceforge.plantuml.ugraphic.UFont;
|
||||
import net.sourceforge.plantuml.ugraphic.UGraphic;
|
||||
import net.sourceforge.plantuml.ugraphic.color.HColor;
|
||||
import net.sourceforge.plantuml.ugraphic.hand.UGraphicHandwritten;
|
||||
|
||||
public class JsonDiagram extends TitledDiagram {
|
||||
|
||||
private final JsonValue root;
|
||||
private final List<String> highlighted;
|
||||
private final boolean handwritten;
|
||||
|
||||
public JsonDiagram(UmlSource source, UmlDiagramType type, JsonValue json, List<String> highlighted) {
|
||||
public JsonDiagram(UmlSource source, UmlDiagramType type, JsonValue json, List<String> highlighted,
|
||||
StyleExtractor styleExtractor) {
|
||||
super(source, type, null);
|
||||
this.handwritten = styleExtractor.isHandwritten();
|
||||
if (json != null && (json.isString() || json.isBoolean() || json.isNumber())) {
|
||||
this.root = new JsonArray();
|
||||
((JsonArray) this.root).add(json);
|
||||
@ -75,6 +80,7 @@ public class JsonDiagram extends TitledDiagram {
|
||||
this.root = json;
|
||||
}
|
||||
this.highlighted = highlighted;
|
||||
setScale(new ScaleSimple(styleExtractor.getScale()));
|
||||
}
|
||||
|
||||
public DiagramDescription getDescription() {
|
||||
@ -95,6 +101,8 @@ public class JsonDiagram extends TitledDiagram {
|
||||
}
|
||||
|
||||
private void drawInternal(UGraphic ug) {
|
||||
if (handwritten)
|
||||
ug = new UGraphicHandwritten(ug);
|
||||
if (root == null) {
|
||||
final Display display = Display
|
||||
.getWithNewlines("Your data does not sound like " + getUmlDiagramType() + " data");
|
||||
|
@ -85,7 +85,7 @@ public class JsonDiagramFactory extends PSystemAbstractFactory {
|
||||
} catch (ParseException e) {
|
||||
json = null;
|
||||
}
|
||||
final JsonDiagram result = new JsonDiagram(source, UmlDiagramType.JSON, json, highlighted);
|
||||
final JsonDiagram result = new JsonDiagram(source, UmlDiagramType.JSON, json, highlighted, styleExtractor);
|
||||
if (styleExtractor != null)
|
||||
styleExtractor.applyStyles(result.getSkinParam());
|
||||
|
||||
|
@ -51,27 +51,42 @@ public class StyleExtractor {
|
||||
private final List<String> list = new ArrayList<>();
|
||||
private final List<StringLocated> style = new ArrayList<>();
|
||||
private String title = null;
|
||||
private boolean handwritten = false;
|
||||
private double scale = 1;
|
||||
|
||||
public StyleExtractor(Iterator<StringLocated> data) {
|
||||
while (data.hasNext()) {
|
||||
StringLocated line = data.next();
|
||||
if (startStyle(line)) {
|
||||
final String s = line.getString().trim();
|
||||
if (s.length() == 0)
|
||||
continue;
|
||||
if (startStyle(s)) {
|
||||
while (data.hasNext()) {
|
||||
style.add(line);
|
||||
if (endStyle(line))
|
||||
break;
|
||||
line = data.next();
|
||||
}
|
||||
} else if (line.getString().trim().startsWith("!assume ")) {
|
||||
} else if (list.size() >= 1 && s.startsWith("!assume ")) {
|
||||
// Ignore
|
||||
} else if (line.getString().trim().startsWith("!pragma ")) {
|
||||
} else if (list.size() >= 1 && s.startsWith("!pragma ")) {
|
||||
// Ignore
|
||||
} else if (line.getString().trim().startsWith("hide ")) {
|
||||
} else if (list.size() >= 1 && s.startsWith("hide ")) {
|
||||
// Ignore
|
||||
} else if (line.getString().trim().startsWith("title ")) {
|
||||
this.title = line.getString().trim().substring("title ".length()).trim();
|
||||
} else if (line.getString().trim().startsWith("skinparam ")) {
|
||||
if (line.getString().trim().contains("{")) {
|
||||
} else if (list.size() >= 1 && s.startsWith("scale ")) {
|
||||
// Ignore
|
||||
try {
|
||||
final double v = Double.parseDouble(s.replaceAll("\\D", ""));
|
||||
if (v > 0)
|
||||
scale = v;
|
||||
} catch (Exception e) {
|
||||
}
|
||||
} else if (list.size() >= 1 && s.startsWith("title ")) {
|
||||
this.title = s.substring("title ".length()).trim();
|
||||
} else if (list.size() >= 1 && s.startsWith("skinparam ")) {
|
||||
if (s.contains("handwritten") && s.contains("true"))
|
||||
handwritten = true;
|
||||
if (s.contains("{")) {
|
||||
while (data.hasNext()) {
|
||||
if (line.getString().trim().equals("}"))
|
||||
break;
|
||||
@ -82,10 +97,11 @@ public class StyleExtractor {
|
||||
list.add(line.getString());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private boolean startStyle(StringLocated line) {
|
||||
return line.getString().trim().equals("<style>");
|
||||
private boolean startStyle(String line) {
|
||||
return line.equals("<style>");
|
||||
}
|
||||
|
||||
private boolean endStyle(StringLocated line) {
|
||||
@ -110,4 +126,12 @@ public class StyleExtractor {
|
||||
return title;
|
||||
}
|
||||
|
||||
public final boolean isHandwritten() {
|
||||
return handwritten;
|
||||
}
|
||||
|
||||
public double getScale() {
|
||||
return scale;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,72 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* (C) Copyright 2009-2023, 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.regex;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import net.sourceforge.plantuml.LineLocation;
|
||||
import net.sourceforge.plantuml.StringLocated;
|
||||
import net.sourceforge.plantuml.command.BlocLines;
|
||||
import net.sourceforge.plantuml.command.CommandExecutionResult;
|
||||
import net.sourceforge.plantuml.command.SingleLineCommand2;
|
||||
import net.sourceforge.plantuml.command.regex.IRegex;
|
||||
import net.sourceforge.plantuml.command.regex.RegexConcat;
|
||||
import net.sourceforge.plantuml.command.regex.RegexLeaf;
|
||||
import net.sourceforge.plantuml.command.regex.RegexResult;
|
||||
import net.sourceforge.plantuml.ugraphic.color.NoSuchColorException;
|
||||
|
||||
public class CommandRegexfSingleLine extends SingleLineCommand2<PSystemRegex> {
|
||||
|
||||
public CommandRegexfSingleLine() {
|
||||
super(true, getRegexConcat());
|
||||
}
|
||||
|
||||
static IRegex getRegexConcat() {
|
||||
return RegexConcat.build(CommandRegexfSingleLine.class.getName(), RegexLeaf.start(), //
|
||||
RegexLeaf.spaceZeroOrMore(), //
|
||||
new RegexLeaf("LINE", "(.*)"), //
|
||||
RegexLeaf.end());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CommandExecutionResult executeArg(PSystemRegex diagram, LineLocation location, RegexResult arg)
|
||||
throws NoSuchColorException {
|
||||
final String line = arg.get("LINE", 0);
|
||||
|
||||
final StringLocated string = new StringLocated(line, location);
|
||||
return diagram.addBlocLines(BlocLines.from(Collections.singletonList(string)));
|
||||
}
|
||||
}
|
284
src/net/sourceforge/plantuml/regex/PSystemRegex.java
Normal file
284
src/net/sourceforge/plantuml/regex/PSystemRegex.java
Normal file
@ -0,0 +1,284 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* (C) Copyright 2009-2023, 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.regex;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Deque;
|
||||
import java.util.List;
|
||||
|
||||
import net.sourceforge.plantuml.FileFormatOption;
|
||||
import net.sourceforge.plantuml.ISkinParam;
|
||||
import net.sourceforge.plantuml.TitledDiagram;
|
||||
import net.sourceforge.plantuml.UmlDiagramType;
|
||||
import net.sourceforge.plantuml.awt.geom.XDimension2D;
|
||||
import net.sourceforge.plantuml.command.BlocLines;
|
||||
import net.sourceforge.plantuml.command.CommandExecutionResult;
|
||||
import net.sourceforge.plantuml.core.DiagramDescription;
|
||||
import net.sourceforge.plantuml.core.ImageData;
|
||||
import net.sourceforge.plantuml.core.UmlSource;
|
||||
import net.sourceforge.plantuml.ebnf.CharIterator;
|
||||
import net.sourceforge.plantuml.ebnf.CharIteratorImpl;
|
||||
import net.sourceforge.plantuml.ebnf.ETile;
|
||||
import net.sourceforge.plantuml.ebnf.ETileAlternation;
|
||||
import net.sourceforge.plantuml.ebnf.ETileBox;
|
||||
import net.sourceforge.plantuml.ebnf.ETileConcatenation;
|
||||
import net.sourceforge.plantuml.ebnf.ETileOneOrMore;
|
||||
import net.sourceforge.plantuml.ebnf.ETileOptional;
|
||||
import net.sourceforge.plantuml.ebnf.ETileZeroOrMore;
|
||||
import net.sourceforge.plantuml.ebnf.Symbol;
|
||||
import net.sourceforge.plantuml.ebnf.TextBlockable;
|
||||
import net.sourceforge.plantuml.graphic.AbstractTextBlock;
|
||||
import net.sourceforge.plantuml.graphic.FontConfiguration;
|
||||
import net.sourceforge.plantuml.graphic.StringBounder;
|
||||
import net.sourceforge.plantuml.graphic.TextBlock;
|
||||
import net.sourceforge.plantuml.graphic.TextBlockUtils;
|
||||
import net.sourceforge.plantuml.style.PName;
|
||||
import net.sourceforge.plantuml.style.Style;
|
||||
import net.sourceforge.plantuml.svek.TextBlockBackcolored;
|
||||
import net.sourceforge.plantuml.ugraphic.UGraphic;
|
||||
import net.sourceforge.plantuml.ugraphic.color.HColor;
|
||||
import net.sourceforge.plantuml.ugraphic.color.HColorSet;
|
||||
import net.sourceforge.plantuml.ugraphic.color.HColors;
|
||||
|
||||
public class PSystemRegex extends TitledDiagram {
|
||||
|
||||
private final List<TextBlockable> expressions = new ArrayList<>();
|
||||
|
||||
public PSystemRegex(UmlSource source) {
|
||||
super(source, UmlDiagramType.REGEX, null);
|
||||
final ISkinParam skinParam = getSkinParam();
|
||||
this.style = ETile.getStyleSignature().getMergedStyle(skinParam.getCurrentStyleBuilder());
|
||||
this.fontConfiguration = style.getFontConfiguration(skinParam.getIHtmlColorSet());
|
||||
this.colorSet = skinParam.getIHtmlColorSet();
|
||||
this.lineColor = style.value(PName.LineColor).asColor(skinParam.getIHtmlColorSet());
|
||||
}
|
||||
|
||||
public DiagramDescription getDescription() {
|
||||
return new DiagramDescription("(Regular Expression)");
|
||||
}
|
||||
|
||||
private final Deque<ETile> stack = new ArrayDeque<>();
|
||||
private final FontConfiguration fontConfiguration;
|
||||
private final Style style;
|
||||
private final HColorSet colorSet;
|
||||
private final HColor lineColor;
|
||||
|
||||
// public CommandExecutionResult addBlocLines(BlocLines blines, String commentAbove, String commentBelow) {
|
||||
// final boolean isCompact = getPragma().isDefine("compact");
|
||||
// final CharIterator it = new CharIteratorImpl(blines);
|
||||
// final EbnfExpression tmp1 = EbnfExpression.create(it, isCompact, commentAbove, commentBelow);
|
||||
// if (tmp1.isEmpty())
|
||||
// return CommandExecutionResult.error("Unparsable expression");
|
||||
// expressions.add(tmp1);
|
||||
// return CommandExecutionResult.ok();
|
||||
//
|
||||
// }
|
||||
//
|
||||
// public CommandExecutionResult addNote(final Display note, Colors colors) {
|
||||
// expressions.add(new TextBlockable() {
|
||||
// @Override
|
||||
// public TextBlock getUDrawable(ISkinParam skinParam) {
|
||||
// final FloatingNote f = FloatingNote.create(note, skinParam, SName.ebnf);
|
||||
// return TextBlockUtils.withMargin(f, 0, 0, 5, 15);
|
||||
// }
|
||||
// });
|
||||
// return CommandExecutionResult.ok();
|
||||
// }
|
||||
|
||||
@Override
|
||||
protected ImageData exportDiagramNow(OutputStream os, int index, FileFormatOption fileFormatOption)
|
||||
throws IOException {
|
||||
return createImageBuilder(fileFormatOption).drawable(getTextBlock()).write(os);
|
||||
}
|
||||
|
||||
private TextBlockBackcolored getTextBlock() {
|
||||
// while (stack.size() > 1)
|
||||
// concatenation();
|
||||
final ETile peekFirst = stack.peekFirst();
|
||||
final TextBlock tb = new AbstractTextBlock() {
|
||||
|
||||
@Override
|
||||
public void drawU(UGraphic ug) {
|
||||
peekFirst.drawU(ug.apply(HColors.BLACK));
|
||||
}
|
||||
|
||||
@Override
|
||||
public XDimension2D calculateDimension(StringBounder stringBounder) {
|
||||
return peekFirst.calculateDimension(stringBounder);
|
||||
}
|
||||
};
|
||||
return TextBlockUtils.addBackcolor(tb, null);
|
||||
|
||||
}
|
||||
|
||||
public CommandExecutionResult addBlocLines(BlocLines from) {
|
||||
final CharIterator it = new CharIteratorImpl(from);
|
||||
final List<ReToken> parsed1 = RegexExpression.parse(it);
|
||||
System.err.println("parsed1=" + parsed1);
|
||||
final List<ReToken> parsed2 = addImplicitConcatenation(parsed1);
|
||||
System.err.println("parsed2=" + parsed2);
|
||||
final ShuntingYard shuntingYard = new ShuntingYard(parsed2.iterator());
|
||||
final List<ReToken> result = shuntingYard.getOuputQueue();
|
||||
System.err.println("result=" + result);
|
||||
for (ReToken token : result)
|
||||
if (token.getType() == ReTokenType.SIMPLE_CHAR)
|
||||
push(token, Symbol.TERMINAL_STRING1);
|
||||
else if (token.getType() == ReTokenType.ESCAPED_CHAR)
|
||||
push(token, Symbol.TERMINAL_STRING1);
|
||||
else if (token.getType() == ReTokenType.GROUP)
|
||||
push(token, Symbol.SPECIAL_SEQUENCE);
|
||||
else if (token.getType() == ReTokenType.CLASS)
|
||||
push(token, Symbol.LITTERAL);
|
||||
else if (token.getType() == ReTokenType.ANCHOR)
|
||||
push(token, Symbol.LITTERAL);
|
||||
else if (token.getType() == ReTokenType.CONCATENATION_IMPLICIT)
|
||||
concatenation();
|
||||
else if (token.getType() == ReTokenType.ALTERNATIVE)
|
||||
alternation();
|
||||
else if (token.getType() == ReTokenType.QUANTIFIER && token.getData().equals("*"))
|
||||
repetitionZeroOrMore(false);
|
||||
else if (token.getType() == ReTokenType.QUANTIFIER && token.getData().equals("+"))
|
||||
repetitionOneOrMore();
|
||||
else if (token.getType() == ReTokenType.QUANTIFIER && token.getData().equals("?"))
|
||||
optional();
|
||||
else
|
||||
throw new UnsupportedOperationException(token.toString());
|
||||
|
||||
return CommandExecutionResult.ok();
|
||||
}
|
||||
|
||||
private List<ReToken> addImplicitConcatenation(List<ReToken> list) {
|
||||
final List<ReToken> result = new ArrayList<>();
|
||||
for (ReToken token : list) {
|
||||
if (result.size() > 0
|
||||
&& ReTokenType.needImplicitConcatenation(result.get(result.size() - 1).getType(), token.getType()))
|
||||
result.add(new ReToken(ReTokenType.CONCATENATION_IMPLICIT, ""));
|
||||
result.add(token);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private void push(ReToken element, Symbol type) {
|
||||
// final Symbol type = Symbol.LITTERAL;
|
||||
stack.addFirst(new ETileBox(element.getData(), type, fontConfiguration, style, colorSet, getSkinParam()));
|
||||
}
|
||||
|
||||
private void repetitionZeroOrMore(boolean isCompact) {
|
||||
final ETile arg1 = stack.removeFirst();
|
||||
if (isCompact)
|
||||
stack.addFirst(new ETileZeroOrMore(arg1));
|
||||
else
|
||||
stack.addFirst(new ETileOptional(new ETileOneOrMore(arg1), getSkinParam()));
|
||||
}
|
||||
|
||||
private void optional() {
|
||||
final ETile arg1 = stack.removeFirst();
|
||||
stack.addFirst(new ETileOptional(arg1, getSkinParam()));
|
||||
}
|
||||
|
||||
private void repetitionOneOrMore() {
|
||||
final ETile arg1 = stack.removeFirst();
|
||||
stack.addFirst(new ETileOneOrMore(arg1));
|
||||
}
|
||||
|
||||
private void alternation() {
|
||||
final ETile arg1 = stack.removeFirst();
|
||||
final ETile arg2 = stack.removeFirst();
|
||||
if (arg1 instanceof ETileAlternation) {
|
||||
arg1.push(arg2);
|
||||
stack.addFirst(arg1);
|
||||
} else if (arg2 instanceof ETileAlternation) {
|
||||
arg2.push(arg1);
|
||||
stack.addFirst(arg2);
|
||||
} else {
|
||||
final ETile concat = new ETileAlternation();
|
||||
concat.push(arg1);
|
||||
concat.push(arg2);
|
||||
stack.addFirst(concat);
|
||||
}
|
||||
}
|
||||
|
||||
private void concatenation() {
|
||||
final ETile arg1 = stack.removeFirst();
|
||||
final ETile arg2 = stack.removeFirst();
|
||||
if (isBoxMergeable(arg1) && isBoxMergeable(arg2)) {
|
||||
final ETileBox box1 = (ETileBox) arg1;
|
||||
final ETileBox box2 = (ETileBox) arg2;
|
||||
stack.addFirst(box2.mergeWith(box1));
|
||||
return;
|
||||
}
|
||||
if (isConcatenation1Mergeable(arg1) && isBoxMergeable(arg2)) {
|
||||
final ETileConcatenation concat1 = (ETileConcatenation) arg1;
|
||||
final ETileBox box1 = (ETileBox) concat1.getFirst();
|
||||
final ETileBox box2 = (ETileBox) arg2;
|
||||
concat1.overideFirst(box2.mergeWith(box1));
|
||||
stack.addFirst(concat1);
|
||||
return;
|
||||
}
|
||||
if (arg1 instanceof ETileConcatenation) {
|
||||
arg1.push(arg2);
|
||||
stack.addFirst(arg1);
|
||||
} else if (arg2 instanceof ETileConcatenation) {
|
||||
arg2.push(arg1);
|
||||
stack.addFirst(arg2);
|
||||
} else {
|
||||
final ETile concat = new ETileConcatenation();
|
||||
concat.push(arg1);
|
||||
concat.push(arg2);
|
||||
stack.addFirst(concat);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isConcatenation1Mergeable(ETile tile) {
|
||||
if (tile instanceof ETileConcatenation) {
|
||||
final ETileConcatenation concat = (ETileConcatenation) tile;
|
||||
return isBoxMergeable(concat.getFirst());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isBoxMergeable(ETile tile) {
|
||||
if (tile instanceof ETileBox) {
|
||||
final ETileBox box = (ETileBox) tile;
|
||||
return box.getSymbol() == Symbol.TERMINAL_STRING1;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
69
src/net/sourceforge/plantuml/regex/PSystemRegexFactory.java
Normal file
69
src/net/sourceforge/plantuml/regex/PSystemRegexFactory.java
Normal file
@ -0,0 +1,69 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* (C) Copyright 2009-2023, 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.regex;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
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 PSystemRegexFactory extends PSystemCommandFactory {
|
||||
|
||||
public PSystemRegexFactory() {
|
||||
super(DiagramType.REGEX);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Command> createCommands() {
|
||||
|
||||
final List<Command> cmds = new ArrayList<>();
|
||||
CommonCommands.addCommonCommands1(cmds);
|
||||
cmds.add(new CommandRegexfSingleLine());
|
||||
|
||||
return cmds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PSystemRegex createEmptyDiagram(UmlSource source, Map<String, String> skinParam) {
|
||||
return new PSystemRegex(source);
|
||||
}
|
||||
|
||||
}
|
61
src/net/sourceforge/plantuml/regex/ReToken.java
Normal file
61
src/net/sourceforge/plantuml/regex/ReToken.java
Normal file
@ -0,0 +1,61 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* (C) Copyright 2009-2020, 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.regex;
|
||||
|
||||
public class ReToken {
|
||||
|
||||
private final ReTokenType type;
|
||||
private final String data;
|
||||
|
||||
public ReToken(ReTokenType type, String data) {
|
||||
this.type = type;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return type.toString() + "[" + data + "]";
|
||||
}
|
||||
|
||||
public final ReTokenType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public final String getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
}
|
65
src/net/sourceforge/plantuml/regex/ReTokenType.java
Normal file
65
src/net/sourceforge/plantuml/regex/ReTokenType.java
Normal file
@ -0,0 +1,65 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* (C) Copyright 2009-2020, 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.regex;
|
||||
|
||||
public enum ReTokenType {
|
||||
|
||||
SIMPLE_CHAR, //
|
||||
ESCAPED_CHAR, //
|
||||
CLASS, //
|
||||
QUANTIFIER, //
|
||||
ANCHOR, //
|
||||
GROUP, //
|
||||
ALTERNATIVE, //
|
||||
PARENTHESIS_OPEN, //
|
||||
PARENTHESIS_CLOSE, //
|
||||
CONCATENATION_IMPLICIT;
|
||||
|
||||
static public boolean needImplicitConcatenation(ReTokenType token1, ReTokenType token2) {
|
||||
if (token1 == ALTERNATIVE)
|
||||
return false;
|
||||
if (token2 == ALTERNATIVE)
|
||||
return false;
|
||||
if (token2 == QUANTIFIER)
|
||||
return false;
|
||||
if (token1 == PARENTHESIS_OPEN)
|
||||
return false;
|
||||
if (token2 == PARENTHESIS_CLOSE)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
223
src/net/sourceforge/plantuml/regex/RegexExpression.java
Normal file
223
src/net/sourceforge/plantuml/regex/RegexExpression.java
Normal file
@ -0,0 +1,223 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* (C) Copyright 2009-2020, 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.regex;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import net.sourceforge.plantuml.ebnf.CharIterator;
|
||||
|
||||
public class RegexExpression {
|
||||
|
||||
public static List<ReToken> parse(CharIterator it) {
|
||||
final List<ReToken> result = new ArrayList<>();
|
||||
while (true) {
|
||||
final char current = it.peek(0);
|
||||
if (current == '\0')
|
||||
break;
|
||||
// System.err.println("current=" + current);
|
||||
if (isStartAnchor(it)) {
|
||||
final String s = readAnchor(it);
|
||||
result.add(new ReToken(ReTokenType.ANCHOR, s));
|
||||
} else if (isEscapedChar(it)) {
|
||||
result.add(new ReToken(ReTokenType.ESCAPED_CHAR, "" + it.peek(1)));
|
||||
it.next();
|
||||
it.next();
|
||||
} else if (current == '|') {
|
||||
result.add(new ReToken(ReTokenType.ALTERNATIVE, "|"));
|
||||
it.next();
|
||||
} else if (current == '[') {
|
||||
final String s = readGroup(it);
|
||||
result.add(new ReToken(ReTokenType.GROUP, s));
|
||||
} else if (isStartOpenParenthesis(it)) {
|
||||
final String s = readOpenParenthesis(it);
|
||||
result.add(new ReToken(ReTokenType.PARENTHESIS_OPEN, s));
|
||||
} else if (current == ')') {
|
||||
result.add(new ReToken(ReTokenType.PARENTHESIS_CLOSE, ")"));
|
||||
it.next();
|
||||
} else if (isStartQuantifier(it)) {
|
||||
final String s = readQuantifier(it);
|
||||
result.add(new ReToken(ReTokenType.QUANTIFIER, s));
|
||||
} else if (isStartClass(it)) {
|
||||
final String s = readClass(it);
|
||||
result.add(new ReToken(ReTokenType.CLASS, s));
|
||||
} else if (isSimpleLetter(current)) {
|
||||
result.add(new ReToken(ReTokenType.SIMPLE_CHAR, "" + current));
|
||||
it.next();
|
||||
} else {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
// System.err.println("result=" + result);
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
private static boolean isStartOpenParenthesis(CharIterator it) {
|
||||
final char current0 = it.peek(0);
|
||||
if (current0 == '(')
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
private static String readOpenParenthesis(CharIterator it) {
|
||||
final char current0 = it.peek(0);
|
||||
it.next();
|
||||
final StringBuilder result = new StringBuilder();
|
||||
result.append(current0);
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
private static boolean isStartQuantifier(CharIterator it) {
|
||||
final char current0 = it.peek(0);
|
||||
if (current0 == '*' || current0 == '+' || current0 == '?' || current0 == '{')
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
private static String readQuantifier(CharIterator it) {
|
||||
final char current0 = it.peek(0);
|
||||
it.next();
|
||||
final StringBuilder result = new StringBuilder();
|
||||
result.append(current0);
|
||||
if (current0 == '{')
|
||||
while (it.peek(0) != 0) {
|
||||
final char ch = it.peek(0);
|
||||
result.append(ch);
|
||||
it.next();
|
||||
if (ch == '}')
|
||||
break;
|
||||
}
|
||||
if (it.peek(0) == '?') {
|
||||
result.append('?');
|
||||
it.next();
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
private static boolean isEscapedChar(CharIterator it) {
|
||||
final char current0 = it.peek(0);
|
||||
if (current0 == '\\') {
|
||||
final char current1 = it.peek(1);
|
||||
if (current1 == '.' || current1 == '*' || current1 == '\\' || current1 == '?' || current1 == '^'
|
||||
|| current1 == '$' || current1 == '|' || current1 == '(' || current1 == ')' || current1 == '['
|
||||
|| current1 == ']' || current1 == '{' || current1 == '}')
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static String readGroup(CharIterator it) {
|
||||
final char current0 = it.peek(0);
|
||||
if (current0 != '[')
|
||||
throw new IllegalStateException();
|
||||
it.next();
|
||||
final StringBuilder result = new StringBuilder();
|
||||
while (it.peek(0) != 0) {
|
||||
char ch = it.peek(0);
|
||||
it.next();
|
||||
if (ch == ']')
|
||||
break;
|
||||
result.append(ch);
|
||||
if (ch == '\\') {
|
||||
ch = it.peek(0);
|
||||
it.next();
|
||||
result.append(ch);
|
||||
}
|
||||
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
private static String readClass(CharIterator it) {
|
||||
final char current0 = it.peek(0);
|
||||
if (current0 == '.') {
|
||||
it.next();
|
||||
return "" + current0;
|
||||
}
|
||||
if (current0 == '\\') {
|
||||
it.next();
|
||||
final String result = "" + current0 + it.peek(0);
|
||||
it.next();
|
||||
return result;
|
||||
}
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
private static boolean isStartClass(CharIterator it) {
|
||||
final char current0 = it.peek(0);
|
||||
if (current0 == '.')
|
||||
return true;
|
||||
if (current0 == '\\')
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean isSimpleLetter(char ch) {
|
||||
if (ch == '\\' || ch == '.')
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean isStartAnchor(CharIterator it) {
|
||||
final char current0 = it.peek(0);
|
||||
if (current0 == '^' || current0 == '$')
|
||||
return true;
|
||||
if (current0 == '\\') {
|
||||
final char current1 = it.peek(1);
|
||||
if (current1 == 'A' || current1 == 'Z' || current1 == 'z' || current1 == 'G' || current1 == 'b'
|
||||
|| current1 == 'B')
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static String readAnchor(CharIterator it) {
|
||||
final char current0 = it.peek(0);
|
||||
if (current0 == '^' || current0 == '$') {
|
||||
it.next();
|
||||
return "" + current0;
|
||||
}
|
||||
if (current0 == '\\') {
|
||||
it.next();
|
||||
final String result = "" + current0 + it.peek(0);
|
||||
it.next();
|
||||
return result;
|
||||
}
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
}
|
108
src/net/sourceforge/plantuml/regex/ShuntingYard.java
Normal file
108
src/net/sourceforge/plantuml/regex/ShuntingYard.java
Normal file
@ -0,0 +1,108 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* (C) Copyright 2009-2020, 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.regex;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Deque;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
public class ShuntingYard {
|
||||
|
||||
final private List<ReToken> ouputQueue = new ArrayList<>();
|
||||
final private Deque<ReToken> operatorStack = new ArrayDeque<>();
|
||||
|
||||
public ShuntingYard(Iterator<ReToken> it) {
|
||||
while (it.hasNext()) {
|
||||
final ReToken token = it.next();
|
||||
// System.err.println("token=" + token);
|
||||
// System.err.println("ouputQueue=" + ouputQueue);
|
||||
// System.err.println("operatorStack=" + operatorStack);
|
||||
if (token.getType() == ReTokenType.SIMPLE_CHAR) {
|
||||
ouputQueue.add(token);
|
||||
} else if (token.getType() == ReTokenType.ESCAPED_CHAR) {
|
||||
ouputQueue.add(token);
|
||||
} else if (token.getType() == ReTokenType.GROUP) {
|
||||
ouputQueue.add(token);
|
||||
} else if (token.getType() == ReTokenType.CLASS) {
|
||||
ouputQueue.add(token);
|
||||
} else if (token.getType() == ReTokenType.ANCHOR) {
|
||||
ouputQueue.add(token);
|
||||
} else if (token.getType() == ReTokenType.QUANTIFIER) {
|
||||
ouputQueue.add(token);
|
||||
} else if (token.getType() == ReTokenType.CONCATENATION_IMPLICIT) {
|
||||
// push it onto the operator stack.
|
||||
operatorStack.addFirst(token);
|
||||
} else if (token.getType() == ReTokenType.ALTERNATIVE) {
|
||||
while (thereIsAConcatenationAtTheTopOfTheOperatorStack())
|
||||
ouputQueue.add(operatorStack.removeFirst());
|
||||
// push it onto the operator stack.
|
||||
operatorStack.addFirst(token);
|
||||
} else if (token.getType() == ReTokenType.PARENTHESIS_OPEN) {
|
||||
operatorStack.addFirst(token);
|
||||
} else if (token.getType() == ReTokenType.PARENTHESIS_CLOSE) {
|
||||
while (operatorStack.peekFirst() != null
|
||||
&& operatorStack.peekFirst().getType() != ReTokenType.PARENTHESIS_OPEN)
|
||||
ouputQueue.add(operatorStack.removeFirst());
|
||||
final ReToken first = operatorStack.removeFirst();
|
||||
// ouputQueue.add(first);
|
||||
|
||||
} else {
|
||||
throw new UnsupportedOperationException(token.toString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
while (operatorStack.isEmpty() == false) {
|
||||
final ReToken token = operatorStack.removeFirst();
|
||||
ouputQueue.add(token);
|
||||
}
|
||||
|
||||
// System.err.println("ouputQueue=" + ouputQueue);
|
||||
}
|
||||
|
||||
private boolean thereIsAConcatenationAtTheTopOfTheOperatorStack() {
|
||||
final ReToken top = operatorStack.peekFirst();
|
||||
return top != null && top.getType() == ReTokenType.CONCATENATION_IMPLICIT;
|
||||
}
|
||||
|
||||
public final List<ReToken> getOuputQueue() {
|
||||
return Collections.unmodifiableList(ouputQueue);
|
||||
}
|
||||
|
||||
}
|
@ -115,6 +115,7 @@ public enum SName {
|
||||
rectangle, //
|
||||
reference, //
|
||||
referenceHeader, //
|
||||
regex, //
|
||||
requirement, //
|
||||
root, //
|
||||
rootNode, //
|
||||
|
@ -260,11 +260,14 @@ public class SvgGraphics {
|
||||
private static String getData(final String name) {
|
||||
try {
|
||||
final InputStream is = SvgGraphics.class.getResourceAsStream("/svg/" + name);
|
||||
return FileUtils.readText(is);
|
||||
if (is == null)
|
||||
Log.error("Cannot retrieve " + name);
|
||||
else
|
||||
return FileUtils.readText(is);
|
||||
} catch (IOException e) {
|
||||
Logme.error(e);
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Element getPathHover(String hover) {
|
||||
|
@ -81,7 +81,7 @@ public class Version {
|
||||
}
|
||||
|
||||
public static int beta() {
|
||||
final int beta = 0;
|
||||
final int beta = 1;
|
||||
return beta;
|
||||
}
|
||||
|
||||
|
@ -42,6 +42,11 @@ import net.sourceforge.plantuml.command.regex.IRegex;
|
||||
import net.sourceforge.plantuml.command.regex.RegexConcat;
|
||||
import net.sourceforge.plantuml.command.regex.RegexLeaf;
|
||||
import net.sourceforge.plantuml.command.regex.RegexResult;
|
||||
import net.sourceforge.plantuml.cucadiagram.Stereotype;
|
||||
import net.sourceforge.plantuml.graphic.color.ColorParser;
|
||||
import net.sourceforge.plantuml.graphic.color.ColorType;
|
||||
import net.sourceforge.plantuml.graphic.color.Colors;
|
||||
import net.sourceforge.plantuml.ugraphic.color.NoSuchColorException;
|
||||
|
||||
public class CommandWBSLink extends SingleLineCommand2<WBSDiagram> {
|
||||
|
||||
@ -53,19 +58,38 @@ public class CommandWBSLink extends SingleLineCommand2<WBSDiagram> {
|
||||
return RegexConcat.build(CommandWBSLink.class.getName(), RegexLeaf.start(), //
|
||||
new RegexLeaf("CODE1", "([%pLN_]+)"), //
|
||||
RegexLeaf.spaceZeroOrMore(), //
|
||||
new RegexLeaf("LINK", "-+\\>"), //
|
||||
new RegexLeaf("LINK", "[.-]+\\>"), //
|
||||
RegexLeaf.spaceZeroOrMore(), //
|
||||
new RegexLeaf("CODE2", "([%pLN_]+)"), //
|
||||
RegexLeaf.spaceZeroOrMore(), //
|
||||
new RegexLeaf("MESSAGE", "(?::[%s]*(.*))?"), RegexLeaf.end());
|
||||
color().getRegex(), //
|
||||
RegexLeaf.spaceZeroOrMore(), //
|
||||
new RegexLeaf("STEREOTYPE", "(\\<\\<.*\\>\\>)?"), //
|
||||
RegexLeaf.spaceZeroOrMore(), //
|
||||
new RegexLeaf("LABEL_LINK", "(?::[%s]*(.+))?"), //
|
||||
RegexLeaf.end());
|
||||
}
|
||||
|
||||
private static ColorParser color() {
|
||||
return ColorParser.simpleColor(ColorType.LINE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CommandExecutionResult executeArg(WBSDiagram diagram, LineLocation location, RegexResult arg) {
|
||||
protected CommandExecutionResult executeArg(WBSDiagram diagram, LineLocation location, RegexResult arg)
|
||||
throws NoSuchColorException {
|
||||
final String code1 = arg.get("CODE1", 0);
|
||||
final String code2 = arg.get("CODE2", 0);
|
||||
// final String message = arg.get("MESSAGE", 0);
|
||||
return diagram.link(code1, code2);
|
||||
// final String message = arg.get("LABEL_LINK", 0);
|
||||
|
||||
final Colors colors = color().getColor(arg, diagram.getSkinParam().getIHtmlColorSet());
|
||||
// link.setColors(color);
|
||||
// link.applyStyle(arg.getLazzy("ARROW_STYLE", 0));
|
||||
Stereotype stereotype = null;
|
||||
if (arg.get("STEREOTYPE", 0) != null) {
|
||||
stereotype = Stereotype.build(arg.get("STEREOTYPE", 0));
|
||||
}
|
||||
|
||||
return diagram.link(code1, code2, colors, stereotype);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -46,6 +46,7 @@ import net.sourceforge.plantuml.Direction;
|
||||
import net.sourceforge.plantuml.FileFormatOption;
|
||||
import net.sourceforge.plantuml.UmlDiagram;
|
||||
import net.sourceforge.plantuml.UmlDiagramType;
|
||||
import net.sourceforge.plantuml.activitydiagram3.ftile.vcompact.FtileGroup;
|
||||
import net.sourceforge.plantuml.awt.geom.XDimension2D;
|
||||
import net.sourceforge.plantuml.awt.geom.XRectangle2D;
|
||||
import net.sourceforge.plantuml.command.CommandExecutionResult;
|
||||
@ -56,10 +57,18 @@ import net.sourceforge.plantuml.core.DiagramDescription;
|
||||
import net.sourceforge.plantuml.core.ImageData;
|
||||
import net.sourceforge.plantuml.core.UmlSource;
|
||||
import net.sourceforge.plantuml.cucadiagram.Display;
|
||||
import net.sourceforge.plantuml.cucadiagram.Stereotype;
|
||||
import net.sourceforge.plantuml.graphic.InnerStrategy;
|
||||
import net.sourceforge.plantuml.graphic.StringBounder;
|
||||
import net.sourceforge.plantuml.graphic.color.ColorType;
|
||||
import net.sourceforge.plantuml.graphic.color.Colors;
|
||||
import net.sourceforge.plantuml.mindmap.IdeaShape;
|
||||
import net.sourceforge.plantuml.style.NoStyleAvailableException;
|
||||
import net.sourceforge.plantuml.style.PName;
|
||||
import net.sourceforge.plantuml.style.SName;
|
||||
import net.sourceforge.plantuml.style.Style;
|
||||
import net.sourceforge.plantuml.style.StyleSignature;
|
||||
import net.sourceforge.plantuml.style.StyleSignatureBasic;
|
||||
import net.sourceforge.plantuml.svek.TextBlockBackcolored;
|
||||
import net.sourceforge.plantuml.ugraphic.AbstractCommonUGraphic;
|
||||
import net.sourceforge.plantuml.ugraphic.MinMax;
|
||||
@ -231,15 +240,23 @@ public class WBSDiagram extends UmlDiagram {
|
||||
}
|
||||
}
|
||||
|
||||
public CommandExecutionResult link(String code1, String code2) {
|
||||
public CommandExecutionResult link(String code1, String code2, Colors colors, Stereotype stereotype) {
|
||||
final WElement element1 = codes.get(code1);
|
||||
if (element1 == null)
|
||||
return CommandExecutionResult.error("No such node " + code1);
|
||||
final WElement element2 = codes.get(code2);
|
||||
if (element2 == null)
|
||||
return CommandExecutionResult.error("No such node " + code2);
|
||||
HColor color = colors.getColor(ColorType.LINE);
|
||||
|
||||
links.add(new WBSLink(element1, element2));
|
||||
if (color == null) {
|
||||
final Style style = StyleSignatureBasic.of(SName.root, SName.element, SName.wbsDiagram, SName.arrow)
|
||||
.withTOBECHANGED(stereotype).getMergedStyle(getCurrentStyleBuilder());
|
||||
|
||||
color = style.value(PName.LineColor).asColor(getSkinParam().getIHtmlColorSet());
|
||||
}
|
||||
|
||||
links.add(new WBSLink(element1, element2, color));
|
||||
|
||||
return CommandExecutionResult.ok();
|
||||
}
|
||||
|
@ -43,16 +43,20 @@ import net.sourceforge.plantuml.graphic.UDrawable;
|
||||
import net.sourceforge.plantuml.svek.extremity.ExtremityArrow;
|
||||
import net.sourceforge.plantuml.ugraphic.UGraphic;
|
||||
import net.sourceforge.plantuml.ugraphic.UTranslate;
|
||||
import net.sourceforge.plantuml.ugraphic.color.HColors;
|
||||
import net.sourceforge.plantuml.ugraphic.color.HColor;
|
||||
|
||||
class WBSLink implements UDrawable {
|
||||
|
||||
private final WElement element1;
|
||||
private final WElement element2;
|
||||
private final HColor color;
|
||||
|
||||
public WBSLink(WElement element1, WElement element2) {
|
||||
public WBSLink(WElement element1, WElement element2, HColor color) {
|
||||
this.element1 = element1;
|
||||
this.element2 = element2;
|
||||
this.color = color;
|
||||
if (color == null)
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
public final WElement getElement1() {
|
||||
@ -83,7 +87,7 @@ class WBSLink implements UDrawable {
|
||||
final XPoint2D c2 = rect2.intersect(line);
|
||||
|
||||
line = new XLine2D(c1, c2);
|
||||
ug = ug.apply(HColors.RED);
|
||||
ug = ug.apply(color);
|
||||
line.drawU(ug);
|
||||
|
||||
final double angle = line.getAngle();
|
||||
|
@ -85,7 +85,7 @@ public class YamlDiagramFactory extends PSystemAbstractFactory {
|
||||
} catch (Exception e) {
|
||||
Logme.error(e);
|
||||
}
|
||||
final JsonDiagram result = new JsonDiagram(source, UmlDiagramType.YAML, yaml, highlighted);
|
||||
final JsonDiagram result = new JsonDiagram(source, UmlDiagramType.YAML, yaml, highlighted, styleExtractor);
|
||||
if (styleExtractor != null) {
|
||||
styleExtractor.applyStyles(result.getSkinParam());
|
||||
final String title = styleExtractor.getTitle();
|
||||
|
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue
Block a user