1
0
mirror of https://github.com/octoleo/plantuml.git synced 2024-12-22 02:49:06 +00:00

fix: improve filelist support and nwdiag

This commit is contained in:
Arnaud Roques 2023-06-12 22:49:47 +02:00
parent 793b78abc5
commit b32500bb61
12 changed files with 259 additions and 100 deletions

View File

@ -1,4 +1,4 @@
# Warning, "version" should be the same in gradle.properties and Version.java
# Any idea anyone how to magically synchronize those :-) ?
version = 1.2023.9beta3
version = 1.2023.9beta4
org.gradle.workers.max = 3

View File

@ -57,15 +57,15 @@ public class AParentFolderRegular implements AParentFolder {
final SFile filecurrent;
// Log.info("AParentFolderRegular::looking for " + nameOrPath);
// Log.info("AParentFolderRegular::dir = " + dir);
if (dir == null) {
if (dir == null)
filecurrent = new SFile(nameOrPath);
} else {
else
filecurrent = dir.getAbsoluteFile().file(nameOrPath);
}
// Log.info("AParentFolderRegular::Filecurrent " + filecurrent);
if (filecurrent.exists()) {
if (filecurrent.exists())
return new AFileRegular(filecurrent.getCanonicalFile());
}
return null;
}

View File

@ -0,0 +1,111 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* (C) Copyright 2009-2024, Arnaud Roques
*
* Project Info: https://plantuml.com
*
* If you like this project or if you find it useful, you can support us at:
*
* https://plantuml.com/patreon (only 1$ per month!)
* https://plantuml.com/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.filesdiagram;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import net.sourceforge.plantuml.klimt.UTranslate;
import net.sourceforge.plantuml.klimt.creole.Display;
import net.sourceforge.plantuml.klimt.drawing.UGraphic;
import net.sourceforge.plantuml.klimt.font.FontConfiguration;
import net.sourceforge.plantuml.klimt.geom.HorizontalAlignment;
import net.sourceforge.plantuml.klimt.shape.TextBlock;
import net.sourceforge.plantuml.style.ISkinParam;
public class FilesEntry implements Iterable<FilesEntry> {
private final String name;
private FilesType type;
private List<FilesEntry> children = new ArrayList<>();
public FilesEntry(String name, FilesType type) {
this.name = name;
this.type = type;
}
public FilesEntry addRawEntry(String raw) {
final int x = raw.indexOf('/');
if (x == -1) {
final FilesEntry result = new FilesEntry(raw, FilesType.DATA);
children.add(result);
return result;
}
final FilesEntry folder = getOrCreateFolder(raw.substring(0, x));
final String remain = raw.substring(x + 1);
if (remain.length() == 0)
return folder;
return folder.addRawEntry(remain);
}
private FilesEntry getOrCreateFolder(String folderName) {
for (FilesEntry child : children)
if (child.type == FilesType.FOLDER && child.getName().equals(folderName))
return child;
final FilesEntry result = new FilesEntry(folderName, FilesType.FOLDER);
children.add(result);
return result;
}
@Override
public Iterator<FilesEntry> iterator() {
return Collections.unmodifiableCollection(children).iterator();
}
public String getName() {
return name;
}
public String getEmoticon() {
if (type == FilesType.FOLDER)
return "<:1f4c2:>";
// return "<:1f4c1:>";
return "<:1f4c4:>";
}
public UGraphic drawAndMove(UGraphic ug, FontConfiguration fontConfiguration, ISkinParam skinParam, double deltax) {
final Display display = Display.getWithNewlines(getEmoticon() + getName());
TextBlock result = display.create(fontConfiguration, HorizontalAlignment.LEFT, skinParam);
result.drawU(ug.apply(UTranslate.dx(deltax)));
ug = ug.apply(UTranslate.dy(result.calculateDimension(ug.getStringBounder()).getHeight() + 2));
for (FilesEntry child : children)
ug = child.drawAndMove(ug, fontConfiguration, skinParam, deltax + 21);
return ug;
}
}

View File

@ -34,26 +34,19 @@
*/
package net.sourceforge.plantuml.filesdiagram;
import java.util.ArrayList;
import java.util.List;
import net.sourceforge.plantuml.klimt.UTranslate;
import net.sourceforge.plantuml.klimt.creole.Display;
import net.sourceforge.plantuml.klimt.drawing.UGraphic;
import net.sourceforge.plantuml.klimt.font.FontConfiguration;
import net.sourceforge.plantuml.klimt.font.StringBounder;
import net.sourceforge.plantuml.klimt.font.UFont;
import net.sourceforge.plantuml.klimt.geom.HorizontalAlignment;
import net.sourceforge.plantuml.klimt.geom.XDimension2D;
import net.sourceforge.plantuml.klimt.shape.AbstractTextBlock;
import net.sourceforge.plantuml.klimt.shape.TextBlock;
import net.sourceforge.plantuml.style.ISkinParam;
public class FilesListing extends AbstractTextBlock {
private final ISkinParam skinParam;
private final FontConfiguration fontConfiguration = FontConfiguration.blackBlueTrue(UFont.courier(14));
private final List<String> tmp = new ArrayList<>();
private final FilesEntry root = new FilesEntry("", FilesType.FOLDER);
public FilesListing(ISkinParam skinParam) {
this.skinParam = skinParam;
@ -66,18 +59,13 @@ public class FilesListing extends AbstractTextBlock {
@Override
public void drawU(UGraphic ug) {
for (String s : tmp) {
final Display display = Display.getWithNewlines("<:1f4c4:>" + s);
TextBlock result = display.create(fontConfiguration, HorizontalAlignment.LEFT, skinParam);
result.drawU(ug);
ug = ug.apply(UTranslate.dy(result.calculateDimension(ug.getStringBounder()).getHeight()));
}
for (FilesEntry ent : root)
ug = ent.drawAndMove(ug, fontConfiguration, skinParam, 0);
}
public void add(String line) {
if (line.startsWith("/"))
tmp.add(line.substring(1));
root.addRawEntry(line.substring(1));
}
}

View File

@ -0,0 +1,40 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* (C) Copyright 2009-2024, Arnaud Roques
*
* Project Info: https://plantuml.com
*
* If you like this project or if you find it useful, you can support us at:
*
* https://plantuml.com/patreon (only 1$ per month!)
* https://plantuml.com/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.filesdiagram;
public enum FilesType {
FOLDER, DATA;
}

View File

@ -66,26 +66,26 @@ public class SpriteColor implements Sprite {
}
public void setGray(int x, int y, int level) {
if (x < 0 || x >= width) {
if (x < 0 || x >= width)
return;
}
if (y < 0 || y >= height) {
if (y < 0 || y >= height)
return;
}
if (level < 0 || level >= 16) {
if (level < 0 || level >= 16)
throw new IllegalArgumentException();
}
gray[y][x] = level;
color[y][x] = -1;
}
public void setColor(int x, int y, int col) {
if (x < 0 || x >= width) {
if (x < 0 || x >= width)
return;
}
if (y < 0 || y >= height) {
if (y < 0 || y >= height)
return;
}
gray[y][x] = -1;
color[y][x] = col;
}
@ -99,14 +99,14 @@ public class SpriteColor implements Sprite {
}
public UImage toUImage(ColorMapper colorMapper, HColor backcolor, HColor forecolor) {
final BufferedImage im = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
final BufferedImage im = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
if (backcolor == null) {
if (backcolor == null)
backcolor = HColors.WHITE;
}
if (forecolor == null) {
if (forecolor == null)
forecolor = HColors.BLACK;
}
final HColorGradient gradient = HColors.gradient(backcolor, forecolor, '\0');
for (int col = 0; col < width; col++) {
for (int line = 0; line < height; line++) {

View File

@ -150,11 +150,27 @@ public class NwDiagram extends UmlDiagram {
for (NStackable element : stack)
if (element instanceof Network)
return CommandExecutionResult.error("Cannot nest network");
if (networks.size() == 0 && groups.size() == 0)
eventuallyConnectAllStandaloneServersToHiddenNetwork();
final Network network = createNetwork(name);
stack.add(0, network);
return CommandExecutionResult.ok();
}
private void eventuallyConnectAllStandaloneServersToHiddenNetwork() {
Network first = null;
for (NServer server : servers.values())
if (server.isAlone()) {
if (first == null) {
first = createNetwork("");
first.goInvisible();
}
server.connectMeIfAlone(first);
}
}
public CommandExecutionResult closeSomething() {
if (initDone == false)
return errorNoInit();

View File

@ -112,6 +112,8 @@ public class NServer {
}
public void learnThisAddress(String address) {
if (address == null)
address = "";
for (Entry<Network, String> ent : connections.entrySet()) {
if (ent.getValue().length() == 0) {
connections.put(ent.getKey(), address);

View File

@ -250,7 +250,7 @@ public class SURL {
/**
* Regex to remove the UserInfo part from a URL.
*/
private static final Pattern PATTERN_USERINFO = Pattern.compile("(^https?://)([-_0-9a-zA-Z]+@)([^@]*)");
private static final Pattern PATTERN_USERINFO = Pattern.compile("(^https?://)([-_0-9a-zA-Z]+@)([^@]*)$");
private static final ExecutorService EXE = Executors.newCachedThreadPool(new ThreadFactory() {
public Thread newThread(Runnable r) {
@ -292,6 +292,9 @@ public class SURL {
}
private boolean forbiddenURL(String full) {
// Thanks to Agasthya Kasturi
if (full.contains("@"))
return true;
if (full.startsWith("https://") == false && full.startsWith("http://") == false)
return true;
if (full.matches("^https?://[-#.0-9:\\[\\]+]+/.*"))
@ -305,6 +308,9 @@ public class SURL {
private boolean isInUrlAllowList() {
final String full = cleanPath(internal.toString());
// Thanks to Agasthya Kasturi
if (full.contains("@"))
return false;
for (String allow : getUrlAllowList())
if (full.startsWith(cleanPath(allow)))
return true;

View File

@ -60,9 +60,9 @@ public class TFunctionImpl implements TFunction {
public TFunctionImpl(String functionName, List<TFunctionArgument> args, boolean unquoted,
TFunctionType functionType) {
final Set<String> names = new HashSet<>();
for (TFunctionArgument tmp : args) {
for (TFunctionArgument tmp : args)
names.add(tmp.getName());
}
this.signature = new TFunctionSignature(functionName, args.size(), names);
this.args = args;
this.unquoted = unquoted;
@ -70,27 +70,26 @@ public class TFunctionImpl implements TFunction {
}
public boolean canCover(int nbArg, Set<String> namedArguments) {
for (String n : namedArguments) {
if (signature.getNamedArguments().contains(n) == false) {
for (String n : namedArguments)
if (signature.getNamedArguments().contains(n) == false)
return false;
}
}
if (nbArg > args.size()) {
if (nbArg > args.size())
return false;
}
assert nbArg <= args.size();
int neededArgument = 0;
for (TFunctionArgument arg : args) {
if (namedArguments.contains(arg.getName())) {
if (namedArguments.contains(arg.getName()))
continue;
}
if (arg.getOptionalDefaultValue() == null) {
if (arg.getOptionalDefaultValue() == null)
neededArgument++;
}
}
if (nbArg < neededArgument) {
if (nbArg < neededArgument)
return false;
}
assert nbArg >= neededArgument;
return true;
}
@ -108,9 +107,9 @@ public class TFunctionImpl implements TFunction {
} else {
value = arg.getOptionalDefaultValue();
}
if (value == null) {
if (value == null)
throw new IllegalStateException();
}
result.put(arg.getName(), value);
}
return memory.forkFromGlobal(result);
@ -125,11 +124,9 @@ public class TFunctionImpl implements TFunction {
body.add(s);
if (s.getType() == TLineType.RETURN) {
this.containsReturn = true;
if (functionType == TFunctionType.PROCEDURE) {
if (functionType == TFunctionType.PROCEDURE)
throw EaterExceptionLocated
.located("A procedure cannot have !return directive. Declare it as a function instead ?", s);
// this.functionType = TFunctionType.RETURN;
}
}
}
@ -147,39 +144,39 @@ public class TFunctionImpl implements TFunction {
public void executeProcedureInternal(TContext context, TMemory memory, List<TValue> args, Map<String, TValue> named)
throws EaterException, EaterExceptionLocated {
if (functionType != TFunctionType.PROCEDURE && functionType != TFunctionType.LEGACY_DEFINELONG) {
if (functionType != TFunctionType.PROCEDURE && functionType != TFunctionType.LEGACY_DEFINELONG)
throw new IllegalStateException();
}
final TMemory copy = getNewMemory(memory, args, named);
context.executeLines(copy, body, TFunctionType.PROCEDURE, false);
}
public TValue executeReturnFunction(TContext context, TMemory memory, LineLocation location, List<TValue> args,
Map<String, TValue> named) throws EaterException, EaterExceptionLocated {
if (functionType == TFunctionType.LEGACY_DEFINE) {
if (functionType == TFunctionType.LEGACY_DEFINE)
return executeReturnLegacyDefine(location, context, memory, args);
}
if (functionType != TFunctionType.RETURN_FUNCTION) {
if (functionType != TFunctionType.RETURN_FUNCTION)
throw EaterException.unlocated("Illegal call here. Is there a return directive in your function?");
}
final TMemory copy = getNewMemory(memory, args, named);
final TValue result = context.executeLines(copy, body, TFunctionType.RETURN_FUNCTION, true);
if (result == null) {
if (result == null)
throw EaterException.unlocated("No return directive found in your function");
}
return result;
}
private TValue executeReturnLegacyDefine(LineLocation location, TContext context, TMemory memory, List<TValue> args)
throws EaterException, EaterExceptionLocated {
if (legacyDefinition == null) {
if (legacyDefinition == null)
throw new IllegalStateException();
}
final TMemory copy = getNewMemory(memory, args, Collections.<String, TValue>emptyMap());
final String tmp = context.applyFunctionsAndVariables(copy, location, legacyDefinition);
if (tmp == null) {
if (tmp == null)
return TValue.fromString("");
}
return TValue.fromString(tmp);
// eaterReturn.execute(context, copy);
// // System.err.println("s3=" + eaterReturn.getValue2());
@ -211,9 +208,9 @@ public class TFunctionImpl implements TFunction {
}
public void finalizeEnddefinelong() {
if (functionType != TFunctionType.LEGACY_DEFINELONG) {
if (functionType != TFunctionType.LEGACY_DEFINELONG)
throw new UnsupportedOperationException();
}
if (body.size() == 1) {
this.functionType = TFunctionType.LEGACY_DEFINE;
this.legacyDefinition = body.get(0).getString();

View File

@ -108,27 +108,27 @@ public class LicenseInfo {
public static synchronized LicenseInfo retrieveNamedSlow() {
cache = LicenseInfo.NONE;
if (OptionFlags.ALLOW_INCLUDE == false) {
if (OptionFlags.ALLOW_INCLUDE == false)
return cache;
}
final String key = prefs.get("license", "");
if (key.length() > 0) {
cache = setIfValid(retrieveNamed(key), cache);
if (cache.isValid()) {
if (cache.isValid())
return cache;
}
}
for (SFile f : fileCandidates()) {
try {
if (f.exists() && f.canRead()) {
final LicenseInfo result = retrieve(f);
if (result == null) {
if (result == null)
return null;
}
cache = setIfValid(result, cache);
if (cache.isValid()) {
if (cache.isValid())
return cache;
}
}
} catch (IOException e) {
Log.info("Error " + e);
@ -157,13 +157,13 @@ public class LicenseInfo {
}
try {
final byte[] s1 = PLSSignature.retrieveDistributorImageSignature();
if (SignatureUtils.toHexString(s1).equals(SignatureUtils.toHexString(licenseInfo.sha)) == false) {
if (SignatureUtils.toHexString(s1).equals(SignatureUtils.toHexString(licenseInfo.sha)) == false)
return null;
}
final InputStream dis = PSystemVersion.class.getResourceAsStream("/distributor.png");
if (dis == null) {
if (dis == null)
return null;
}
try {
final BufferedImage result = SImageIO.read(dis);
return result;
@ -178,9 +178,9 @@ public class LicenseInfo {
public static LicenseInfo retrieveDistributor() {
final InputStream dis = PSystemVersion.class.getResourceAsStream("/distributor.txt");
if (dis == null) {
if (dis == null)
return null;
}
try {
final BufferedReader br = new BufferedReader(new InputStreamReader(dis));
final String licenseString = br.readLine();
@ -188,11 +188,10 @@ public class LicenseInfo {
final LicenseInfo result = PLSSignature.retrieveDistributor(licenseString);
final Throwable creationPoint = new Throwable();
creationPoint.fillInStackTrace();
for (StackTraceElement ste : creationPoint.getStackTrace()) {
if (ste.toString().contains(result.context)) {
for (StackTraceElement ste : creationPoint.getStackTrace())
if (ste.toString().contains(result.context))
return result;
}
}
return null;
} catch (Exception e) {
Logme.error(e);
@ -208,34 +207,34 @@ public class LicenseInfo {
if (s == null)
continue;
SFile dir = new SFile(s);
if (dir.isFile()) {
if (dir.isFile())
dir = dir.getParentFile();
}
if (dir != null && dir.isDirectory()) {
if (dir != null && dir.isDirectory())
result.add(dir.file("license.txt"));
}
}
return result;
}
private static LicenseInfo setIfValid(LicenseInfo value, LicenseInfo def) {
if (value.isValid() || def.isNone()) {
if (value.isValid() || def.isNone())
return value;
}
return def;
}
private static LicenseInfo retrieve(SFile f) throws IOException {
final BufferedReader br = f.openBufferedReader();
if (br == null) {
if (br == null)
return null;
}
try {
final String s = br.readLine();
final LicenseInfo result = retrieveNamed(s);
if (result != null) {
if (result != null)
Log.info("Reading license from " + f.getAbsolutePath());
}
return result;
} finally {
br.close();

View File

@ -46,7 +46,7 @@ public class Version {
// Warning, "version" should be the same in gradle.properties and Version.java
// Any idea anyone how to magically synchronize those :-) ?
private static final String version = "1.2023.9beta3";
private static final String version = "1.2023.9beta4";
public static String versionString() {
return version;