diff options
| author | Ben Culkin <scorpress@gmail.com> | 2022-09-16 18:58:48 -0400 |
|---|---|---|
| committer | Ben Culkin <scorpress@gmail.com> | 2022-09-16 18:58:48 -0400 |
| commit | a3d2728f84375566da3da560b3faad018d34005d (patch) | |
| tree | d50829207b8b4418c11d6385f49386259bb2cc8a /base/src | |
| parent | 6186f1d87c5e170fa89aa327001706b0692526fc (diff) | |
Cleanup
Diffstat (limited to 'base/src')
15 files changed, 338 insertions, 119 deletions
diff --git a/base/src/examples/java/bjc/utils/examples/AbbrevMapTest.java b/base/src/examples/java/bjc/utils/examples/AbbrevMapTest.java index a526408..9deaf34 100644 --- a/base/src/examples/java/bjc/utils/examples/AbbrevMapTest.java +++ b/base/src/examples/java/bjc/utils/examples/AbbrevMapTest.java @@ -22,6 +22,7 @@ public class AbbrevMapTest { * Unused CLI args. */ public static void main(final String[] args) { + @SuppressWarnings("resource") final Scanner scn = new Scanner(System.in); final AbbrevMap2 map = new AbbrevMap2(); diff --git a/base/src/examples/java/bjc/utils/examples/ShuntTest.java b/base/src/examples/java/bjc/utils/examples/ShuntTest.java index 39d37ee..b20012a 100644 --- a/base/src/examples/java/bjc/utils/examples/ShuntTest.java +++ b/base/src/examples/java/bjc/utils/examples/ShuntTest.java @@ -21,19 +21,17 @@ public class ShuntTest * Unused CLI args */ public static void main(final String[] args) { - Scanner inputSource = new Scanner(System.in); + try (Scanner inputSource = new Scanner(System.in)) { + System.out.print("Enter a expression to shunt: "); + String line = inputSource.nextLine(); - System.out.print("Enter a expression to shunt: "); - String line = inputSource.nextLine(); + ShuntingYard<String> yard = new ShuntingYard<>(true); - ShuntingYard<String> yard = new ShuntingYard<>(true); + FunctionalStringTokenizer tokenizer = new FunctionalStringTokenizer(line); + ListEx<String> preTokens = tokenizer.toList(strang -> strang); + ListEx<String> shuntedTokens = yard.postfix(preTokens, strang -> strang); - FunctionalStringTokenizer tokenizer = new FunctionalStringTokenizer(line); - ListEx<String> preTokens = tokenizer.toList(strang -> strang); - ListEx<String> shuntedTokens = yard.postfix(preTokens, strang -> strang); - - System.out.println(shuntedTokens.toString()); - - inputSource.close(); + System.out.println(shuntedTokens.toString()); + } } } diff --git a/base/src/main/java/bjc/utils/cli/objects/BlockReaderCLI.java b/base/src/main/java/bjc/utils/cli/objects/BlockReaderCLI.java index 1c50df3..6b4bbb3 100644 --- a/base/src/main/java/bjc/utils/cli/objects/BlockReaderCLI.java +++ b/base/src/main/java/bjc/utils/cli/objects/BlockReaderCLI.java @@ -114,9 +114,9 @@ public class BlockReaderCLI { sources.put("stdio", new InputStreamReader(System.in)); - Scanner input = new Scanner(System.in); - reader.run(input, "console", true); - input.close(); + try (Scanner input = new Scanner(System.in)) { + reader.run(input, "console", true); + } } /** diff --git a/base/src/main/java/bjc/utils/graph/Graphs.java b/base/src/main/java/bjc/utils/graph/Graphs.java new file mode 100644 index 0000000..2844a68 --- /dev/null +++ b/base/src/main/java/bjc/utils/graph/Graphs.java @@ -0,0 +1,67 @@ +package bjc.utils.graph; + +import java.util.*; + +import bjc.data.Holder; +import bjc.data.Identity; + +public class Graphs { + /** + * Uses Prim's algorithm to calculate a MST for the graph. + * + * If the graph is non-connected, this will lead to unpredictable results. + * + * @return A list of edges that constitute the MST. + */ + public static <T, L> List<Edge<T, L>> getMinimumSpanningTree(Graph<T, L> grap, Comparator<L> comp) { + /* Set of all of the currently available edges. */ + final Queue<Edge<T, L>> available = new PriorityQueue<>(10, + (left, right) -> comp.compare(left.getDistance(), right.getDistance())); + + /* The MST of the graph. */ + final List<Edge<T, L>> minimums = new ArrayList<>(); + + /* The set of all of the visited vertices. */ + final Set<T> visited = new HashSet<>(); + + /* Start at the initial vertex and visit it */ + final Holder<T> source = new Identity<>(grap.getInitial()); + + visited.add(source.getValue()); + + /* Make sure we visit all the nodes. */ + while (visited.size() != grap.getVertexCount()) { + /* Grab all edges adjacent to the provided edge. */ + + grap.forAllEdgesMatchingAt(source.getValue(), + (target, weight) -> !visited.contains(target), + (target, weight) -> { + final T vert = source.unwrap(vertex -> vertex); + + available.add(new Edge<>(vert, target, weight)); + } + ); + + /* Get the edge with the minimum distance. */ + final Holder<Edge<T, L>> minimum = new Identity<>(available.poll()); + + /* + * Only consider edges where we haven't visited the target of the edge. + */ + while (visited.contains(minimum.getValue().getTarget())) { + minimum.transform(edge -> available.poll()); + } + + /* Add it to our MST. */ + minimums.add(minimum.getValue()); + + /* Advance to the next node. */ + source.transform(vertex -> minimum.unwrap(edge -> edge.getTarget())); + + /* Visit this node. */ + visited.add(source.getValue()); + } + + return minimums; + } +} diff --git a/base/src/main/java/bjc/utils/ioutils/DuplicateKeys.java b/base/src/main/java/bjc/utils/ioutils/DuplicateKeys.java new file mode 100644 index 0000000..604cc69 --- /dev/null +++ b/base/src/main/java/bjc/utils/ioutils/DuplicateKeys.java @@ -0,0 +1,21 @@ +package bjc.utils.ioutils; + +/** + * Exception thrown when there is a duplicate key, when they are forbidden. + * + * @author 15405 + * + */ +public class DuplicateKeys extends RuntimeException { + private static final long serialVersionUID = -5521190136366024804L; + + /** + * Create a new duplicate key exception. + * + * @param keyName + * The name of the key that has been duplicated. + */ + public DuplicateKeys(String keyName) { + super(String.format("Duplicate value encountered for key '%s'", keyName)); + } +}
\ No newline at end of file diff --git a/base/src/main/java/bjc/utils/ioutils/InvalidLineFormat.java b/base/src/main/java/bjc/utils/ioutils/InvalidLineFormat.java new file mode 100644 index 0000000..2763eb1 --- /dev/null +++ b/base/src/main/java/bjc/utils/ioutils/InvalidLineFormat.java @@ -0,0 +1,20 @@ +package bjc.utils.ioutils; + +/** + * Exception thrown when a line is formattted incorrectly. + * @author Ben Culkin + * + */ +public class InvalidLineFormat extends RuntimeException { + private static final long serialVersionUID = 5332131472090792841L; + + /** + * Create a new exception for an incorrectly formatted line. + * @param lne The line that was incorrectly formatted. + */ + public InvalidLineFormat(String lne) { + super(String.format( + "Line '%s' is improperly formatted.\n\tExpected format is a string key, followed by a single space, followed by the value", + "")); + } +}
\ No newline at end of file diff --git a/base/src/main/java/bjc/utils/ioutils/SimpleProperties.java b/base/src/main/java/bjc/utils/ioutils/SimpleProperties.java index d380866..0aa18b4 100644 --- a/base/src/main/java/bjc/utils/ioutils/SimpleProperties.java +++ b/base/src/main/java/bjc/utils/ioutils/SimpleProperties.java @@ -17,45 +17,6 @@ import java.util.Set; * */ public class SimpleProperties implements Map<String, String> { - /** - * Exception thrown when there is a duplicate key, when they are forbidden. - * - * @author 15405 - * - */ - public static class DuplicateKeys extends RuntimeException { - private static final long serialVersionUID = -5521190136366024804L; - - /** - * Create a new duplicate key exception. - * - * @param keyName - * The name of the key that has been duplicated. - */ - public DuplicateKeys(String keyName) { - super(String.format("Duplicate value encountered for key '%s'", keyName)); - } - } - - /** - * Exception thrown when a line is formattted incorrectly. - * @author Ben Culkin - * - */ - public static class InvalidLineFormat extends RuntimeException { - private static final long serialVersionUID = 5332131472090792841L; - - /** - * Create a new exception for an incorrectly formatted line. - * @param lne The line that was incorrectly formatted. - */ - public InvalidLineFormat(String lne) { - super(String.format( - "Line '%s' is improperly formatted.\n\tExpected format is a string key, followed by a single space, followed by the value", - "")); - } - } - private final Map<String, String> props; /** @@ -170,20 +131,17 @@ public class SimpleProperties implements Map<String, String> { return props.isEmpty(); } - @SuppressWarnings("unlikely-arg-type") - @Override + @Override public boolean containsKey(final Object key) { return props.containsKey(key); } - @SuppressWarnings("unlikely-arg-type") - @Override + @Override public boolean containsValue(final Object value) { return props.containsValue(value); } - @SuppressWarnings("unlikely-arg-type") - @Override + @Override public String get(final Object key) { return props.get(key); } @@ -193,8 +151,7 @@ public class SimpleProperties implements Map<String, String> { return props.put(key, value); } - @SuppressWarnings("unlikely-arg-type") - @Override + @Override public String remove(final Object key) { return props.remove(key); } diff --git a/base/src/main/java/bjc/utils/ioutils/blocks/SerialBlockReader.java b/base/src/main/java/bjc/utils/ioutils/blocks/SerialBlockReader.java index 265a781..9617ebd 100644 --- a/base/src/main/java/bjc/utils/ioutils/blocks/SerialBlockReader.java +++ b/base/src/main/java/bjc/utils/ioutils/blocks/SerialBlockReader.java @@ -102,6 +102,8 @@ public class SerialBlockReader implements BlockReader { @Override public void close() throws IOException { while (!readerQueue.isEmpty()) { + // We are explicitly closing these + @SuppressWarnings("resource") final BlockReader reader = readerQueue.pop(); reader.close(); diff --git a/base/src/main/java/bjc/utils/ioutils/blocks/package-info.java b/base/src/main/java/bjc/utils/ioutils/blocks/package-info.java index 3d05ed4..d321725 100644 --- a/base/src/main/java/bjc/utils/ioutils/blocks/package-info.java +++ b/base/src/main/java/bjc/utils/ioutils/blocks/package-info.java @@ -2,16 +2,16 @@ * is structured as a series of 'blocks' or records. * <p> * - * The most fundamental unit here is that of {@link Block}. Each {@link - * BlockReader} will yield a sequence of these, which contain a piece of text + * The most fundamental unit here is that of {@link bjc.utils.ioutils.blocks.Block}. Each {@link + * bjc.utils.ioutils.blocks.BlockReader} will yield a sequence of these, which contain a piece of text * as its contents, as well as the beginning/ending line for that block. * - * There are a number of different types of {@link BlockReader}, which are + * There are a number of different types of {@link bjc.utils.ioutils.blocks.BlockReader}, which are * summarized here. * </p> * * <dl> - * <dt>{@link SimpleBlockReader}</dt> + * <dt>{@link bjc.utils.ioutils.blocks.SimpleBlockReader}</dt> * <dd> * The most basic form of BlockReader. This uses a regular expression to * delimit input reader from a {@link Reader} into a series of blocks. diff --git a/base/src/main/java/bjc/utils/parserutils/pattern/FunctionalPatternPart.java b/base/src/main/java/bjc/utils/parserutils/pattern/FunctionalPatternPart.java new file mode 100644 index 0000000..535825e --- /dev/null +++ b/base/src/main/java/bjc/utils/parserutils/pattern/FunctionalPatternPart.java @@ -0,0 +1,23 @@ +package bjc.utils.parserutils.pattern; + +import java.util.function.Supplier; + +final class FunctionalPatternPart implements PatternPart { + private final Supplier<String> func; + private final boolean canOptimize; + + FunctionalPatternPart(Supplier<String> func, boolean canOptimize) { + this.func = func; + this.canOptimize = canOptimize; + } + + @Override + public String toRegex() { + return func.get(); + } + + @Override + public boolean canOptimize() { + return canOptimize; + } +}
\ No newline at end of file diff --git a/base/src/main/java/bjc/utils/parserutils/pattern/JoinerPatternPart.java b/base/src/main/java/bjc/utils/parserutils/pattern/JoinerPatternPart.java new file mode 100644 index 0000000..2f3b16d --- /dev/null +++ b/base/src/main/java/bjc/utils/parserutils/pattern/JoinerPatternPart.java @@ -0,0 +1,28 @@ +package bjc.utils.parserutils.pattern; + +import java.util.StringJoiner; + +final class JoinerPatternPart implements PatternPart { + private final PatternPart[] parts; + private final String joiner; + + JoinerPatternPart(PatternPart[] parts, String joiner) { + this.parts = parts; + this.joiner = joiner; + } + + @Override + public String toRegex() { + StringJoiner sj = new StringJoiner(joiner); + for (PatternPart part : parts) sj.add(part.toRegex()); + return sj.toString(); + } + + @Override + public boolean canOptimize() { + for (PatternPart part : parts) + if (!part.canOptimize()) return false; + + return true; + } +}
\ No newline at end of file diff --git a/base/src/main/java/bjc/utils/parserutils/pattern/PatternPart.java b/base/src/main/java/bjc/utils/parserutils/pattern/PatternPart.java index 6661072..2fd59ca 100644 --- a/base/src/main/java/bjc/utils/parserutils/pattern/PatternPart.java +++ b/base/src/main/java/bjc/utils/parserutils/pattern/PatternPart.java @@ -1,12 +1,14 @@ package bjc.utils.parserutils.pattern; -import java.util.StringJoiner; import java.util.function.Supplier; import java.util.regex.*; /** * Builder interface for regex patterns. * + * Note that you may need to add explicit non-grouping to get things to work + * right, based on the precedence of your regex operators. + * * @author bjculkin * */ @@ -17,27 +19,37 @@ public interface PatternPart { * @return The regex this part represents. */ public String toRegex(); - + + /** + * Can this regex be optimized? + * + * @return Whether or not this regex can be optimized to a string + */ public boolean canOptimize(); - + + /** + * Create a new pattern part from component bits. + * + * @param canOptimize Whether this part can be optimized + * @param func The function that provides the regex text + * + * @return A pattern part w/ the given body + */ static PatternPart part(boolean canOptimize, Supplier<String> func) { - return new PatternPart() { - - @Override - public String toRegex() { - return func.get(); - } - - @Override - public boolean canOptimize() { - return canOptimize; - } - }; - } - + return new FunctionalPatternPart(func, canOptimize); + } + + /** + * Create a new variable pattern part. + * + * @param source The function which supplies the text. + * + * @return A part that retrieves its bits from the given source + */ static PatternPart var(Supplier<String> source) { return part(false, source); } + /** * Create a 'raw' pattern part, which just echoes the given string. * @@ -48,26 +60,20 @@ public interface PatternPart { static PatternPart raw(String str) { return part(true, () -> str); } - + + /** + * Create a pattern composed of other patterns, interspersed with the given + * string. + * + * @param joiner The string to use as a joiner. + * @param parts The composed pattern parts. + * + * @return The given patterns composed by the parts, joined by `joiner`. + */ static PatternPart joining(String joiner, PatternPart... parts) { - return new PatternPart() { - - @Override - public String toRegex() { - StringJoiner sj = new StringJoiner(joiner); - for (PatternPart part : parts) sj.add(part.toRegex()); - return sj.toString(); - } - - @Override - public boolean canOptimize() { - for (PatternPart part : parts) - if (!part.canOptimize()) return false; - - return true; - } - }; + return new JoinerPatternPart(parts, joiner); } + /** * Create a pattern part which matches the given string. * @@ -78,7 +84,7 @@ public interface PatternPart { static PatternPart literal(String str) { return part(true, () -> Pattern.quote(str)); } - + /** * Create a pattern part which matches a single digit. * @@ -87,60 +93,149 @@ public interface PatternPart { static PatternPart digit() { return raw("\\d"); } - + + /** + * Create a character class pattern + * + * @param chars The characters that make up the class. + * + * @return A pattern representing the character class. + */ static PatternPart cclass(char... chars) { return part(true, () -> { StringBuilder sb = new StringBuilder("["); - for (char ch : chars) sb.append(ch); + for (char ch : chars) + sb.append(ch); sb.append("]"); return sb.toString(); }); } - + + /** + * Represents an inverted character class. + * + * @param chars The characters for the class not to include. + * + * @return A pattern representing a class that doesn't match the characters. + */ static PatternPart notCClass(char... chars) { return part(true, () -> { StringBuilder sb = new StringBuilder("[^"); - for (char ch : chars) sb.append(ch); + for (char ch : chars) + sb.append(ch); sb.append("]"); return sb.toString(); }); } - + + /** + * Represents a pattern that matches any non-space character. + * + * @return A pattern that matches any non-space character. + */ static PatternPart nonspace() { return raw("\\S"); } - + + /** + * Concatenate a series of pattern parts with whitespace. + * + * @param parts The parts to join + * + * @return A pattern that matches each of the given parts, separated by + * whitespace. + */ static PatternPart concat(PatternPart... parts) { return joining(" ", parts); } - + + /** + * Create a pattern which matches one of the given patterns. + * + * @param parts The possible patterns to match. + * + * @return A pattern which matches one of the given patterns. + */ static PatternPart alternate(PatternPart... parts) { return joining("|", parts); } - + + /** + * Create a pattern which matches the given pattern zero or more times. + * + * @param part The pattern to repeat + * + * @return A pattern which matches the given one zero or more times. + */ static PatternPart repeat(PatternPart part) { return part(part.canOptimize(), () -> part.toRegex() + "*"); } - + + /** + * Create a pattern which matches the given one zero or more times. + * + * @param part The pattern to be optional. + * + * @return A pattern where the part is optional + */ static PatternPart optional(PatternPart part) { return part(part.canOptimize(), () -> part.toRegex() + "?"); } - + + /** + * Create a pattern which matches the given pattern one or more times. + * + * @param part The pattern to repeat. + * + * @return A pattern which matches the given one one or more times. + */ static PatternPart repeatAtLeastOnce(PatternPart part) { return part(part.canOptimize(), () -> part.toRegex() + "*"); } - + + /** + * Surround the given pattern with strings. + * + * @param lhs The left-hand side of the pattern. + * @param rhs The right-hand side of the pattern. + * @param part The pattern to match. + * + * @return A pattern surrounded by the given strings. + */ static PatternPart surround(String lhs, String rhs, PatternPart part) { return part(part.canOptimize(), () -> lhs + part.toRegex() + rhs); } + + /** + * Wrap the given pattern in a capturing group. + * + * @param part The pattern to wrap. + * + * @return The pattern, wrapped in a capturing group + */ static PatternPart group(PatternPart part) { return surround("(", ")", part); } + /** + * Wrap the given pattern in a named-capturing group. + * + * @param groupName The name of the group + * @param part The pattern to wrap. + * + * @return A pattern wrap in a named-capturing group. + */ static PatternPart namedGroup(String groupName, PatternPart part) { return surround("(<" + groupName + ">", ")", part); } - + + /** + * Wrap the given pattern in a non-capturing group. + * + * @param part The pattern to wrap. + * + * @return A pattern wrap in a non-capturing group. + */ static PatternPart nonCaptureGroup(PatternPart part) { return surround("(?:", ")", part); } diff --git a/base/src/main/java/bjc/utils/patterns/MutablePatternMatcher.java b/base/src/main/java/bjc/utils/patterns/MutablePatternMatcher.java index 176f588..28e9cd7 100644 --- a/base/src/main/java/bjc/utils/patterns/MutablePatternMatcher.java +++ b/base/src/main/java/bjc/utils/patterns/MutablePatternMatcher.java @@ -79,8 +79,7 @@ public class MutablePatternMatcher<ReturnType, InputType> * * @return Whether or not the pattern was removed. */ - @SuppressWarnings("unlikely-arg-type") - public boolean removePattern(ComplexPattern<ReturnType, ?, InputType> pattern) { + public boolean removePattern(ComplexPattern<ReturnType, ?, InputType> pattern) { return patterns.remove(pattern); } } diff --git a/base/src/main/java/module-info.java b/base/src/main/java/module-info.java index 3901514..1032ce5 100644 --- a/base/src/main/java/module-info.java +++ b/base/src/main/java/module-info.java @@ -1,3 +1,11 @@ +/** + * Various utilities and other things. + * + * Just contains a whole bunch of useful things. + * + * @author bjculkin + * + */ module bjc.utils { exports bjc.utils.exceptions; exports bjc.utils.funcutils; @@ -22,11 +30,11 @@ module bjc.utils { exports bjc.utils.ioutils.properties; requires commons.lang3; - requires esodata; + requires transitive esodata; requires guava; requires hamcrest.core; requires icu4j; - requires java.desktop; + requires transitive java.desktop; requires java.logging; requires junit; }
\ No newline at end of file diff --git a/base/src/test/java/bjc/utils/test/ioutils/SimplePropertiesTest.java b/base/src/test/java/bjc/utils/test/ioutils/SimplePropertiesTest.java index 5f166ab..cf3809a 100644 --- a/base/src/test/java/bjc/utils/test/ioutils/SimplePropertiesTest.java +++ b/base/src/test/java/bjc/utils/test/ioutils/SimplePropertiesTest.java @@ -6,9 +6,9 @@ import java.io.StringReader; import org.junit.Test; +import bjc.utils.ioutils.DuplicateKeys; +import bjc.utils.ioutils.InvalidLineFormat; import bjc.utils.ioutils.SimpleProperties; -import bjc.utils.ioutils.SimpleProperties.DuplicateKeys; -import bjc.utils.ioutils.SimpleProperties.InvalidLineFormat; /** * Tests for SimpleProperties. |
