This commit is contained in:
Arnaud Roques 2022-12-13 18:30:41 +01:00
parent 117102bb65
commit 80217d8c90
34 changed files with 1057 additions and 72 deletions

View File

@ -85,6 +85,7 @@ import net.sourceforge.plantuml.openiconic.PSystemListOpenIconicFactory;
import net.sourceforge.plantuml.openiconic.PSystemOpenIconicFactory; import net.sourceforge.plantuml.openiconic.PSystemOpenIconicFactory;
import net.sourceforge.plantuml.oregon.PSystemOregonFactory; import net.sourceforge.plantuml.oregon.PSystemOregonFactory;
import net.sourceforge.plantuml.project.GanttDiagramFactory; import net.sourceforge.plantuml.project.GanttDiagramFactory;
import net.sourceforge.plantuml.regex.PSystemRegexFactory;
import net.sourceforge.plantuml.salt.PSystemSaltFactory2; import net.sourceforge.plantuml.salt.PSystemSaltFactory2;
import net.sourceforge.plantuml.security.SecurityProfile; import net.sourceforge.plantuml.security.SecurityProfile;
import net.sourceforge.plantuml.security.SecurityUtils; import net.sourceforge.plantuml.security.SecurityUtils;
@ -212,7 +213,6 @@ public class PSystemBuilder {
factories.add(new PSystemXearthFactory()); factories.add(new PSystemXearthFactory());
} }
factories.add(new GanttDiagramFactory(DiagramType.GANTT)); factories.add(new GanttDiagramFactory(DiagramType.GANTT));
// factories.add(new GanttDiagramFactory(DiagramType.UML));
GanttDiagramFactory.clearCache(); GanttDiagramFactory.clearCache();
factories.add(new FlowDiagramFactory()); factories.add(new FlowDiagramFactory());
// factories.add(new PSystemTreeFactory(DiagramType.JUNGLE)); // factories.add(new PSystemTreeFactory(DiagramType.JUNGLE));
@ -227,6 +227,7 @@ public class PSystemBuilder {
factories.add(new YamlDiagramFactory()); factories.add(new YamlDiagramFactory());
factories.add(new HclDiagramFactory()); factories.add(new HclDiagramFactory());
factories.add(new PSystemEbnfFactory()); factories.add(new PSystemEbnfFactory());
factories.add(new PSystemRegexFactory());
} }
private boolean isOk(Diagram ps) { private boolean isOk(Diagram ps) {

View File

@ -41,12 +41,12 @@ abstract class ScaleProtected implements Scale {
final public double getScale(double width, double height) { final public double getScale(double width, double height) {
final double result = getScaleInternal(width, height); final double result = getScaleInternal(width, height);
if (result <= 0) { if (result <= 0)
return 1; return 1;
}
if (result > 4) { if (result > 4)
return 4; return 4;
}
return result; return result;
} }

View File

@ -39,7 +39,7 @@ import net.sourceforge.plantuml.style.SName;
public enum UmlDiagramType { public enum UmlDiagramType {
SEQUENCE, STATE, CLASS, OBJECT, ACTIVITY, DESCRIPTION, COMPOSITE, FLOW, TIMING, BPM, NWDIAG, MINDMAP, WBS, WIRE, SEQUENCE, STATE, CLASS, OBJECT, ACTIVITY, DESCRIPTION, COMPOSITE, FLOW, TIMING, BPM, NWDIAG, MINDMAP, WBS, WIRE,
HELP, GANTT, SALT, JSON, GIT, BOARD, YAML, HCL, EBNF; HELP, GANTT, SALT, JSON, GIT, BOARD, YAML, HCL, EBNF, REGEX;
public SName getStyleName() { public SName getStyleName() {
if (this == SEQUENCE) if (this == SEQUENCE)
@ -93,6 +93,9 @@ public enum UmlDiagramType {
if (this == EBNF) if (this == EBNF)
return SName.ebnf; return SName.ebnf;
if (this == REGEX)
return SName.regex;
return SName.activityDiagram; return SName.activityDiagram;
} }
} }

View File

@ -67,14 +67,14 @@ public class CommandScale extends SingleLineCommand2<AbstractPSystem> {
@Override @Override
protected CommandExecutionResult executeArg(AbstractPSystem diagram, LineLocation location, RegexResult arg) { protected CommandExecutionResult executeArg(AbstractPSystem diagram, LineLocation location, RegexResult arg) {
double scale = Double.parseDouble(arg.get("SCALE", 0)); double scale = Double.parseDouble(arg.get("SCALE", 0));
if (scale == 0) { if (scale == 0)
return CommandExecutionResult.error("Scale cannot be zero"); return CommandExecutionResult.error("Scale cannot be zero");
}
if (arg.get("DIV", 0) != null) { if (arg.get("DIV", 0) != null) {
final double div = Double.parseDouble(arg.get("DIV", 0)); final double div = Double.parseDouble(arg.get("DIV", 0));
if (div == 0) { if (div == 0)
return CommandExecutionResult.error("Scale cannot be zero"); return CommandExecutionResult.error("Scale cannot be zero");
}
scale /= div; scale /= div;
} }
diagram.setScale(new ScaleSimple(scale)); diagram.setScale(new ScaleSimple(scale));

View File

@ -39,7 +39,7 @@ import net.sourceforge.plantuml.utils.StartUtils;
public enum DiagramType { public enum DiagramType {
UML, BPM, DITAA, DOT, PROJECT, JCCKIT, SALT, FLOW, CREOLE, JUNGLE, CUTE, MATH, LATEX, DEFINITION, GANTT, NW, 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) { static public DiagramType getTypeFromArobaseStart(String s) {
s = s.toLowerCase(); s = s.toLowerCase();
@ -121,6 +121,9 @@ public enum DiagramType {
if (StartUtils.startsWithSymbolAnd("startebnf", s)) if (StartUtils.startsWithSymbolAnd("startebnf", s))
return EBNF; return EBNF;
if (StartUtils.startsWithSymbolAnd("startregex", s))
return REGEX;
return UNKNOWN; return UNKNOWN;
} }
} }

View File

@ -84,9 +84,9 @@ public class AtomImg extends AbstractAtom implements Atom {
public static Atom createQrcode(String flash, double scale) { public static Atom createQrcode(String flash, double scale) {
final FlashCodeUtils utils = FlashCodeFactory.getFlashCodeUtils(); final FlashCodeUtils utils = FlashCodeFactory.getFlashCodeUtils();
BufferedImage im = utils.exportFlashcode(flash, Color.BLACK, Color.WHITE); BufferedImage im = utils.exportFlashcode(flash, Color.BLACK, Color.WHITE);
if (im == null) { if (im == null)
im = new BufferedImage(10, 10, BufferedImage.TYPE_INT_RGB); im = new BufferedImage(10, 10, BufferedImage.TYPE_INT_RGB);
}
return new AtomImg( return new AtomImg(
new UImage(new PixelImage(im, AffineTransformType.TYPE_NEAREST_NEIGHBOR)).scale(scale).getImage(1), 1, new UImage(new PixelImage(im, AffineTransformType.TYPE_NEAREST_NEIGHBOR)).scale(scale).getImage(1), 1,
null, null); null, null);
@ -120,38 +120,38 @@ public class AtomImg extends AbstractAtom implements Atom {
try { try {
// Check if valid URL // Check if valid URL
if (src.startsWith("http:") || src.startsWith("https:")) { 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 buildSvgFromUrl(src, fc, SURL.create(src), scale, url);
return buildRasterFromUrl(src, fc, SURL.create(src), scale, url); return buildRasterFromUrl(src, fc, SURL.create(src), scale, url);
} }
final SFile f = FileSystem.getInstance().getFile(src); final SFile f = FileSystem.getInstance().getFile(src);
if (f.exists() == false) { 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("(File not found: " + f.getPrintablePath() + ")", fc);
return AtomTextUtils.createLegacy("(Cannot decode)", fc); return AtomTextUtils.createLegacy("(Cannot decode)", fc);
} }
if (f.getName().endsWith(".svg")) { if (f.getName().endsWith(".svg")) {
final String tmp = FileUtils.readSvg(f); final String tmp = FileUtils.readSvg(f);
if (tmp == null) if (tmp == null)
return AtomTextUtils.createLegacy("(Cannot decode)", fc); return AtomTextUtils.createLegacy("(Cannot decode)", fc);
return new AtomImgSvg(new TileImageSvg(tmp, scale)); return new AtomImgSvg(new TileImageSvg(tmp, scale));
} }
final BufferedImage read = f.readRasterImageFromFile(); final BufferedImage read = f.readRasterImageFromFile();
if (read == null) { 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: " + f.getPrintablePath() + ")", fc);
return AtomTextUtils.createLegacy("(Cannot decode)", fc); return AtomTextUtils.createLegacy("(Cannot decode)", fc);
} }
return new AtomImg(f.readRasterImageFromFile(), scale, url, src); return new AtomImg(f.readRasterImageFromFile(), scale, url, src);
} catch (IOException e) { } catch (IOException e) {
Logme.error(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 " + e.toString(), fc);
return AtomTextUtils.createLegacy("ERROR", 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, private static Atom buildRasterFromData(String source, final FontConfiguration fc, final byte[] data, double scale,
Url url) throws IOException { Url url) throws IOException {
final BufferedImage read = SImageIO.read(data); final BufferedImage read = SImageIO.read(data);
if (read == null) { if (read == null)
return AtomTextUtils.createLegacy("(Cannot decode: " + source + ")", fc); return AtomTextUtils.createLegacy("(Cannot decode: " + source + ")", fc);
}
return new AtomImg(read, scale, url, null); return new AtomImg(read, scale, url, null);
} }
private static Atom buildRasterFromUrl(String text, final FontConfiguration fc, SURL source, double scale, Url url) private static Atom buildRasterFromUrl(String text, final FontConfiguration fc, SURL source, double scale, Url url)
throws IOException { throws IOException {
if (source == null) { if (source == null)
return AtomTextUtils.createLegacy("(Cannot decode: " + text + ")", fc); return AtomTextUtils.createLegacy("(Cannot decode: " + text + ")", fc);
}
final BufferedImage read = source.readRasterImageFromURL(); final BufferedImage read = source.readRasterImageFromURL();
if (read == null) { if (read == null)
return AtomTextUtils.createLegacy("(Cannot decode: " + text + ")", fc); return AtomTextUtils.createLegacy("(Cannot decode: " + text + ")", fc);
}
return new AtomImg(read, scale, url, "http"); return new AtomImg(read, scale, url, "http");
} }
private static Atom buildSvgFromUrl(String text, final FontConfiguration fc, SURL source, double scale, Url url) private static Atom buildSvgFromUrl(String text, final FontConfiguration fc, SURL source, double scale, Url url)
throws IOException { throws IOException {
if (source == null) { if (source == null)
return AtomTextUtils.createLegacy("(Cannot decode SVG: " + text + ")", fc); return AtomTextUtils.createLegacy("(Cannot decode SVG: " + text + ")", fc);
}
final byte[] read = source.getBytes(); final byte[] read = source.getBytes();
if (read == null) { if (read == null)
return AtomTextUtils.createLegacy("(Cannot decode SVG: " + text + ")", fc); return AtomTextUtils.createLegacy("(Cannot decode SVG: " + text + ")", fc);
}
return new AtomImgSvg(new TileImageSvg(new String(read, UTF_8), scale)); 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) { public void drawU(UGraphic ug) {
if (url != null) { if (url != null)
ug.startUrl(url); ug.startUrl(url);
}
ug.draw(new UImage(new PixelImage(image, AffineTransformType.TYPE_BILINEAR)).withRawFileName(rawFileName) ug.draw(new UImage(new PixelImage(image, AffineTransformType.TYPE_BILINEAR)).withRawFileName(rawFileName)
.scale(scale)); .scale(scale));
if (url != null) {
if (url != null)
ug.closeUrl(); ug.closeUrl();
}
} }
} }

View File

@ -35,7 +35,7 @@
*/ */
package net.sourceforge.plantuml.ebnf; package net.sourceforge.plantuml.ebnf;
interface CharIterator { public interface CharIterator {
char peek(int ahead); char peek(int ahead);
void next(); void next();

View File

@ -37,7 +37,7 @@ package net.sourceforge.plantuml.ebnf;
import net.sourceforge.plantuml.command.BlocLines; import net.sourceforge.plantuml.command.BlocLines;
class CharIteratorImpl implements CharIterator { public class CharIteratorImpl implements CharIterator {
final private BlocLines data; final private BlocLines data;
private int line = 0; private int line = 0;

View File

@ -42,6 +42,7 @@ import net.sourceforge.plantuml.awt.geom.XDimension2D;
import net.sourceforge.plantuml.graphic.StringBounder; import net.sourceforge.plantuml.graphic.StringBounder;
import net.sourceforge.plantuml.ugraphic.UGraphic; import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.UTranslate; import net.sourceforge.plantuml.ugraphic.UTranslate;
import net.sourceforge.plantuml.ugraphic.color.HColor;
public class ETileAlternation extends ETile { public class ETileAlternation extends ETile {

View File

@ -68,6 +68,10 @@ public class ETileBox extends ETile {
private String commentAbove; private String commentAbove;
private String commentBelow; 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, public ETileBox(String value, Symbol symbol, FontConfiguration fc, Style style, HColorSet colorSet,
ISkinParam skinParam) { ISkinParam skinParam) {
this.symbol = symbol; this.symbol = symbol;
@ -225,4 +229,8 @@ public class ETileBox extends ETile {
return value; return value;
} }
public final Symbol getSymbol() {
return symbol;
}
} }

View File

@ -52,6 +52,10 @@ public class ETileConcatenation extends ETile {
tiles.add(0, tile); tiles.add(0, tile);
} }
public void overideFirst(ETile tile) {
tiles.set(0, tile);
}
@Override @Override
public void drawU(UGraphic ug) { public void drawU(UGraphic ug) {
final StringBounder stringBounder = ug.getStringBounder(); final StringBounder stringBounder = ug.getStringBounder();
@ -104,4 +108,8 @@ public class ETileConcatenation extends ETile {
return width; return width;
} }
public ETile getFirst() {
return tiles.get(0);
}
} }

View File

@ -39,15 +39,11 @@ import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import net.sourceforge.plantuml.Direction;
import net.sourceforge.plantuml.ISkinParam; import net.sourceforge.plantuml.ISkinParam;
import net.sourceforge.plantuml.activitydiagram3.ftile.vcompact.FloatingNote; 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.cucadiagram.Display;
import net.sourceforge.plantuml.graphic.FontConfiguration; import net.sourceforge.plantuml.graphic.FontConfiguration;
import net.sourceforge.plantuml.graphic.HorizontalAlignment; import net.sourceforge.plantuml.graphic.HorizontalAlignment;
import net.sourceforge.plantuml.graphic.StringBounder;
import net.sourceforge.plantuml.graphic.TextBlock; import net.sourceforge.plantuml.graphic.TextBlock;
import net.sourceforge.plantuml.graphic.TextBlockUtils; import net.sourceforge.plantuml.graphic.TextBlockUtils;
import net.sourceforge.plantuml.style.PName; import net.sourceforge.plantuml.style.PName;

View File

@ -85,9 +85,9 @@ public class PSystemWelcome extends PlainDiagram {
} }
public TextBlockBackcolored getGraphicStrings() { public TextBlockBackcolored getGraphicStrings() {
if (position != null) { if (position != null)
return GraphicStrings.createBlackOnWhite(strings, PSystemVersion.getPlantumlImage(), position); return GraphicStrings.createBlackOnWhite(strings, PSystemVersion.getPlantumlImage(), position);
}
return GraphicStrings.createBlackOnWhite(strings); return GraphicStrings.createBlackOnWhite(strings);
} }

View File

@ -78,7 +78,7 @@ public class HclDiagramFactory extends PSystemAbstractFactory {
} catch (Exception e) { } catch (Exception e) {
Logme.error(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) { // if (styleExtractor != null) {
// styleExtractor.applyStyles(result.getSkinParam()); // styleExtractor.applyStyles(result.getSkinParam());
// final String title = styleExtractor.getTitle(); // final String title = styleExtractor.getTitle();

View File

@ -49,6 +49,7 @@ import net.sourceforge.plantuml.json.JsonObject;
import net.sourceforge.plantuml.json.JsonString; import net.sourceforge.plantuml.json.JsonString;
import net.sourceforge.plantuml.json.JsonValue; import net.sourceforge.plantuml.json.JsonValue;
// https://github.com/hashicorp/hcl
public class HclParser { public class HclParser {
private final List<HclTerm> terms = new ArrayList<HclTerm>(); private final List<HclTerm> terms = new ArrayList<HclTerm>();

View File

@ -39,6 +39,7 @@ import java.io.OutputStream;
import java.util.List; import java.util.List;
import net.sourceforge.plantuml.FileFormatOption; import net.sourceforge.plantuml.FileFormatOption;
import net.sourceforge.plantuml.ScaleSimple;
import net.sourceforge.plantuml.TitledDiagram; import net.sourceforge.plantuml.TitledDiagram;
import net.sourceforge.plantuml.UmlDiagramType; import net.sourceforge.plantuml.UmlDiagramType;
import net.sourceforge.plantuml.awt.geom.XDimension2D; 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.UFont;
import net.sourceforge.plantuml.ugraphic.UGraphic; import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.color.HColor; import net.sourceforge.plantuml.ugraphic.color.HColor;
import net.sourceforge.plantuml.ugraphic.hand.UGraphicHandwritten;
public class JsonDiagram extends TitledDiagram { public class JsonDiagram extends TitledDiagram {
private final JsonValue root; private final JsonValue root;
private final List<String> highlighted; 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); super(source, type, null);
this.handwritten = styleExtractor.isHandwritten();
if (json != null && (json.isString() || json.isBoolean() || json.isNumber())) { if (json != null && (json.isString() || json.isBoolean() || json.isNumber())) {
this.root = new JsonArray(); this.root = new JsonArray();
((JsonArray) this.root).add(json); ((JsonArray) this.root).add(json);
@ -75,6 +80,7 @@ public class JsonDiagram extends TitledDiagram {
this.root = json; this.root = json;
} }
this.highlighted = highlighted; this.highlighted = highlighted;
setScale(new ScaleSimple(styleExtractor.getScale()));
} }
public DiagramDescription getDescription() { public DiagramDescription getDescription() {
@ -95,6 +101,8 @@ public class JsonDiagram extends TitledDiagram {
} }
private void drawInternal(UGraphic ug) { private void drawInternal(UGraphic ug) {
if (handwritten)
ug = new UGraphicHandwritten(ug);
if (root == null) { if (root == null) {
final Display display = Display final Display display = Display
.getWithNewlines("Your data does not sound like " + getUmlDiagramType() + " data"); .getWithNewlines("Your data does not sound like " + getUmlDiagramType() + " data");

View File

@ -85,7 +85,7 @@ public class JsonDiagramFactory extends PSystemAbstractFactory {
} catch (ParseException e) { } catch (ParseException e) {
json = null; 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) if (styleExtractor != null)
styleExtractor.applyStyles(result.getSkinParam()); styleExtractor.applyStyles(result.getSkinParam());

View File

@ -51,27 +51,42 @@ public class StyleExtractor {
private final List<String> list = new ArrayList<>(); private final List<String> list = new ArrayList<>();
private final List<StringLocated> style = new ArrayList<>(); private final List<StringLocated> style = new ArrayList<>();
private String title = null; private String title = null;
private boolean handwritten = false;
private double scale = 1;
public StyleExtractor(Iterator<StringLocated> data) { public StyleExtractor(Iterator<StringLocated> data) {
while (data.hasNext()) { while (data.hasNext()) {
StringLocated line = data.next(); StringLocated line = data.next();
if (startStyle(line)) { final String s = line.getString().trim();
if (s.length() == 0)
continue;
if (startStyle(s)) {
while (data.hasNext()) { while (data.hasNext()) {
style.add(line); style.add(line);
if (endStyle(line)) if (endStyle(line))
break; break;
line = data.next(); line = data.next();
} }
} else if (line.getString().trim().startsWith("!assume ")) { } else if (list.size() >= 1 && s.startsWith("!assume ")) {
// Ignore // Ignore
} else if (line.getString().trim().startsWith("!pragma ")) { } else if (list.size() >= 1 && s.startsWith("!pragma ")) {
// Ignore // Ignore
} else if (line.getString().trim().startsWith("hide ")) { } else if (list.size() >= 1 && s.startsWith("hide ")) {
// Ignore // Ignore
} else if (line.getString().trim().startsWith("title ")) { } else if (list.size() >= 1 && s.startsWith("scale ")) {
this.title = line.getString().trim().substring("title ".length()).trim(); // Ignore
} else if (line.getString().trim().startsWith("skinparam ")) { try {
if (line.getString().trim().contains("{")) { 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()) { while (data.hasNext()) {
if (line.getString().trim().equals("}")) if (line.getString().trim().equals("}"))
break; break;
@ -82,10 +97,11 @@ public class StyleExtractor {
list.add(line.getString()); list.add(line.getString());
} }
} }
} }
private boolean startStyle(StringLocated line) { private boolean startStyle(String line) {
return line.getString().trim().equals("<style>"); return line.equals("<style>");
} }
private boolean endStyle(StringLocated line) { private boolean endStyle(StringLocated line) {
@ -110,4 +126,12 @@ public class StyleExtractor {
return title; return title;
} }
public final boolean isHandwritten() {
return handwritten;
}
public double getScale() {
return scale;
}
} }

View File

@ -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)));
}
}

View 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;
}
}

View 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);
}
}

View 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;
}
}

View 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;
}
}

View 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();
}
}

View 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);
}
}

View File

@ -115,6 +115,7 @@ public enum SName {
rectangle, // rectangle, //
reference, // reference, //
referenceHeader, // referenceHeader, //
regex, //
requirement, // requirement, //
root, // root, //
rootNode, // rootNode, //

View File

@ -260,11 +260,14 @@ public class SvgGraphics {
private static String getData(final String name) { private static String getData(final String name) {
try { try {
final InputStream is = SvgGraphics.class.getResourceAsStream("/svg/" + name); 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) { } catch (IOException e) {
Logme.error(e); Logme.error(e);
return null;
} }
return null;
} }
private Element getPathHover(String hover) { private Element getPathHover(String hover) {

View File

@ -81,7 +81,7 @@ public class Version {
} }
public static int beta() { public static int beta() {
final int beta = 0; final int beta = 1;
return beta; return beta;
} }

View File

@ -42,6 +42,11 @@ import net.sourceforge.plantuml.command.regex.IRegex;
import net.sourceforge.plantuml.command.regex.RegexConcat; import net.sourceforge.plantuml.command.regex.RegexConcat;
import net.sourceforge.plantuml.command.regex.RegexLeaf; import net.sourceforge.plantuml.command.regex.RegexLeaf;
import net.sourceforge.plantuml.command.regex.RegexResult; 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> { public class CommandWBSLink extends SingleLineCommand2<WBSDiagram> {
@ -53,19 +58,38 @@ public class CommandWBSLink extends SingleLineCommand2<WBSDiagram> {
return RegexConcat.build(CommandWBSLink.class.getName(), RegexLeaf.start(), // return RegexConcat.build(CommandWBSLink.class.getName(), RegexLeaf.start(), //
new RegexLeaf("CODE1", "([%pLN_]+)"), // new RegexLeaf("CODE1", "([%pLN_]+)"), //
RegexLeaf.spaceZeroOrMore(), // RegexLeaf.spaceZeroOrMore(), //
new RegexLeaf("LINK", "-+\\>"), // new RegexLeaf("LINK", "[.-]+\\>"), //
RegexLeaf.spaceZeroOrMore(), // RegexLeaf.spaceZeroOrMore(), //
new RegexLeaf("CODE2", "([%pLN_]+)"), // new RegexLeaf("CODE2", "([%pLN_]+)"), //
RegexLeaf.spaceZeroOrMore(), // 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 @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 code1 = arg.get("CODE1", 0);
final String code2 = arg.get("CODE2", 0); final String code2 = arg.get("CODE2", 0);
// final String message = arg.get("MESSAGE", 0); // final String message = arg.get("LABEL_LINK", 0);
return diagram.link(code1, code2);
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);
} }
} }

View File

@ -46,6 +46,7 @@ import net.sourceforge.plantuml.Direction;
import net.sourceforge.plantuml.FileFormatOption; import net.sourceforge.plantuml.FileFormatOption;
import net.sourceforge.plantuml.UmlDiagram; import net.sourceforge.plantuml.UmlDiagram;
import net.sourceforge.plantuml.UmlDiagramType; 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.XDimension2D;
import net.sourceforge.plantuml.awt.geom.XRectangle2D; import net.sourceforge.plantuml.awt.geom.XRectangle2D;
import net.sourceforge.plantuml.command.CommandExecutionResult; 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.ImageData;
import net.sourceforge.plantuml.core.UmlSource; import net.sourceforge.plantuml.core.UmlSource;
import net.sourceforge.plantuml.cucadiagram.Display; import net.sourceforge.plantuml.cucadiagram.Display;
import net.sourceforge.plantuml.cucadiagram.Stereotype;
import net.sourceforge.plantuml.graphic.InnerStrategy; import net.sourceforge.plantuml.graphic.InnerStrategy;
import net.sourceforge.plantuml.graphic.StringBounder; 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.mindmap.IdeaShape;
import net.sourceforge.plantuml.style.NoStyleAvailableException; 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.svek.TextBlockBackcolored;
import net.sourceforge.plantuml.ugraphic.AbstractCommonUGraphic; import net.sourceforge.plantuml.ugraphic.AbstractCommonUGraphic;
import net.sourceforge.plantuml.ugraphic.MinMax; 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); final WElement element1 = codes.get(code1);
if (element1 == null) if (element1 == null)
return CommandExecutionResult.error("No such node " + code1); return CommandExecutionResult.error("No such node " + code1);
final WElement element2 = codes.get(code2); final WElement element2 = codes.get(code2);
if (element2 == null) if (element2 == null)
return CommandExecutionResult.error("No such node " + code2); 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(); return CommandExecutionResult.ok();
} }

View File

@ -43,16 +43,20 @@ import net.sourceforge.plantuml.graphic.UDrawable;
import net.sourceforge.plantuml.svek.extremity.ExtremityArrow; import net.sourceforge.plantuml.svek.extremity.ExtremityArrow;
import net.sourceforge.plantuml.ugraphic.UGraphic; import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.UTranslate; import net.sourceforge.plantuml.ugraphic.UTranslate;
import net.sourceforge.plantuml.ugraphic.color.HColors; import net.sourceforge.plantuml.ugraphic.color.HColor;
class WBSLink implements UDrawable { class WBSLink implements UDrawable {
private final WElement element1; private final WElement element1;
private final WElement element2; 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.element1 = element1;
this.element2 = element2; this.element2 = element2;
this.color = color;
if (color == null)
throw new IllegalArgumentException();
} }
public final WElement getElement1() { public final WElement getElement1() {
@ -83,7 +87,7 @@ class WBSLink implements UDrawable {
final XPoint2D c2 = rect2.intersect(line); final XPoint2D c2 = rect2.intersect(line);
line = new XLine2D(c1, c2); line = new XLine2D(c1, c2);
ug = ug.apply(HColors.RED); ug = ug.apply(color);
line.drawU(ug); line.drawU(ug);
final double angle = line.getAngle(); final double angle = line.getAngle();

View File

@ -85,7 +85,7 @@ public class YamlDiagramFactory extends PSystemAbstractFactory {
} catch (Exception e) { } catch (Exception e) {
Logme.error(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) { if (styleExtractor != null) {
styleExtractor.applyStyles(result.getSkinParam()); styleExtractor.applyStyles(result.getSkinParam());
final String title = styleExtractor.getTitle(); final String title = styleExtractor.getTitle();

Binary file not shown.

Binary file not shown.