mirror of
https://github.com/octoleo/plantuml.git
synced 2024-11-27 23:36:35 +00:00
version 1.2018.9
This commit is contained in:
parent
a363246176
commit
87ee4898b1
2
pom.xml
2
pom.xml
@ -35,7 +35,7 @@
|
||||
|
||||
<groupId>net.sourceforge.plantuml</groupId>
|
||||
<artifactId>plantuml</artifactId>
|
||||
<version>1.2018.9-SNAPSHOT</version>
|
||||
<version>1.2018.10-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>PlantUML</name>
|
||||
|
@ -38,17 +38,18 @@ package net.sourceforge.plantuml;
|
||||
import net.sourceforge.plantuml.graphic.HorizontalAlignment;
|
||||
|
||||
|
||||
public enum AlignParam {
|
||||
public enum AlignmentParam {
|
||||
|
||||
ARROW_MESSAGE_ALIGN(HorizontalAlignment.LEFT),
|
||||
SEQUENCE_MESSAGE_ALIGN(HorizontalAlignment.LEFT),
|
||||
SEQUENCE_MESSAGETEXT_ALIGN(HorizontalAlignment.LEFT),
|
||||
SEQUENCE_REFERENCE_ALIGN(HorizontalAlignment.CENTER),
|
||||
PACKAGE_TITLE_ALIGNMENT(HorizontalAlignment.CENTER);
|
||||
arrowMessageAlignment(HorizontalAlignment.LEFT),
|
||||
sequenceMessageAlignment(HorizontalAlignment.LEFT),
|
||||
sequenceMessageTextAlignment(HorizontalAlignment.LEFT),
|
||||
sequenceReferenceAlignment(HorizontalAlignment.CENTER),
|
||||
packageTitleAlignment(HorizontalAlignment.CENTER),
|
||||
noteTextAlignment(HorizontalAlignment.LEFT);
|
||||
|
||||
private final HorizontalAlignment defaultValue;
|
||||
|
||||
private AlignParam(HorizontalAlignment defaultValue) {
|
||||
private AlignmentParam(HorizontalAlignment defaultValue) {
|
||||
this.defaultValue = defaultValue;
|
||||
}
|
||||
|
@ -173,9 +173,9 @@ public class BlockUml {
|
||||
return data.get(0).toString().equalsIgnoreCase(signature);
|
||||
}
|
||||
|
||||
public List<? extends CharSequence> getDefinition() {
|
||||
if (data.get(0).toString().startsWith("@startdef") == false) {
|
||||
throw new IllegalStateException();
|
||||
public List<? extends CharSequence> getDefinition(boolean withHeader) {
|
||||
if (withHeader) {
|
||||
return Collections.unmodifiableList(data);
|
||||
}
|
||||
return Collections.unmodifiableList(data.subList(1, data.size() - 1));
|
||||
}
|
||||
|
@ -141,7 +141,7 @@ public final class BlockUmlBuilder implements DefinitionsContainer {
|
||||
for (BlockUml block : blocks) {
|
||||
if (block.isStartDef(name)) {
|
||||
this.defines.importFrom(block.getLocalDefines());
|
||||
return block.getDefinition();
|
||||
return block.getDefinition(false);
|
||||
}
|
||||
}
|
||||
return Collections.emptyList();
|
||||
|
@ -56,11 +56,11 @@ public class EmptyImageBuilder {
|
||||
|
||||
public EmptyImageBuilder(int width, int height, Color background) {
|
||||
if (width > GraphvizUtils.getenvImageLimit()) {
|
||||
Log.info("Width too large " + width);
|
||||
Log.info("Width too large " + width + ". You should set PLANTUML_LIMIT_SIZE");
|
||||
width = GraphvizUtils.getenvImageLimit();
|
||||
}
|
||||
if (height > GraphvizUtils.getenvImageLimit()) {
|
||||
Log.info("Height too large " + height);
|
||||
Log.info("Height too large " + height + ". You should set PLANTUML_LIMIT_SIZE");
|
||||
height = GraphvizUtils.getenvImageLimit();
|
||||
}
|
||||
Log.info("Creating image " + width + "x" + height);
|
||||
|
@ -55,7 +55,7 @@ import net.sourceforge.plantuml.ugraphic.UFont;
|
||||
*
|
||||
*/
|
||||
public enum FileFormat {
|
||||
PNG, SVG, EPS, EPS_TEXT, ATXT, UTXT, XMI_STANDARD, XMI_STAR, XMI_ARGO, SCXML, PDF, MJPEG, ANIMATED_GIF, HTML, HTML5, VDX, LATEX, LATEX_NO_PREAMBLE, BASE64, BRAILLE_PNG;
|
||||
PNG, SVG, EPS, EPS_TEXT, ATXT, UTXT, XMI_STANDARD, XMI_STAR, XMI_ARGO, SCXML, PDF, MJPEG, ANIMATED_GIF, HTML, HTML5, VDX, LATEX, LATEX_NO_PREAMBLE, BASE64, BRAILLE_PNG, PREPROC;
|
||||
|
||||
/**
|
||||
* Returns the file format to be used for that format.
|
||||
|
@ -51,6 +51,8 @@ import net.sourceforge.plantuml.ugraphic.UStroke;
|
||||
|
||||
public interface ISkinParam extends ISkinSimple {
|
||||
|
||||
public static final int SWIMLANE_WIDTH_SAME = -1;
|
||||
|
||||
public HtmlColor getHyperlinkColor();
|
||||
|
||||
public boolean useUnderlineForHyperlink();
|
||||
@ -67,7 +69,7 @@ public interface ISkinParam extends ISkinSimple {
|
||||
|
||||
public UFont getFont(Stereotype stereotype, boolean inPackageTitle, FontParam... fontParam);
|
||||
|
||||
public HorizontalAlignment getHorizontalAlignment(AlignParam param, ArrowDirection arrowDirection);
|
||||
public HorizontalAlignment getHorizontalAlignment(AlignmentParam param, ArrowDirection arrowDirection);
|
||||
|
||||
public HorizontalAlignment getDefaultTextAlignment(HorizontalAlignment defaultValue);
|
||||
|
||||
@ -109,6 +111,8 @@ public interface ISkinParam extends ISkinSimple {
|
||||
|
||||
public LineBreakStrategy wrapWidth();
|
||||
|
||||
public LineBreakStrategy swimlaneWrapTitleWidth();
|
||||
|
||||
public boolean strictUmlStyle();
|
||||
|
||||
public boolean forceSequenceParticipantUnderlined();
|
||||
|
@ -45,7 +45,11 @@ public class LineBreakStrategy {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public double getMathWidth() {
|
||||
public boolean isAuto() {
|
||||
return "auto".equalsIgnoreCase(value);
|
||||
}
|
||||
|
||||
public double getMaxWidth() {
|
||||
if (value != null && value.matches("-?\\d+")) {
|
||||
return Double.parseDouble(value);
|
||||
}
|
||||
|
@ -68,6 +68,7 @@ public class Option {
|
||||
private boolean pipeNoStdErr = false;
|
||||
private boolean syntax = false;
|
||||
private boolean checkOnly = false;
|
||||
private OptionPreprocOutputMode preprocessorOutput = null;
|
||||
private boolean failfast = false;
|
||||
private boolean failfast2 = false;
|
||||
private boolean pattern = false;
|
||||
@ -332,6 +333,10 @@ public class Option {
|
||||
textProgressBar = true;
|
||||
} else if (s.equalsIgnoreCase("-nometadata")) {
|
||||
hideMetadata = true;
|
||||
} else if (s.equalsIgnoreCase("-preproc")) {
|
||||
preprocessorOutput = OptionPreprocOutputMode.NORMAL;
|
||||
} else if (s.equalsIgnoreCase("-cypher")) {
|
||||
preprocessorOutput = OptionPreprocOutputMode.CYPHER;
|
||||
} else if (s.equalsIgnoreCase("-checkmetadata")) {
|
||||
checkMetadata = true;
|
||||
} else if (s.equalsIgnoreCase("-pipeimageindex")) {
|
||||
@ -588,4 +593,12 @@ public class Option {
|
||||
return checkMetadata;
|
||||
}
|
||||
|
||||
public final OptionPreprocOutputMode getPreprocessorOutputMode() {
|
||||
return preprocessorOutput;
|
||||
}
|
||||
|
||||
// public final void setPreprocessorOutput(boolean preprocessorOutput) {
|
||||
// this.preprocessorOutput = preprocessorOutput;
|
||||
// }
|
||||
|
||||
}
|
||||
|
41
src/net/sourceforge/plantuml/OptionPreprocOutputMode.java
Normal file
41
src/net/sourceforge/plantuml/OptionPreprocOutputMode.java
Normal file
@ -0,0 +1,41 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* (C) Copyright 2009-2017, Arnaud Roques
|
||||
*
|
||||
* Project Info: http://plantuml.com
|
||||
*
|
||||
* If you like this project or if you find it useful, you can support us at:
|
||||
*
|
||||
* http://plantuml.com/patreon (only 1$ per month!)
|
||||
* http://plantuml.com/paypal
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*
|
||||
*
|
||||
* Original Author: Arnaud Roques
|
||||
*
|
||||
*
|
||||
*/
|
||||
package net.sourceforge.plantuml;
|
||||
|
||||
public enum OptionPreprocOutputMode {
|
||||
NORMAL, CYPHER
|
||||
|
||||
}
|
@ -142,9 +142,10 @@ public class OptionPrint {
|
||||
System.out.println(" -splash\t\tTo display a splash screen with some progress bar");
|
||||
System.out.println(" -progress\t\tTo display a textual progress bar in console");
|
||||
System.out.println(" -pipeimageindex N\tTo generate the Nth image with pipe option");
|
||||
System.out.println(" -stdlib\tTo print standart library info");
|
||||
System.out.println(" -stdlib\t\tTo print standart library info");
|
||||
System.out.println(" -extractstdlib\tTo extract PlantUML Standard Library into stdlib folder");
|
||||
System.out.println(" -filename \"example.puml\"\tTo override %filename% variable");
|
||||
System.out.println(" -preproc\t\tTo output preprocessor text of diagrams");
|
||||
System.out.println();
|
||||
System.out.println("If needed, you can setup the environment variable GRAPHVIZ_DOT.");
|
||||
exit();
|
||||
|
@ -71,6 +71,7 @@ import net.sourceforge.plantuml.ugraphic.UGraphic;
|
||||
import net.sourceforge.plantuml.ugraphic.UImage;
|
||||
import net.sourceforge.plantuml.ugraphic.UTranslate;
|
||||
import net.sourceforge.plantuml.ugraphic.txt.UGraphicTxt;
|
||||
import net.sourceforge.plantuml.version.LicenseInfo;
|
||||
import net.sourceforge.plantuml.version.PSystemVersion;
|
||||
|
||||
public class PSystemError extends AbstractPSystem {
|
||||
@ -144,9 +145,11 @@ public class PSystemError extends AbstractPSystem {
|
||||
} else {
|
||||
udrawable = result;
|
||||
}
|
||||
final int min = (int) (System.currentTimeMillis() / 60000L) % 60;
|
||||
if (min == 0) {
|
||||
udrawable = addMessage(udrawable);
|
||||
if (LicenseInfo.retrieveQuick().isValid() == false) {
|
||||
final int min = (int) (System.currentTimeMillis() / 60000L) % 60;
|
||||
if (min == 0) {
|
||||
udrawable = addMessage(udrawable);
|
||||
}
|
||||
}
|
||||
imageBuilder.setUDrawable(udrawable);
|
||||
final ImageData imageData = imageBuilder.writeImageTOBEMOVED(fileFormat, seed(), os);
|
||||
|
@ -43,6 +43,9 @@ import java.awt.geom.Rectangle2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
@ -67,12 +70,16 @@ import net.sourceforge.plantuml.sequencediagram.SequenceDiagramFactory;
|
||||
import net.sourceforge.plantuml.statediagram.StateDiagramFactory;
|
||||
import net.sourceforge.plantuml.stats.StatsUtils;
|
||||
import net.sourceforge.plantuml.swing.MainWindow2;
|
||||
import net.sourceforge.plantuml.syntax.LanguageDescriptor;
|
||||
import net.sourceforge.plantuml.ugraphic.sprite.SpriteGrayLevel;
|
||||
import net.sourceforge.plantuml.ugraphic.sprite.SpriteUtils;
|
||||
import net.sourceforge.plantuml.utils.Cypher;
|
||||
import net.sourceforge.plantuml.version.Version;
|
||||
|
||||
public class Run {
|
||||
|
||||
private static Cypher cypher;
|
||||
|
||||
public static void main(String[] argsArray) throws IOException, InterruptedException {
|
||||
System.setProperty("log4j.debug", "false");
|
||||
final long start = System.currentTimeMillis();
|
||||
@ -135,6 +142,9 @@ public class Run {
|
||||
}
|
||||
|
||||
forceOpenJdkResourceLoad();
|
||||
if (option.getPreprocessorOutputMode() == OptionPreprocOutputMode.CYPHER) {
|
||||
cypher = new LanguageDescriptor().getCypher();
|
||||
}
|
||||
boolean error = false;
|
||||
boolean forceQuit = false;
|
||||
if (option.isPattern()) {
|
||||
@ -231,10 +241,13 @@ public class Run {
|
||||
return false;
|
||||
}
|
||||
|
||||
static private final String httpProtocol = "http://";
|
||||
static private final String httpsProtocol = "https://";
|
||||
|
||||
private static void encodeSprite(List<String> result) throws IOException {
|
||||
SpriteGrayLevel level = SpriteGrayLevel.GRAY_16;
|
||||
boolean compressed = false;
|
||||
final File f;
|
||||
final String path;
|
||||
if (result.size() > 1 && result.get(0).matches("(4|8|16)z?")) {
|
||||
if (result.get(0).startsWith("8")) {
|
||||
level = SpriteGrayLevel.GRAY_8;
|
||||
@ -243,28 +256,52 @@ public class Run {
|
||||
level = SpriteGrayLevel.GRAY_4;
|
||||
}
|
||||
compressed = StringUtils.goLowerCase(result.get(0)).endsWith("z");
|
||||
f = new File(result.get(1));
|
||||
path = result.get(1);
|
||||
} else {
|
||||
f = new File(result.get(0));
|
||||
path = result.get(0);
|
||||
}
|
||||
final BufferedImage im = ImageIO.read(f);
|
||||
final String name = getSpriteName(f);
|
||||
|
||||
final String fileName;
|
||||
final URL source;
|
||||
final String lowerPath = StringUtils.goLowerCase(path);
|
||||
if (lowerPath.startsWith(httpProtocol) || lowerPath.startsWith(httpsProtocol)) {
|
||||
source = new URL(path);
|
||||
final String p = source.getPath();
|
||||
fileName = p.substring(p.lastIndexOf('/') + 1, p.length());
|
||||
} else {
|
||||
final File f = new File(path);
|
||||
source = f.toURI().toURL();
|
||||
fileName = f.getName();
|
||||
}
|
||||
|
||||
InputStream stream = null;
|
||||
final BufferedImage im;
|
||||
try {
|
||||
stream = source.openStream();
|
||||
im = ImageIO.read(stream);
|
||||
} finally {
|
||||
if (stream != null) {
|
||||
stream.close();
|
||||
}
|
||||
}
|
||||
|
||||
final String name = getSpriteName(fileName);
|
||||
final String s = compressed ? SpriteUtils.encodeCompressed(im, name, level) : SpriteUtils.encode(im, name,
|
||||
level);
|
||||
System.out.println(s);
|
||||
}
|
||||
|
||||
private static String getSpriteName(File f) {
|
||||
final String s = getSpriteNameInternal(f);
|
||||
private static String getSpriteName(String fileName) {
|
||||
final String s = getSpriteNameInternal(fileName);
|
||||
if (s.length() == 0) {
|
||||
return "test";
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
private static String getSpriteNameInternal(File f) {
|
||||
private static String getSpriteNameInternal(String fileName) {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
for (char c : f.getName().toCharArray()) {
|
||||
for (char c : fileName.toCharArray()) {
|
||||
if (("" + c).matches("[\\p{L}0-9_]")) {
|
||||
sb.append(c);
|
||||
} else {
|
||||
@ -291,7 +328,6 @@ public class Run {
|
||||
for (String n : name) {
|
||||
System.out.println("n=" + n);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void managePattern() {
|
||||
@ -356,6 +392,7 @@ public class Run {
|
||||
files.addAll(group.getFiles());
|
||||
}
|
||||
}
|
||||
Log.info("Found " + files.size() + " files");
|
||||
for (File f : files) {
|
||||
try {
|
||||
final boolean error = manageFileInternal(f, option);
|
||||
@ -417,6 +454,7 @@ public class Run {
|
||||
}
|
||||
|
||||
private static boolean manageFileInternal(File f, Option option) throws IOException, InterruptedException {
|
||||
Log.info("Working on " + f.getAbsolutePath());
|
||||
if (OptionFlags.getInstance().isExtractFromMetadata()) {
|
||||
System.out.println("------------------------");
|
||||
System.out.println(f);
|
||||
@ -435,6 +473,7 @@ public class Run {
|
||||
option.getConfig(), option.getCharset(), option.getFileFormatOption());
|
||||
}
|
||||
sourceFileReader.setCheckMetadata(option.isCheckMetadata());
|
||||
|
||||
if (option.isComputeurl()) {
|
||||
for (BlockUml s : sourceFileReader.getBlocks()) {
|
||||
System.out.println(s.getEncodedUrl());
|
||||
@ -447,10 +486,33 @@ public class Run {
|
||||
hasErrors(f, result);
|
||||
return hasError;
|
||||
}
|
||||
if (option.getPreprocessorOutputMode() != null) {
|
||||
extractPreproc(option, sourceFileReader);
|
||||
return false;
|
||||
}
|
||||
final List<GeneratedImage> result = sourceFileReader.getGeneratedImages();
|
||||
|
||||
return hasErrors(f, result);
|
||||
}
|
||||
|
||||
private static void extractPreproc(Option option, final ISourceFileReader sourceFileReader) throws IOException {
|
||||
final String charset = option.getCharset();
|
||||
for (BlockUml blockUml : sourceFileReader.getBlocks()) {
|
||||
final SuggestedFile suggested = ((SourceFileReaderAbstract) sourceFileReader).getSuggestedFile(blockUml)
|
||||
.withPreprocFormat();
|
||||
final File file = suggested.getFile(0);
|
||||
Log.info("Export preprocessing source to " + file.getAbsolutePath());
|
||||
final PrintWriter pw = charset == null ? new PrintWriter(file) : new PrintWriter(file, charset);
|
||||
for (CharSequence s : blockUml.getDefinition(true)) {
|
||||
if (cypher != null) {
|
||||
s = cypher.cypher(s.toString());
|
||||
}
|
||||
pw.println(s);
|
||||
}
|
||||
pw.close();
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean hasErrors(File f, final List<GeneratedImage> list) throws IOException {
|
||||
boolean result = false;
|
||||
for (GeneratedImage i : list) {
|
||||
|
@ -42,18 +42,30 @@ import java.io.InputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.SecretKeyFactory;
|
||||
import javax.crypto.spec.PBEKeySpec;
|
||||
|
||||
import net.sourceforge.plantuml.code.AsciiEncoder;
|
||||
|
||||
public class SignatureUtils {
|
||||
|
||||
public static byte[] salting(String pass, byte[] salt) throws NoSuchAlgorithmException, InvalidKeySpecException,
|
||||
UnsupportedEncodingException {
|
||||
final int iterations = 10000;
|
||||
final int keyLength = 512;
|
||||
final SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
|
||||
final PBEKeySpec spec = new PBEKeySpec(pass.toCharArray(), salt, iterations, keyLength);
|
||||
final SecretKey key = skf.generateSecret(spec);
|
||||
return SignatureUtils.getSHA512raw(key.getEncoded());
|
||||
}
|
||||
|
||||
public static String getSignature(String s) {
|
||||
try {
|
||||
final AsciiEncoder coder = new AsciiEncoder();
|
||||
final MessageDigest msgDigest = MessageDigest.getInstance("MD5");
|
||||
msgDigest.update(s.getBytes("UTF-8"));
|
||||
final byte[] digest = msgDigest.digest();
|
||||
return coder.encode(digest);
|
||||
final byte[] digest = getMD5raw(s);
|
||||
return toString(digest);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
throw new UnsupportedOperationException(e);
|
||||
@ -63,21 +75,24 @@ public class SignatureUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static String getMD5(String s) {
|
||||
public static String toString(byte data[]) {
|
||||
final AsciiEncoder coder = new AsciiEncoder();
|
||||
return coder.encode(data);
|
||||
}
|
||||
|
||||
public static String toHexString(byte data[]) {
|
||||
final StringBuilder sb = new StringBuilder(data.length * 2);
|
||||
for (byte b : data) {
|
||||
sb.append(String.format("%02x", b));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static String getMD5Hex(String s) {
|
||||
try {
|
||||
final MessageDigest msgDigest = MessageDigest.getInstance("MD5");
|
||||
msgDigest.update(s.getBytes("UTF-8"));
|
||||
final byte[] digest = msgDigest.digest();
|
||||
final StringBuilder result = new StringBuilder(32);
|
||||
for (byte b : digest) {
|
||||
final String tmp = Integer.toHexString(b & 0xFF);
|
||||
if (tmp.length() == 1) {
|
||||
result.append("0");
|
||||
}
|
||||
result.append(tmp);
|
||||
}
|
||||
assert result.length() == 32;
|
||||
return result.toString();
|
||||
final byte[] digest = getMD5raw(s);
|
||||
assert digest.length == 16;
|
||||
return toHexString(digest);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
throw new UnsupportedOperationException(e);
|
||||
@ -87,6 +102,36 @@ public class SignatureUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static String getSHA512Hex(String s) {
|
||||
try {
|
||||
final byte[] digest = getSHA512raw(s);
|
||||
assert digest.length == 64;
|
||||
return toHexString(digest);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
throw new UnsupportedOperationException(e);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
throw new UnsupportedOperationException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] getMD5raw(String s) throws NoSuchAlgorithmException, UnsupportedEncodingException {
|
||||
final MessageDigest msgDigest = MessageDigest.getInstance("MD5");
|
||||
msgDigest.update(s.getBytes("UTF-8"));
|
||||
return msgDigest.digest();
|
||||
}
|
||||
|
||||
public static byte[] getSHA512raw(String s) throws NoSuchAlgorithmException, UnsupportedEncodingException {
|
||||
return getSHA512raw(s.getBytes("UTF-8"));
|
||||
}
|
||||
|
||||
public static byte[] getSHA512raw(byte data[]) throws NoSuchAlgorithmException, UnsupportedEncodingException {
|
||||
final MessageDigest msgDigest = MessageDigest.getInstance("SHA-512");
|
||||
msgDigest.update(data);
|
||||
return msgDigest.digest();
|
||||
}
|
||||
|
||||
public static String getSignatureSha512(File f) throws IOException {
|
||||
final InputStream is = new FileInputStream(f);
|
||||
try {
|
||||
@ -98,14 +143,13 @@ public class SignatureUtils {
|
||||
|
||||
public static String getSignatureSha512(InputStream is) throws IOException {
|
||||
try {
|
||||
final AsciiEncoder coder = new AsciiEncoder();
|
||||
final MessageDigest msgDigest = MessageDigest.getInstance("SHA-512");
|
||||
int read = 0;
|
||||
while ((read = is.read()) != -1) {
|
||||
msgDigest.update((byte) read);
|
||||
}
|
||||
final byte[] digest = msgDigest.digest();
|
||||
return coder.encode(digest);
|
||||
return toString(digest);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
throw new UnsupportedOperationException(e);
|
||||
@ -130,7 +174,6 @@ public class SignatureUtils {
|
||||
|
||||
public static String getSignature(File f) throws IOException {
|
||||
try {
|
||||
final AsciiEncoder coder = new AsciiEncoder();
|
||||
final MessageDigest msgDigest = MessageDigest.getInstance("MD5");
|
||||
final FileInputStream is = new FileInputStream(f);
|
||||
int read = -1;
|
||||
@ -139,7 +182,7 @@ public class SignatureUtils {
|
||||
}
|
||||
is.close();
|
||||
final byte[] digest = msgDigest.digest();
|
||||
return coder.encode(digest);
|
||||
return toString(digest);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
throw new UnsupportedOperationException(e);
|
||||
|
@ -137,6 +137,7 @@ public class SkinParam implements ISkinParam {
|
||||
key = key.replaceAll("statearrow", "arrow");
|
||||
key = key.replaceAll("usecasearrow", "arrow");
|
||||
key = key.replaceAll("sequencearrow", "arrow");
|
||||
key = key.replaceAll("align$", "alignment");
|
||||
final Matcher2 mm = stereoPattern.matcher(key);
|
||||
final List<String> result = new ArrayList<String>();
|
||||
while (mm.find()) {
|
||||
@ -427,7 +428,9 @@ public class SkinParam implements ISkinParam {
|
||||
result.add("PageBorderColor");
|
||||
result.add("PageExternalColor");
|
||||
result.add("PageMargin");
|
||||
|
||||
result.add("WrapWidth");
|
||||
result.add("SwimlaneWidth");
|
||||
result.add("SwimlaneWrapTitleWidth");
|
||||
|
||||
for (FontParam p : EnumSet.allOf(FontParam.class)) {
|
||||
final String h = humanName(p.name());
|
||||
@ -444,6 +447,10 @@ public class SkinParam implements ISkinParam {
|
||||
final String h = capitalize(p.name());
|
||||
result.add(h + "Thickness");
|
||||
}
|
||||
for (AlignmentParam p : EnumSet.allOf(AlignmentParam.class)) {
|
||||
final String h = capitalize(p.name());
|
||||
result.add(h);
|
||||
}
|
||||
return Collections.unmodifiableSet(result);
|
||||
}
|
||||
|
||||
@ -470,14 +477,14 @@ public class SkinParam implements ISkinParam {
|
||||
return DotSplines.SPLINES;
|
||||
}
|
||||
|
||||
public HorizontalAlignment getHorizontalAlignment(AlignParam param, ArrowDirection arrowDirection) {
|
||||
public HorizontalAlignment getHorizontalAlignment(AlignmentParam param, ArrowDirection arrowDirection) {
|
||||
final String value;
|
||||
switch (param) {
|
||||
case SEQUENCE_MESSAGE_ALIGN:
|
||||
value = getArg(getValue(AlignParam.SEQUENCE_MESSAGE_ALIGN.name()), 0);
|
||||
case sequenceMessageAlignment:
|
||||
value = getArg(getValue(AlignmentParam.sequenceMessageAlignment.name()), 0);
|
||||
break;
|
||||
case SEQUENCE_MESSAGETEXT_ALIGN:
|
||||
value = getArg(getValue(AlignParam.SEQUENCE_MESSAGE_ALIGN.name()), 1);
|
||||
case sequenceMessageTextAlignment:
|
||||
value = getArg(getValue(AlignmentParam.sequenceMessageAlignment.name()), 1);
|
||||
break;
|
||||
default:
|
||||
value = getValue(param.name());
|
||||
@ -489,6 +496,9 @@ public class SkinParam implements ISkinParam {
|
||||
if (arrowDirection == ArrowDirection.RIGHT_TO_LEFT_REVERSE) {
|
||||
return HorizontalAlignment.RIGHT;
|
||||
}
|
||||
if (arrowDirection == ArrowDirection.BOTH_DIRECTION) {
|
||||
return HorizontalAlignment.CENTER;
|
||||
}
|
||||
}
|
||||
if ("reversedirection".equalsIgnoreCase(value)) {
|
||||
if (arrowDirection == ArrowDirection.LEFT_TO_RIGHT_NORMAL) {
|
||||
@ -497,9 +507,14 @@ public class SkinParam implements ISkinParam {
|
||||
if (arrowDirection == ArrowDirection.RIGHT_TO_LEFT_REVERSE) {
|
||||
return HorizontalAlignment.LEFT;
|
||||
}
|
||||
if (arrowDirection == ArrowDirection.BOTH_DIRECTION) {
|
||||
return HorizontalAlignment.CENTER;
|
||||
}
|
||||
}
|
||||
final HorizontalAlignment result = HorizontalAlignment.fromString(value);
|
||||
if (result == null) {
|
||||
if (result == null && param == AlignmentParam.noteTextAlignment) {
|
||||
return getDefaultTextAlignment(HorizontalAlignment.LEFT);
|
||||
} else if (result == null) {
|
||||
return param.getDefaultValue();
|
||||
}
|
||||
return result;
|
||||
@ -755,6 +770,11 @@ public class SkinParam implements ISkinParam {
|
||||
return new LineBreakStrategy(value);
|
||||
}
|
||||
|
||||
public LineBreakStrategy swimlaneWrapTitleWidth() {
|
||||
final String value = getValue("swimlanewraptitlewidth");
|
||||
return new LineBreakStrategy(value);
|
||||
}
|
||||
|
||||
public boolean strictUmlStyle() {
|
||||
final String value = getValue("style");
|
||||
if ("strictuml".equalsIgnoreCase(value)) {
|
||||
@ -917,7 +937,7 @@ public class SkinParam implements ISkinParam {
|
||||
public int swimlaneWidth() {
|
||||
final String value = getValue("swimlanewidth");
|
||||
if ("same".equalsIgnoreCase(value)) {
|
||||
return -1;
|
||||
return SWIMLANE_WIDTH_SAME;
|
||||
}
|
||||
if (value != null && value.matches("\\d+")) {
|
||||
return Integer.parseInt(value);
|
||||
|
@ -103,7 +103,7 @@ public class SkinParamDelegator implements ISkinParam {
|
||||
return skinParam.getDotExecutable();
|
||||
}
|
||||
|
||||
public HorizontalAlignment getHorizontalAlignment(AlignParam param, ArrowDirection arrowDirection) {
|
||||
public HorizontalAlignment getHorizontalAlignment(AlignmentParam param, ArrowDirection arrowDirection) {
|
||||
return skinParam.getHorizontalAlignment(param, arrowDirection);
|
||||
}
|
||||
|
||||
@ -295,4 +295,8 @@ public class SkinParamDelegator implements ISkinParam {
|
||||
return skinParam.getCircledCharacter(stereotype);
|
||||
}
|
||||
|
||||
public LineBreakStrategy swimlaneWrapTitleWidth() {
|
||||
return skinParam.swimlaneWrapTitleWidth();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -140,7 +140,7 @@ public abstract class SourceFileReaderAbstract {
|
||||
final List<GeneratedImage> result = new ArrayList<GeneratedImage>();
|
||||
|
||||
for (BlockUml blockUml : builder.getBlockUmls()) {
|
||||
SuggestedFile suggested = getSuggestedFile(blockUml);
|
||||
final SuggestedFile suggested = getSuggestedFile(blockUml);
|
||||
|
||||
final Diagram system;
|
||||
try {
|
||||
|
@ -52,6 +52,10 @@ public class SuggestedFile {
|
||||
this.initialCpt = initialCpt;
|
||||
}
|
||||
|
||||
public SuggestedFile withPreprocFormat() {
|
||||
return new SuggestedFile(outputFile, FileFormat.PREPROC, initialCpt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return outputFile.getAbsolutePath() + "[" + initialCpt + "]";
|
||||
|
@ -48,8 +48,11 @@ public class SvgString {
|
||||
this.scale = scale;
|
||||
}
|
||||
|
||||
public String getSvg() {
|
||||
public String getSvg(boolean raw) {
|
||||
String result = svg;
|
||||
if (raw) {
|
||||
return result;
|
||||
}
|
||||
if (result.startsWith("<?xml")) {
|
||||
final int idx = result.indexOf("<svg");
|
||||
result = result.substring(idx);
|
||||
|
@ -270,7 +270,7 @@ public abstract class UmlDiagram extends AbstractPSystem implements Diagram, Ann
|
||||
graphicStrings.drawU(ug);
|
||||
final double height = graphicStrings.calculateDimension(ug.getStringBounder()).getHeight();
|
||||
ug = ug.apply(new UTranslate(0, height));
|
||||
ug.draw(new UImage(im));
|
||||
ug.draw(new UImage(im).scaleNearestNeighbor(3));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ import net.sourceforge.plantuml.UmlDiagram;
|
||||
import net.sourceforge.plantuml.UmlDiagramType;
|
||||
import net.sourceforge.plantuml.Url;
|
||||
import net.sourceforge.plantuml.activitydiagram3.ftile.BoxStyle;
|
||||
import net.sourceforge.plantuml.activitydiagram3.ftile.Swimlanes;
|
||||
import net.sourceforge.plantuml.activitydiagram3.ftile.SwimlanesC;
|
||||
import net.sourceforge.plantuml.command.CommandExecutionResult;
|
||||
import net.sourceforge.plantuml.core.DiagramDescription;
|
||||
import net.sourceforge.plantuml.core.ImageData;
|
||||
@ -56,12 +56,13 @@ import net.sourceforge.plantuml.cucadiagram.Display;
|
||||
import net.sourceforge.plantuml.graphic.HtmlColor;
|
||||
import net.sourceforge.plantuml.graphic.Rainbow;
|
||||
import net.sourceforge.plantuml.graphic.TextBlock;
|
||||
import net.sourceforge.plantuml.graphic.TextBlockCompressed;
|
||||
import net.sourceforge.plantuml.graphic.TextBlockRecentred;
|
||||
import net.sourceforge.plantuml.graphic.color.Colors;
|
||||
import net.sourceforge.plantuml.sequencediagram.NotePosition;
|
||||
import net.sourceforge.plantuml.sequencediagram.NoteType;
|
||||
import net.sourceforge.plantuml.ugraphic.ImageBuilder;
|
||||
import net.sourceforge.plantuml.ugraphic.comp.CompressionMode;
|
||||
import net.sourceforge.plantuml.ugraphic.comp.TextBlockCompressedOnXorY;
|
||||
|
||||
public class ActivityDiagram3 extends UmlDiagram {
|
||||
|
||||
@ -71,7 +72,7 @@ public class ActivityDiagram3 extends UmlDiagram {
|
||||
|
||||
private SwimlaneStrategy swimlaneStrategy;
|
||||
|
||||
private final Swimlanes swinlanes = new Swimlanes(getSkinParam(), getPragma());
|
||||
private final SwimlanesC swinlanes = new SwimlanesC(getSkinParam(), getPragma());
|
||||
|
||||
private void manageSwimlaneStrategy() {
|
||||
if (swimlaneStrategy == null) {
|
||||
@ -191,8 +192,10 @@ public class ActivityDiagram3 extends UmlDiagram {
|
||||
throws IOException {
|
||||
// BUG42
|
||||
// COMPRESSION
|
||||
// TextBlock result = swinlanes;
|
||||
TextBlock result = new TextBlockCompressed(swinlanes);
|
||||
TextBlock result = swinlanes;
|
||||
// result = new TextBlockCompressedOnY(CompressionMode.ON_Y, result);
|
||||
// result = new TextBlockCompressedOnXorY(CompressionMode.ON_X, result);
|
||||
result = new TextBlockCompressedOnXorY(CompressionMode.ON_Y, result);
|
||||
result = new TextBlockRecentred(result);
|
||||
final ISkinParam skinParam = getSkinParam();
|
||||
result = new AnnotatedWorker(this, skinParam).addAdd(result);
|
||||
|
@ -39,7 +39,7 @@ import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import net.sourceforge.plantuml.AlignParam;
|
||||
import net.sourceforge.plantuml.AlignmentParam;
|
||||
import net.sourceforge.plantuml.ISkinParam;
|
||||
import net.sourceforge.plantuml.LineParam;
|
||||
import net.sourceforge.plantuml.activitydiagram3.LinkRendering;
|
||||
@ -98,7 +98,7 @@ public abstract class AbstractFtile extends AbstractTextBlock implements Ftile {
|
||||
}
|
||||
|
||||
public HorizontalAlignment arrowHorizontalAlignment() {
|
||||
return skinParam.getHorizontalAlignment(AlignParam.ARROW_MESSAGE_ALIGN, null);
|
||||
return skinParam.getHorizontalAlignment(AlignmentParam.arrowMessageAlignment, null);
|
||||
}
|
||||
|
||||
private FtileGeometry cachedGeometry;
|
||||
|
@ -49,12 +49,12 @@ import net.sourceforge.plantuml.graphic.Rainbow;
|
||||
import net.sourceforge.plantuml.graphic.StringBounder;
|
||||
import net.sourceforge.plantuml.graphic.TextBlock;
|
||||
import net.sourceforge.plantuml.graphic.TextBlockUtils;
|
||||
import net.sourceforge.plantuml.ugraphic.CompressionTransform;
|
||||
import net.sourceforge.plantuml.ugraphic.MinMax;
|
||||
import net.sourceforge.plantuml.ugraphic.UGraphic;
|
||||
import net.sourceforge.plantuml.ugraphic.UPolygon;
|
||||
import net.sourceforge.plantuml.ugraphic.UShape;
|
||||
import net.sourceforge.plantuml.ugraphic.UTranslate;
|
||||
import net.sourceforge.plantuml.ugraphic.comp.CompressionTransform;
|
||||
|
||||
public class Snake implements UShape {
|
||||
|
||||
|
@ -50,7 +50,7 @@ public class Swimlane implements SpecificBackcolorable {
|
||||
private Display display;
|
||||
|
||||
private UTranslate translate = new UTranslate();
|
||||
private double totalWidth;
|
||||
private double actualWidth;
|
||||
|
||||
public Swimlane(String name) {
|
||||
this.name = name;
|
||||
@ -79,9 +79,9 @@ public class Swimlane implements SpecificBackcolorable {
|
||||
return translate;
|
||||
}
|
||||
|
||||
public final void setTranslateAndWidth(UTranslate translate, double totalWidth) {
|
||||
public final void setTranslateAndWidth(UTranslate translate, double actualWidth) {
|
||||
this.translate = translate;
|
||||
this.totalWidth = totalWidth;
|
||||
this.actualWidth = actualWidth;
|
||||
}
|
||||
|
||||
public Colors getColors(ISkinParam skinParam) {
|
||||
@ -96,8 +96,8 @@ public class Swimlane implements SpecificBackcolorable {
|
||||
|
||||
private Colors colors = Colors.empty();
|
||||
|
||||
public final double getTotalWidth() {
|
||||
return totalWidth;
|
||||
public final double getActualWidth() {
|
||||
return actualWidth;
|
||||
}
|
||||
|
||||
public void setColors(Colors colors) {
|
||||
|
@ -71,7 +71,6 @@ import net.sourceforge.plantuml.skin.rose.Rose;
|
||||
import net.sourceforge.plantuml.svek.UGraphicForSnake;
|
||||
import net.sourceforge.plantuml.ugraphic.LimitFinder;
|
||||
import net.sourceforge.plantuml.ugraphic.MinMax;
|
||||
import net.sourceforge.plantuml.ugraphic.SlotSet;
|
||||
import net.sourceforge.plantuml.ugraphic.UChange;
|
||||
import net.sourceforge.plantuml.ugraphic.UChangeBackColor;
|
||||
import net.sourceforge.plantuml.ugraphic.UChangeColor;
|
||||
@ -81,6 +80,7 @@ import net.sourceforge.plantuml.ugraphic.URectangle;
|
||||
import net.sourceforge.plantuml.ugraphic.UShape;
|
||||
import net.sourceforge.plantuml.ugraphic.UStroke;
|
||||
import net.sourceforge.plantuml.ugraphic.UTranslate;
|
||||
import net.sourceforge.plantuml.ugraphic.comp.SlotSet;
|
||||
import net.sourceforge.plantuml.utils.MathUtils;
|
||||
|
||||
public class Swimlanes extends AbstractTextBlock implements TextBlock {
|
||||
@ -216,21 +216,20 @@ public class Swimlanes extends AbstractTextBlock implements TextBlock {
|
||||
if (back != null) {
|
||||
final UGraphic background = ug.apply(new UChangeBackColor(back)).apply(new UChangeColor(back))
|
||||
.apply(new UTranslate(x2, 0));
|
||||
background.draw(new URectangle(swimlane.getTotalWidth(), dimensionFull.getHeight()
|
||||
background.draw(new URectangle(swimlane.getActualWidth(), dimensionFull.getHeight()
|
||||
+ titleHeightTranslate.getDy()));
|
||||
}
|
||||
|
||||
final TextBlock swTitle = swimlane.getDisplay().create(getFontConfiguration(), HorizontalAlignment.LEFT,
|
||||
skinParam);
|
||||
final TextBlock swTitle = getTitle(swimlane);
|
||||
final double titleWidth = swTitle.calculateDimension(stringBounder).getWidth();
|
||||
final double posTitle = x2 + (swimlane.getTotalWidth() - titleWidth) / 2;
|
||||
final double posTitle = x2 + (swimlane.getActualWidth() - titleWidth) / 2;
|
||||
swTitle.drawU(ug.apply(new UTranslate(posTitle, 0)));
|
||||
|
||||
drawSeparation(ug.apply(new UTranslate(x2, 0)), dimensionFull.getHeight() + titleHeightTranslate.getDy());
|
||||
|
||||
full.drawU(new UGraphicInterceptorOneSwimlane(ug, swimlane).apply(swimlane.getTranslate()).apply(
|
||||
titleHeightTranslate));
|
||||
x2 += swimlane.getTotalWidth();
|
||||
x2 += swimlane.getActualWidth();
|
||||
|
||||
}
|
||||
drawSeparation(ug.apply(new UTranslate(x2, 0)), dimensionFull.getHeight() + titleHeightTranslate.getDy());
|
||||
@ -270,8 +269,7 @@ public class Swimlanes extends AbstractTextBlock implements TextBlock {
|
||||
final MinMax minMax = swimlane.getMinMax();
|
||||
|
||||
final double drawingWidth = minMax.getWidth() + 2 * separationMargin;
|
||||
final TextBlock swTitle = swimlane.getDisplay().create(getFontConfiguration(), HorizontalAlignment.LEFT,
|
||||
skinParam);
|
||||
final TextBlock swTitle = getTitle(swimlane);
|
||||
final double titleWidth = swTitle.calculateDimension(stringBounder).getWidth();
|
||||
final double totalWidth = MathUtils.max(swimlaneWidth, drawingWidth, titleWidth + 2 * separationMargin);
|
||||
|
||||
@ -286,8 +284,7 @@ public class Swimlanes extends AbstractTextBlock implements TextBlock {
|
||||
private UTranslate getTitleHeightTranslate(final StringBounder stringBounder) {
|
||||
double titlesHeight = 0;
|
||||
for (Swimlane swimlane : swimlanes) {
|
||||
final TextBlock swTitle = swimlane.getDisplay().create(getFontConfiguration(), HorizontalAlignment.LEFT,
|
||||
skinParam);
|
||||
final TextBlock swTitle = getTitle(swimlane);
|
||||
|
||||
titlesHeight = Math.max(titlesHeight, swTitle.calculateDimension(stringBounder).getHeight());
|
||||
}
|
||||
@ -295,6 +292,11 @@ public class Swimlanes extends AbstractTextBlock implements TextBlock {
|
||||
return titleHeightTranslate;
|
||||
}
|
||||
|
||||
private TextBlock getTitle(Swimlane swimlane) {
|
||||
return swimlane.getDisplay().create(getFontConfiguration(), HorizontalAlignment.LEFT, skinParam,
|
||||
skinParam.wrapWidth());
|
||||
}
|
||||
|
||||
private void drawSeparation(UGraphic ug, double height) {
|
||||
HtmlColor color = skinParam.getHtmlColor(ColorParam.swimlaneBorder, null, false);
|
||||
if (color == null) {
|
||||
|
@ -0,0 +1,309 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* (C) Copyright 2009-2017, Arnaud Roques
|
||||
*
|
||||
* Project Info: http://plantuml.com
|
||||
*
|
||||
* If you like this project or if you find it useful, you can support us at:
|
||||
*
|
||||
* http://plantuml.com/patreon (only 1$ per month!)
|
||||
* http://plantuml.com/paypal
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*
|
||||
*
|
||||
* Original Author: Arnaud Roques
|
||||
*
|
||||
*
|
||||
*/
|
||||
package net.sourceforge.plantuml.activitydiagram3.ftile;
|
||||
|
||||
import java.awt.geom.Dimension2D;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import net.sourceforge.plantuml.FontParam;
|
||||
import net.sourceforge.plantuml.ISkinParam;
|
||||
import net.sourceforge.plantuml.Pragma;
|
||||
import net.sourceforge.plantuml.activitydiagram3.Instruction;
|
||||
import net.sourceforge.plantuml.activitydiagram3.InstructionList;
|
||||
import net.sourceforge.plantuml.activitydiagram3.LinkRendering;
|
||||
import net.sourceforge.plantuml.activitydiagram3.ftile.vcompact.FtileFactoryDelegatorAddNote;
|
||||
import net.sourceforge.plantuml.activitydiagram3.ftile.vcompact.FtileFactoryDelegatorAddUrl;
|
||||
import net.sourceforge.plantuml.activitydiagram3.ftile.vcompact.FtileFactoryDelegatorAssembly;
|
||||
import net.sourceforge.plantuml.activitydiagram3.ftile.vcompact.FtileFactoryDelegatorCreateGroup;
|
||||
import net.sourceforge.plantuml.activitydiagram3.ftile.vcompact.FtileFactoryDelegatorCreateParallel;
|
||||
import net.sourceforge.plantuml.activitydiagram3.ftile.vcompact.FtileFactoryDelegatorIf;
|
||||
import net.sourceforge.plantuml.activitydiagram3.ftile.vcompact.FtileFactoryDelegatorRepeat;
|
||||
import net.sourceforge.plantuml.activitydiagram3.ftile.vcompact.FtileFactoryDelegatorWhile;
|
||||
import net.sourceforge.plantuml.activitydiagram3.ftile.vcompact.UGraphicInterceptorOneSwimlane;
|
||||
import net.sourceforge.plantuml.activitydiagram3.ftile.vcompact.VCompactFactory;
|
||||
import net.sourceforge.plantuml.cucadiagram.Display;
|
||||
import net.sourceforge.plantuml.graphic.AbstractTextBlock;
|
||||
import net.sourceforge.plantuml.graphic.FontConfiguration;
|
||||
import net.sourceforge.plantuml.graphic.HorizontalAlignment;
|
||||
import net.sourceforge.plantuml.graphic.HtmlColor;
|
||||
import net.sourceforge.plantuml.graphic.StringBounder;
|
||||
import net.sourceforge.plantuml.graphic.TextBlock;
|
||||
import net.sourceforge.plantuml.graphic.TextBlockUtils;
|
||||
import net.sourceforge.plantuml.graphic.UGraphicDelegator;
|
||||
import net.sourceforge.plantuml.graphic.color.ColorType;
|
||||
import net.sourceforge.plantuml.svek.UGraphicForSnake;
|
||||
import net.sourceforge.plantuml.ugraphic.LimitFinder;
|
||||
import net.sourceforge.plantuml.ugraphic.MinMax;
|
||||
import net.sourceforge.plantuml.ugraphic.UChange;
|
||||
import net.sourceforge.plantuml.ugraphic.UChangeBackColor;
|
||||
import net.sourceforge.plantuml.ugraphic.UChangeColor;
|
||||
import net.sourceforge.plantuml.ugraphic.UGraphic;
|
||||
import net.sourceforge.plantuml.ugraphic.URectangle;
|
||||
import net.sourceforge.plantuml.ugraphic.UShape;
|
||||
import net.sourceforge.plantuml.ugraphic.UTranslate;
|
||||
import net.sourceforge.plantuml.ugraphic.comp.SlotSet;
|
||||
import net.sourceforge.plantuml.utils.MathUtils;
|
||||
|
||||
public class SwimlanesA extends AbstractTextBlock implements TextBlock {
|
||||
|
||||
protected final ISkinParam skinParam;;
|
||||
private final Pragma pragma;
|
||||
|
||||
protected final List<Swimlane> swimlanes = new ArrayList<Swimlane>();
|
||||
private Swimlane currentSwimlane = null;
|
||||
|
||||
private final Instruction root = new InstructionList();
|
||||
private Instruction currentInstruction = root;
|
||||
|
||||
private LinkRendering nextLinkRenderer = LinkRendering.none();
|
||||
|
||||
public SwimlanesA(ISkinParam skinParam, Pragma pragma) {
|
||||
this.skinParam = skinParam;
|
||||
this.pragma = pragma;
|
||||
}
|
||||
|
||||
private FtileFactory getFtileFactory(StringBounder stringBounder) {
|
||||
FtileFactory factory = new VCompactFactory(skinParam, stringBounder);
|
||||
factory = new FtileFactoryDelegatorAddUrl(factory);
|
||||
factory = new FtileFactoryDelegatorAssembly(factory);
|
||||
factory = new FtileFactoryDelegatorIf(factory, pragma);
|
||||
factory = new FtileFactoryDelegatorWhile(factory);
|
||||
factory = new FtileFactoryDelegatorRepeat(factory);
|
||||
factory = new FtileFactoryDelegatorCreateParallel(factory);
|
||||
// factory = new FtileFactoryDelegatorCreateParallelAddingMargin(new
|
||||
// FtileFactoryDelegatorCreateParallel1(factory));
|
||||
factory = new FtileFactoryDelegatorAddNote(factory);
|
||||
factory = new FtileFactoryDelegatorCreateGroup(factory);
|
||||
return factory;
|
||||
}
|
||||
|
||||
public void swimlane(String name, HtmlColor color, Display label) {
|
||||
currentSwimlane = getOrCreate(name);
|
||||
if (color != null) {
|
||||
currentSwimlane.setSpecificColorTOBEREMOVED(ColorType.BACK, color);
|
||||
}
|
||||
if (Display.isNull(label) == false) {
|
||||
currentSwimlane.setDisplay(label);
|
||||
}
|
||||
}
|
||||
|
||||
private Swimlane getOrCreate(String name) {
|
||||
for (Swimlane s : swimlanes) {
|
||||
if (s.getName().equals(name)) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
final Swimlane result = new Swimlane(name);
|
||||
swimlanes.add(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
class Cross extends UGraphicDelegator {
|
||||
|
||||
private Cross(UGraphic ug) {
|
||||
super(ug);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(UShape shape) {
|
||||
if (shape instanceof Ftile) {
|
||||
final Ftile tile = (Ftile) shape;
|
||||
tile.drawU(this);
|
||||
} else if (shape instanceof Connection) {
|
||||
final Connection connection = (Connection) shape;
|
||||
final Ftile tile1 = connection.getFtile1();
|
||||
final Ftile tile2 = connection.getFtile2();
|
||||
|
||||
if (tile1 == null || tile2 == null) {
|
||||
return;
|
||||
}
|
||||
if (tile1.getSwimlaneOut() != tile2.getSwimlaneIn()) {
|
||||
final ConnectionCross connectionCross = new ConnectionCross(connection);
|
||||
connectionCross.drawU(getUg());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public UGraphic apply(UChange change) {
|
||||
return new Cross(getUg().apply(change));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static protected final double separationMargin = 10;
|
||||
|
||||
private TextBlock full;
|
||||
|
||||
public void drawU(UGraphic ug) {
|
||||
if (full == null) {
|
||||
final FtileFactory factory = getFtileFactory(ug.getStringBounder());
|
||||
full = root.createFtile(factory);
|
||||
if (swimlanes.size() <= 1) {
|
||||
// BUG42
|
||||
full = new TextBlockInterceptorUDrawable(full);
|
||||
}
|
||||
}
|
||||
|
||||
ug = new UGraphicForSnake(ug);
|
||||
if (swimlanes.size() <= 1) {
|
||||
full.drawU(ug);
|
||||
ug.flushUg();
|
||||
return;
|
||||
}
|
||||
|
||||
drawWhenSwimlanes(ug, full);
|
||||
}
|
||||
|
||||
static private void printDebug(UGraphic ug, SlotSet slot, HtmlColor col, TextBlock full) {
|
||||
slot.drawDebugX(ug.apply(new UChangeColor(col)).apply(new UChangeBackColor(col)),
|
||||
full.calculateDimension(ug.getStringBounder()).getHeight());
|
||||
|
||||
}
|
||||
|
||||
protected void drawWhenSwimlanes(final UGraphic ug, TextBlock full) {
|
||||
final StringBounder stringBounder = ug.getStringBounder();
|
||||
final Dimension2D dimensionFull = full.calculateDimension(stringBounder);
|
||||
|
||||
computeSize(ug, full);
|
||||
final UTranslate titleHeightTranslate = getTitleHeightTranslate(stringBounder);
|
||||
|
||||
double x2 = 0;
|
||||
for (Swimlane swimlane : swimlanes) {
|
||||
final HtmlColor back = swimlane.getColors(skinParam).getColor(ColorType.BACK);
|
||||
if (back != null) {
|
||||
final UGraphic background = ug.apply(new UChangeBackColor(back)).apply(new UChangeColor(back))
|
||||
.apply(new UTranslate(x2, 0));
|
||||
background.draw(new URectangle(swimlane.getActualWidth(), dimensionFull.getHeight()
|
||||
+ titleHeightTranslate.getDy()));
|
||||
}
|
||||
|
||||
full.drawU(new UGraphicInterceptorOneSwimlane(ug, swimlane).apply(swimlane.getTranslate()).apply(
|
||||
titleHeightTranslate));
|
||||
x2 += swimlane.getActualWidth();
|
||||
|
||||
}
|
||||
final Cross cross = new Cross(ug.apply(titleHeightTranslate));
|
||||
full.drawU(cross);
|
||||
cross.flushUg();
|
||||
}
|
||||
|
||||
protected UTranslate getTitleHeightTranslate(final StringBounder stringBounder) {
|
||||
return new UTranslate();
|
||||
}
|
||||
|
||||
private void computeDrawingWidths(UGraphic ug, TextBlock full) {
|
||||
final StringBounder stringBounder = ug.getStringBounder();
|
||||
for (Swimlane swimlane : swimlanes) {
|
||||
final LimitFinder limitFinder = new LimitFinder(stringBounder, false);
|
||||
final UGraphicInterceptorOneSwimlane interceptor = new UGraphicInterceptorOneSwimlane(new UGraphicForSnake(
|
||||
limitFinder), swimlane);
|
||||
full.drawU(interceptor);
|
||||
interceptor.flushUg();
|
||||
final MinMax minMax = limitFinder.getMinMax();
|
||||
swimlane.setMinMax(minMax);
|
||||
}
|
||||
}
|
||||
|
||||
private void computeSize(UGraphic ug, TextBlock full) {
|
||||
computeDrawingWidths(ug, full);
|
||||
double x1 = 0;
|
||||
|
||||
double swimlaneWidth = skinParam.swimlaneWidth();
|
||||
|
||||
if (swimlaneWidth == ISkinParam.SWIMLANE_WIDTH_SAME) {
|
||||
for (Swimlane swimlane : swimlanes) {
|
||||
swimlaneWidth = Math.max(swimlaneWidth, rawDrawingWidth(swimlane));
|
||||
}
|
||||
|
||||
}
|
||||
for (Swimlane swimlane : swimlanes) {
|
||||
final double swimlaneActualWidth = swimlaneActualWidth(ug.getStringBounder(), swimlaneWidth, swimlane);
|
||||
|
||||
final UTranslate translate = new UTranslate(x1 - swimlane.getMinMax().getMinX() + separationMargin
|
||||
+ (swimlaneActualWidth - rawDrawingWidth(swimlane)) / 2.0, 0);
|
||||
swimlane.setTranslateAndWidth(translate, swimlaneActualWidth);
|
||||
|
||||
x1 += swimlaneActualWidth;
|
||||
}
|
||||
}
|
||||
|
||||
protected double swimlaneActualWidth(StringBounder stringBounder, double swimlaneWidth, Swimlane swimlane) {
|
||||
return MathUtils.max(swimlaneWidth, rawDrawingWidth(swimlane));
|
||||
}
|
||||
|
||||
private double rawDrawingWidth(Swimlane swimlane) {
|
||||
return swimlane.getMinMax().getWidth() + 2 * separationMargin;
|
||||
}
|
||||
|
||||
public Dimension2D calculateDimension(StringBounder stringBounder) {
|
||||
return getMinMax(stringBounder).getDimension();
|
||||
}
|
||||
|
||||
public Instruction getCurrent() {
|
||||
return currentInstruction;
|
||||
}
|
||||
|
||||
public void setCurrent(Instruction current) {
|
||||
this.currentInstruction = current;
|
||||
}
|
||||
|
||||
public LinkRendering nextLinkRenderer() {
|
||||
return nextLinkRenderer;
|
||||
}
|
||||
|
||||
public void setNextLinkRenderer(LinkRendering link) {
|
||||
if (link == null) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
this.nextLinkRenderer = link;
|
||||
}
|
||||
|
||||
public Swimlane getCurrentSwimlane() {
|
||||
return currentSwimlane;
|
||||
}
|
||||
|
||||
private MinMax cachedMinMax;
|
||||
|
||||
@Override
|
||||
public MinMax getMinMax(StringBounder stringBounder) {
|
||||
if (cachedMinMax == null) {
|
||||
cachedMinMax = TextBlockUtils.getMinMax(this, stringBounder);
|
||||
}
|
||||
return cachedMinMax;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,112 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* (C) Copyright 2009-2017, Arnaud Roques
|
||||
*
|
||||
* Project Info: http://plantuml.com
|
||||
*
|
||||
* If you like this project or if you find it useful, you can support us at:
|
||||
*
|
||||
* http://plantuml.com/patreon (only 1$ per month!)
|
||||
* http://plantuml.com/paypal
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*
|
||||
*
|
||||
* Original Author: Arnaud Roques
|
||||
*
|
||||
*
|
||||
*/
|
||||
package net.sourceforge.plantuml.activitydiagram3.ftile;
|
||||
|
||||
import net.sourceforge.plantuml.FontParam;
|
||||
import net.sourceforge.plantuml.ISkinParam;
|
||||
import net.sourceforge.plantuml.LineBreakStrategy;
|
||||
import net.sourceforge.plantuml.Pragma;
|
||||
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.ugraphic.UGraphic;
|
||||
import net.sourceforge.plantuml.ugraphic.UTranslate;
|
||||
import net.sourceforge.plantuml.utils.MathUtils;
|
||||
|
||||
public class SwimlanesB extends SwimlanesA {
|
||||
|
||||
public SwimlanesB(ISkinParam skinParam, Pragma pragma) {
|
||||
super(skinParam, pragma);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawWhenSwimlanes(UGraphic ug, TextBlock full) {
|
||||
super.drawWhenSwimlanes(ug, full);
|
||||
double x2 = 0;
|
||||
|
||||
final StringBounder stringBounder = ug.getStringBounder();
|
||||
for (Swimlane swimlane : swimlanes) {
|
||||
final TextBlock swTitle = getTitle(swimlane);
|
||||
final double titleWidth = swTitle.calculateDimension(stringBounder).getWidth();
|
||||
final double posTitle = x2 + (swimlane.getActualWidth() - titleWidth) / 2;
|
||||
swTitle.drawU(ug.apply(new UTranslate(posTitle, 0)));
|
||||
x2 += swimlane.getActualWidth();
|
||||
}
|
||||
}
|
||||
|
||||
private TextBlock getTitle(Swimlane swimlane) {
|
||||
final FontConfiguration fontConfiguration = new FontConfiguration(skinParam, FontParam.SWIMLANE_TITLE, null);
|
||||
|
||||
LineBreakStrategy wrap = getWrap();
|
||||
if (wrap.isAuto()) {
|
||||
wrap = new LineBreakStrategy("" + ((int) swimlane.getActualWidth()));
|
||||
}
|
||||
|
||||
return swimlane.getDisplay().create(fontConfiguration, HorizontalAlignment.LEFT, skinParam, wrap);
|
||||
}
|
||||
|
||||
private LineBreakStrategy getWrap() {
|
||||
LineBreakStrategy wrap = skinParam.swimlaneWrapTitleWidth();
|
||||
if (wrap == LineBreakStrategy.NONE) {
|
||||
wrap = skinParam.wrapWidth();
|
||||
}
|
||||
return wrap;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected double swimlaneActualWidth(StringBounder stringBounder, double swimlaneWidth, Swimlane swimlane) {
|
||||
final double m1 = super.swimlaneActualWidth(stringBounder, swimlaneWidth, swimlane);
|
||||
if (getWrap().isAuto()) {
|
||||
return m1;
|
||||
}
|
||||
|
||||
final double titleWidth = getTitle(swimlane).calculateDimension(stringBounder).getWidth();
|
||||
return MathUtils.max(m1, titleWidth + 2 * separationMargin);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected UTranslate getTitleHeightTranslate(final StringBounder stringBounder) {
|
||||
double titlesHeight = 0;
|
||||
for (Swimlane swimlane : swimlanes) {
|
||||
final TextBlock swTitle = getTitle(swimlane);
|
||||
titlesHeight = Math.max(titlesHeight, swTitle.calculateDimension(stringBounder).getHeight());
|
||||
}
|
||||
return new UTranslate(0, titlesHeight);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,89 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* (C) Copyright 2009-2017, Arnaud Roques
|
||||
*
|
||||
* Project Info: http://plantuml.com
|
||||
*
|
||||
* If you like this project or if you find it useful, you can support us at:
|
||||
*
|
||||
* http://plantuml.com/patreon (only 1$ per month!)
|
||||
* http://plantuml.com/paypal
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*
|
||||
*
|
||||
* Original Author: Arnaud Roques
|
||||
*
|
||||
*
|
||||
*/
|
||||
package net.sourceforge.plantuml.activitydiagram3.ftile;
|
||||
|
||||
import java.awt.geom.Dimension2D;
|
||||
|
||||
import net.sourceforge.plantuml.ColorParam;
|
||||
import net.sourceforge.plantuml.ISkinParam;
|
||||
import net.sourceforge.plantuml.LineParam;
|
||||
import net.sourceforge.plantuml.Pragma;
|
||||
import net.sourceforge.plantuml.graphic.HtmlColor;
|
||||
import net.sourceforge.plantuml.graphic.StringBounder;
|
||||
import net.sourceforge.plantuml.graphic.TextBlock;
|
||||
import net.sourceforge.plantuml.skin.rose.Rose;
|
||||
import net.sourceforge.plantuml.ugraphic.UChangeColor;
|
||||
import net.sourceforge.plantuml.ugraphic.UGraphic;
|
||||
import net.sourceforge.plantuml.ugraphic.ULine;
|
||||
import net.sourceforge.plantuml.ugraphic.UStroke;
|
||||
import net.sourceforge.plantuml.ugraphic.UTranslate;
|
||||
|
||||
public class SwimlanesC extends SwimlanesB {
|
||||
|
||||
public SwimlanesC(ISkinParam skinParam, Pragma pragma) {
|
||||
super(skinParam, pragma);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawWhenSwimlanes(UGraphic ug, TextBlock full) {
|
||||
super.drawWhenSwimlanes(ug, full);
|
||||
double x2 = 0;
|
||||
|
||||
final StringBounder stringBounder = ug.getStringBounder();
|
||||
final Dimension2D dimensionFull = full.calculateDimension(stringBounder);
|
||||
|
||||
final UTranslate titleHeightTranslate = getTitleHeightTranslate(stringBounder);
|
||||
|
||||
for (Swimlane swimlane : swimlanes) {
|
||||
drawSeparation(ug.apply(new UTranslate(x2, 0)), dimensionFull.getHeight() + titleHeightTranslate.getDy());
|
||||
|
||||
x2 += swimlane.getActualWidth();
|
||||
|
||||
}
|
||||
drawSeparation(ug.apply(new UTranslate(x2, 0)), dimensionFull.getHeight() + titleHeightTranslate.getDy());
|
||||
|
||||
}
|
||||
|
||||
private void drawSeparation(UGraphic ug, double height) {
|
||||
HtmlColor color = skinParam.getHtmlColor(ColorParam.swimlaneBorder, null, false);
|
||||
if (color == null) {
|
||||
color = ColorParam.swimlaneBorder.getDefaultValue();
|
||||
}
|
||||
final UStroke thickness = Rose.getStroke(skinParam, LineParam.swimlaneBorder, 2);
|
||||
ug.apply(thickness).apply(new UChangeColor(color)).draw(new ULine(0, height));
|
||||
}
|
||||
|
||||
}
|
@ -38,7 +38,7 @@ package net.sourceforge.plantuml.activitydiagram3.ftile.vcompact;
|
||||
import java.awt.geom.Dimension2D;
|
||||
import java.util.Set;
|
||||
|
||||
import net.sourceforge.plantuml.AlignParam;
|
||||
import net.sourceforge.plantuml.AlignmentParam;
|
||||
import net.sourceforge.plantuml.FontParam;
|
||||
import net.sourceforge.plantuml.ISkinParam;
|
||||
import net.sourceforge.plantuml.LineParam;
|
||||
@ -196,7 +196,7 @@ public class FtileGroup extends AbstractFtile {
|
||||
|
||||
final SymbolContext symbolContext = new SymbolContext(backColor, borderColor).withShadow(
|
||||
skinParam().shadowing()).withStroke(stroke);
|
||||
USymbol.FRAME.asBig(name, inner.skinParam().getHorizontalAlignment(AlignParam.PACKAGE_TITLE_ALIGNMENT, null),
|
||||
USymbol.FRAME.asBig(name, inner.skinParam().getHorizontalAlignment(AlignmentParam.packageTitleAlignment, null),
|
||||
TextBlockUtils.empty(0, 0), dimTotal.getWidth(), dimTotal.getHeight(), symbolContext).drawU(ug);
|
||||
|
||||
final Dimension2D dimHeaderNote = headerNote.calculateDimension(stringBounder);
|
||||
|
@ -250,7 +250,6 @@ class FtileWhile extends AbstractFtile {
|
||||
final double x1 = p1.getX();
|
||||
final double y1 = p1.getY();
|
||||
final double x2 = p2.getX() + dimDiamond1.getWidth();
|
||||
// final double y2 = p2.getY() + dimDiamond1.getOutY() / 2;
|
||||
final double half = (dimDiamond1.getOutY() - dimDiamond1.getInY()) / 2;
|
||||
final double y2 = p2.getY() + dimDiamond1.getInY() + half;
|
||||
|
||||
@ -268,8 +267,6 @@ class FtileWhile extends AbstractFtile {
|
||||
|
||||
ug.apply(new UTranslate(x1, y1bis)).draw(new UEmpty(5, Diamond.diamondHalfSize));
|
||||
|
||||
// ug = ug.apply(new UChangeColor(endInlinkColor)).apply(new UChangeBackColor(endInlinkColor));
|
||||
// ug.apply(new UTranslate(xx, (y1 + y2) / 2)).draw(Arrows.asToUp());
|
||||
}
|
||||
|
||||
public void drawTranslate(UGraphic ug, UTranslate translate1, UTranslate translate2) {
|
||||
@ -281,12 +278,13 @@ class FtileWhile extends AbstractFtile {
|
||||
final Point2D p1 = translate1.getTranslated(ap1);
|
||||
final Point2D p2 = translate2.getTranslated(ap2);
|
||||
|
||||
final Dimension2D dimDiamond1 = diamond1.calculateDimension(stringBounder);
|
||||
final FtileGeometry dimDiamond1 = diamond1.calculateDimension(stringBounder);
|
||||
|
||||
final double x1 = p1.getX();
|
||||
final double y1 = p1.getY();
|
||||
final double x2 = p2.getX() + dimDiamond1.getWidth();
|
||||
final double y2 = p2.getY() + dimDiamond1.getHeight() / 2;
|
||||
final double half = (dimDiamond1.getOutY() - dimDiamond1.getInY()) / 2;
|
||||
final double y2 = p2.getY() + dimDiamond1.getInY() + half;
|
||||
|
||||
snake.addPoint(x1, y1);
|
||||
snake.addPoint(x1, y1 + Diamond.diamondHalfSize);
|
||||
@ -402,8 +400,6 @@ class FtileWhile extends AbstractFtile {
|
||||
snake.goUnmergeable(MergeStrategy.LIMITED);
|
||||
|
||||
ug.draw(snake);
|
||||
// ug = ug.apply(new UChangeColor(afterEndwhileColor)).apply(new UChangeBackColor(afterEndwhileColor));
|
||||
// ug.apply(new UTranslate(Diamond.diamondHalfSize, (y1 + y2) / 2)).draw(Arrows.asToDown());
|
||||
|
||||
final Snake snake2 = new Snake(arrowHorizontalAlignment(), afterEndwhileColor);
|
||||
snake2.addPoint(Diamond.diamondHalfSize, y2);
|
||||
|
@ -125,7 +125,7 @@ public class FtileBox extends AbstractFtile {
|
||||
final FontConfiguration fc = new FontConfiguration(skinParam, FontParam.ACTIVITY, null);
|
||||
final Sheet sheet = new CreoleParser(fc, skinParam.getDefaultTextAlignment(HorizontalAlignment.LEFT),
|
||||
skinParam, CreoleMode.FULL).createSheet(label);
|
||||
this.tb = new SheetBlock2(new SheetBlock1(sheet, LineBreakStrategy.NONE, skinParam.getPadding()), new MyStencil(), new UStroke(1));
|
||||
this.tb = new SheetBlock2(new SheetBlock1(sheet, skinParam.wrapWidth(), skinParam.getPadding()), new MyStencil(), new UStroke(1));
|
||||
this.print = label.toString();
|
||||
}
|
||||
|
||||
|
@ -33,31 +33,30 @@
|
||||
*
|
||||
*
|
||||
*/
|
||||
package net.sourceforge.plantuml.graphic;
|
||||
package net.sourceforge.plantuml.code;
|
||||
|
||||
import java.awt.geom.Dimension2D;
|
||||
import java.io.IOException;
|
||||
|
||||
import net.sourceforge.plantuml.Dimension2DDouble;
|
||||
import net.sourceforge.plantuml.ugraphic.CompressionTransform;
|
||||
import net.sourceforge.plantuml.ugraphic.UGraphic;
|
||||
import net.sourceforge.plantuml.ugraphic.UGraphicCompress2;
|
||||
import net.sourceforge.plantuml.StringUtils;
|
||||
|
||||
public class TextBlockCompressed2 extends AbstractTextBlock implements TextBlock {
|
||||
public class ArobaseStringCompressor2 implements StringCompressor {
|
||||
|
||||
private final TextBlock textBlock;
|
||||
private final CompressionTransform compressionTransform;
|
||||
|
||||
public TextBlockCompressed2(TextBlock textBlock, CompressionTransform compressionTransform) {
|
||||
this.textBlock = textBlock;
|
||||
this.compressionTransform = compressionTransform;
|
||||
public String compress(String data) throws IOException {
|
||||
return clean2(data);
|
||||
}
|
||||
|
||||
public void drawU(final UGraphic ug) {
|
||||
textBlock.drawU(new UGraphicCompress2(ug, compressionTransform));
|
||||
public String decompress(String s) throws IOException {
|
||||
return clean2(s);
|
||||
}
|
||||
|
||||
public Dimension2D calculateDimension(StringBounder stringBounder) {
|
||||
final Dimension2D dim = textBlock.calculateDimension(stringBounder);
|
||||
return new Dimension2DDouble(compressionTransform.transform(dim.getWidth()), dim.getHeight());
|
||||
private String clean2(String s) {
|
||||
s = s.replace("\0", "");
|
||||
s = StringUtils.trin(s);
|
||||
s = s.replace("\r", "").replaceAll("\n+$", "");
|
||||
if (s.startsWith("@start")) {
|
||||
return s;
|
||||
}
|
||||
return "@startuml\n" + s + "\n@enduml";
|
||||
}
|
||||
|
||||
}
|
109
src/net/sourceforge/plantuml/code/TranscoderSmart2.java
Normal file
109
src/net/sourceforge/plantuml/code/TranscoderSmart2.java
Normal file
@ -0,0 +1,109 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* (C) Copyright 2009-2017, Arnaud Roques
|
||||
*
|
||||
* Project Info: http://plantuml.com
|
||||
*
|
||||
* If you like this project or if you find it useful, you can support us at:
|
||||
*
|
||||
* http://plantuml.com/patreon (only 1$ per month!)
|
||||
* http://plantuml.com/paypal
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*
|
||||
*
|
||||
* Original Author: Arnaud Roques
|
||||
*
|
||||
*
|
||||
*/
|
||||
package net.sourceforge.plantuml.code;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class TranscoderSmart2 implements Transcoder {
|
||||
|
||||
// Legacy encoder
|
||||
private final Transcoder oldOne = new TranscoderImpl(new AsciiEncoder(), new ArobaseStringCompressor2(),
|
||||
new CompressionHuffman());
|
||||
private final Transcoder zlib = new TranscoderImpl(new AsciiEncoder(), new ArobaseStringCompressor2(),
|
||||
new CompressionZlib());
|
||||
private final Transcoder brotli = new TranscoderImpl(new AsciiEncoder(), new ArobaseStringCompressor2(),
|
||||
new CompressionBrotli());
|
||||
|
||||
|
||||
private final Transcoder zlibBase64 = new TranscoderImpl(new AsciiEncoderBase64(), new ArobaseStringCompressor2(),
|
||||
new CompressionZlib());
|
||||
private final Transcoder brotliBase64 = new TranscoderImpl(new AsciiEncoderBase64(), new ArobaseStringCompressor2(),
|
||||
new CompressionBrotli());
|
||||
private final Transcoder base64only = new TranscoderImpl(new AsciiEncoderBase64(), new ArobaseStringCompressor2(),
|
||||
new CompressionNone());
|
||||
private final Transcoder hexOnly = new TranscoderImpl(new AsciiEncoderHex(), new ArobaseStringCompressor2(),
|
||||
new CompressionNone());
|
||||
|
||||
public String decode(String code) throws IOException {
|
||||
// Work in progress
|
||||
// See https://github.com/plantuml/plantuml/issues/117
|
||||
|
||||
// Two char headers
|
||||
if (code.startsWith("0A")) {
|
||||
return zlibBase64.decode(code.substring(2));
|
||||
}
|
||||
if (code.startsWith("0B")) {
|
||||
return brotliBase64.decode(code.substring(2));
|
||||
}
|
||||
if (code.startsWith("0C")) {
|
||||
return base64only.decode(code.substring(2));
|
||||
}
|
||||
if (code.startsWith("0D")) {
|
||||
return hexOnly.decode(code.substring(2));
|
||||
}
|
||||
// Text prefix
|
||||
// Just a wild try: use them only for testing
|
||||
if (code.startsWith("-deflate-")) {
|
||||
return zlibBase64.decode(code.substring("-deflate-".length()));
|
||||
}
|
||||
if (code.startsWith("-brotli-")) {
|
||||
return brotliBase64.decode(code.substring("-brotli-".length()));
|
||||
}
|
||||
if (code.startsWith("-base64-")) {
|
||||
return base64only.decode(code.substring("-base64-".length()));
|
||||
}
|
||||
if (code.startsWith("-hex-")) {
|
||||
return hexOnly.decode(code.substring("-hex-".length()));
|
||||
}
|
||||
|
||||
// Legacy decoding : you should not use it any more.
|
||||
if (code.startsWith("0")) {
|
||||
return brotli.decode(code.substring(1));
|
||||
}
|
||||
try {
|
||||
return zlib.decode(code);
|
||||
} catch (Exception ex) {
|
||||
return oldOne.decode(code);
|
||||
}
|
||||
// return zlib.decode(code);
|
||||
}
|
||||
|
||||
public String encode(String text) throws IOException {
|
||||
// Right now, we still use the legacy encoding.
|
||||
// This will be changed in the incoming months
|
||||
return zlib.encode(text);
|
||||
}
|
||||
}
|
@ -41,4 +41,8 @@ public class TranscoderUtil {
|
||||
return new TranscoderSmart();
|
||||
}
|
||||
|
||||
public static Transcoder getDefaultTranscoder2() {
|
||||
return new TranscoderSmart2();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -40,6 +40,8 @@ import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import net.sourceforge.plantuml.Log;
|
||||
|
||||
public class Matcher2 {
|
||||
|
||||
private final static boolean INSTRUMENT = false;
|
||||
@ -80,6 +82,7 @@ public class Matcher2 {
|
||||
}
|
||||
|
||||
private static final Map<String, Long> durations = new HashMap<String, Long>();
|
||||
private static long printed;
|
||||
|
||||
private static synchronized void addTime(String id, long duration) {
|
||||
Long total = durations.get(id);
|
||||
@ -88,12 +91,29 @@ public class Matcher2 {
|
||||
}
|
||||
total += duration;
|
||||
durations.put(id, total);
|
||||
if (total > 200) {
|
||||
System.err.println("foo " + total + " " + id);
|
||||
final String longest = getLongest();
|
||||
if (longest == null) {
|
||||
return;
|
||||
}
|
||||
if (durations.get(longest) > printed) {
|
||||
Log.info("---------- Regex " + longest + " " + durations.get(longest) + "ms (" + durations.size() + ")");
|
||||
printed = durations.get(longest);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static String getLongest() {
|
||||
long max = 0;
|
||||
String result = null;
|
||||
for (Map.Entry<String, Long> ent : durations.entrySet()) {
|
||||
if (ent.getValue() > max) {
|
||||
max = ent.getValue();
|
||||
result = ent.getKey();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public String group(int n) {
|
||||
final long now = System.currentTimeMillis();
|
||||
try {
|
||||
|
@ -291,7 +291,7 @@ public class AtomText implements Atom {
|
||||
}
|
||||
|
||||
public List<AtomText> getSplitted(StringBounder stringBounder, LineBreakStrategy maxWidthAsString) {
|
||||
final double maxWidth = maxWidthAsString.getMathWidth();
|
||||
final double maxWidth = maxWidthAsString.getMaxWidth();
|
||||
final List<AtomText> result = new ArrayList<AtomText>();
|
||||
final StringTokenizer st = new StringTokenizer(text, " ", true);
|
||||
final StringBuilder currentLine = new StringBuilder();
|
||||
|
@ -58,7 +58,7 @@ public class Fission {
|
||||
}
|
||||
|
||||
public List<Stripe> getSplitted(StringBounder stringBounder) {
|
||||
final double valueMaxWidth = maxWidth.getMathWidth();
|
||||
final double valueMaxWidth = maxWidth.getMaxWidth();
|
||||
if (valueMaxWidth == 0) {
|
||||
return Arrays.asList(stripe);
|
||||
}
|
||||
|
@ -146,7 +146,7 @@ public class BodyEnhanced extends AbstractTextBlock implements TextBlock, WithPo
|
||||
char separator = lineFirst ? '_' : 0;
|
||||
TextBlock title = null;
|
||||
List<Member> members = new ArrayList<Member>();
|
||||
final LineBreakStrategy lineBreakStrategy = skinParam.wrapWidth();
|
||||
// final LineBreakStrategy lineBreakStrategy = skinParam.wrapWidth();
|
||||
for (ListIterator<String> it = rawBody.listIterator(); it.hasNext();) {
|
||||
final String s = it.next();
|
||||
if (manageHorizontalLine && isBlockSeparator(s)) {
|
||||
|
@ -95,7 +95,8 @@ public class Display implements Iterable<CharSequence> {
|
||||
}
|
||||
|
||||
public boolean isWhite() {
|
||||
return display.size() == 0 || (display.size() == 1 && display.get(0).toString().matches("\\s*"));
|
||||
return display == null || display.size() == 0
|
||||
|| (display.size() == 1 && display.get(0).toString().matches("\\s*"));
|
||||
}
|
||||
|
||||
public static Display empty() {
|
||||
@ -398,8 +399,8 @@ public class Display implements Iterable<CharSequence> {
|
||||
|
||||
public TextBlock create(FontConfiguration fontConfiguration, HorizontalAlignment horizontalAlignment,
|
||||
ISkinSimple spriteContainer, CreoleMode modeSimpleLine, LineBreakStrategy maxMessageSize) {
|
||||
return create(fontConfiguration, horizontalAlignment, spriteContainer, maxMessageSize, modeSimpleLine,
|
||||
null, null);
|
||||
return create(fontConfiguration, horizontalAlignment, spriteContainer, maxMessageSize, modeSimpleLine, null,
|
||||
null);
|
||||
}
|
||||
|
||||
public TextBlock create(FontConfiguration fontConfiguration, HorizontalAlignment horizontalAlignment,
|
||||
|
@ -40,6 +40,8 @@ import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.math.BigInteger;
|
||||
|
||||
import net.sourceforge.plantuml.version.Magic;
|
||||
|
||||
public class QBlock {
|
||||
|
||||
private final BigInteger big;
|
||||
@ -59,6 +61,20 @@ public class QBlock {
|
||||
return new QBlock(new BigInteger(block));
|
||||
}
|
||||
|
||||
public static QBlock fromMagic(Magic magic) {
|
||||
final byte[] buffer = magic.getBuffer();
|
||||
final byte[] block = new byte[buffer.length + 1];
|
||||
System.arraycopy(buffer, 0, block, 1, buffer.length);
|
||||
final BigInteger big = new BigInteger(block);
|
||||
return new QBlock(big);
|
||||
}
|
||||
|
||||
public Magic toMagic() {
|
||||
final Magic magic = new Magic();
|
||||
magic.set(0, getData512());
|
||||
return magic;
|
||||
}
|
||||
|
||||
public QBlock(BigInteger number) {
|
||||
this.big = number;
|
||||
}
|
||||
@ -68,13 +84,27 @@ public class QBlock {
|
||||
return new QBlock(changed);
|
||||
}
|
||||
|
||||
public byte[] getData() {
|
||||
private byte[] getData512() {
|
||||
final byte[] nb = big.toByteArray();
|
||||
if (nb.length == 512) {
|
||||
return nb;
|
||||
}
|
||||
final byte[] result = new byte[512];
|
||||
if (nb.length < 512) {
|
||||
System.arraycopy(nb, 0, result, 512 - nb.length, nb.length);
|
||||
} else {
|
||||
System.arraycopy(nb, nb.length - 512, result, 0, 512);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public byte[] getDataRaw() {
|
||||
return big.toByteArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return big.toByteArray().length + " " + big.toString();
|
||||
return big.toByteArray().length + " " + big.toString(36);
|
||||
}
|
||||
|
||||
public void write(OutputStream os, int size) throws IOException {
|
||||
|
@ -77,24 +77,24 @@ public class QBlocks {
|
||||
}
|
||||
}
|
||||
|
||||
public String encodeAscii() {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
final AsciiEncoder encoder = new AsciiEncoder();
|
||||
for (QBlock rsa : all) {
|
||||
sb.append(encoder.encode(rsa.getData()));
|
||||
sb.append("!");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
// public String encodeAscii() {
|
||||
// final StringBuilder sb = new StringBuilder();
|
||||
// final AsciiEncoder encoder = new AsciiEncoder();
|
||||
// for (QBlock rsa : all) {
|
||||
// sb.append(encoder.encode(rsa.getDataRaw()));
|
||||
// sb.append("!");
|
||||
// }
|
||||
// return sb.toString();
|
||||
// }
|
||||
|
||||
public static QBlocks descodeAscii(String s) {
|
||||
final QBlocks result = new QBlocks();
|
||||
final AsciiEncoder encoder = new AsciiEncoder();
|
||||
for (String bl : s.split("!")) {
|
||||
final BigInteger bigInteger = new BigInteger(encoder.decode(bl));
|
||||
result.all.add(new QBlock(bigInteger));
|
||||
|
||||
}
|
||||
return result;
|
||||
}
|
||||
// public static QBlocks descodeAscii(String s) {
|
||||
// final QBlocks result = new QBlocks();
|
||||
// final AsciiEncoder encoder = new AsciiEncoder();
|
||||
// for (String bl : s.split("!")) {
|
||||
// final BigInteger bigInteger = new BigInteger(encoder.decode(bl));
|
||||
// result.all.add(new QBlock(bigInteger));
|
||||
//
|
||||
// }
|
||||
// return result;
|
||||
// }
|
||||
}
|
||||
|
@ -35,7 +35,7 @@
|
||||
*/
|
||||
package net.sourceforge.plantuml.dedication;
|
||||
|
||||
class TurningBytes {
|
||||
public class TurningBytes {
|
||||
|
||||
private final byte key[];
|
||||
private int idx;
|
||||
|
@ -39,6 +39,9 @@ import java.util.List;
|
||||
|
||||
import net.sourceforge.plantuml.FontParam;
|
||||
import net.sourceforge.plantuml.StringUtils;
|
||||
import net.sourceforge.plantuml.Url;
|
||||
import net.sourceforge.plantuml.UrlBuilder;
|
||||
import net.sourceforge.plantuml.UrlBuilder.ModeUrl;
|
||||
import net.sourceforge.plantuml.classdiagram.AbstractEntityDiagram;
|
||||
import net.sourceforge.plantuml.command.BlocLines;
|
||||
import net.sourceforge.plantuml.command.CommandExecutionResult;
|
||||
@ -89,6 +92,8 @@ public class CommandCreateElementMultilines extends CommandMultilines2<AbstractE
|
||||
new RegexLeaf("[%s]*"), //
|
||||
new RegexLeaf("STEREO", "(\\<\\<.+\\>\\>)?"), //
|
||||
new RegexLeaf("[%s]*"), //
|
||||
new RegexLeaf("URL", "(" + UrlBuilder.getRegexp() + ")?"), //
|
||||
new RegexLeaf("[%s]*"), //
|
||||
ColorParser.exp1(), //
|
||||
new RegexLeaf("[%s]*"), //
|
||||
new RegexLeaf("DESC", "as[%s]*[%g]([^%g]*)$"));
|
||||
@ -100,6 +105,8 @@ public class CommandCreateElementMultilines extends CommandMultilines2<AbstractE
|
||||
new RegexLeaf("[%s]*"), //
|
||||
new RegexLeaf("STEREO", "(\\<\\<.+\\>\\>)?"), //
|
||||
new RegexLeaf("[%s]*"), //
|
||||
new RegexLeaf("URL", "(" + UrlBuilder.getRegexp() + ")?"), //
|
||||
new RegexLeaf("[%s]*"), //
|
||||
ColorParser.exp1(), //
|
||||
new RegexLeaf("[%s]*"), //
|
||||
new RegexLeaf("DESC", "\\[(.*)$"));
|
||||
@ -155,6 +162,14 @@ public class CommandCreateElementMultilines extends CommandMultilines2<AbstractE
|
||||
.getIHtmlColorSet()));
|
||||
}
|
||||
|
||||
final String urlString = line0.get("URL", 0);
|
||||
if (urlString != null) {
|
||||
final UrlBuilder urlBuilder = new UrlBuilder(diagram.getSkinParam().getValue("topurl"), ModeUrl.STRICT);
|
||||
final Url url = urlBuilder.getUrl(urlString);
|
||||
result.addUrl(url);
|
||||
}
|
||||
|
||||
|
||||
result.setSpecificColorTOBEREMOVED(ColorType.BACK,
|
||||
diagram.getSkinParam().getIHtmlColorSet().getColorIfValid(line0.get("COLOR", 0)));
|
||||
|
||||
|
@ -68,7 +68,7 @@ import net.sourceforge.plantuml.version.PSystemVersion;
|
||||
|
||||
public class PSystemDonors extends AbstractPSystem {
|
||||
|
||||
public static final String DONORS = "6vG70AmEU9ELAuNYZT_MZn6AGOgeeHNOWjgQuZoZA1P0SxnDhXdMoRgDdR45mND5SGKL8Az2C-THCiPX"
|
||||
public static final String DONORS = "6wW70AmEU9ELAuNYZT_MZn6AGOgeeHNOWjgQuZoZA1P0SxnDhXdMoRgDdR45mND5SGKL8Az2C-THCiPX"
|
||||
+ "qGYJjjcQVk6-VTu2CLLilsL2UtyTQ4BoLZ2km4tbpF_b0XiJv0R8GZti1NIZZNlZcZIc_NyMPXz_WHRm"
|
||||
+ "DBfiMLGwq5cTNHLD233np1odb9A7OjnVaSBNZIs0buu7kTfO7U4RgRFlr0AQj6RJa9are5X6YaJpiT7Q"
|
||||
+ "SO3jOnWuqM5T7JOGEvGuw1kC0-eRCKh65JJ8ZE9cRAZcdIS4J3YXmavyKPAQeuLaHXawq65jWGAyFnC4"
|
||||
@ -81,7 +81,7 @@ public class PSystemDonors extends AbstractPSystem {
|
||||
+ "F7JnJ-yMjT1vT_j7wljDVYMrr2F6esimz9PTrczjikXOG6prZ0Kk0tPgjnkJ0vNSGgSsd1KznGbOzxRE"
|
||||
+ "mN4jWukcTREIdQcT73Dh1nskINx8qO1HqPr83hwsEoFFU1G5zYVddLZrKD-757yNK2o62PvIeMmZfEWA"
|
||||
+ "czF9f76hPzmTl8zRcozKj_7DXIS4XH-RQDDoWzUd0FSK-a5J1v0wgrNoqiR42E1tVFq6FS-j3ZpAQ6cL"
|
||||
+ "SNQv8PRIf_S8y1ioyae0";
|
||||
+ "SNQv8PRIf_S8y1ioyahsjhkX10q0";
|
||||
|
||||
@Override
|
||||
final protected ImageData exportDiagramNow(OutputStream os, int num, FileFormatOption fileFormat, long seed)
|
||||
|
@ -35,7 +35,6 @@
|
||||
*/
|
||||
package net.sourceforge.plantuml.graphic;
|
||||
|
||||
import java.awt.Font;
|
||||
import java.awt.geom.Dimension2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.List;
|
||||
|
@ -36,7 +36,6 @@
|
||||
package net.sourceforge.plantuml.graphic;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@ -44,8 +43,6 @@ import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
import net.sourceforge.plantuml.FileSystem;
|
||||
import net.sourceforge.plantuml.FileUtils;
|
||||
import net.sourceforge.plantuml.StringUtils;
|
||||
|
@ -36,12 +36,11 @@
|
||||
package net.sourceforge.plantuml.graphic;
|
||||
|
||||
import net.sourceforge.plantuml.ColorParam;
|
||||
import net.sourceforge.plantuml.CornerParam;
|
||||
import net.sourceforge.plantuml.FontParam;
|
||||
import net.sourceforge.plantuml.ISkinParam;
|
||||
import net.sourceforge.plantuml.LineParam;
|
||||
import net.sourceforge.plantuml.CornerParam;
|
||||
import net.sourceforge.plantuml.cucadiagram.Stereotype;
|
||||
import net.sourceforge.plantuml.svek.RoundedContainer;
|
||||
import net.sourceforge.plantuml.ugraphic.UStroke;
|
||||
|
||||
public class SkinParameter {
|
||||
|
@ -37,7 +37,6 @@ package net.sourceforge.plantuml.graphic;
|
||||
|
||||
import java.awt.geom.Dimension2D;
|
||||
|
||||
import net.sourceforge.plantuml.Log;
|
||||
import net.sourceforge.plantuml.svek.TextBlockBackcolored;
|
||||
import net.sourceforge.plantuml.ugraphic.MinMax;
|
||||
import net.sourceforge.plantuml.ugraphic.UGraphic;
|
||||
|
@ -57,7 +57,8 @@ public class TextBlockTitle implements TextBlock {
|
||||
if (stringsToDisplay.size() == 1 && stringsToDisplay.get(0).length() == 0) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
textBlock = stringsToDisplay.create(font, HorizontalAlignment.CENTER, spriteContainer, LineBreakStrategy.NONE,
|
||||
final LineBreakStrategy lineBreak = LineBreakStrategy.NONE;
|
||||
textBlock = stringsToDisplay.create(font, HorizontalAlignment.CENTER, spriteContainer, lineBreak,
|
||||
CreoleMode.FULL, null, null);
|
||||
}
|
||||
|
||||
|
@ -46,10 +46,10 @@ import java.awt.geom.Rectangle2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
import net.sourceforge.plantuml.ColorParam;
|
||||
import net.sourceforge.plantuml.CornerParam;
|
||||
import net.sourceforge.plantuml.Dimension2DDouble;
|
||||
import net.sourceforge.plantuml.ISkinParam;
|
||||
import net.sourceforge.plantuml.LineParam;
|
||||
import net.sourceforge.plantuml.CornerParam;
|
||||
import net.sourceforge.plantuml.cucadiagram.Display;
|
||||
import net.sourceforge.plantuml.posimo.Positionable;
|
||||
import net.sourceforge.plantuml.posimo.PositionableImpl;
|
||||
|
@ -146,11 +146,11 @@ class USymbolDatabase extends USymbol {
|
||||
drawDatabase(ug, dim.getWidth(), dim.getHeight(), symbolContext.isShadowing());
|
||||
final Dimension2D dimStereo = stereotype.calculateDimension(ug.getStringBounder());
|
||||
final double posStereo = (width - dimStereo.getWidth()) / 2;
|
||||
stereotype.drawU(ug.apply(new UTranslate(posStereo, 0)));
|
||||
stereotype.drawU(ug.apply(new UTranslate(posStereo, 2 + 20)));
|
||||
|
||||
final Dimension2D dimTitle = title.calculateDimension(ug.getStringBounder());
|
||||
final double posTitle = (width - dimTitle.getWidth()) / 2;
|
||||
title.drawU(ug.apply(new UTranslate(posTitle, 21)));
|
||||
title.drawU(ug.apply(new UTranslate(posTitle, 2 + 20 + dimStereo.getHeight())));
|
||||
}
|
||||
|
||||
public Dimension2D calculateDimension(StringBounder stringBounder) {
|
||||
|
@ -35,8 +35,6 @@
|
||||
*/
|
||||
package net.sourceforge.plantuml.graphic;
|
||||
|
||||
import gen.lib.dotgen.dotinit__c;
|
||||
|
||||
import java.awt.geom.Dimension2D;
|
||||
import java.awt.geom.Point2D;
|
||||
|
||||
|
@ -147,7 +147,7 @@ public class ScientificEquationSafe {
|
||||
return new ImageDataSimple(image.getWidth(), image.getHeight());
|
||||
}
|
||||
if (fileFormat.getFileFormat() == FileFormat.SVG) {
|
||||
os.write(getSvg(1, foregroundColor, backgroundColor).getSvg().getBytes());
|
||||
os.write(getSvg(1, foregroundColor, backgroundColor).getSvg(true).getBytes());
|
||||
return dimSvg;
|
||||
}
|
||||
return null;
|
||||
|
@ -43,6 +43,7 @@ import net.sourceforge.plantuml.SkinParam;
|
||||
import net.sourceforge.plantuml.SpriteContainerEmpty;
|
||||
import net.sourceforge.plantuml.cucadiagram.Display;
|
||||
import net.sourceforge.plantuml.graphic.FontConfiguration;
|
||||
import net.sourceforge.plantuml.graphic.HorizontalAlignment;
|
||||
import net.sourceforge.plantuml.graphic.HtmlColor;
|
||||
import net.sourceforge.plantuml.graphic.HtmlColorSetSimple;
|
||||
import net.sourceforge.plantuml.graphic.HtmlColorUtils;
|
||||
@ -117,7 +118,7 @@ public class PostIt {
|
||||
final FontConfiguration font2 = fontNote.toFont2(HtmlColorUtils.BLACK, true, HtmlColorUtils.BLUE, 8);
|
||||
final ComponentRoseNote note = new ComponentRoseNote(
|
||||
new SymbolContext(noteBackgroundColor, borderColor).withStroke(new UStroke()), font2, text, 0, 0,
|
||||
new SpriteContainerEmpty(), 0);
|
||||
new SpriteContainerEmpty(), 0, HorizontalAlignment.LEFT);
|
||||
return note;
|
||||
}
|
||||
}
|
||||
|
@ -49,7 +49,6 @@ public class Define {
|
||||
private final boolean emptyParentheses;
|
||||
|
||||
public Define(String key, List<String> lines, boolean emptyParentheses) {
|
||||
this.signature = new DefineSignature(key);
|
||||
this.emptyParentheses = emptyParentheses;
|
||||
if (lines == null) {
|
||||
this.definition = null;
|
||||
@ -65,6 +64,7 @@ public class Define {
|
||||
this.definition = sb.toString();
|
||||
this.definitionQuoted = Matcher.quoteReplacement(definition);
|
||||
}
|
||||
this.signature = new DefineSignature(key, this.definitionQuoted);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -78,7 +78,7 @@ public class Define {
|
||||
}
|
||||
if (signature.isMethod()) {
|
||||
for (Variables vars : signature.getVariationVariables()) {
|
||||
line = vars.applyOn(line, signature.getFonctionName(), definitionQuoted);
|
||||
line = vars.applyOn(line);
|
||||
}
|
||||
} else {
|
||||
final String regex = "\\b" + signature.getKey() + "\\b" + (emptyParentheses ? "(\\(\\))?" : "");
|
||||
|
@ -43,24 +43,30 @@ import java.util.StringTokenizer;
|
||||
public class DefineSignature {
|
||||
|
||||
private final String key;
|
||||
private final String fctName;
|
||||
private final Variables vars = new Variables();
|
||||
private final String fonctionName;
|
||||
private final List<Variables> variables = new ArrayList<Variables>();
|
||||
|
||||
public DefineSignature(String key) {
|
||||
public DefineSignature(String key, String definitionQuoted) {
|
||||
this.key = key;
|
||||
|
||||
final StringTokenizer st = new StringTokenizer(key, "(),");
|
||||
this.fctName = st.nextToken().trim();
|
||||
this.fonctionName = st.nextToken().trim();
|
||||
final Variables master = new Variables(fonctionName, definitionQuoted);
|
||||
|
||||
while (st.hasMoreTokens()) {
|
||||
final String var1 = st.nextToken().trim();
|
||||
this.vars.add(new DefineVariable(var1));
|
||||
master.add(new DefineVariable(var1));
|
||||
}
|
||||
|
||||
final int count = master.countDefaultValue();
|
||||
for (int i = 0; i <= count; i++) {
|
||||
variables.add(master.removeSomeDefaultValues(i));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return key + "/" + fctName + "/" + vars;
|
||||
return key + "/" + fonctionName;
|
||||
}
|
||||
|
||||
public boolean isMethod() {
|
||||
@ -72,16 +78,7 @@ public class DefineSignature {
|
||||
}
|
||||
|
||||
public List<Variables> getVariationVariables() {
|
||||
final List<Variables> result = new ArrayList<Variables>();
|
||||
final int count = vars.countDefaultValue();
|
||||
for (int i = 0; i <= count; i++) {
|
||||
result.add(vars.removeSomeDefaultValues(i));
|
||||
}
|
||||
return Collections.unmodifiableList(result);
|
||||
}
|
||||
|
||||
public String getFonctionName() {
|
||||
return fctName;
|
||||
return Collections.unmodifiableList(variables);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ import net.sourceforge.plantuml.command.regex.MyPattern;
|
||||
import net.sourceforge.plantuml.command.regex.Pattern2;
|
||||
import net.sourceforge.plantuml.version.Version;
|
||||
|
||||
class IfManager implements ReadLine {
|
||||
class IfManager extends ReadLineInstrumented implements ReadLine {
|
||||
|
||||
protected static final Pattern2 ifdefPattern = MyPattern.cmpile("^[%s]*!if(n)?def[%s]+(.+)$");
|
||||
protected static final Pattern2 ifcomparePattern = MyPattern
|
||||
@ -61,7 +61,8 @@ class IfManager implements ReadLine {
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
final public CharSequence2 readLine() throws IOException {
|
||||
@Override
|
||||
final CharSequence2 readLineInst() throws IOException {
|
||||
if (child != null) {
|
||||
final CharSequence2 s = child.readLine();
|
||||
if (s != null) {
|
||||
@ -117,7 +118,8 @@ class IfManager implements ReadLine {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
@Override
|
||||
void closeInst() throws IOException {
|
||||
source.close();
|
||||
}
|
||||
|
||||
|
@ -37,192 +37,62 @@ package net.sourceforge.plantuml.preproc;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import net.sourceforge.plantuml.CharSequence2;
|
||||
import net.sourceforge.plantuml.CharSequence2Impl;
|
||||
import net.sourceforge.plantuml.DefinitionsContainer;
|
||||
import net.sourceforge.plantuml.StringUtils;
|
||||
import net.sourceforge.plantuml.command.regex.Matcher2;
|
||||
import net.sourceforge.plantuml.command.regex.MyPattern;
|
||||
import net.sourceforge.plantuml.command.regex.Pattern2;
|
||||
import net.sourceforge.plantuml.utils.StartUtils;
|
||||
import net.sourceforge.plantuml.Log;
|
||||
|
||||
public class Preprocessor implements ReadLine {
|
||||
public class Preprocessor extends ReadLineInstrumented implements ReadLine {
|
||||
|
||||
private static final String END_DEFINE_LONG = "!enddefinelong";
|
||||
private static final String ID = "[A-Za-z_][A-Za-z_0-9]*";
|
||||
private static final String ID_ARG = "\\s*[A-Za-z_][A-Za-z_0-9]*\\s*(?:=\\s*(?:\"[^\"]*\"|'[^']*')\\s*)?";
|
||||
private static final String ARG = "(?:\\(" + ID_ARG + "(?:," + ID_ARG + ")*?\\))?";
|
||||
private static final Pattern2 definePattern = MyPattern.cmpile("^[%s]*!define[%s]+(" + ID + ARG + ")"
|
||||
+ "(?:[%s]+(.*))?$");
|
||||
private static final Pattern2 filenamePattern = MyPattern.cmpile("^[%s]*!filename[%s]+(.+)$");
|
||||
private static final Pattern2 undefPattern = MyPattern.cmpile("^[%s]*!undef[%s]+(" + ID + ")$");
|
||||
private static final Pattern2 definelongPattern = MyPattern.cmpile("^[%s]*!definelong[%s]+(" + ID + ARG + ")");
|
||||
private static final Pattern2 enddefinelongPattern = MyPattern.cmpile("^[%s]*" + END_DEFINE_LONG + "[%s]*$");
|
||||
|
||||
private final Defines defines;
|
||||
private final PreprocessorInclude rawSource;
|
||||
private final ReadLineInsertable source;
|
||||
private final PreprocessorInclude include;
|
||||
private final SubPreprocessor subPreprocessor;
|
||||
private final String description;
|
||||
|
||||
public Sub getSub(String blocname) {
|
||||
return subPreprocessor.getSub(blocname);
|
||||
}
|
||||
|
||||
// public Preprocessor(List<String> config, ReadLine reader, String charset, Defines defines, File newCurrentDir,
|
||||
// DefinitionsContainer definitionsContainer) {
|
||||
//
|
||||
// final ReadLine source2 = new IfManager(reader, defines);
|
||||
// final ReadLineInsertable source3 = new ReadLineInsertable(source2);
|
||||
// final ReadLine source4 = new PreprocessorDefine(defines, source3);
|
||||
// this.include = new PreprocessorInclude(config, source4, defines, charset, newCurrentDir, definitionsContainer);
|
||||
// this.subPreprocessor = new SubPreprocessor(config, charset, defines, definitionsContainer, include);
|
||||
// }
|
||||
|
||||
public Preprocessor(List<String> config, ReadLine reader, String charset, Defines defines, File newCurrentDir,
|
||||
DefinitionsContainer definitionsContainer) {
|
||||
this.defines = defines;
|
||||
this.defines.saveState();
|
||||
this.rawSource = new PreprocessorInclude(config, reader, defines, charset, newCurrentDir, definitionsContainer);
|
||||
this.source = new ReadLineInsertable(new IfManager(rawSource, defines));
|
||||
this.subPreprocessor = new SubPreprocessor(config, charset, defines, definitionsContainer, new ReadLine() {
|
||||
|
||||
public void close() throws IOException {
|
||||
Preprocessor.this.close();
|
||||
}
|
||||
|
||||
public CharSequence2 readLine() throws IOException {
|
||||
return readLineInternal();
|
||||
}
|
||||
});
|
||||
this.description = reader.toString();
|
||||
this.include = new PreprocessorInclude(config, reader, defines, charset, newCurrentDir, definitionsContainer);
|
||||
final ReadLine source2 = new IfManager(include, defines);
|
||||
final ReadLineInsertable source3 = new ReadLineInsertable(source2);
|
||||
final ReadLine source4 = new PreprocessorDefine(defines, source3);
|
||||
this.subPreprocessor = new SubPreprocessor(config, charset, defines, definitionsContainer, source4);
|
||||
}
|
||||
|
||||
public CharSequence2 readLine() throws IOException {
|
||||
@Override
|
||||
CharSequence2 readLineInst() throws IOException {
|
||||
return subPreprocessor.readLine();
|
||||
}
|
||||
|
||||
private CharSequence2 readLineInternal() throws IOException {
|
||||
final CharSequence2 s = source.readLine();
|
||||
if (s == null) {
|
||||
return null;
|
||||
}
|
||||
if (StartUtils.isArobaseStartDiagram(s)) {
|
||||
this.defines.restoreState();
|
||||
}
|
||||
|
||||
Matcher2 m = filenamePattern.matcher(s);
|
||||
if (m.find()) {
|
||||
return manageFilename(m);
|
||||
}
|
||||
m = definePattern.matcher(s);
|
||||
if (m.find()) {
|
||||
return manageDefine(m, s.toString().trim().endsWith("()"));
|
||||
}
|
||||
|
||||
m = definelongPattern.matcher(s);
|
||||
if (m.find()) {
|
||||
return manageDefineLong(m, s.toString().trim().endsWith("()"));
|
||||
}
|
||||
|
||||
m = undefPattern.matcher(s);
|
||||
if (m.find()) {
|
||||
return manageUndef(m);
|
||||
}
|
||||
|
||||
if (ignoreDefineDuringSeveralLines > 0) {
|
||||
ignoreDefineDuringSeveralLines--;
|
||||
return s;
|
||||
}
|
||||
|
||||
List<String> result = defines.applyDefines(s.toString2());
|
||||
if (result.size() > 1) {
|
||||
result = cleanEndDefineLong(result);
|
||||
final List<String> inserted = cleanEndDefineLong(result.subList(1, result.size()));
|
||||
ignoreDefineDuringSeveralLines = inserted.size();
|
||||
source.insert(inserted, s.getLocation());
|
||||
}
|
||||
return new CharSequence2Impl(result.get(0), s.getLocation(), s.getPreprocessorError());
|
||||
}
|
||||
|
||||
private List<String> cleanEndDefineLong(List<String> data) {
|
||||
final List<String> result = new ArrayList<String>();
|
||||
for (String s : data) {
|
||||
final String clean = cleanEndDefineLong(s);
|
||||
if (clean != null) {
|
||||
result.add(clean);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
private String cleanEndDefineLong(String s) {
|
||||
if (s.trim().startsWith(END_DEFINE_LONG)) {
|
||||
s = s.trim().substring(END_DEFINE_LONG.length());
|
||||
if (s.length() == 0) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
private int ignoreDefineDuringSeveralLines = 0;
|
||||
|
||||
private CharSequence2 manageUndef(Matcher2 m) throws IOException {
|
||||
defines.undefine(m.group(1));
|
||||
return this.readLine();
|
||||
}
|
||||
|
||||
private CharSequence2 manageDefineLong(Matcher2 m, boolean emptyParentheses) throws IOException {
|
||||
final String group1 = m.group(1);
|
||||
final List<String> def = new ArrayList<String>();
|
||||
while (true) {
|
||||
final CharSequence2 read = this.readLine();
|
||||
if (read == null) {
|
||||
return null;
|
||||
}
|
||||
if (enddefinelongPattern.matcher(read).find()) {
|
||||
defines.define(group1, def, emptyParentheses);
|
||||
return this.readLine();
|
||||
}
|
||||
def.add(read.toString2());
|
||||
}
|
||||
}
|
||||
|
||||
private CharSequence2 manageFilename(Matcher2 m) throws IOException {
|
||||
final String group1 = m.group(1);
|
||||
this.defines.overrideFilename(group1);
|
||||
return this.readLine();
|
||||
}
|
||||
|
||||
private CharSequence2 manageDefine(Matcher2 m, boolean emptyParentheses) throws IOException {
|
||||
final String group1 = m.group(1);
|
||||
final String group2 = m.group(2);
|
||||
if (group2 == null) {
|
||||
defines.define(group1, null, emptyParentheses);
|
||||
} else {
|
||||
final List<String> strings = defines.applyDefines(group2);
|
||||
if (strings.size() > 1) {
|
||||
defines.define(group1, strings, emptyParentheses);
|
||||
} else {
|
||||
final StringBuilder value = new StringBuilder(strings.get(0));
|
||||
while (StringUtils.endsWithBackslash(value.toString())) {
|
||||
value.setLength(value.length() - 1);
|
||||
final CharSequence2 read = this.readLine();
|
||||
value.append(read.toString2());
|
||||
}
|
||||
final List<String> li = new ArrayList<String>();
|
||||
li.add(value.toString());
|
||||
defines.define(group1, li, emptyParentheses);
|
||||
}
|
||||
}
|
||||
return this.readLine();
|
||||
}
|
||||
|
||||
public int getLineNumber() {
|
||||
return rawSource.getLineNumber();
|
||||
return include.getLineNumber();
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
rawSource.close();
|
||||
@Override
|
||||
void closeInst() throws IOException {
|
||||
// Log.info("Closing preprocessor of " + description);
|
||||
include.close();
|
||||
subPreprocessor.close();
|
||||
}
|
||||
|
||||
public Set<FileWithSuffix> getFilesUsed() {
|
||||
return Collections.unmodifiableSet(rawSource.getFilesUsedGlobal());
|
||||
return Collections.unmodifiableSet(include.getFilesUsedGlobal());
|
||||
}
|
||||
|
||||
}
|
201
src/net/sourceforge/plantuml/preproc/PreprocessorDefine.java
Normal file
201
src/net/sourceforge/plantuml/preproc/PreprocessorDefine.java
Normal file
@ -0,0 +1,201 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* (C) Copyright 2009-2017, Arnaud Roques
|
||||
*
|
||||
* Project Info: http://plantuml.com
|
||||
*
|
||||
* If you like this project or if you find it useful, you can support us at:
|
||||
*
|
||||
* http://plantuml.com/patreon (only 1$ per month!)
|
||||
* http://plantuml.com/paypal
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*
|
||||
*
|
||||
* Original Author: Arnaud Roques
|
||||
*
|
||||
*
|
||||
*/
|
||||
package net.sourceforge.plantuml.preproc;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import net.sourceforge.plantuml.CharSequence2;
|
||||
import net.sourceforge.plantuml.CharSequence2Impl;
|
||||
import net.sourceforge.plantuml.StringUtils;
|
||||
import net.sourceforge.plantuml.command.regex.Matcher2;
|
||||
import net.sourceforge.plantuml.command.regex.MyPattern;
|
||||
import net.sourceforge.plantuml.command.regex.Pattern2;
|
||||
import net.sourceforge.plantuml.utils.StartUtils;
|
||||
|
||||
public class PreprocessorDefine extends ReadLineInstrumented implements ReadLine {
|
||||
|
||||
private static final String END_DEFINE_LONG = "!enddefinelong";
|
||||
private static final String ID = "[A-Za-z_][A-Za-z_0-9]*";
|
||||
private static final String ID_ARG = "\\s*[A-Za-z_][A-Za-z_0-9]*\\s*(?:=\\s*(?:\"[^\"]*\"|'[^']*')\\s*)?";
|
||||
private static final String ARG = "(?:\\(" + ID_ARG + "(?:," + ID_ARG + ")*?\\))?";
|
||||
private static final Pattern2 definePattern = MyPattern.cmpile("^[%s]*!define[%s]+(" + ID + ARG + ")"
|
||||
+ "(?:[%s]+(.*))?$");
|
||||
private static final Pattern2 filenamePattern = MyPattern.cmpile("^[%s]*!filename[%s]+(.+)$");
|
||||
private static final Pattern2 undefPattern = MyPattern.cmpile("^[%s]*!undef[%s]+(" + ID + ")$");
|
||||
private static final Pattern2 definelongPattern = MyPattern.cmpile("^[%s]*!definelong[%s]+(" + ID + ARG + ")");
|
||||
private static final Pattern2 enddefinelongPattern = MyPattern.cmpile("^[%s]*" + END_DEFINE_LONG + "[%s]*$");
|
||||
|
||||
private final Defines defines;
|
||||
|
||||
private final ReadLineInsertable source;
|
||||
|
||||
public PreprocessorDefine(Defines defines, ReadLineInsertable source) {
|
||||
this.defines = defines;
|
||||
this.defines.saveState();
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
@Override
|
||||
CharSequence2 readLineInst() throws IOException {
|
||||
final CharSequence2 s = source.readLine();
|
||||
if (s == null) {
|
||||
return null;
|
||||
}
|
||||
if (StartUtils.isArobaseStartDiagram(s)) {
|
||||
this.defines.restoreState();
|
||||
}
|
||||
|
||||
Matcher2 m = filenamePattern.matcher(s);
|
||||
if (m.find()) {
|
||||
return manageFilename(m);
|
||||
}
|
||||
m = definePattern.matcher(s);
|
||||
if (m.find()) {
|
||||
return manageDefine(m, s.toString().trim().endsWith("()"));
|
||||
}
|
||||
|
||||
m = definelongPattern.matcher(s);
|
||||
if (m.find()) {
|
||||
return manageDefineLong(m, s.toString().trim().endsWith("()"));
|
||||
}
|
||||
|
||||
m = undefPattern.matcher(s);
|
||||
if (m.find()) {
|
||||
return manageUndef(m);
|
||||
}
|
||||
|
||||
if (ignoreDefineDuringSeveralLines > 0) {
|
||||
ignoreDefineDuringSeveralLines--;
|
||||
return s;
|
||||
}
|
||||
|
||||
List<String> result = defines.applyDefines(s.toString2());
|
||||
if (result.size() > 1) {
|
||||
result = cleanEndDefineLong(result);
|
||||
final List<String> inserted = cleanEndDefineLong(result.subList(1, result.size()));
|
||||
ignoreDefineDuringSeveralLines = inserted.size();
|
||||
source.insert(inserted, s.getLocation());
|
||||
}
|
||||
return new CharSequence2Impl(result.get(0), s.getLocation(), s.getPreprocessorError());
|
||||
}
|
||||
|
||||
private List<String> cleanEndDefineLong(List<String> data) {
|
||||
final List<String> result = new ArrayList<String>();
|
||||
for (String s : data) {
|
||||
final String clean = cleanEndDefineLong(s);
|
||||
if (clean != null) {
|
||||
result.add(clean);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
private String cleanEndDefineLong(String s) {
|
||||
if (s.trim().startsWith(END_DEFINE_LONG)) {
|
||||
s = s.trim().substring(END_DEFINE_LONG.length());
|
||||
if (s.length() == 0) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
private int ignoreDefineDuringSeveralLines = 0;
|
||||
|
||||
private CharSequence2 manageUndef(Matcher2 m) throws IOException {
|
||||
defines.undefine(m.group(1));
|
||||
return this.readLine();
|
||||
}
|
||||
|
||||
private CharSequence2 manageDefineLong(Matcher2 m, boolean emptyParentheses) throws IOException {
|
||||
final String group1 = m.group(1);
|
||||
final List<String> def = new ArrayList<String>();
|
||||
while (true) {
|
||||
final CharSequence2 read = this.readLine();
|
||||
if (read == null) {
|
||||
return null;
|
||||
}
|
||||
if (enddefinelongPattern.matcher(read).find()) {
|
||||
defines.define(group1, def, emptyParentheses);
|
||||
return this.readLine();
|
||||
}
|
||||
def.add(read.toString2());
|
||||
}
|
||||
}
|
||||
|
||||
private CharSequence2 manageFilename(Matcher2 m) throws IOException {
|
||||
final String group1 = m.group(1);
|
||||
this.defines.overrideFilename(group1);
|
||||
return this.readLine();
|
||||
}
|
||||
|
||||
private CharSequence2 manageDefine(Matcher2 m, boolean emptyParentheses) throws IOException {
|
||||
final String group1 = m.group(1);
|
||||
final String group2 = m.group(2);
|
||||
if (group2 == null) {
|
||||
defines.define(group1, null, emptyParentheses);
|
||||
} else {
|
||||
final List<String> strings = defines.applyDefines(group2);
|
||||
if (strings.size() > 1) {
|
||||
defines.define(group1, strings, emptyParentheses);
|
||||
} else {
|
||||
final StringBuilder value = new StringBuilder(strings.get(0));
|
||||
while (StringUtils.endsWithBackslash(value.toString())) {
|
||||
value.setLength(value.length() - 1);
|
||||
final CharSequence2 read = this.readLine();
|
||||
value.append(read.toString2());
|
||||
}
|
||||
final List<String> li = new ArrayList<String>();
|
||||
li.add(value.toString());
|
||||
defines.define(group1, li, emptyParentheses);
|
||||
}
|
||||
}
|
||||
return this.readLine();
|
||||
}
|
||||
|
||||
// public int getLineNumber() {
|
||||
// return source.getLineNumber();
|
||||
// }
|
||||
|
||||
@Override
|
||||
void closeInst() throws IOException {
|
||||
source.close();
|
||||
}
|
||||
|
||||
}
|
@ -63,7 +63,7 @@ import net.sourceforge.plantuml.command.regex.MyPattern;
|
||||
import net.sourceforge.plantuml.command.regex.Pattern2;
|
||||
import net.sourceforge.plantuml.utils.StartUtils;
|
||||
|
||||
public class PreprocessorInclude implements ReadLine {
|
||||
public class PreprocessorInclude extends ReadLineInstrumented implements ReadLine {
|
||||
|
||||
private static final Pattern2 includeDefPattern = MyPattern.cmpile("^[%s]*!includedef[%s]+[%g]?([^%g]+)[%g]?$");
|
||||
private static final Pattern2 includePattern = MyPattern.cmpile("^[%s]*!include[%s]+[%g]?([^%g]+)[%g]?$");
|
||||
@ -119,7 +119,8 @@ public class PreprocessorInclude implements ReadLine {
|
||||
}
|
||||
}
|
||||
|
||||
public CharSequence2 readLine() throws IOException {
|
||||
@Override
|
||||
CharSequence2 readLineInst() throws IOException {
|
||||
final CharSequence2 result = readLineInternal();
|
||||
if (result != null && StartUtils.isArobaseStartDiagram(result) && config.size() > 0) {
|
||||
final List<String> empty = new ArrayList<String>();
|
||||
@ -266,21 +267,13 @@ public class PreprocessorInclude implements ReadLine {
|
||||
}
|
||||
|
||||
private InputStream getStdlibInputStream(String filename) {
|
||||
return Stdlib.getResourceAsStream(filename);
|
||||
}
|
||||
|
||||
private InputStream getStdlibInputStreamOld(String filename) {
|
||||
if (filename.endsWith(".puml") == false) {
|
||||
filename = filename + ".puml";
|
||||
}
|
||||
InputStream is = PreprocessorInclude.class.getResourceAsStream("/stdlib/" + filename);
|
||||
if (is == null) {
|
||||
is = PreprocessorInclude.class.getResourceAsStream("/stdlib/" + filename.toLowerCase());
|
||||
}
|
||||
return is;
|
||||
final InputStream result = Stdlib.getResourceAsStream(filename);
|
||||
// Log.info("Loading sdlib " + filename + " ok");
|
||||
return result;
|
||||
}
|
||||
|
||||
private ReadLine getReaderStdlibInclude(CharSequence2 s, String filename) {
|
||||
Log.info("Loading sdlib " + filename);
|
||||
InputStream is = getStdlibInputStream(filename);
|
||||
if (is == null) {
|
||||
return null;
|
||||
@ -295,23 +288,12 @@ public class PreprocessorInclude implements ReadLine {
|
||||
if (is == null) {
|
||||
return null;
|
||||
}
|
||||
return ReadLineReader.create(new InputStreamReader(is), filename);
|
||||
return ReadLineReader.create(new InputStreamReader(is), description);
|
||||
} catch (IOException e) {
|
||||
return new ReadLineSimple(s, e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
// private ReadLine getReaderStdlibInclude2(CharSequence2 s, String filename) {
|
||||
// InputStream is = DummyEmptyStdlibFile.class.getResourceAsStream(filename);
|
||||
// if (is == null) {
|
||||
// is = DummyEmptyStdlibFile.class.getResourceAsStream(filename.toLowerCase());
|
||||
// }
|
||||
// if (is == null) {
|
||||
// return null;
|
||||
// }
|
||||
// return new ReadLineReader(new InputStreamReader(is), filename);
|
||||
// }
|
||||
|
||||
private ReadLine getReaderInclude(CharSequence2 s, final File f, String suf) {
|
||||
try {
|
||||
if (StartDiagramExtractReader.containsStartDiagram(s, f, charset)) {
|
||||
@ -352,7 +334,8 @@ public class PreprocessorInclude implements ReadLine {
|
||||
return numLine;
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
@Override
|
||||
void closeInst() throws IOException {
|
||||
restoreCurrentDir();
|
||||
reader2.close();
|
||||
}
|
||||
|
@ -0,0 +1,98 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* (C) Copyright 2009-2017, Arnaud Roques
|
||||
*
|
||||
* Project Info: http://plantuml.com
|
||||
*
|
||||
* If you like this project or if you find it useful, you can support us at:
|
||||
*
|
||||
* http://plantuml.com/patreon (only 1$ per month!)
|
||||
* http://plantuml.com/paypal
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*
|
||||
*
|
||||
* Original Author: Arnaud Roques
|
||||
*
|
||||
*
|
||||
*/
|
||||
package net.sourceforge.plantuml.preproc;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import net.sourceforge.plantuml.CharSequence2;
|
||||
import net.sourceforge.plantuml.Log;
|
||||
|
||||
public abstract class ReadLineInstrumented implements ReadLine {
|
||||
|
||||
private static final boolean TRACE = false;
|
||||
|
||||
private static ConcurrentMap<Class, AtomicLong> durations = new ConcurrentHashMap<Class, AtomicLong>();
|
||||
private static ConcurrentMap<Class, AtomicLong> maxes = new ConcurrentHashMap<Class, AtomicLong>();
|
||||
|
||||
private long current = 0;
|
||||
|
||||
private AtomicLong get(ConcurrentMap<Class, AtomicLong> source) {
|
||||
AtomicLong result = source.get(getClass());
|
||||
if (result == null) {
|
||||
result = new AtomicLong();
|
||||
source.put(getClass(), result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public final CharSequence2 readLine() throws IOException {
|
||||
if (TRACE == false) {
|
||||
return readLineInst();
|
||||
}
|
||||
final long now = System.currentTimeMillis();
|
||||
try {
|
||||
return readLineInst();
|
||||
} finally {
|
||||
final long time = System.currentTimeMillis() - now;
|
||||
current += time;
|
||||
get(durations).addAndGet(time);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.toString() + " current=" + current;
|
||||
}
|
||||
|
||||
abstract CharSequence2 readLineInst() throws IOException;
|
||||
|
||||
public final void close() throws IOException {
|
||||
if (TRACE) {
|
||||
if (current > get(maxes).get()) {
|
||||
get(maxes).set(current);
|
||||
}
|
||||
Log.info("DURATION::" + getClass() + " duration= " + get(durations).get() + " current=" + current + " max="
|
||||
+ get(maxes).get());
|
||||
}
|
||||
closeInst();
|
||||
}
|
||||
|
||||
abstract void closeInst() throws IOException;
|
||||
|
||||
}
|
@ -40,7 +40,7 @@ import java.io.IOException;
|
||||
import net.sourceforge.plantuml.CharSequence2;
|
||||
import net.sourceforge.plantuml.CharSequence2Impl;
|
||||
|
||||
public class ReadLineQuoteComment implements ReadLine {
|
||||
public class ReadLineQuoteComment extends ReadLineInstrumented implements ReadLine {
|
||||
|
||||
private final ReadLine raw;
|
||||
private boolean longComment = false;
|
||||
@ -49,11 +49,13 @@ public class ReadLineQuoteComment implements ReadLine {
|
||||
this.raw = source;
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
@Override
|
||||
void closeInst() throws IOException {
|
||||
raw.close();
|
||||
}
|
||||
|
||||
public CharSequence2 readLine() throws IOException {
|
||||
@Override
|
||||
CharSequence2 readLineInst() throws IOException {
|
||||
while (true) {
|
||||
final CharSequence2 result = raw.readLine();
|
||||
if (result == null) {
|
||||
|
@ -43,19 +43,28 @@ import net.sourceforge.plantuml.CharSequence2;
|
||||
import net.sourceforge.plantuml.CharSequence2Impl;
|
||||
import net.sourceforge.plantuml.LineLocation;
|
||||
import net.sourceforge.plantuml.LineLocationImpl;
|
||||
import net.sourceforge.plantuml.Log;
|
||||
|
||||
public class ReadLineReader implements ReadLine {
|
||||
public class ReadLineReader extends ReadLineInstrumented implements ReadLine {
|
||||
|
||||
// private static final int LIMIT = 850;
|
||||
private final BufferedReader br;
|
||||
private LineLocationImpl location;
|
||||
private final String description;
|
||||
|
||||
private ReadLineReader(Reader reader, String description, LineLocation parent) {
|
||||
if (description == null) {
|
||||
description = "?";
|
||||
}
|
||||
br = new BufferedReader(reader);
|
||||
location = new LineLocationImpl(description, parent);
|
||||
this.br = new BufferedReader(reader);
|
||||
this.location = new LineLocationImpl(description, parent);
|
||||
this.description = description;
|
||||
Log.info("Reading from " + description);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.toString() + " " + description;
|
||||
}
|
||||
|
||||
private ReadLineReader(Reader reader, String desc) {
|
||||
@ -70,7 +79,8 @@ public class ReadLineReader implements ReadLine {
|
||||
return new ReadLineReader(reader, description, parent);
|
||||
}
|
||||
|
||||
public CharSequence2 readLine() throws IOException {
|
||||
@Override
|
||||
CharSequence2 readLineInst() throws IOException {
|
||||
String s = br.readLine();
|
||||
location = location.oneLineRead();
|
||||
if (s == null) {
|
||||
@ -99,7 +109,8 @@ public class ReadLineReader implements ReadLine {
|
||||
return new CharSequence2Impl(s, location);
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
@Override
|
||||
void closeInst() throws IOException {
|
||||
br.close();
|
||||
}
|
||||
|
||||
|
@ -76,9 +76,11 @@ public class Stdlib {
|
||||
if (cached != null) {
|
||||
final String cachedResult = cached.get();
|
||||
if (cachedResult != null) {
|
||||
// Log.info("Using cache for " + file);
|
||||
return cachedResult;
|
||||
}
|
||||
}
|
||||
Log.info("No cache for " + file);
|
||||
final DataInputStream dataStream = getDataStream();
|
||||
if (dataStream == null) {
|
||||
return null;
|
||||
@ -94,6 +96,7 @@ public class Stdlib {
|
||||
while (true) {
|
||||
final String filename = dataStream.readUTF();
|
||||
if (filename.equals(SEPARATOR)) {
|
||||
Log.info("Not found " + filename);
|
||||
return null;
|
||||
}
|
||||
if (filename.equalsIgnoreCase(file)) {
|
||||
@ -121,8 +124,10 @@ public class Stdlib {
|
||||
}
|
||||
final int width = Integer.parseInt(m.group(1));
|
||||
final int height = Integer.parseInt(m.group(2));
|
||||
final String sprite = readSprite(width, height, spriteStream);
|
||||
if (found != null) {
|
||||
if (found == null) {
|
||||
skipSprite(width, height, spriteStream);
|
||||
} else {
|
||||
final String sprite = readSprite(width, height, spriteStream);
|
||||
found.append(sprite);
|
||||
found.append("}\n");
|
||||
}
|
||||
@ -141,9 +146,14 @@ public class Stdlib {
|
||||
fillMap(info);
|
||||
}
|
||||
|
||||
private String readSprite(int width, int height, InputStream inputStream) throws IOException {
|
||||
final StringBuilder result = new StringBuilder();
|
||||
private void skipSprite(int width, int height, InputStream inputStream) throws IOException {
|
||||
final int nbLines = (height + 1) / 2;
|
||||
inputStream.skip(nbLines * width);
|
||||
}
|
||||
|
||||
private String readSprite(int width, int height, InputStream inputStream) throws IOException {
|
||||
final int nbLines = (height + 1) / 2;
|
||||
final StringBuilder result = new StringBuilder();
|
||||
int line = 0;
|
||||
for (int j = 0; j < nbLines; j++) {
|
||||
final StringBuilder sb1 = new StringBuilder();
|
||||
|
@ -52,7 +52,7 @@ import net.sourceforge.plantuml.command.regex.Matcher2;
|
||||
import net.sourceforge.plantuml.command.regex.MyPattern;
|
||||
import net.sourceforge.plantuml.command.regex.Pattern2;
|
||||
|
||||
public class SubPreprocessor implements ReadLine {
|
||||
public class SubPreprocessor extends ReadLineInstrumented implements ReadLine {
|
||||
|
||||
private static final String ID = "[A-Za-z_][A-Za-z_0-9]*";
|
||||
|
||||
@ -79,7 +79,8 @@ public class SubPreprocessor implements ReadLine {
|
||||
this.definitionsContainer = definitionsContainer;
|
||||
}
|
||||
|
||||
public CharSequence2 readLine() throws IOException {
|
||||
@Override
|
||||
CharSequence2 readLineInst() throws IOException {
|
||||
if (includedSub != null) {
|
||||
final CharSequence2 s = includedSub.readLine();
|
||||
if (s != null) {
|
||||
@ -176,7 +177,8 @@ public class SubPreprocessor implements ReadLine {
|
||||
return result;
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
@Override
|
||||
void closeInst() throws IOException {
|
||||
source.close();
|
||||
}
|
||||
|
||||
|
@ -44,21 +44,27 @@ import net.sourceforge.plantuml.command.regex.MyPattern;
|
||||
import net.sourceforge.plantuml.command.regex.Pattern2;
|
||||
import net.sourceforge.plantuml.utils.StartUtils;
|
||||
|
||||
public class UncommentReadLine implements ReadLine {
|
||||
public class UncommentReadLine extends ReadLineInstrumented implements ReadLine {
|
||||
|
||||
private static final Pattern2 unpause = MyPattern.cmpile(StartUtils.PAUSE_PATTERN);
|
||||
|
||||
private final ReadLine raw;
|
||||
private final Pattern2 start;
|
||||
private final Pattern2 unpause;
|
||||
// private final Pattern2 start;
|
||||
private String headerToRemove;
|
||||
private boolean paused;
|
||||
|
||||
public UncommentReadLine(ReadLine source) {
|
||||
this.raw = source;
|
||||
this.start = MyPattern.cmpile(StartUtils.START_PATTERN);
|
||||
this.unpause = MyPattern.cmpile(StartUtils.PAUSE_PATTERN);
|
||||
// this.start = MyPattern.cmpile(StartUtils.START_PATTERN);
|
||||
}
|
||||
|
||||
public CharSequence2 readLine() throws IOException {
|
||||
@Override
|
||||
public String toString() {
|
||||
return "UncommentReadLine of " + raw;
|
||||
}
|
||||
|
||||
@Override
|
||||
CharSequence2 readLineInst() throws IOException {
|
||||
final CharSequence2 result = raw.readLine();
|
||||
|
||||
if (result == null) {
|
||||
@ -88,7 +94,8 @@ public class UncommentReadLine implements ReadLine {
|
||||
return result;
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
@Override
|
||||
void closeInst() throws IOException {
|
||||
this.raw.close();
|
||||
}
|
||||
|
||||
|
@ -38,10 +38,18 @@ package net.sourceforge.plantuml.preproc;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class Variables {
|
||||
|
||||
private final List<DefineVariable> all = new ArrayList<DefineVariable>();
|
||||
private final String fonctionName;
|
||||
private final String definitionQuoted;
|
||||
|
||||
public Variables(String fonctionName, String definitionQuoted) {
|
||||
this.fonctionName = fonctionName;
|
||||
this.definitionQuoted = definitionQuoted;
|
||||
}
|
||||
|
||||
public void add(DefineVariable var) {
|
||||
this.all.add(var);
|
||||
@ -61,7 +69,7 @@ public class Variables {
|
||||
if (nb == 0) {
|
||||
return this;
|
||||
}
|
||||
final Variables result = new Variables();
|
||||
final Variables result = new Variables(fonctionName, definitionQuoted);
|
||||
for (DefineVariable v : all) {
|
||||
if (v.getDefaultValue() != null && nb > 0) {
|
||||
result.add(v.removeDefault());
|
||||
@ -76,36 +84,39 @@ public class Variables {
|
||||
return result;
|
||||
}
|
||||
|
||||
public String applyOn(String line, String fonctionName, String newValue) {
|
||||
// System.err.println("KEY="+key);
|
||||
// final StringTokenizer st = new StringTokenizer(key, "(),");
|
||||
// final String fctName = st.nextToken();
|
||||
final StringBuilder regex = new StringBuilder("\\b" + fonctionName + "\\(");
|
||||
private String newValue;
|
||||
private Pattern regex2;
|
||||
|
||||
final List<DefineVariable> variables = all;
|
||||
boolean appended = false;
|
||||
for (int j = 0; j < variables.size(); j++) {
|
||||
final DefineVariable variable = variables.get(j);
|
||||
final String varName = variable.getName();
|
||||
final String var2 = "(##" + varName + "\\b)|(\\b" + varName + "##)|(\\b" + varName + "\\b)";
|
||||
if (variable.getDefaultValue() == null) {
|
||||
regex.append("(?:(?:\\s*\"([^\"]*)\"\\s*)|(?:\\s*'([^']*)'\\s*)|\\s*" + "((?:\\([^()]*\\)|[^,'\"])*?)"
|
||||
+ ")");
|
||||
final int i = 1 + 3 * j;
|
||||
newValue = newValue.replaceAll(var2, "\\$" + i + "\\$" + (i + 1) + "\\$" + (i + 2));
|
||||
regex.append(",");
|
||||
appended = true;
|
||||
} else {
|
||||
newValue = newValue.replaceAll(var2, Matcher.quoteReplacement(variable.getDefaultValue()));
|
||||
public String applyOn(String line) {
|
||||
if (newValue == null) {
|
||||
newValue = definitionQuoted;
|
||||
final StringBuilder regex = new StringBuilder("\\b" + fonctionName + "\\(");
|
||||
|
||||
final List<DefineVariable> variables = all;
|
||||
boolean appended = false;
|
||||
for (int j = 0; j < variables.size(); j++) {
|
||||
final DefineVariable variable = variables.get(j);
|
||||
final String varName = variable.getName();
|
||||
final String var2 = "(##" + varName + "\\b)|(\\b" + varName + "##)|(\\b" + varName + "\\b)";
|
||||
if (variable.getDefaultValue() == null) {
|
||||
regex.append("(?:(?:\\s*\"([^\"]*)\"\\s*)|(?:\\s*'([^']*)'\\s*)|\\s*"
|
||||
+ "((?:\\([^()]*\\)|[^,'\"])*?)" + ")");
|
||||
final int i = 1 + 3 * j;
|
||||
newValue = newValue.replaceAll(var2, "\\$" + i + "\\$" + (i + 1) + "\\$" + (i + 2));
|
||||
regex.append(",");
|
||||
appended = true;
|
||||
} else {
|
||||
newValue = newValue.replaceAll(var2, Matcher.quoteReplacement(variable.getDefaultValue()));
|
||||
}
|
||||
}
|
||||
if (appended == true) {
|
||||
regex.setLength(regex.length() - 1);
|
||||
}
|
||||
regex.append("\\)");
|
||||
regex2 = Pattern.compile(regex.toString());
|
||||
}
|
||||
if (appended == true) {
|
||||
regex.setLength(regex.length() - 1);
|
||||
}
|
||||
regex.append("\\)");
|
||||
// System.err.println("regex=" + regex);
|
||||
// System.err.println("newValue=" + newValue);
|
||||
line = line.replaceAll(regex.toString(), newValue);
|
||||
// line = line.replaceAll(regex.toString(), newValue);
|
||||
line = regex2.matcher(line).replaceAll(newValue);
|
||||
return line;
|
||||
}
|
||||
|
||||
|
@ -48,7 +48,7 @@ public class SubjectTask implements SubjectPattern {
|
||||
|
||||
public Collection<VerbPattern> getVerbs() {
|
||||
return Arrays.<VerbPattern> asList(new VerbLasts(), new VerbTaskStarts(), new VerbTaskStartsAbsolute(),
|
||||
new VerbHappens(), new VerbEnds(), new VerbIsColored());
|
||||
new VerbHappens(), new VerbEnds(), new VerbTaskEndsAbsolute(), new VerbIsColored());
|
||||
}
|
||||
|
||||
public IRegex toRegex() {
|
||||
|
@ -0,0 +1,71 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* (C) Copyright 2009-2017, Arnaud Roques
|
||||
*
|
||||
* Project Info: http://plantuml.com
|
||||
*
|
||||
* If you like this project or if you find it useful, you can support us at:
|
||||
*
|
||||
* http://plantuml.com/patreon (only 1$ per month!)
|
||||
* http://plantuml.com/paypal
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*
|
||||
*
|
||||
* Original Author: Arnaud Roques
|
||||
*
|
||||
*
|
||||
*/
|
||||
package net.sourceforge.plantuml.project3;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
import net.sourceforge.plantuml.command.CommandExecutionResult;
|
||||
import net.sourceforge.plantuml.command.regex.IRegex;
|
||||
import net.sourceforge.plantuml.command.regex.RegexLeaf;
|
||||
import net.sourceforge.plantuml.command.regex.RegexResult;
|
||||
|
||||
public class VerbTaskEndsAbsolute implements VerbPattern {
|
||||
|
||||
public Collection<ComplementPattern> getComplements() {
|
||||
return Arrays.<ComplementPattern> asList(new ComplementDate());
|
||||
}
|
||||
|
||||
public IRegex toRegex() {
|
||||
return new RegexLeaf("ends[%s]*(the[%s]*|on[%s]*|at[%s]*)*");
|
||||
}
|
||||
|
||||
public Verb getVerb(final GanttDiagram project, RegexResult arg) {
|
||||
return new Verb() {
|
||||
public CommandExecutionResult execute(Subject subject, Complement complement) {
|
||||
final Task task = (Task) subject;
|
||||
final DayAsDate end = (DayAsDate) complement;
|
||||
final DayAsDate startingDate = project.getStartingDate();
|
||||
if (startingDate == null) {
|
||||
return CommandExecutionResult.error("No starting date for the project");
|
||||
}
|
||||
task.setEnd(end.asInstantDay(startingDate));
|
||||
return CommandExecutionResult.ok();
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
}
|
@ -47,6 +47,7 @@ import net.sourceforge.plantuml.AbstractPSystem;
|
||||
import net.sourceforge.plantuml.Dimension2DDouble;
|
||||
import net.sourceforge.plantuml.FileFormatOption;
|
||||
import net.sourceforge.plantuml.Log;
|
||||
import net.sourceforge.plantuml.ScaleSimple;
|
||||
import net.sourceforge.plantuml.UmlDiagram;
|
||||
import net.sourceforge.plantuml.WithSprite;
|
||||
import net.sourceforge.plantuml.api.ImageDataSimple;
|
||||
@ -108,7 +109,12 @@ public class PSystemSalt extends AbstractPSystem implements WithSprite {
|
||||
final Element salt = createElement(manageSprite());
|
||||
|
||||
final Dimension2D size = salt.getPreferredDimension(fileFormat.getDefaultStringBounder(), 0, 0);
|
||||
final ImageBuilder builder = new ImageBuilder(new ColorMapperIdentity(), 1.0, HtmlColorUtils.WHITE, null,
|
||||
|
||||
double scale = 1;
|
||||
if (getScale() != null) {
|
||||
scale = getScale().getScale(size.getWidth(), size.getHeight());
|
||||
}
|
||||
final ImageBuilder builder = new ImageBuilder(new ColorMapperIdentity(), scale, HtmlColorUtils.WHITE, null,
|
||||
null, 5, 5, null, false);
|
||||
builder.setUDrawable(new UDrawable() {
|
||||
|
||||
@ -146,6 +152,10 @@ public class PSystemSalt extends AbstractPSystem implements WithSprite {
|
||||
// System.err.println("skipping " + s);
|
||||
} else if (s.startsWith("skinparam ")) {
|
||||
// System.err.println("skipping " + s);
|
||||
} else if (s.startsWith("scale ")) {
|
||||
final Double scale = Double.parseDouble(s.substring("scale ".length()));
|
||||
this.setScale(new ScaleSimple(scale));
|
||||
// System.err.println("skipping " + s);
|
||||
} else if (s.startsWith("sprite $")) {
|
||||
BlocLines bloc = BlocLines.single(s);
|
||||
do {
|
||||
|
@ -280,7 +280,10 @@ public class SequenceDiagram extends UmlDiagram {
|
||||
p.incInitialLife(new SymbolContext(backcolor, linecolor));
|
||||
return null;
|
||||
}
|
||||
return "Only activate command can occur before message are send";
|
||||
if (p.getInitialLife() == 0) {
|
||||
return "You cannot deactivate here";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
if (lifeEventType == LifeEventType.ACTIVATE && lastEventWithDeactivate instanceof Message) {
|
||||
activationState.push((Message) lastEventWithDeactivate);
|
||||
|
@ -41,15 +41,19 @@ import java.io.OutputStream;
|
||||
import java.io.PrintStream;
|
||||
|
||||
import net.sourceforge.plantuml.FileFormat;
|
||||
import net.sourceforge.plantuml.StringUtils;
|
||||
import net.sourceforge.plantuml.api.ImageDataSimple;
|
||||
import net.sourceforge.plantuml.asciiart.TextSkin;
|
||||
import net.sourceforge.plantuml.asciiart.TextStringBounder;
|
||||
import net.sourceforge.plantuml.asciiart.UmlCharArea;
|
||||
import net.sourceforge.plantuml.core.ImageData;
|
||||
import net.sourceforge.plantuml.cucadiagram.Display;
|
||||
import net.sourceforge.plantuml.graphic.StringBounder;
|
||||
import net.sourceforge.plantuml.sequencediagram.Event;
|
||||
import net.sourceforge.plantuml.sequencediagram.Participant;
|
||||
import net.sourceforge.plantuml.sequencediagram.SequenceDiagram;
|
||||
import net.sourceforge.plantuml.skin.Skin;
|
||||
import net.sourceforge.plantuml.ugraphic.UTranslate;
|
||||
import net.sourceforge.plantuml.ugraphic.txt.UGraphicTxt;
|
||||
|
||||
public class SequenceDiagramTxtMaker implements FileMaker {
|
||||
@ -75,18 +79,18 @@ public class SequenceDiagramTxtMaker implements FileMaker {
|
||||
}
|
||||
for (Event ev : sequenceDiagram.events()) {
|
||||
initializer.addEvent(ev);
|
||||
// if (ev instanceof Message) {
|
||||
// // TODO mieux faire
|
||||
// final Message m = (Message) ev;
|
||||
// for (LifeEvent lifeEvent : m.getLiveEvents()) {
|
||||
// if (lifeEvent.getType() == LifeEventType.DESTROY
|
||||
// /*
|
||||
// * || lifeEvent.getType() == LifeEventType.CREATE
|
||||
// */) {
|
||||
// initializer.addEvent(lifeEvent);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// if (ev instanceof Message) {
|
||||
// // TODO mieux faire
|
||||
// final Message m = (Message) ev;
|
||||
// for (LifeEvent lifeEvent : m.getLiveEvents()) {
|
||||
// if (lifeEvent.getType() == LifeEventType.DESTROY
|
||||
// /*
|
||||
// * || lifeEvent.getType() == LifeEventType.CREATE
|
||||
// */) {
|
||||
// initializer.addEvent(lifeEvent);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
drawableSet = initializer.createDrawableSet(dummyStringBounder);
|
||||
// final List<Newpage> newpages = new ArrayList<Newpage>();
|
||||
@ -100,10 +104,24 @@ public class SequenceDiagramTxtMaker implements FileMaker {
|
||||
final double tailHeight = drawableSet.getTailHeight(dummyStringBounder, diagram.isShowFootbox());
|
||||
final double newpage2 = fullDimension.getHeight() - (diagram.isShowFootbox() ? tailHeight : 0) - headerHeight;
|
||||
final Page page = new Page(headerHeight, 0, newpage2, tailHeight, 0, null);
|
||||
//drawableSet.drawU_REMOVEDME_4243(ug, 0, fullDimension.getWidth(), page, diagram.isShowFootbox());
|
||||
drawableSet.drawU22(ug, 0, fullDimension.getWidth(), page, diagram.isShowFootbox());
|
||||
}
|
||||
// drawableSet.drawU_REMOVEDME_4243(ug, 0, fullDimension.getWidth(), page, diagram.isShowFootbox());
|
||||
|
||||
final Display title = diagram.getTitle().getDisplay();
|
||||
|
||||
final UGraphicTxt ug2;
|
||||
if (title.isWhite()) {
|
||||
ug2 = ug;
|
||||
} else {
|
||||
ug2 = (UGraphicTxt) ug.apply(new UTranslate(0, title.as().size() + 1));
|
||||
}
|
||||
drawableSet.drawU22(ug2, 0, fullDimension.getWidth(), page, diagram.isShowFootbox());
|
||||
if (title.isWhite() == false) {
|
||||
final int widthTitle = StringUtils.getWcWidth(title);
|
||||
final UmlCharArea charArea = ug.getCharArea();
|
||||
charArea.drawStringsLR(title.as(), (int) ((fullDimension.getWidth() - widthTitle) / 2), 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public ImageData createOne(OutputStream os, int index, boolean isWithMetadata) throws IOException {
|
||||
if (fileFormat == FileFormat.UTXT) {
|
||||
|
@ -60,7 +60,7 @@ public class LifeEventTile implements TileWithUpdateStairs {
|
||||
private final ISkinParam skinParam;
|
||||
|
||||
public void updateStairs(StringBounder stringBounder, double y) {
|
||||
System.err.println("LifeEventTile::updateStairs " + lifeEvent + " " + livingSpace.getParticipant() + " y=" + y);
|
||||
// System.err.println("LifeEventTile::updateStairs " + lifeEvent + " " + livingSpace.getParticipant() + " y=" + y);
|
||||
livingSpace.addStepForLivebox(getEvent(), y);
|
||||
}
|
||||
|
||||
|
@ -148,8 +148,9 @@ public class SequenceDiagramFileMakerTeoz implements FileMaker {
|
||||
|
||||
public void drawU(UGraphic ug) {
|
||||
ug = ug.apply(min1translate);
|
||||
englobers.drawEnglobers(goDownForEnglobers(ug), main.calculateDimension(stringBounder).getHeight()
|
||||
+ heightEnglober1 + heightEnglober2 / 2, new SimpleContext2D(true));
|
||||
|
||||
englobers.drawEnglobers(goDownAndCenterForEnglobers(ug), main.calculateDimension(stringBounder)
|
||||
.getHeight() + heightEnglober1 + heightEnglober2 / 2, new SimpleContext2D(true));
|
||||
|
||||
printAligned(ug, diagram.getFooterOrHeaderTeoz(FontParam.HEADER).getHorizontalAlignment(), header);
|
||||
ug = goDown(ug, header);
|
||||
@ -182,13 +183,14 @@ public class SequenceDiagramFileMakerTeoz implements FileMaker {
|
||||
|
||||
}
|
||||
|
||||
private UGraphic goDownForEnglobers(UGraphic ug) {
|
||||
private UGraphic goDownAndCenterForEnglobers(UGraphic ug) {
|
||||
ug = goDown(ug, title);
|
||||
ug = goDown(ug, header);
|
||||
if (diagram.getLegend().getVerticalAlignment() == VerticalAlignment.TOP) {
|
||||
ug = goDown(ug, legend);
|
||||
}
|
||||
return ug;
|
||||
final double dx = (dimTotal.getWidth() - main.calculateDimension(stringBounder).getWidth()) / 2;
|
||||
return ug.apply(new UTranslate(dx, 0));
|
||||
}
|
||||
|
||||
private UGraphic goDown(UGraphic ug, TextBlock size) {
|
||||
|
@ -84,7 +84,7 @@ public abstract class AbstractTextualComponent extends AbstractComponent {
|
||||
if (strings.size() == 1 && strings.get(0).length() == 0) {
|
||||
textBlock = new TextBlockEmpty();
|
||||
} else if (enhanced) {
|
||||
textBlock = new BodyEnhanced2(strings, FontParam.NOTE, spriteContainer, HorizontalAlignment.LEFT, font,
|
||||
textBlock = new BodyEnhanced2(strings, FontParam.NOTE, spriteContainer, horizontalAlignment, font,
|
||||
maxMessageSize);
|
||||
} else {
|
||||
textBlock = strings.create(font, horizontalAlignment, spriteContainer, maxMessageSize, CreoleMode.FULL,
|
||||
|
@ -60,9 +60,9 @@ final public class ComponentRoseNote extends AbstractTextualComponent implements
|
||||
private final double roundCorner;
|
||||
|
||||
public ComponentRoseNote(SymbolContext symbolContext, FontConfiguration font, Display strings, double paddingX,
|
||||
double paddingY, ISkinSimple spriteContainer, double roundCorner) {
|
||||
super(LineBreakStrategy.NONE, strings, font, HorizontalAlignment.LEFT, 6, 15, 5, spriteContainer, true, null,
|
||||
null);
|
||||
double paddingY, ISkinSimple spriteContainer, double roundCorner, HorizontalAlignment horizontalAlignment) {
|
||||
super(LineBreakStrategy.NONE, strings, font, horizontalAlignment,
|
||||
horizontalAlignment == HorizontalAlignment.CENTER ? 15 : 6, 15, 5, spriteContainer, true, null, null);
|
||||
this.roundCorner = roundCorner;
|
||||
this.paddingX = paddingX;
|
||||
this.paddingY = paddingY;
|
||||
|
@ -35,7 +35,7 @@
|
||||
*/
|
||||
package net.sourceforge.plantuml.skin.rose;
|
||||
|
||||
import net.sourceforge.plantuml.AlignParam;
|
||||
import net.sourceforge.plantuml.AlignmentParam;
|
||||
import net.sourceforge.plantuml.ColorParam;
|
||||
import net.sourceforge.plantuml.FontParam;
|
||||
import net.sourceforge.plantuml.ISkinParam;
|
||||
@ -100,9 +100,9 @@ public class Rose implements Skin {
|
||||
config, param, param.maxMessageSize(), param.strictUmlStyle() == false);
|
||||
}
|
||||
final HorizontalAlignment messageHorizontalAlignment = param.getHorizontalAlignment(
|
||||
AlignParam.SEQUENCE_MESSAGE_ALIGN, config.getArrowDirection());
|
||||
AlignmentParam.sequenceMessageAlignment, config.getArrowDirection());
|
||||
final HorizontalAlignment textHorizontalAlignment = param.getHorizontalAlignment(
|
||||
AlignParam.SEQUENCE_MESSAGETEXT_ALIGN, config.getArrowDirection());
|
||||
AlignmentParam.sequenceMessageTextAlignment, config.getArrowDirection());
|
||||
return new ComponentRoseArrow(sequenceArrow, getUFont2(param, FontParam.ARROW), stringsToDisplay, config,
|
||||
messageHorizontalAlignment, param, textHorizontalAlignment, param.maxMessageSize(),
|
||||
param.strictUmlStyle() == false, param.responseMessageBelowArrow());
|
||||
@ -198,8 +198,9 @@ public class Rose implements Skin {
|
||||
FontParam.DATABASE_STEREOTYPE));
|
||||
}
|
||||
if (type == ComponentType.NOTE) {
|
||||
final HorizontalAlignment alignment = param.getHorizontalAlignment(AlignmentParam.noteTextAlignment, null);
|
||||
return new ComponentRoseNote(getSymbolContext(param, ColorParam.noteBorder), getUFont2(param,
|
||||
FontParam.NOTE), stringsToDisplay, paddingX, paddingY, param, roundCorner);
|
||||
FontParam.NOTE), stringsToDisplay, paddingX, paddingY, param, roundCorner, alignment);
|
||||
}
|
||||
if (type == ComponentType.NOTE_HEXAGONAL) {
|
||||
return new ComponentRoseNoteHexagonal(getSymbolContext(param, ColorParam.noteBorder), getUFont2(param,
|
||||
@ -258,7 +259,7 @@ public class Rose implements Skin {
|
||||
if (type == ComponentType.REFERENCE) {
|
||||
return new ComponentRoseReference(getUFont2(param, FontParam.SEQUENCE_REFERENCE), getSymbolContext(param,
|
||||
ColorParam.sequenceReferenceBorder), bigFont, stringsToDisplay, param.getHorizontalAlignment(
|
||||
AlignParam.SEQUENCE_REFERENCE_ALIGN, null), param, getHtmlColor(param,
|
||||
AlignmentParam.sequenceReferenceAlignment, null), param, getHtmlColor(param,
|
||||
ColorParam.sequenceReferenceBackground));
|
||||
}
|
||||
// if (type == ComponentType.TITLE) {
|
||||
|
@ -48,7 +48,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import net.sourceforge.plantuml.AlignParam;
|
||||
import net.sourceforge.plantuml.AlignmentParam;
|
||||
import net.sourceforge.plantuml.ColorParam;
|
||||
import net.sourceforge.plantuml.Dimension2DDouble;
|
||||
import net.sourceforge.plantuml.FontParam;
|
||||
@ -365,7 +365,7 @@ public class Cluster implements Moveable {
|
||||
final ClusterDecoration decoration = new ClusterDecoration(style, group.getUSymbol(), ztitle, zstereo,
|
||||
minX, minY, maxX, maxY, stroke2);
|
||||
decoration.drawU(ug, back, borderColor, shadowing, roundCorner,
|
||||
skinParam2.getHorizontalAlignment(AlignParam.PACKAGE_TITLE_ALIGNMENT, null));
|
||||
skinParam2.getHorizontalAlignment(AlignmentParam.packageTitleAlignment, null));
|
||||
return;
|
||||
}
|
||||
final URectangle rect = new URectangle(maxX - minX, maxY - minY);
|
||||
@ -742,7 +742,7 @@ public class Cluster implements Moveable {
|
||||
sblabel.append(">");
|
||||
label = sblabel.toString();
|
||||
final HorizontalAlignment align = skinParam
|
||||
.getHorizontalAlignment(AlignParam.PACKAGE_TITLE_ALIGNMENT, null);
|
||||
.getHorizontalAlignment(AlignmentParam.packageTitleAlignment, null);
|
||||
sb.append("labeljust=\"" + align.getGraphVizValue() + "\";");
|
||||
} else {
|
||||
label = "\"\"";
|
||||
|
@ -184,7 +184,7 @@ public class GraphvizCrash extends AbstractTextBlock implements IEntityImage {
|
||||
if (flashCode != null) {
|
||||
final double h = graphicStrings.calculateDimension(ug.getStringBounder()).getHeight();
|
||||
ug = ug.apply(new UTranslate(0, h));
|
||||
ug.draw(new UImage(flashCode));
|
||||
ug.draw(new UImage(flashCode).scaleNearestNeighbor(3));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -51,6 +51,11 @@ public class UGraphicForSnake extends UGraphicDelegator {
|
||||
private final double dy;
|
||||
private final List<PendingSnake> snakes;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.toString() + " " + getUg();
|
||||
}
|
||||
|
||||
public UTranslate getTranslation() {
|
||||
return new UTranslate(dx, dy);
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ package net.sourceforge.plantuml.svek.image;
|
||||
|
||||
import java.awt.geom.Dimension2D;
|
||||
|
||||
import net.sourceforge.plantuml.AlignParam;
|
||||
import net.sourceforge.plantuml.AlignmentParam;
|
||||
import net.sourceforge.plantuml.ColorParam;
|
||||
import net.sourceforge.plantuml.Dimension2DDouble;
|
||||
import net.sourceforge.plantuml.FontParam;
|
||||
@ -130,7 +130,7 @@ public class EntityImageEmptyPackage extends AbstractEntityImage {
|
||||
|
||||
decoration.drawU(ug, back, SkinParamUtils.getColor(getSkinParam(), ColorParam.packageBorder, getStereo()),
|
||||
getSkinParam().shadowing(), roundCorner,
|
||||
getSkinParam().getHorizontalAlignment(AlignParam.PACKAGE_TITLE_ALIGNMENT, null));
|
||||
getSkinParam().getHorizontalAlignment(AlignmentParam.packageTitleAlignment, null));
|
||||
|
||||
if (url != null) {
|
||||
ug.closeAction();
|
||||
|
@ -743,11 +743,11 @@ public class SvgGraphics {
|
||||
private String manageScale(SvgString svg) {
|
||||
final double svgScale = svg.getScale();
|
||||
if (svgScale * scale == 1) {
|
||||
return svg.getSvg();
|
||||
return svg.getSvg(false);
|
||||
}
|
||||
final String s1 = "\\<g\\b";
|
||||
final String s2 = "<g transform=\"scale(" + format(svgScale) + "," + format(svgScale) + ")\" ";
|
||||
return svg.getSvg().replaceFirst(s1, s2);
|
||||
return svg.getSvg(false).replaceFirst(s1, s2);
|
||||
}
|
||||
|
||||
private String toBase64(BufferedImage image) throws IOException {
|
||||
|
@ -42,6 +42,7 @@ import java.util.TreeSet;
|
||||
|
||||
import net.sourceforge.plantuml.SkinParam;
|
||||
import net.sourceforge.plantuml.graphic.HtmlColorSetSimple;
|
||||
import net.sourceforge.plantuml.utils.Cypher;
|
||||
|
||||
public class LanguageDescriptor {
|
||||
|
||||
@ -165,6 +166,26 @@ public class LanguageDescriptor {
|
||||
preproc.add("!enddefinelong");
|
||||
}
|
||||
|
||||
public Cypher getCypher() {
|
||||
final Cypher cypher = new Cypher();
|
||||
for (String s : type) {
|
||||
cypher.addException(s);
|
||||
}
|
||||
for (String s : keyword) {
|
||||
cypher.addException(s.replace("@", ""));
|
||||
}
|
||||
for (String s : preproc) {
|
||||
cypher.addException(s.substring(1));
|
||||
}
|
||||
for (String s : SkinParam.getPossibleValues()) {
|
||||
cypher.addException(s);
|
||||
}
|
||||
for (String s : new HtmlColorSetSimple().names()) {
|
||||
cypher.addException(s);
|
||||
}
|
||||
return cypher;
|
||||
}
|
||||
|
||||
public void print(PrintStream ps) {
|
||||
print(ps, "type", type);
|
||||
print(ps, "keyword", keyword);
|
||||
@ -175,7 +196,7 @@ public class LanguageDescriptor {
|
||||
}
|
||||
|
||||
private static void print(PrintStream ps, String name, Collection<String> data) {
|
||||
ps.println(";"+name);
|
||||
ps.println(";" + name);
|
||||
ps.println(";" + data.size());
|
||||
for (String k : data) {
|
||||
ps.println(k);
|
||||
|
@ -48,7 +48,6 @@ import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
@ -55,6 +55,7 @@ import javax.swing.ImageIcon;
|
||||
import net.sourceforge.plantuml.AnimatedGifEncoder;
|
||||
import net.sourceforge.plantuml.CMapData;
|
||||
import net.sourceforge.plantuml.ColorParam;
|
||||
import net.sourceforge.plantuml.CornerParam;
|
||||
import net.sourceforge.plantuml.Dimension2DDouble;
|
||||
import net.sourceforge.plantuml.EmptyImageBuilder;
|
||||
import net.sourceforge.plantuml.FileFormat;
|
||||
@ -63,7 +64,6 @@ import net.sourceforge.plantuml.FileUtils;
|
||||
import net.sourceforge.plantuml.ISkinParam;
|
||||
import net.sourceforge.plantuml.LineParam;
|
||||
import net.sourceforge.plantuml.OptionFlags;
|
||||
import net.sourceforge.plantuml.CornerParam;
|
||||
import net.sourceforge.plantuml.StringUtils;
|
||||
import net.sourceforge.plantuml.Url;
|
||||
import net.sourceforge.plantuml.anim.AffineTransformation;
|
||||
|
@ -1,156 +0,0 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* (C) Copyright 2009-2017, Arnaud Roques
|
||||
*
|
||||
* Project Info: http://plantuml.com
|
||||
*
|
||||
* If you like this project or if you find it useful, you can support us at:
|
||||
*
|
||||
* http://plantuml.com/patreon (only 1$ per month!)
|
||||
* http://plantuml.com/paypal
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*
|
||||
*
|
||||
* Original Author: Arnaud Roques
|
||||
*
|
||||
*
|
||||
*/
|
||||
package net.sourceforge.plantuml.ugraphic;
|
||||
|
||||
import net.sourceforge.plantuml.Url;
|
||||
import net.sourceforge.plantuml.graphic.StringBounder;
|
||||
|
||||
public class SlotFinderX implements UGraphic {
|
||||
|
||||
public boolean matchesProperty(String propertyName) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public double dpiFactor() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
public UGraphic apply(UChange change) {
|
||||
if (change instanceof UTranslate) {
|
||||
return new SlotFinderX(stringBounder, xslot, yslot, translate.compose((UTranslate) change));
|
||||
} else if (change instanceof UStroke) {
|
||||
return new SlotFinderX(this);
|
||||
} else if (change instanceof UChangeBackColor) {
|
||||
return new SlotFinderX(this);
|
||||
} else if (change instanceof UChangeColor) {
|
||||
return new SlotFinderX(this);
|
||||
}
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
private final SlotSet xslot;
|
||||
private final SlotSet yslot;
|
||||
private final StringBounder stringBounder;
|
||||
private final UTranslate translate;
|
||||
|
||||
public SlotFinderX(StringBounder stringBounder) {
|
||||
this(stringBounder, new SlotSet(), new SlotSet(), new UTranslate());
|
||||
}
|
||||
|
||||
private SlotFinderX(StringBounder stringBounder, SlotSet xslot, SlotSet yslot, UTranslate translate) {
|
||||
this.stringBounder = stringBounder;
|
||||
this.xslot = xslot;
|
||||
this.yslot = yslot;
|
||||
this.translate = translate;
|
||||
}
|
||||
|
||||
private SlotFinderX(SlotFinderX other) {
|
||||
this(other.stringBounder, other.xslot, other.yslot, other.translate);
|
||||
}
|
||||
|
||||
public StringBounder getStringBounder() {
|
||||
return stringBounder;
|
||||
}
|
||||
|
||||
public UParam getParam() {
|
||||
return new UParamNull();
|
||||
}
|
||||
|
||||
public void draw(UShape shape) {
|
||||
final double x = translate.getDx();
|
||||
final double y = translate.getDy();
|
||||
if (shape instanceof URectangle) {
|
||||
drawRectangle(x, y, (URectangle) shape);
|
||||
} else if (shape instanceof UPolygon) {
|
||||
drawPolygon(x, y, (UPolygon) shape);
|
||||
} else if (shape instanceof UEllipse) {
|
||||
drawEllipse(x, y, (UEllipse) shape);
|
||||
} else if (shape instanceof UText) {
|
||||
drawText(x, y, (UText) shape);
|
||||
} else if (shape instanceof UEmpty) {
|
||||
drawEmpty(x, y, (UEmpty) shape);
|
||||
}
|
||||
}
|
||||
|
||||
private void drawEmpty(double x, double y, UEmpty shape) {
|
||||
xslot.addSlot(x, x + shape.getWidth());
|
||||
yslot.addSlot(y, y + shape.getHeight());
|
||||
}
|
||||
|
||||
private void drawText(double x, double y, UText shape) {
|
||||
final TextLimitFinder finder = new TextLimitFinder(stringBounder, false);
|
||||
finder.apply(new UTranslate(x, y)).draw(shape);
|
||||
xslot.addSlot(finder.getMinX(), finder.getMaxX());
|
||||
yslot.addSlot(finder.getMinY(), finder.getMaxY());
|
||||
}
|
||||
|
||||
private void drawEllipse(double x, double y, UEllipse shape) {
|
||||
xslot.addSlot(x, x + shape.getWidth());
|
||||
yslot.addSlot(y, y + shape.getHeight());
|
||||
}
|
||||
|
||||
private void drawPolygon(double x, double y, UPolygon shape) {
|
||||
xslot.addSlot(x + shape.getMinX(), x + shape.getMaxX());
|
||||
yslot.addSlot(y + shape.getMinY(), y + shape.getMaxY());
|
||||
}
|
||||
|
||||
private void drawRectangle(double x, double y, URectangle shape) {
|
||||
xslot.addSlot(x, x + shape.getWidth());
|
||||
yslot.addSlot(y, y + shape.getHeight());
|
||||
}
|
||||
|
||||
public ColorMapper getColorMapper() {
|
||||
return new ColorMapperIdentity();
|
||||
}
|
||||
|
||||
public void startUrl(Url url) {
|
||||
}
|
||||
|
||||
public void closeAction() {
|
||||
}
|
||||
|
||||
public SlotSet getXSlotSet() {
|
||||
return xslot;
|
||||
}
|
||||
|
||||
public SlotSet getYSlotSet() {
|
||||
return yslot;
|
||||
}
|
||||
|
||||
public void flushUg() {
|
||||
}
|
||||
|
||||
}
|
@ -1,98 +0,0 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* (C) Copyright 2009-2017, Arnaud Roques
|
||||
*
|
||||
* Project Info: http://plantuml.com
|
||||
*
|
||||
* If you like this project or if you find it useful, you can support us at:
|
||||
*
|
||||
* http://plantuml.com/patreon (only 1$ per month!)
|
||||
* http://plantuml.com/paypal
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*
|
||||
*
|
||||
* Original Author: Arnaud Roques
|
||||
*
|
||||
*
|
||||
*/
|
||||
package net.sourceforge.plantuml.ugraphic;
|
||||
|
||||
import net.sourceforge.plantuml.activitydiagram3.ftile.Snake;
|
||||
import net.sourceforge.plantuml.graphic.UGraphicDelegator;
|
||||
|
||||
public class UGraphicCompress2 extends UGraphicDelegator {
|
||||
|
||||
public UGraphic apply(UChange change) {
|
||||
if (change instanceof UTranslate) {
|
||||
return new UGraphicCompress2(getUg(), compressionTransform, translate.compose((UTranslate) change));
|
||||
} else if (change instanceof UStroke || change instanceof UChangeBackColor || change instanceof UChangeColor) {
|
||||
return new UGraphicCompress2(getUg().apply(change), compressionTransform, translate);
|
||||
}
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
private final CompressionTransform compressionTransform;
|
||||
private final UTranslate translate;
|
||||
|
||||
public UGraphicCompress2(UGraphic ug, CompressionTransform compressionTransform) {
|
||||
this(ug, compressionTransform, new UTranslate());
|
||||
}
|
||||
|
||||
private UGraphicCompress2(UGraphic ug, CompressionTransform compressionTransform, UTranslate translate) {
|
||||
super(ug);
|
||||
this.compressionTransform = compressionTransform;
|
||||
this.translate = translate;
|
||||
}
|
||||
|
||||
public void draw(UShape shape) {
|
||||
final double x = translate.getDx();
|
||||
final double y = translate.getDy();
|
||||
if (shape instanceof ULine) {
|
||||
drawLine(x, y, (ULine) shape);
|
||||
} else if (shape instanceof Snake) {
|
||||
drawSnake(x, y, (Snake) shape);
|
||||
} else {
|
||||
getUg().apply(new UTranslate(ct(x), y)).draw(shape);
|
||||
}
|
||||
}
|
||||
|
||||
private void drawSnake(double x, double y, Snake shape) {
|
||||
final Snake transformed = shape.translate(new UTranslate(x, y)).transformX(compressionTransform);
|
||||
getUg().draw(transformed);
|
||||
}
|
||||
|
||||
private void drawLine(double x, double y, ULine shape) {
|
||||
drawLine(ct(x), y, ct(x + shape.getDX()), y + shape.getDY());
|
||||
}
|
||||
|
||||
private double ct(double v) {
|
||||
return compressionTransform.transform(v);
|
||||
}
|
||||
|
||||
private void drawLine(double x1, double y1, double x2, double y2) {
|
||||
final double xmin = Math.min(x1, x2);
|
||||
final double xmax = Math.max(x1, x2);
|
||||
final double ymin = Math.min(y1, y2);
|
||||
final double ymax = Math.max(y1, y2);
|
||||
getUg().apply(new UTranslate(xmin, ymin)).draw(new ULine(xmax - xmin, ymax - ymin));
|
||||
}
|
||||
|
||||
}
|
@ -43,32 +43,19 @@ public class UImage implements UShape {
|
||||
|
||||
private final BufferedImage image;
|
||||
|
||||
// public final double getScale() {
|
||||
// return scale;
|
||||
// }
|
||||
|
||||
public UImage(BufferedImage image) {
|
||||
this.image = image;
|
||||
}
|
||||
|
||||
// public UImage(BufferedImage before, double scale) {
|
||||
// this.image = before;
|
||||
// this.scale = scale;
|
||||
// // if (scale == 1) {
|
||||
// // this.image = before;
|
||||
// // return;
|
||||
// // }
|
||||
//
|
||||
// // final int w = (int) Math.round(before.getWidth() * scale);
|
||||
// // final int h = (int) Math.round(before.getHeight() * scale);
|
||||
// // final BufferedImage after = new BufferedImage(w, h, before.getType());
|
||||
// // final AffineTransform at = new AffineTransform();
|
||||
// // at.scale(scale, scale);
|
||||
// // final AffineTransformOp scaleOp = new AffineTransformOp(at, AffineTransformOp.TYPE_BILINEAR);
|
||||
// // this.image = scaleOp.filter(before, after);
|
||||
// }
|
||||
|
||||
public UImage scale(double scale) {
|
||||
return scale(scale, AffineTransformOp.TYPE_BILINEAR);
|
||||
}
|
||||
|
||||
public UImage scaleNearestNeighbor(double scale) {
|
||||
return scale(scale, AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
|
||||
}
|
||||
|
||||
private UImage scale(double scale, final int type) {
|
||||
if (scale == 1) {
|
||||
return this;
|
||||
}
|
||||
@ -77,7 +64,7 @@ public class UImage implements UShape {
|
||||
final BufferedImage after = new BufferedImage(w, h, image.getType());
|
||||
final AffineTransform at = new AffineTransform();
|
||||
at.scale(scale, scale);
|
||||
final AffineTransformOp scaleOp = new AffineTransformOp(at, AffineTransformOp.TYPE_BILINEAR);
|
||||
final AffineTransformOp scaleOp = new AffineTransformOp(at, type);
|
||||
return new UImage(scaleOp.filter(image, after));
|
||||
}
|
||||
|
||||
@ -93,8 +80,4 @@ public class UImage implements UShape {
|
||||
return image.getHeight() - 1;
|
||||
}
|
||||
|
||||
// public UShape getScaled(double scale) {
|
||||
// return scale(scale);
|
||||
// }
|
||||
|
||||
}
|
||||
|
@ -44,13 +44,20 @@ public class URectangle extends AbstractShadowable implements Scalable, UShapeSi
|
||||
private final double ry;
|
||||
private final String comment;
|
||||
|
||||
public URectangle withWidth(double newHeight) {
|
||||
public URectangle withHeight(double newHeight) {
|
||||
final URectangle result = new URectangle(width, newHeight, rx, ry, comment);
|
||||
result.ignoreForCompression = this.ignoreForCompression;
|
||||
result.setDeltaShadow(this.getDeltaShadow());
|
||||
return result;
|
||||
}
|
||||
|
||||
public URectangle withWidth(double newWidth) {
|
||||
final URectangle result = new URectangle(newWidth, height, rx, ry, comment);
|
||||
result.ignoreForCompression = this.ignoreForCompression;
|
||||
result.setDeltaShadow(this.getDeltaShadow());
|
||||
return result;
|
||||
}
|
||||
|
||||
public UShape getScaled(double scale) {
|
||||
if (scale == 1) {
|
||||
return this;
|
||||
|
@ -0,0 +1,41 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* (C) Copyright 2009-2017, Arnaud Roques
|
||||
*
|
||||
* Project Info: http://plantuml.com
|
||||
*
|
||||
* If you like this project or if you find it useful, you can support us at:
|
||||
*
|
||||
* http://plantuml.com/patreon (only 1$ per month!)
|
||||
* http://plantuml.com/paypal
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*
|
||||
*
|
||||
* Original Author: Arnaud Roques
|
||||
*
|
||||
*
|
||||
*/
|
||||
package net.sourceforge.plantuml.ugraphic.comp;
|
||||
|
||||
public enum CompressionMode {
|
||||
ON_X, ON_Y
|
||||
|
||||
}
|
@ -33,7 +33,7 @@
|
||||
*
|
||||
*
|
||||
*/
|
||||
package net.sourceforge.plantuml.ugraphic;
|
||||
package net.sourceforge.plantuml.ugraphic.comp;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -33,7 +33,7 @@
|
||||
*
|
||||
*
|
||||
*/
|
||||
package net.sourceforge.plantuml.ugraphic;
|
||||
package net.sourceforge.plantuml.ugraphic.comp;
|
||||
|
||||
public class Slot implements Comparable<Slot> {
|
||||
|
@ -33,10 +33,28 @@
|
||||
*
|
||||
*
|
||||
*/
|
||||
package net.sourceforge.plantuml.ugraphic;
|
||||
package net.sourceforge.plantuml.ugraphic.comp;
|
||||
|
||||
import net.sourceforge.plantuml.Url;
|
||||
import net.sourceforge.plantuml.graphic.StringBounder;
|
||||
import net.sourceforge.plantuml.ugraphic.ColorMapper;
|
||||
import net.sourceforge.plantuml.ugraphic.ColorMapperIdentity;
|
||||
import net.sourceforge.plantuml.ugraphic.TextLimitFinder;
|
||||
import net.sourceforge.plantuml.ugraphic.UChange;
|
||||
import net.sourceforge.plantuml.ugraphic.UChangeBackColor;
|
||||
import net.sourceforge.plantuml.ugraphic.UChangeColor;
|
||||
import net.sourceforge.plantuml.ugraphic.UEllipse;
|
||||
import net.sourceforge.plantuml.ugraphic.UEmpty;
|
||||
import net.sourceforge.plantuml.ugraphic.UGraphic;
|
||||
import net.sourceforge.plantuml.ugraphic.UParam;
|
||||
import net.sourceforge.plantuml.ugraphic.UParamNull;
|
||||
import net.sourceforge.plantuml.ugraphic.UPath;
|
||||
import net.sourceforge.plantuml.ugraphic.UPolygon;
|
||||
import net.sourceforge.plantuml.ugraphic.URectangle;
|
||||
import net.sourceforge.plantuml.ugraphic.UShape;
|
||||
import net.sourceforge.plantuml.ugraphic.UStroke;
|
||||
import net.sourceforge.plantuml.ugraphic.UText;
|
||||
import net.sourceforge.plantuml.ugraphic.UTranslate;
|
||||
|
||||
public class SlotFinder implements UGraphic {
|
||||
|
||||
@ -50,7 +68,7 @@ public class SlotFinder implements UGraphic {
|
||||
|
||||
public UGraphic apply(UChange change) {
|
||||
if (change instanceof UTranslate) {
|
||||
return new SlotFinder(stringBounder, yslot, translate.compose((UTranslate) change));
|
||||
return new SlotFinder(mode, stringBounder, slot, translate.compose((UTranslate) change));
|
||||
} else if (change instanceof UStroke) {
|
||||
return new SlotFinder(this);
|
||||
} else if (change instanceof UChangeBackColor) {
|
||||
@ -61,22 +79,25 @@ public class SlotFinder implements UGraphic {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
private final SlotSet yslot;
|
||||
private final SlotSet slot;
|
||||
|
||||
private final StringBounder stringBounder;
|
||||
private final UTranslate translate;
|
||||
private final CompressionMode mode;
|
||||
|
||||
public SlotFinder(StringBounder stringBounder) {
|
||||
this(stringBounder, new SlotSet(), new UTranslate());
|
||||
public SlotFinder(CompressionMode mode, StringBounder stringBounder) {
|
||||
this(mode, stringBounder, new SlotSet(), new UTranslate());
|
||||
}
|
||||
|
||||
private SlotFinder(StringBounder stringBounder, SlotSet yslot, UTranslate translate) {
|
||||
private SlotFinder(CompressionMode mode, StringBounder stringBounder, SlotSet slot, UTranslate translate) {
|
||||
this.stringBounder = stringBounder;
|
||||
this.yslot = yslot;
|
||||
this.slot = slot;
|
||||
this.translate = translate;
|
||||
this.mode = mode;
|
||||
}
|
||||
|
||||
private SlotFinder(SlotFinder other) {
|
||||
this(other.stringBounder, other.yslot, other.translate);
|
||||
this(other.mode, other.stringBounder, other.slot, other.translate);
|
||||
}
|
||||
|
||||
public StringBounder getStringBounder() {
|
||||
@ -92,12 +113,19 @@ public class SlotFinder implements UGraphic {
|
||||
final double y = translate.getDy();
|
||||
if (shape instanceof URectangle) {
|
||||
final URectangle rect = (URectangle) shape;
|
||||
if (rect.isIgnoreForCompression()) {
|
||||
if (mode == CompressionMode.ON_X && rect.isIgnoreForCompression()) {
|
||||
drawRectangle(x, y, new URectangle(2, rect.getHeight()));
|
||||
drawRectangle(x + rect.getWidth() - 2, y, new URectangle(2, rect.getHeight()));
|
||||
return;
|
||||
}
|
||||
if (mode == CompressionMode.ON_Y && rect.isIgnoreForCompression()) {
|
||||
drawRectangle(x, y, new URectangle(rect.getWidth(), 2));
|
||||
drawRectangle(x, y + rect.getHeight() - 2, new URectangle(rect.getWidth(), 2));
|
||||
return;
|
||||
}
|
||||
drawRectangle(x, y, rect);
|
||||
drawRectangle(x, y, (URectangle) shape);
|
||||
} else if (shape instanceof UPath) {
|
||||
drawPath(x, y, (UPath) shape);
|
||||
} else if (shape instanceof UPolygon) {
|
||||
drawPolygon(x, y, (UPolygon) shape);
|
||||
} else if (shape instanceof UEllipse) {
|
||||
@ -109,26 +137,55 @@ public class SlotFinder implements UGraphic {
|
||||
}
|
||||
}
|
||||
|
||||
private void drawPath(double x, double y, UPath shape) {
|
||||
if (mode == CompressionMode.ON_X) {
|
||||
slot.addSlot(x + shape.getMinX(), x + shape.getMaxX());
|
||||
} else {
|
||||
slot.addSlot(y + shape.getMinY(), y + shape.getMaxY());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void drawEmpty(double x, double y, UEmpty shape) {
|
||||
yslot.addSlot(y, y + shape.getHeight());
|
||||
if (mode == CompressionMode.ON_X) {
|
||||
slot.addSlot(x, x + shape.getWidth());
|
||||
} else {
|
||||
slot.addSlot(y, y + shape.getHeight());
|
||||
}
|
||||
}
|
||||
|
||||
private void drawText(double x, double y, UText shape) {
|
||||
final TextLimitFinder finder = new TextLimitFinder(stringBounder, false);
|
||||
finder.apply(new UTranslate(x, y)).draw(shape);
|
||||
yslot.addSlot(finder.getMinY(), finder.getMaxY());
|
||||
if (mode == CompressionMode.ON_X) {
|
||||
slot.addSlot(finder.getMinX(), finder.getMaxX());
|
||||
} else {
|
||||
slot.addSlot(finder.getMinY(), finder.getMaxY());
|
||||
}
|
||||
}
|
||||
|
||||
private void drawEllipse(double x, double y, UEllipse shape) {
|
||||
yslot.addSlot(y, y + shape.getHeight());
|
||||
if (mode == CompressionMode.ON_X) {
|
||||
slot.addSlot(x, x + shape.getWidth());
|
||||
} else {
|
||||
slot.addSlot(y, y + shape.getHeight());
|
||||
}
|
||||
}
|
||||
|
||||
private void drawPolygon(double x, double y, UPolygon shape) {
|
||||
yslot.addSlot(y + shape.getMinY(), y + shape.getMaxY());
|
||||
if (mode == CompressionMode.ON_X) {
|
||||
slot.addSlot(x + shape.getMinX(), x + shape.getMaxX());
|
||||
} else {
|
||||
slot.addSlot(y + shape.getMinY(), y + shape.getMaxY());
|
||||
}
|
||||
}
|
||||
|
||||
private void drawRectangle(double x, double y, URectangle shape) {
|
||||
yslot.addSlot(y, y + shape.getHeight());
|
||||
if (mode == CompressionMode.ON_X) {
|
||||
slot.addSlot(x, x + shape.getWidth());
|
||||
} else {
|
||||
slot.addSlot(y, y + shape.getHeight());
|
||||
}
|
||||
}
|
||||
|
||||
public ColorMapper getColorMapper() {
|
||||
@ -141,8 +198,8 @@ public class SlotFinder implements UGraphic {
|
||||
public void closeAction() {
|
||||
}
|
||||
|
||||
public SlotSet getYSlotSet() {
|
||||
return yslot;
|
||||
public SlotSet getSlotSet() {
|
||||
return slot;
|
||||
}
|
||||
|
||||
public void flushUg() {
|
@ -33,13 +33,17 @@
|
||||
*
|
||||
*
|
||||
*/
|
||||
package net.sourceforge.plantuml.ugraphic;
|
||||
package net.sourceforge.plantuml.ugraphic.comp;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import net.sourceforge.plantuml.ugraphic.UGraphic;
|
||||
import net.sourceforge.plantuml.ugraphic.URectangle;
|
||||
import net.sourceforge.plantuml.ugraphic.UTranslate;
|
||||
|
||||
public class SlotSet implements Iterable<Slot> {
|
||||
|
||||
private final List<Slot> all = new ArrayList<Slot>();
|
@ -33,30 +33,32 @@
|
||||
*
|
||||
*
|
||||
*/
|
||||
package net.sourceforge.plantuml.graphic;
|
||||
package net.sourceforge.plantuml.ugraphic.comp;
|
||||
|
||||
import java.awt.geom.Dimension2D;
|
||||
|
||||
import net.sourceforge.plantuml.Dimension2DDouble;
|
||||
import net.sourceforge.plantuml.ugraphic.CompressionTransform;
|
||||
import net.sourceforge.plantuml.graphic.AbstractTextBlock;
|
||||
import net.sourceforge.plantuml.graphic.StringBounder;
|
||||
import net.sourceforge.plantuml.graphic.TextBlock;
|
||||
import net.sourceforge.plantuml.graphic.TextBlockUtils;
|
||||
import net.sourceforge.plantuml.ugraphic.MinMax;
|
||||
import net.sourceforge.plantuml.ugraphic.SlotFinder;
|
||||
import net.sourceforge.plantuml.ugraphic.SlotSet;
|
||||
import net.sourceforge.plantuml.ugraphic.UGraphic;
|
||||
import net.sourceforge.plantuml.ugraphic.UGraphicCompress;
|
||||
|
||||
public class TextBlockCompressed extends AbstractTextBlock implements TextBlock {
|
||||
public class TextBlockCompressedOnXorY extends AbstractTextBlock implements TextBlock {
|
||||
|
||||
private final TextBlock textBlock;
|
||||
private final CompressionMode mode;
|
||||
|
||||
public TextBlockCompressed(TextBlock textBlock) {
|
||||
public TextBlockCompressedOnXorY(CompressionMode mode, TextBlock textBlock) {
|
||||
this.textBlock = textBlock;
|
||||
this.mode = mode;
|
||||
}
|
||||
|
||||
public void drawU(final UGraphic ug) {
|
||||
final StringBounder stringBounder = ug.getStringBounder();
|
||||
final CompressionTransform compressionTransform = getCompressionTransform(stringBounder);
|
||||
textBlock.drawU(new UGraphicCompress(ug, compressionTransform));
|
||||
textBlock.drawU(new UGraphicCompressOnXorY(mode, ug, compressionTransform));
|
||||
}
|
||||
|
||||
private MinMax cachedMinMax;
|
||||
@ -79,9 +81,9 @@ public class TextBlockCompressed extends AbstractTextBlock implements TextBlock
|
||||
}
|
||||
|
||||
private CompressionTransform getCompressionTransformSlow(final StringBounder stringBounder) {
|
||||
final SlotFinder slotFinder = new SlotFinder(stringBounder);
|
||||
final SlotFinder slotFinder = new SlotFinder(mode, stringBounder);
|
||||
textBlock.drawU(slotFinder);
|
||||
final SlotSet ysSlotSet = slotFinder.getYSlotSet().reverse().smaller(5.0);
|
||||
final SlotSet ysSlotSet = slotFinder.getSlotSet().reverse().smaller(5.0);
|
||||
final CompressionTransform compressionTransform = new CompressionTransform(ysSlotSet);
|
||||
return compressionTransform;
|
||||
}
|
||||
@ -89,6 +91,10 @@ public class TextBlockCompressed extends AbstractTextBlock implements TextBlock
|
||||
public Dimension2D calculateDimension(StringBounder stringBounder) {
|
||||
final CompressionTransform compressionTransform = getCompressionTransform(stringBounder);
|
||||
final Dimension2D dim = textBlock.calculateDimension(stringBounder);
|
||||
return new Dimension2DDouble(dim.getWidth(), compressionTransform.transform(dim.getHeight()));
|
||||
if (mode == CompressionMode.ON_X) {
|
||||
return new Dimension2DDouble(compressionTransform.transform(dim.getWidth()), dim.getHeight());
|
||||
} else {
|
||||
return new Dimension2DDouble(dim.getWidth(), compressionTransform.transform(dim.getHeight()));
|
||||
}
|
||||
}
|
||||
}
|
@ -33,30 +33,42 @@
|
||||
*
|
||||
*
|
||||
*/
|
||||
package net.sourceforge.plantuml.ugraphic;
|
||||
package net.sourceforge.plantuml.ugraphic.comp;
|
||||
|
||||
import net.sourceforge.plantuml.graphic.UGraphicDelegator;
|
||||
import net.sourceforge.plantuml.ugraphic.UChange;
|
||||
import net.sourceforge.plantuml.ugraphic.UChangeBackColor;
|
||||
import net.sourceforge.plantuml.ugraphic.UChangeColor;
|
||||
import net.sourceforge.plantuml.ugraphic.UGraphic;
|
||||
import net.sourceforge.plantuml.ugraphic.ULine;
|
||||
import net.sourceforge.plantuml.ugraphic.URectangle;
|
||||
import net.sourceforge.plantuml.ugraphic.UShape;
|
||||
import net.sourceforge.plantuml.ugraphic.UStroke;
|
||||
import net.sourceforge.plantuml.ugraphic.UTranslate;
|
||||
|
||||
public class UGraphicCompress extends UGraphicDelegator {
|
||||
public class UGraphicCompressOnXorY extends UGraphicDelegator {
|
||||
|
||||
public UGraphic apply(UChange change) {
|
||||
if (change instanceof UTranslate) {
|
||||
return new UGraphicCompress(getUg(), compressionTransform, translate.compose((UTranslate) change));
|
||||
return new UGraphicCompressOnXorY(mode, getUg(), compressionTransform, translate.compose((UTranslate) change));
|
||||
} else if (change instanceof UStroke || change instanceof UChangeBackColor || change instanceof UChangeColor) {
|
||||
return new UGraphicCompress(getUg().apply(change), compressionTransform, translate);
|
||||
return new UGraphicCompressOnXorY(mode, getUg().apply(change), compressionTransform, translate);
|
||||
}
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
private final CompressionMode mode;
|
||||
private final CompressionTransform compressionTransform;
|
||||
private final UTranslate translate;
|
||||
|
||||
public UGraphicCompress(UGraphic ug, CompressionTransform compressionTransform) {
|
||||
this(ug, compressionTransform, new UTranslate());
|
||||
public UGraphicCompressOnXorY(CompressionMode mode, UGraphic ug, CompressionTransform compressionTransform) {
|
||||
this(mode, ug, compressionTransform, new UTranslate());
|
||||
}
|
||||
|
||||
private UGraphicCompress(UGraphic ug, CompressionTransform compressionTransform, UTranslate translate) {
|
||||
private UGraphicCompressOnXorY(CompressionMode mode, UGraphic ug, CompressionTransform compressionTransform,
|
||||
UTranslate translate) {
|
||||
super(ug);
|
||||
this.mode = mode;
|
||||
this.compressionTransform = compressionTransform;
|
||||
this.translate = translate;
|
||||
}
|
||||
@ -67,19 +79,32 @@ public class UGraphicCompress extends UGraphicDelegator {
|
||||
if (shape instanceof URectangle) {
|
||||
final URectangle rect = (URectangle) shape;
|
||||
if (rect.isIgnoreForCompression()) {
|
||||
final double y2 = ct(y + rect.getHeight());
|
||||
shape = rect.withWidth(y2 - ct(y));
|
||||
if (mode == CompressionMode.ON_X) {
|
||||
final double x2 = ct(x + rect.getWidth());
|
||||
shape = rect.withWidth(x2 - ct(x));
|
||||
} else {
|
||||
final double y2 = ct(y + rect.getHeight());
|
||||
shape = rect.withHeight(y2 - ct(y));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (shape instanceof ULine) {
|
||||
drawLine(x, y, (ULine) shape);
|
||||
} else {
|
||||
getUg().apply(new UTranslate(x, ct(y))).draw(shape);
|
||||
if (mode == CompressionMode.ON_X) {
|
||||
getUg().apply(new UTranslate(ct(x), y)).draw(shape);
|
||||
} else {
|
||||
getUg().apply(new UTranslate(x, ct(y))).draw(shape);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void drawLine(double x, double y, ULine shape) {
|
||||
drawLine(x, ct(y), x + shape.getDX(), ct(y + shape.getDY()));
|
||||
if (mode == CompressionMode.ON_X) {
|
||||
drawLine(ct(x), y, ct(x + shape.getDX()), y + shape.getDY());
|
||||
} else {
|
||||
drawLine(x, ct(y), x + shape.getDX(), ct(y + shape.getDY()));
|
||||
}
|
||||
}
|
||||
|
||||
private double ct(double v) {
|
||||
@ -92,15 +117,7 @@ public class UGraphicCompress extends UGraphicDelegator {
|
||||
return;
|
||||
}
|
||||
assert y1 <= y2;
|
||||
final double xmin = Math.min(x1, x2);
|
||||
final double xmax = Math.max(x1, x2);
|
||||
final double ymin = Math.min(y1, y2);
|
||||
final double ymax = Math.max(y1, y2);
|
||||
if (x2 >= x1) {
|
||||
getUg().apply(new UTranslate(xmin, ymin)).draw(new ULine(xmax - xmin, ymax - ymin));
|
||||
} else {
|
||||
getUg().apply(new UTranslate(xmax, ymin)).draw(new ULine(-(xmax - xmin), ymax - ymin));
|
||||
}
|
||||
getUg().apply(new UTranslate(x1, y1)).draw(new ULine(x2 - x1, y2 - y1));
|
||||
}
|
||||
|
||||
}
|
@ -84,7 +84,6 @@ public class UGraphicTxt extends AbstractCommonUGraphic implements ClipContainer
|
||||
if (shape instanceof UText) {
|
||||
final UText txt = (UText) shape;
|
||||
final int y = ((int) (getTranslateY() + txt.getDescent())) / 10;
|
||||
System.err.println("x=" + getDx());
|
||||
if (txt.getFontConfiguration().containsStyle(FontStyle.WAVE)) {
|
||||
charArea.drawHLine('^', y, getDx(), txt.getText().length());
|
||||
charArea.drawStringLR(txt.getText(), getDx(), y + 1);
|
||||
|
98
src/net/sourceforge/plantuml/utils/Cypher.java
Normal file
98
src/net/sourceforge/plantuml/utils/Cypher.java
Normal file
@ -0,0 +1,98 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* (C) Copyright 2009-2017, Arnaud Roques
|
||||
*
|
||||
* Project Info: http://plantuml.com
|
||||
*
|
||||
* If you like this project or if you find it useful, you can support us at:
|
||||
*
|
||||
* http://plantuml.com/patreon (only 1$ per month!)
|
||||
* http://plantuml.com/paypal
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*
|
||||
*
|
||||
* Original Author: Arnaud Roques
|
||||
*
|
||||
*
|
||||
*/
|
||||
package net.sourceforge.plantuml.utils;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class Cypher {
|
||||
|
||||
final private static Pattern p = Pattern.compile("[\\p{L}\\p{N}]+");
|
||||
|
||||
private final SecureRandom rnd = new SecureRandom();
|
||||
private final Map<String, String> convert = new HashMap<String, String>();
|
||||
private final Set<String> except = new HashSet<String>();
|
||||
|
||||
public synchronized String cypher(String s) {
|
||||
|
||||
final Matcher m = p.matcher(s);
|
||||
final StringBuffer sb = new StringBuffer();
|
||||
while (m.find()) {
|
||||
final String word = m.group(0);
|
||||
m.appendReplacement(sb, changeWord(word));
|
||||
}
|
||||
m.appendTail(sb);
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private String changeWord(final String word) {
|
||||
final String lower = word.toLowerCase();
|
||||
if (except.contains(lower) || lower.matches("^[a-f0-9]{6}$")) {
|
||||
return word;
|
||||
}
|
||||
String res = convert.get(word);
|
||||
if (res != null) {
|
||||
return res;
|
||||
}
|
||||
int len = word.length();
|
||||
if (len < 4) {
|
||||
len = 4;
|
||||
}
|
||||
while (true) {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < len; i++) {
|
||||
final char letter = (char) ('a' + rnd.nextInt(26));
|
||||
sb.append(letter);
|
||||
}
|
||||
res = sb.toString();
|
||||
if (convert.containsValue(res) == false) {
|
||||
convert.put(word, res);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void addException(String word) {
|
||||
except.add(word.toLowerCase());
|
||||
}
|
||||
|
||||
}
|
@ -34,6 +34,7 @@
|
||||
*/
|
||||
package net.sourceforge.plantuml.version;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@ -48,81 +49,81 @@ public enum License {
|
||||
return GPL;
|
||||
}
|
||||
|
||||
private void addMit(final List<String> text) {
|
||||
private void addMit(final LicenseInfo licenseInfo, final List<String> text) {
|
||||
text.add("PlantUML is free software; you can redistribute it and/or modify it");
|
||||
text.add("under the terms of the MIT License.");
|
||||
text.add("");
|
||||
text.add(" ");
|
||||
text.add("See http://opensource.org/licenses/MIT");
|
||||
text.add("");
|
||||
text.add(" ");
|
||||
text.add("Permission is hereby granted, free of charge, to any person obtaining");
|
||||
text.add("a copy of this software and associated documentation files (the \"Software\"),");
|
||||
text.add("to deal in the Software without restriction, including without limitation");
|
||||
text.add("the rights to use, copy, modify, merge, publish, distribute, sublicense,");
|
||||
text.add("and/or sell copies of the Software, and to permit persons to whom the");
|
||||
text.add("Software is furnished to do so, subject to the following conditions:");
|
||||
text.add("");
|
||||
text.add(" ");
|
||||
text.add("The above copyright notice and this permission notice shall be included");
|
||||
text.add("in all copies or substantial portions of the Software.");
|
||||
text.add("");
|
||||
text.add(" ");
|
||||
text.add("THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS");
|
||||
text.add("OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,");
|
||||
text.add("FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE");
|
||||
text.add("AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,");
|
||||
text.add("WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR");
|
||||
text.add("IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.");
|
||||
text.add("");
|
||||
addSupplementary(text);
|
||||
text.add(" ");
|
||||
addSupplementary(licenseInfo, text);
|
||||
text.add("the MIT License.");
|
||||
text.add("");
|
||||
text.add(" ");
|
||||
text.add("The generated images can then be used without any reference to the MIT License.");
|
||||
text.add("It is not even necessary to stipulate that they have been generated with PlantUML,");
|
||||
text.add("also this will be appreciate by PlantUML team.");
|
||||
text.add("");
|
||||
text.add(" ");
|
||||
text.add("There is an exception : if the textual description in PlantUML language is also covered");
|
||||
text.add("by a license (like the MIT), then the generated images are logically covered");
|
||||
text.add("by the very same license.");
|
||||
}
|
||||
|
||||
private void addEpl(final List<String> text) {
|
||||
private void addEpl(final LicenseInfo licenseInfo, final List<String> text) {
|
||||
text.add("PlantUML is free software; you can redistribute it and/or modify it");
|
||||
text.add("under the terms of the Eclipse Public License.");
|
||||
text.add("");
|
||||
text.add(" ");
|
||||
text.add("THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC");
|
||||
text.add("LICENSE (\"AGREEMENT\"). [Eclipse Public License - v 1.0]");
|
||||
text.add("");
|
||||
text.add(" ");
|
||||
text.add("ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES");
|
||||
text.add("RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.");
|
||||
text.add("");
|
||||
text.add(" ");
|
||||
text.add("You may obtain a copy of the License at");
|
||||
text.add("");
|
||||
text.add(" ");
|
||||
text.add("http://www.eclipse.org/legal/epl-v10.html");
|
||||
text.add("");
|
||||
text.add(" ");
|
||||
text.add("Unless required by applicable law or agreed to in writing, software");
|
||||
text.add("distributed under the License is distributed on an \"AS IS\" BASIS,");
|
||||
text.add("WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.");
|
||||
text.add("See the License for the specific language governing permissions and");
|
||||
text.add("limitations under the License.");
|
||||
text.add("");
|
||||
addSupplementary(text);
|
||||
text.add(" ");
|
||||
addSupplementary(licenseInfo, text);
|
||||
text.add("the Eclipse Public License.");
|
||||
text.add("");
|
||||
text.add(" ");
|
||||
text.add("The generated images can then be used without any reference to the Eclipse Public License.");
|
||||
text.add("It is not even necessary to stipulate that they have been generated with PlantUML,");
|
||||
text.add("also this will be appreciate by PlantUML team.");
|
||||
text.add("");
|
||||
text.add(" ");
|
||||
text.add("There is an exception : if the textual description in PlantUML language is also covered");
|
||||
text.add("by a license (like the EPL), then the generated images are logically covered");
|
||||
text.add("by the very same license.");
|
||||
}
|
||||
|
||||
private void addBsd(final List<String> text) {
|
||||
private void addBsd(final LicenseInfo licenseInfo, final List<String> text) {
|
||||
text.add("PlantUML is free software; you can redistribute it and/or modify it");
|
||||
text.add("under the terms of the Revised BSD License.");
|
||||
text.add("");
|
||||
text.add(" ");
|
||||
text.add("All rights reserved.");
|
||||
text.add("Redistribution and use in source and binary forms, with or without");
|
||||
text.add("modification, are permitted provided that the following conditions are met:");
|
||||
text.add("");
|
||||
text.add(" ");
|
||||
text.add("* Redistributions of source code must retain the above copyright");
|
||||
text.add(" notice, this list of conditions and the following disclaimer.");
|
||||
text.add("* Redistributions in binary form must reproduce the above copyright");
|
||||
@ -131,7 +132,7 @@ public enum License {
|
||||
text.add("* Neither the name of the University of California, Berkeley nor the");
|
||||
text.add(" names of its contributors may be used to endorse or promote products");
|
||||
text.add(" derived from this software without specific prior written permission.");
|
||||
text.add("");
|
||||
text.add(" ");
|
||||
text.add("THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY");
|
||||
text.add("EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED");
|
||||
text.add("WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE");
|
||||
@ -142,159 +143,180 @@ public enum License {
|
||||
text.add("ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT");
|
||||
text.add("(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS");
|
||||
text.add("SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.");
|
||||
text.add("");
|
||||
addSupplementary(text);
|
||||
text.add(" ");
|
||||
addSupplementary(licenseInfo, text);
|
||||
text.add("the Eclipse Public License.");
|
||||
text.add("");
|
||||
text.add(" ");
|
||||
text.add("The generated images can then be used without any reference to the Eclipse Public License.");
|
||||
text.add("It is not even necessary to stipulate that they have been generated with PlantUML,");
|
||||
text.add("also this will be appreciate by PlantUML team.");
|
||||
text.add("");
|
||||
text.add(" ");
|
||||
text.add("There is an exception : if the textual description in PlantUML language is also covered");
|
||||
text.add("by a license (like the BSD), then the generated images are logically covered");
|
||||
text.add("by the very same license.");
|
||||
}
|
||||
|
||||
private void addApache(final List<String> text) {
|
||||
private void addApache(final LicenseInfo licenseInfo, final List<String> text) {
|
||||
text.add("PlantUML is free software; you can redistribute it and/or modify it");
|
||||
text.add("under the terms of the Apache Software License.");
|
||||
text.add("");
|
||||
text.add(" ");
|
||||
text.add("Licensed under the Apache License, Version 2.0 (the \"License\");");
|
||||
text.add("you may not use this file except in compliance with the License.");
|
||||
text.add("You may obtain a copy of the License at");
|
||||
text.add("");
|
||||
text.add(" ");
|
||||
text.add("http://www.apache.org/licenses/LICENSE-2.0");
|
||||
text.add("");
|
||||
text.add(" ");
|
||||
text.add("Unless required by applicable law or agreed to in writing, software");
|
||||
text.add("distributed under the License is distributed on an \"AS IS\" BASIS,");
|
||||
text.add("WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.");
|
||||
text.add("See the License for the specific language governing permissions and");
|
||||
text.add("limitations under the License.");
|
||||
text.add("");
|
||||
addSupplementary(text);
|
||||
text.add(" ");
|
||||
addSupplementary(licenseInfo, text);
|
||||
text.add("the Apache license.");
|
||||
text.add("");
|
||||
text.add(" ");
|
||||
text.add("The generated images can then be used without any reference to the Apache license.");
|
||||
text.add("It is not even necessary to stipulate that they have been generated with PlantUML,");
|
||||
text.add("also this will be appreciate by PlantUML team.");
|
||||
text.add("");
|
||||
text.add(" ");
|
||||
text.add("There is an exception : if the textual description in PlantUML language is also covered");
|
||||
text.add("by a license (like the Apache), then the generated images are logically covered");
|
||||
text.add("by the very same license.");
|
||||
}
|
||||
|
||||
private void addGpl(final List<String> text) {
|
||||
private void addGpl(final LicenseInfo licenseInfo, final List<String> text) {
|
||||
text.add("PlantUML is free software; you can redistribute it and/or modify it");
|
||||
text.add("under the terms of the GNU General Public License as published by");
|
||||
text.add("the Free Software Foundation, either version 3 of the License, or");
|
||||
text.add("(at your option) any later version.");
|
||||
text.add("");
|
||||
text.add(" ");
|
||||
text.add("PlantUML distributed in the hope that it will be useful, but");
|
||||
text.add("WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY");
|
||||
text.add("or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public");
|
||||
text.add("License for more details.");
|
||||
text.add("");
|
||||
text.add(" ");
|
||||
text.add("You should have received a copy of the GNU General Public");
|
||||
text.add("License along with this library; if not, write to the Free Software");
|
||||
text.add("Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,");
|
||||
text.add("USA.");
|
||||
text.add("");
|
||||
addSupplementary(text);
|
||||
text.add(" ");
|
||||
addSupplementary(licenseInfo, text);
|
||||
text.add("the GPL license.");
|
||||
text.add("");
|
||||
text.add(" ");
|
||||
text.add("The generated images can then be used without any reference to the GPL license.");
|
||||
text.add("It is not even necessary to stipulate that they have been generated with PlantUML,");
|
||||
text.add("also this will be appreciate by PlantUML team.");
|
||||
text.add("");
|
||||
text.add(" ");
|
||||
text.add("There is an exception : if the textual description in PlantUML language is also covered");
|
||||
text.add("by a license (like the GPL), then the generated images are logically covered");
|
||||
text.add("by the very same license.");
|
||||
}
|
||||
|
||||
private void addGplV2(final List<String> text) {
|
||||
private void addGplV2(final LicenseInfo licenseInfo, final List<String> text) {
|
||||
text.add("PlantUML is free software; you can redistribute it and/or modify it");
|
||||
text.add("under the terms of the GNU General Public License as published by");
|
||||
text.add("the Free Software Foundation, either version 2 of the License, or");
|
||||
text.add("(at your option) any later version.");
|
||||
text.add("");
|
||||
text.add(" ");
|
||||
text.add("PlantUML distributed in the hope that it will be useful, but");
|
||||
text.add("WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY");
|
||||
text.add("or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public");
|
||||
text.add("License for more details.");
|
||||
text.add("");
|
||||
text.add(" ");
|
||||
text.add("You should have received a copy of the GNU General Public");
|
||||
text.add("License along with this library; if not, write to the Free Software");
|
||||
text.add("Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,");
|
||||
text.add("USA.");
|
||||
text.add("");
|
||||
addSupplementary(text);
|
||||
text.add(" ");
|
||||
addSupplementary(licenseInfo, text);
|
||||
text.add("the GPL license.");
|
||||
text.add("");
|
||||
text.add(" ");
|
||||
text.add("The generated images can then be used without any reference to the GPL license.");
|
||||
text.add("It is not even necessary to stipulate that they have been generated with PlantUML,");
|
||||
text.add("also this will be appreciate by PlantUML team.");
|
||||
text.add("");
|
||||
text.add(" ");
|
||||
text.add("There is an exception : if the textual description in PlantUML language is also covered");
|
||||
text.add("by a license (like the GPL), then the generated images are logically covered");
|
||||
text.add("by the very same license.");
|
||||
}
|
||||
|
||||
private void addLgpl(final List<String> text) {
|
||||
private void addLgpl(final LicenseInfo licenseInfo, final List<String> text) {
|
||||
text.add("PlantUML is free software; you can redistribute it and/or modify it");
|
||||
text.add("under the terms of the GNU Lesser General Public License as published by");
|
||||
text.add("the Free Software Foundation, either version 3 of the License, or");
|
||||
text.add("(at your option) any later version.");
|
||||
text.add("");
|
||||
text.add(" ");
|
||||
text.add("PlantUML distributed in the hope that it will be useful, but");
|
||||
text.add("WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY");
|
||||
text.add("or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public");
|
||||
text.add("License for more details.");
|
||||
text.add("");
|
||||
text.add(" ");
|
||||
text.add("You should have received a copy of the GNU Lesser General Public");
|
||||
text.add("License along with this library; if not, write to the Free Software");
|
||||
text.add("Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,");
|
||||
text.add("USA.");
|
||||
text.add("");
|
||||
addSupplementary(text);
|
||||
text.add(" ");
|
||||
addSupplementary(licenseInfo, text);
|
||||
text.add("the LGPL license.");
|
||||
text.add("");
|
||||
text.add(" ");
|
||||
text.add("The generated images can then be used without any reference to the LGPL license.");
|
||||
text.add("It is not even necessary to stipulate that they have been generated with PlantUML,");
|
||||
text.add("although this will be appreciate by PlantUML team.");
|
||||
text.add("");
|
||||
text.add(" ");
|
||||
text.add("There is an exception : if the textual description in PlantUML language is also covered");
|
||||
text.add("by a license (like the LGPL), then the generated images are logically covered");
|
||||
text.add("by the very same license.");
|
||||
}
|
||||
|
||||
private void addSupplementary(final List<String> text) {
|
||||
text.add("PlantUML can occasionally display sponsored or advertising messages. Those");
|
||||
text.add("messages are usually generated on welcome or error images and never on");
|
||||
text.add("functional diagrams.");
|
||||
text.add(" ");
|
||||
private void addSupplementary(final LicenseInfo licenseInfo, final List<String> text) {
|
||||
if (licenseInfo.isValid() == false) {
|
||||
text.add("PlantUML can occasionally display sponsored or advertising messages. Those");
|
||||
text.add("messages are usually generated on welcome or error images and never on");
|
||||
text.add("functional diagrams.");
|
||||
text.add(" ");
|
||||
}
|
||||
text.add("Images (whatever their format : PNG, SVG, EPS...) generated by running PlantUML");
|
||||
text.add("are owned by the author of their corresponding sources code (that is, their");
|
||||
text.add("textual description in PlantUML language). Those images are not covered by");
|
||||
}
|
||||
|
||||
private List<String> getHeaderStart() {
|
||||
private List<String> getHeaderStart(LicenseInfo licenseInfo) {
|
||||
final List<String> text = new ArrayList<String>();
|
||||
text.add("========================================================================");
|
||||
text.add("PlantUML : a free UML diagram generator");
|
||||
text.add("========================================================================");
|
||||
text.add("");
|
||||
if (licenseInfo.isNone()) {
|
||||
text.add("========================================================================");
|
||||
text.add("PlantUML : a free UML diagram generator");
|
||||
text.add("========================================================================");
|
||||
text.add(" ");
|
||||
} else {
|
||||
text.add("========================================================================");
|
||||
text.add("This is PlantUML Professional Edition");
|
||||
text.add("========================================================================");
|
||||
addLicenseInfo(text, licenseInfo);
|
||||
text.add("========================================================================");
|
||||
text.add(" ");
|
||||
}
|
||||
text.add("(C) Copyright 2009-2017, Arnaud Roques");
|
||||
text.add("");
|
||||
text.add(" ");
|
||||
text.add("Project Info: http://plantuml.com");
|
||||
text.add("");
|
||||
text.add("If you like this project or if you find it useful, you can support us at:");
|
||||
text.add("");
|
||||
text.add("http://plantuml.com/patreon (only 1$ per month!)");
|
||||
text.add("http://plantuml.com/paypal");
|
||||
text.add("");
|
||||
text.add(" ");
|
||||
if (licenseInfo.isValid() == false) {
|
||||
text.add("If you like this project or if you find it useful, you can support us at:");
|
||||
text.add(" ");
|
||||
text.add("http://plantuml.com/patreon (only 1$ per month!)");
|
||||
text.add("http://plantuml.com/paypal");
|
||||
text.add(" ");
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
public static void addLicenseInfo(final List<String> text, LicenseInfo licenseInfo) {
|
||||
text.add("LICENSED TO : " + licenseInfo.getOwner());
|
||||
text.add("EXPIRATION DATE : " + DateFormat.getDateInstance().format(licenseInfo.getExpirationDate()));
|
||||
if (licenseInfo.hasExpired()) {
|
||||
text.add("<i>Warning: Your license has expired.");
|
||||
}
|
||||
}
|
||||
|
||||
public List<String> getJavaHeader() {
|
||||
final List<String> h = new ArrayList<String>();
|
||||
h.add("/* ========================================================================");
|
||||
@ -430,30 +452,31 @@ public enum License {
|
||||
}
|
||||
|
||||
public List<String> getText() {
|
||||
final List<String> text = getHeaderStart();
|
||||
final LicenseInfo licenseInfo = LicenseInfo.retrieveSlow();
|
||||
final List<String> text = getHeaderStart(licenseInfo);
|
||||
if (this == License.GPL) {
|
||||
addGpl(text);
|
||||
addGpl(licenseInfo, text);
|
||||
} else if (this == License.GPLV2) {
|
||||
addGplV2(text);
|
||||
addGplV2(licenseInfo, text);
|
||||
} else if (this == License.MIT) {
|
||||
addMit(text);
|
||||
addMit(licenseInfo, text);
|
||||
} else if (this == License.EPL) {
|
||||
addEpl(text);
|
||||
addEpl(licenseInfo, text);
|
||||
} else if (this == License.BSD) {
|
||||
addBsd(text);
|
||||
addBsd(licenseInfo, text);
|
||||
} else if (this == License.APACHE) {
|
||||
addApache(text);
|
||||
addApache(licenseInfo, text);
|
||||
} else if (this == License.LGPL) {
|
||||
addLgpl(text);
|
||||
addLgpl(licenseInfo, text);
|
||||
} else {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
if (OptionFlags.getInstance().isEnableStats()) {
|
||||
text.add("");
|
||||
text.add(" ");
|
||||
text.add("This version of PlantUML records general local statistics about usage.");
|
||||
text.add("(more info on http://plantuml.com/statistics-report)");
|
||||
}
|
||||
text.add("");
|
||||
text.add(" ");
|
||||
text.add("Icons provided by OpenIconic : https://useiconic.com/open");
|
||||
text.add("Archimate sprites provided by Archi : http://www.archimatetool.com");
|
||||
text.add("Stdlib AWS provided by https://github.com/milo-minderbinder/AWS-PlantUML");
|
||||
@ -462,8 +485,7 @@ public enum License {
|
||||
text.add("ASCIIMathML (c) David Lippman http://www.pierce.ctc.edu/dlippman");
|
||||
text.add("CafeUndZopfli ported by Eugene Klyuchnikov https://github.com/eustas/CafeUndZopfli");
|
||||
text.add("Brotli (c) by the Brotli Authors https://github.com/google/brotli");
|
||||
text.add("");
|
||||
text.add(" ");
|
||||
return text;
|
||||
}
|
||||
|
||||
}
|
||||
|
221
src/net/sourceforge/plantuml/version/LicenseInfo.java
Normal file
221
src/net/sourceforge/plantuml/version/LicenseInfo.java
Normal file
@ -0,0 +1,221 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* (C) Copyright 2009-2017, Arnaud Roques
|
||||
*
|
||||
* Project Info: http://plantuml.com
|
||||
*
|
||||
* If you like this project or if you find it useful, you can support us at:
|
||||
*
|
||||
* http://plantuml.com/patreon (only 1$ per month!)
|
||||
* http://plantuml.com/paypal
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*
|
||||
*
|
||||
* Original Author: Arnaud Roques
|
||||
*
|
||||
*/
|
||||
package net.sourceforge.plantuml.version;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.prefs.BackingStoreException;
|
||||
import java.util.prefs.Preferences;
|
||||
|
||||
import net.sourceforge.plantuml.Log;
|
||||
import net.sourceforge.plantuml.SignatureUtils;
|
||||
import net.sourceforge.plantuml.dedication.Dedication;
|
||||
import net.sourceforge.plantuml.dedication.QBlock;
|
||||
|
||||
public class LicenseInfo {
|
||||
|
||||
private final static Preferences prefs = Preferences.userNodeForPackage(LicenseInfo.class);
|
||||
private final static LicenseInfo NONE = new LicenseInfo();
|
||||
|
||||
public static final int POS_TYPE = 2;
|
||||
public static final int POS_SIGNATURE = 10;
|
||||
public static final int POS_GENERATION = 100;
|
||||
public static final int POS_EXPIRATION = 108;
|
||||
public static final int POS_OWNER = 128;
|
||||
|
||||
private final long generationDate;
|
||||
private final long expirationDate;
|
||||
private final String owner;
|
||||
|
||||
private LicenseInfo() {
|
||||
this.expirationDate = 0;
|
||||
this.generationDate = 0;
|
||||
this.owner = null;
|
||||
}
|
||||
|
||||
private LicenseInfo(Magic magic) throws NoSuchAlgorithmException, IOException {
|
||||
final String signature = SignatureUtils.toHexString(magic.get(LicenseInfo.POS_SIGNATURE, 64));
|
||||
final String local = SignatureUtils.toHexString(Magic.signature());
|
||||
if (local.equals(signature) == false) {
|
||||
throw new IOException();
|
||||
}
|
||||
final int type = magic.getByte(Magic.signature(), LicenseInfo.POS_TYPE);
|
||||
this.generationDate = bytesToLong(magic.get(LicenseInfo.POS_GENERATION, 8));
|
||||
this.expirationDate = bytesToLong(magic.get(LicenseInfo.POS_EXPIRATION, 8));
|
||||
this.owner = magic.getString(LicenseInfo.POS_OWNER);
|
||||
}
|
||||
|
||||
public static long bytesToLong(byte[] b) {
|
||||
long result = 0;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
result <<= 8;
|
||||
result |= (b[i] & 0xFF);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void persistMe(String key) throws BackingStoreException {
|
||||
prefs.sync();
|
||||
prefs.put("license", key);
|
||||
}
|
||||
|
||||
private static LicenseInfo cache;
|
||||
|
||||
public static synchronized LicenseInfo retrieveQuick() {
|
||||
if (cache == null) {
|
||||
return retrieveSlow();
|
||||
}
|
||||
return cache;
|
||||
}
|
||||
|
||||
public static synchronized LicenseInfo retrieveSlow() {
|
||||
cache = LicenseInfo.NONE;
|
||||
final String key = prefs.get("license", "");
|
||||
if (key.length() > 0) {
|
||||
cache = setIfValid(retrieve(key), cache);
|
||||
if (cache.isValid()) {
|
||||
return cache;
|
||||
}
|
||||
}
|
||||
for (File f : fileCandidates()) {
|
||||
try {
|
||||
if (f.exists() && f.canRead()) {
|
||||
final LicenseInfo result = retrieve(f);
|
||||
cache = setIfValid(result, cache);
|
||||
if (cache.isValid()) {
|
||||
return cache;
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Log.info("Error " + e);
|
||||
// e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return cache;
|
||||
}
|
||||
|
||||
private static LicenseInfo setIfValid(LicenseInfo value, LicenseInfo def) {
|
||||
if (value.isValid() || def.isNone()) {
|
||||
return value;
|
||||
}
|
||||
return def;
|
||||
}
|
||||
|
||||
private static LicenseInfo retrieve(File f) throws IOException {
|
||||
final BufferedReader br = new BufferedReader(new FileReader(f));
|
||||
final String s = br.readLine();
|
||||
br.close();
|
||||
final LicenseInfo result = retrieve(s);
|
||||
if (result != null) {
|
||||
Log.info("Reading license from " + f.getAbsolutePath());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static LicenseInfo retrieve(final String key) {
|
||||
if (key.matches("^[0-9a-z]+$")) {
|
||||
try {
|
||||
final BigInteger lu = new BigInteger(key, 36);
|
||||
final QBlock qb2 = new QBlock(lu);
|
||||
final QBlock qb3 = qb2.change(Dedication.E, Dedication.N);
|
||||
final Magic magic = qb3.toMagic();
|
||||
|
||||
final String sig = SignatureUtils.toHexString(Magic.signature());
|
||||
magic.xor(SignatureUtils.getSHA512raw(SignatureUtils.salting(sig, Magic.getSalt(sig))));
|
||||
return new LicenseInfo(magic);
|
||||
} catch (Exception e) {
|
||||
// e.printStackTrace();
|
||||
Log.info("Error " + e);
|
||||
}
|
||||
}
|
||||
return LicenseInfo.NONE;
|
||||
}
|
||||
|
||||
public static Collection<File> fileCandidates() {
|
||||
final Set<File> result = new TreeSet<File>();
|
||||
final String classpath = System.getProperty("java.class.path");
|
||||
String[] classpathEntries = classpath.split(File.pathSeparator);
|
||||
for (String s : classpathEntries) {
|
||||
File dir = new File(s);
|
||||
if (dir.isFile()) {
|
||||
dir = dir.getParentFile();
|
||||
}
|
||||
if (dir.isDirectory()) {
|
||||
result.add(new File(dir, "license.txt"));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
LicenseInfo info = retrieveSlow();
|
||||
System.err.println("valid=" + info.isValid());
|
||||
System.err.println("info=" + info.owner);
|
||||
|
||||
}
|
||||
|
||||
public final Date getGenerationDate() {
|
||||
return new Date(generationDate);
|
||||
}
|
||||
|
||||
public final Date getExpirationDate() {
|
||||
return new Date(expirationDate);
|
||||
}
|
||||
|
||||
public final String getOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
public boolean isNone() {
|
||||
return owner == null;
|
||||
}
|
||||
|
||||
public boolean isValid() {
|
||||
return owner != null && System.currentTimeMillis() <= this.expirationDate;
|
||||
}
|
||||
|
||||
public boolean hasExpired() {
|
||||
return owner != null && System.currentTimeMillis() > this.expirationDate;
|
||||
}
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user