diff options
| author | Benjamin J. Culkin <bjculkin@mix.wvu.edu> | 2017-10-08 22:39:59 -0300 |
|---|---|---|
| committer | Benjamin J. Culkin <bjculkin@mix.wvu.edu> | 2017-10-08 22:39:59 -0300 |
| commit | c82e3b3b2de0633317ec8fc85925e91422820597 (patch) | |
| tree | 96567416ce23c5ce85601f9cedc3a94bb1c55cba /BJC-Utils2/src | |
| parent | b3ac1c8690c3e14c879913e5dcc03a5f5e14876e (diff) | |
Start splitting into maven modules
Diffstat (limited to 'BJC-Utils2/src')
180 files changed, 0 insertions, 22645 deletions
diff --git a/BJC-Utils2/src/examples/java/bjc/utils/examples/AbbrevMapTest.java b/BJC-Utils2/src/examples/java/bjc/utils/examples/AbbrevMapTest.java deleted file mode 100644 index ac4ea76..0000000 --- a/BJC-Utils2/src/examples/java/bjc/utils/examples/AbbrevMapTest.java +++ /dev/null @@ -1,59 +0,0 @@ -package bjc.utils.examples; - -import java.util.Scanner; - -import bjc.utils.esodata.AbbrevMap; -import bjc.utils.funcutils.StringUtils; - -/** - * Test for abbreviation map. - * - * @author EVE - * - */ -public class AbbrevMapTest { - /** - * Main method. - * - * @param args - * Unused CLI args. - */ - public static void main(final String[] args) { - final Scanner scn = new Scanner(System.in); - - final AbbrevMap map = new AbbrevMap(); - - System.out.print("Enter a command (blank line to quit): "); - String ln = scn.nextLine(); - - while (!ln.equals("")) { - final String[] commParts = ln.split(" "); - - switch (commParts[0]) { - case "add": - map.addWords(commParts[1]); - break; - case "remove": - map.removeWords(commParts[1]); - break; - case "recalc": - map.recalculate(); - break; - case "check": - final String list = StringUtils.toEnglishList(map.deabbrev(commParts[1]), false); - System.out.println(list); - break; - case "debug": - System.out.println(map.toString()); - break; - default: - System.out.println("Unknown command: " + ln); - } - - System.out.print("Enter a command (blank line to quit): "); - ln = scn.nextLine(); - } - - scn.close(); - } -} diff --git a/BJC-Utils2/src/examples/java/bjc/utils/examples/BinarySearchTest.java b/BJC-Utils2/src/examples/java/bjc/utils/examples/BinarySearchTest.java deleted file mode 100644 index 758af61..0000000 --- a/BJC-Utils2/src/examples/java/bjc/utils/examples/BinarySearchTest.java +++ /dev/null @@ -1,123 +0,0 @@ -package bjc.utils.examples; - -import java.util.Scanner; - -import bjc.utils.funcdata.bst.BinarySearchTree; -import bjc.utils.funcdata.bst.TreeLinearizationMethod; - -/** - * Example showing how to use the binary search tree. - * - * @author ben - * - */ -public class BinarySearchTest { - private static void display(final BinarySearchTree<Character> tree, final Scanner input) { - System.out.print("What order would you like the tree to be printed in (m for options): "); - char command; - - while (true) { - command = input.nextLine().charAt(0); - TreeLinearizationMethod method = null; - - switch (command) { - case 'm': - System.out.println("Possible tree printing methods: "); - System.out.println("\tp: Preorder printing (print parent first, then left & right)."); - System.out.println("\ti: Inorder printing (print left first, then parent & right)."); - System.out.println("\to: Postorder printing (print left first, then right & parent)."); - break; - case 'p': - method = TreeLinearizationMethod.PREORDER; - break; - case 'i': - method = TreeLinearizationMethod.INORDER; - break; - case 'o': - method = TreeLinearizationMethod.POSTORDER; - break; - default: - System.out.println("ERROR: Unknown command."); - } - - if (method != null) { - tree.traverse(method, (element) -> { - System.out.println("Node: " + element); - return true; - }); - - return; - } - - System.out.print("What order would you like the tree to be printed in (m for options): "); - } - } - - /** - * Main method of class - * - * @param args - * Unused CLI args - */ - public static void main(final String[] args) { - final Scanner input = new Scanner(System.in); - System.out.println("Binary Tree Constructor/Searcher"); - final BinarySearchTree<Character> tree = new BinarySearchTree<>((o1, o2) -> o1 - o2); - - char command = ' '; - while (command != 'e') { - System.out.print("Enter a command (m for help): "); - command = input.nextLine().charAt(0); - - switch (command) { - case 'm': - System.out.println("Valid commands: "); - System.out.println("\tm: Display this help message."); - System.out.println("\te: Exit this program."); - System.out.println("\ta: Add a node to the binary tree."); - System.out.println("\td: Display the binary tree."); - System.out.println("\tr: Remove a node from the binary tree."); - System.out.println("\tf: Check if a given node is in the binary tree."); - System.out.println("\tt: Trim all deleted nodes from the tree."); - System.out.println("\tb: Balance the tree (also trims dead nodes)"); - break; - case 'a': - System.out.print("Enter the letter to add to the binary tree: "); - command = input.nextLine().charAt(0); - - tree.addNode(command); - break; - case 'r': - System.out.print("Enter the letter to add to the binary tree: "); - command = input.nextLine().charAt(0); - - tree.deleteNode(command); - break; - case 'd': - display(tree, input); - break; - case 'f': - System.out.print("Enter the letter to add to the binary tree: "); - command = input.nextLine().charAt(0); - - final boolean inTree = tree.isInTree(command); - if (inTree) { - System.out.printf("Node %s was found\n", command); - } else { - System.out.printf("Node %s was not found\n", command); - } - break; - case 't': - tree.trim(); - break; - case 'b': - tree.balance(); - break; - default: - System.out.println("ERROR: Unrecognized command."); - } - } - - input.close(); - } -} diff --git a/BJC-Utils2/src/examples/java/bjc/utils/examples/DelimSplitterTest.java b/BJC-Utils2/src/examples/java/bjc/utils/examples/DelimSplitterTest.java deleted file mode 100644 index 428f276..0000000 --- a/BJC-Utils2/src/examples/java/bjc/utils/examples/DelimSplitterTest.java +++ /dev/null @@ -1,504 +0,0 @@ -package bjc.utils.examples; - -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.util.Arrays; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Scanner; - -import bjc.utils.data.ITree; -import bjc.utils.funcdata.FunctionalList; -import bjc.utils.funcdata.IList; -import bjc.utils.funcutils.StringUtils; -import bjc.utils.parserutils.delims.DelimiterException; -import bjc.utils.parserutils.delims.DelimiterGroup; -import bjc.utils.parserutils.delims.RegexCloser; -import bjc.utils.parserutils.delims.RegexOpener; -import bjc.utils.parserutils.delims.SequenceDelimiter; -import bjc.utils.parserutils.delims.StringDelimiter; -import bjc.utils.parserutils.splitter.ConfigurableTokenSplitter; - -/** - * Test for {@link SequenceDelimiter} as well as - * {@link ConfigurableTokenSplitter} - * - * @author EVE - * - */ -public class DelimSplitterTest { - private ConfigurableTokenSplitter split; - - private StringDelimiter dlm; - - private Map<String, String> mirrored; - - private Map<String, DelimiterGroup<String>> groups; - - boolean verbose; - - /* - * Create a new tester. - */ - private DelimSplitterTest() { - loadMirrorDB(); - - groups = new HashMap<>(); - - split = new ConfigurableTokenSplitter(true); - - dlm = new StringDelimiter(); - - verbose = true; - } - - private void loadMirrorDB() { - mirrored = new HashMap<>(); - - final InputStream stream = getClass().getResourceAsStream("/BidiMirrorDB.txt"); - - try (Scanner scn = new Scanner(stream)) { - String ln = ""; - - while (scn.hasNextLine()) { - ln = scn.nextLine(); - - if (ln.equals("")) { - continue; - } - if (ln.startsWith("#")) { - continue; - } - - final int cp1 = Integer.parseInt(ln.substring(0, 4), 16); - final int cp2 = Integer.parseInt(ln.substring(6, 10), 16); - - final char[] cpa1 = Character.toChars(cp1); - final char[] cpa2 = Character.toChars(cp2); - - final String cps1 = new String(cpa1); - final String cps2 = new String(cpa2); - - mirrored.put(cps1, cps2); - } - } - } - - /* - * Run the tester interface. - */ - private void runLoop() { - final Scanner scn = new Scanner(System.in); - - System.out.print("Enter a command (blank line to quit): "); - String inp = scn.nextLine().trim(); - System.out.println(); - - while (!inp.equals("")) { - handleCommand(inp, scn, true); - - System.out.println(); - - System.out.print("Enter a command (blank line to quit): "); - inp = scn.nextLine(); - - System.out.println(); - } - - scn.close(); - } - - /* - * Handle a input command. - */ - private void handleCommand(final String inp, final Scanner scn, final boolean isInteractive) { - if (inp.equals("")) return; - - int idx = inp.indexOf(' '); - - if (idx == -1) { - idx = inp.length(); - } - - final String command = inp.substring(0, idx); - - final String args = inp.substring(idx).trim(); - final String[] argArray = args.split(" "); - - switch (command) { - case "test": - handleTest(args, false); - break; - case "test-ws": - handleTest(args, true); - break; - case "splitter-split": - handleSplit(argArray); - break; - case "splitter-compile": - split.compile(); - if (verbose) { - System.out.println("Compiled splitter"); - } - break; - case "splitter-add": - split.addSimpleDelimiters(argArray); - if (verbose) { - System.out.println("Added delimiters " + StringUtils.toEnglishList(argArray, true)); - } - break; - case "splitter-addmulti": - split.addMultiDelimiters(argArray); - if (verbose) { - System.out.println( - "Added multi-delimiters " + StringUtils.toEnglishList(argArray, true)); - } - break; - case "splitter-addmatch": - for (final String arg : argArray) { - split.addSimpleDelimiters(arg, mirrored.get(arg)); - } - if (verbose) { - System.out.println("Added matched delimiters " - + StringUtils.toEnglishList(argArray, true)); - } - break; - case "splitter-debug": - System.out.println(split.toString()); - break; - case "splitter-reset": - split = new ConfigurableTokenSplitter(true); - if (verbose) { - System.out.println("Reset splitter"); - } - break; - - case "delims-addgroup": - for (final String arg : argArray) { - dlm.addGroup(groups.get(arg)); - } - if (verbose) { - System.out.println("Added groups " + StringUtils.toEnglishList(argArray, true)); - } - break; - case "delims-setinitial": - dlm.setInitialGroup(groups.get(argArray[0])); - if (verbose) { - System.out.println("Set initial group"); - } - break; - case "delims-debug": - System.out.println(dlm.toString()); - break; - case "delims-test": - handleDelim(args); - break; - case "delims-reset": - dlm = new StringDelimiter(); - if (verbose) { - System.out.println("Reset delimiter"); - } - break; - case "delimgroups-new": - for (final String arg : argArray) { - groups.put(arg, new DelimiterGroup<>(arg)); - } - if (verbose) { - System.out.println("Created groups " + StringUtils.toEnglishList(argArray, true)); - } - break; - case "delimgroups-edit": - for (final String arg : argArray) { - handleEditGroup(arg, scn, isInteractive); - } - break; - case "delimgroups-debug": - for (final DelimiterGroup<String> group : groups.values()) { - System.out.println(group.toString()); - } - break; - case "delimgroups-reset": - dlm = new StringDelimiter(); - groups = new HashMap<>(); - if (verbose) { - System.out.println("Reset delimiter groups + delimiter"); - } - break; - case "load-file": - handleLoadFile(args); - break; - default: - System.out.println("Unknown command "); - } - - } - - /* - * Load script commands from a file. - */ - private void handleLoadFile(final String args) { - String pth = args; - - if (args.startsWith("\"")) { - pth = args.substring(1, args.length() - 1); - } - - try (FileInputStream fis = new FileInputStream(pth)) { - final Scanner scn = new Scanner(fis); - - while (scn.hasNextLine()) { - final String ln = scn.nextLine().trim(); - - if (ln.equals("")) { - continue; - } - if (ln.startsWith("#")) { - continue; - } - - if (verbose) { - System.out.println("\nRead command '" + ln + "' from file\n"); - } - handleCommand(ln, scn, false); - } - - scn.close(); - } catch (final FileNotFoundException fnfex) { - System.out.println("Couldn't find file '" + args + "'"); - } catch (final IOException ioex) { - System.out.println("I/O error with file '" + args + "'\nCause: " + ioex.getMessage()); - } - } - - /* - * Handle editing a group. - */ - private void handleEditGroup(final String arg, final Scanner scn, final boolean isInteractive) { - if (!groups.containsKey(arg)) { - System.out.println("No group named '" + arg + "'"); - return; - } - - final DelimiterGroup<String> group = groups.get(arg); - - if (verbose) { - System.out.println("Editing group '" + arg + "'"); - } - if (isInteractive) { - System.out.println("Enter command (blank line to stop editing): "); - } - - String ln = scn.nextLine().trim(); - - while (!ln.equals("")) { - int idx = ln.indexOf(' '); - - if (idx == -1) { - idx = ln.length(); - } - - final String command = ln.substring(0, idx); - - final String args = ln.substring(idx).trim(); - final String[] argArray = args.split(" "); - - switch (command) { - case "add-closing": - group.addClosing(argArray); - if (verbose) { - System.out.println( - "Added closers " + StringUtils.toEnglishList(argArray, true)); - } - break; - case "add-tlexclude": - group.addTopLevelForbid(argArray); - if (verbose) { - System.out.println("Added top-level exclusions " - + StringUtils.toEnglishList(argArray, true)); - } - break; - case "add-exclude": - group.addTopLevelForbid(argArray); - if (verbose) { - System.out.println("Added nested exclusions " - + StringUtils.toEnglishList(argArray, true)); - } - break; - case "add-subgroup": - group.addSubgroup(argArray[0], Integer.parseInt(argArray[1])); - if (verbose) { - System.out.printf("Added subgroup %s with priority %s\n", argArray[0], - argArray[1]); - } - break; - case "add-implied-subgroup": - group.implySubgroup(argArray[0], argArray[1]); - if (verbose) { - System.out.printf("Made closer '%s' imply a '%s' subgroup\n", argArray[0], - argArray[1]); - } - break; - case "add-opener": - group.addOpener(argArray[0], argArray[1]); - if (verbose) { - System.out.printf("Added opener '%s' for group '%s'\n", argArray[0], - argArray[1]); - } - break; - case "add-reopener": - group.addPredOpener(new RegexOpener(argArray[0], argArray[1])); - if (verbose) { - System.out.printf("Added regex '%s' as opener for '%s'\n", argArray[1], - argArray[0]); - } - break; - case "add-recloser": - group.addPredCloser(new RegexCloser(argArray[0])); - if (verbose) { - System.out.printf("Added parameterized string '%s' as closer\n", argArray[0]); - } - break; - case "debug": - System.out.println(group.toString()); - break; - default: - System.out.println("Unknown command " + command); - } - - if (isInteractive) { - System.out.println("Enter command (blank line to stop editing): "); - } - - ln = scn.nextLine().trim(); - } - - if (verbose) { - System.out.println("Finished editing group '" + arg + "'"); - } - } - - private void handleDelim(final String args) { - try { - final ITree<String> res = dlm.delimitSequence(args.split(" ")); - - printDelimSeq(res); - } catch (final DelimiterException dex) { - System.out.println("Expression '" + args + "' isn't properly delimited.\n\tCause: " - + dex.getMessage()); - } - } - - private void handleSplit(final String[] argArray) { - for (int i = 0; i < argArray.length; i++) { - final String arg = argArray[i]; - - final IList<String> strangs = split.split(arg); - - System.out.printf("%d '%s' %s\n", i, arg, strangs); - } - } - - private void handleTest(final String inp, final boolean splitWS) { - IList<String> strings; - - try { - strings = split.split(inp); - } catch (final IllegalStateException isex) { - System.out.println("Splitter must be compiled at least once before use."); - return; - } - - System.out.println("Split tokens: " + strings); - - if (splitWS) { - final List<String> tks = new LinkedList<>(); - - for (final String strang : strings) { - tks.addAll(Arrays.asList(strang.split(" "))); - } - - strings = new FunctionalList<>(tks); - } - try { - final ITree<String> delim = dlm.delimitSequence(strings.toArray(new String[0])); - - printDelimSeq(delim); - } catch (final DelimiterException dex) { - System.out.println("Expression isn't properly delimited."); - System.out.println("Cause: " + dex.getMessage()); - } - } - - private void printDelimSeq(final ITree<String> delim) { - System.out.println("Delimited tokens:\n" + delim.getChild(1).toString()); - System.out.print("Delimited expr: "); - printDelimTree(delim); - System.out.println(); - System.out.println(); - - System.out.println(); - } - - private void printDelimTree(final ITree<String> tree) { - final StringBuilder sb = new StringBuilder(); - - intPrintDelimTree(tree.getChild(1), sb); - - System.out.println(sb.toString().replaceAll("\\s+", " ")); - } - - private void intPrintDelimTree(final ITree<String> tree, final StringBuilder sb) { - tree.doForChildren((child) -> { - intPrintDelimNode(child, sb); - }); - } - - private void intPrintDelimNode(final ITree<String> tree, final StringBuilder sb) { - if (tree.getHead().equals("contents")) { - intPrintDelimTree(tree, sb); - return; - } - - switch (tree.getChildrenCount()) { - case 0: - sb.append(tree.getHead()); - sb.append(" "); - - break; - case 1: - intPrintDelimTree(tree.getChild(0), sb); - - break; - case 2: - intPrintDelimTree(tree.getChild(0).getChild(0), sb); - intPrintDelimNode(tree.getChild(1), sb); - - break; - case 3: - intPrintDelimNode(tree.getChild(0), sb); - - final ITree<String> contents = tree.getChild(1); - - intPrintDelimTree(contents.getChild(0), sb); - intPrintDelimNode(tree.getChild(2), sb); - - break; - } - } - - /** - * Main method - * - * @param args - * Unused CLI args. - */ - public static void main(final String[] args) { - final DelimSplitterTest tst = new DelimSplitterTest(); - - tst.runLoop(); - } -} diff --git a/BJC-Utils2/src/examples/java/bjc/utils/examples/ShuntTest.java b/BJC-Utils2/src/examples/java/bjc/utils/examples/ShuntTest.java deleted file mode 100644 index ed530ed..0000000 --- a/BJC-Utils2/src/examples/java/bjc/utils/examples/ShuntTest.java +++ /dev/null @@ -1,37 +0,0 @@ -package bjc.utils.examples; - -import java.util.Scanner; - -import bjc.utils.funcdata.FunctionalStringTokenizer; -import bjc.utils.funcdata.IList; -import bjc.utils.parserutils.ShuntingYard; - -/** - * Test of shunting yard - * - * @author ben - * - */ -public class ShuntTest { - /** - * Main method - * - * @param args - * Unused CLI args - */ - public static void main(final String[] args) { - final Scanner inputSource = new Scanner(System.in); - - System.out.print("Enter a expression to shunt: "); - final String line = inputSource.nextLine(); - - final ShuntingYard<String> yard = new ShuntingYard<>(true); - - final IList<String> preTokens = new FunctionalStringTokenizer(line).toList(strang -> strang); - final IList<String> shuntedTokens = yard.postfix(preTokens, strang -> strang); - - System.out.println(shuntedTokens.toString()); - - inputSource.close(); - } -} diff --git a/BJC-Utils2/src/examples/java/bjc/utils/examples/rangen/DiabloItemGen.java b/BJC-Utils2/src/examples/java/bjc/utils/examples/rangen/DiabloItemGen.java deleted file mode 100644 index 250318f..0000000 --- a/BJC-Utils2/src/examples/java/bjc/utils/examples/rangen/DiabloItemGen.java +++ /dev/null @@ -1,94 +0,0 @@ -package bjc.utils.examples.rangen; - -import bjc.utils.funcdata.FunctionalStringTokenizer; -import bjc.utils.funcdata.IList; -import bjc.utils.gen.WeightedGrammar; - -/** - * Example showing how to use the weighted random number generator. - * - * @author ben - * - */ -public class DiabloItemGen { - private static WeightedGrammar<String> rules = new WeightedGrammar<>(); - - private static void addCase(final String ruleName, final int probability, final String ruleParts) { - final IList<String> parts = FunctionalStringTokenizer.fromString(ruleParts).toList(strang -> strang); - - rules.addCase(ruleName, probability, parts); - } - - private static void addInfixRules() { - final String rn = "<infix>"; - - addCase(rn, 60, "sword"); - addCase(rn, 50, "armor"); - addCase(rn, 40, "rune"); - addCase(rn, 30, "scroll"); - addCase(rn, 20, "potion"); - addCase(rn, 10, "helm"); - } - - private static void addItemRules() { - final String rn = "<item>"; - - addCase(rn, 10, "<infix>"); - addCase(rn, 20, "<prefix> <infix>"); - addCase(rn, 30, "<infix> <suffix>"); - addCase(rn, 40, "<prefix> <infix> <suffix>"); - addCase(rn, 50, "<prefix> <prefix> <infix>"); - addCase(rn, 60, "<prefix> <prefix> <infix> <suffix>"); - } - - private static void addPrefixRules() { - final String rn = "<prefix>"; - - addCase(rn, 60, "sturdy"); - addCase(rn, 50, "fine"); - addCase(rn, 40, "strong"); - addCase(rn, 30, "azure"); - addCase(rn, 20, "crimson"); - addCase(rn, 10, "phasing"); - } - - private static void addSuffixRules() { - final String rn = "<suffix>"; - - addCase(rn, 60, "of Health"); - addCase(rn, 50, "of Wealth"); - addCase(rn, 40, "of Life"); - addCase(rn, 30, "of the Jackal"); - addCase(rn, 20, "of Vitality"); - addCase(rn, 10, "of Ability"); - } - - /** - * Main Method - * - * @param args - * Unused CLI args - */ - public static void main(final String[] args) { - rules.addRule("<item>"); - addItemRules(); - - rules.addRule("<suffix>"); - addSuffixRules(); - - rules.addRule("<prefix>"); - addPrefixRules(); - - rules.addRule("<infix>"); - addInfixRules(); - - for (int i = 0; i < 100; i++) { - final IList<String> ls = rules.generateListValues("<item>", " "); - - final StringBuilder sb = new StringBuilder(); - ls.forEach(sb::append); - - System.out.println(sb.toString().replaceAll("\\s+", " ")); - } - } -} diff --git a/BJC-Utils2/src/examples/java/bjc/utils/examples/rangen/RandomStringExamples.java b/BJC-Utils2/src/examples/java/bjc/utils/examples/rangen/RandomStringExamples.java deleted file mode 100644 index a84f70d..0000000 --- a/BJC-Utils2/src/examples/java/bjc/utils/examples/rangen/RandomStringExamples.java +++ /dev/null @@ -1,64 +0,0 @@ -package bjc.utils.examples.rangen; - -import bjc.utils.funcdata.FunctionalList; -import bjc.utils.funcdata.FunctionalStringTokenizer; -import bjc.utils.funcdata.IList; -import bjc.utils.gen.RandomGrammar; - -/** - * Examples of random grammar - * - * @author ben - * - */ -public class RandomStringExamples { - private static RandomGrammar<String> rg; - - private static void addRule(final String rule, final String... cases) { - final IList<IList<String>> cses = new FunctionalList<>(); - - for (final String strang : cases) { - final IList<String> lst = FunctionalStringTokenizer.fromString(strang).toList(s -> s); - - cses.add(lst); - } - - rg.makeRule(rule, cses); - } - - /** - * Main method - * - * @param args - * Unused CLI args - */ - public static void main(final String[] args) { - rg = new RandomGrammar<>(); - - addRule("<sentance>", "<person> <opines> <something>", "<person> thinks that I am <property>", - "I <opine> <something>", "You think that I am <property>"); - - addRule("<activity>", "dancing", "eating", "sleeping"); - - addRule("<object>", "<person>", "life", "my computer", "my friends"); - - addRule("<opine>", "hate", "am jealous of", "love"); - - addRule("<opines>", "hates", "loves"); - - addRule("<person>", "my sister", "my father", "my girlfriend", "the man next door"); - - addRule("<property>", "creative", "intelligent"); - - addRule("<something>", "<activity>", "<activity> with <person>", "<object>"); - - for (int i = 0; i < 10; i++) { - final IList<String> ls = rg.generateListValues("<sentance>", " "); - - final StringBuilder sb = new StringBuilder(); - ls.forEach(sb::append); - - System.out.println(sb.toString().replaceAll("\\s+", " ")); - } - } -} diff --git a/BJC-Utils2/src/examples/java/bjc/utils/examples/sample-ds-files/html.ds b/BJC-Utils2/src/examples/java/bjc/utils/examples/sample-ds-files/html.ds deleted file mode 100644 index 103fa12..0000000 --- a/BJC-Utils2/src/examples/java/bjc/utils/examples/sample-ds-files/html.ds +++ /dev/null @@ -1,10 +0,0 @@ -delimgroups-new tag initial - -delimgroups-edit tag - add-recloser </%2$s> - -delimgroups-edit initial - add-reopener tag <(\w+)> - -delims-addgroup tag initial -delims-setinitial initial
\ No newline at end of file diff --git a/BJC-Utils2/src/examples/java/bjc/utils/examples/sample-ds-files/json.ds b/BJC-Utils2/src/examples/java/bjc/utils/examples/sample-ds-files/json.ds deleted file mode 100644 index d110d95..0000000 --- a/BJC-Utils2/src/examples/java/bjc/utils/examples/sample-ds-files/json.ds +++ /dev/null @@ -1,23 +0,0 @@ -splitter-addmatch ( { [ -splitter-add : , " -splitter-compile - -delimgroups-new braces brackets initial -delimgroups-edit braces - add-closing } - add-subgroup : 0 - add-subgroup , 1 - add-implied-subgroup } , - -delimgroups-edit brackets - add-subgroup , 0 - add-closing ] - add-implied-subgroup ] , - -delimgroups-edit initial - add-opener { braces - add-opener [ brackets - -delims-addgroup braces brackets initial - -delims-setinitial initial
\ No newline at end of file diff --git a/BJC-Utils2/src/examples/java/bjc/utils/examples/test.tree b/BJC-Utils2/src/examples/java/bjc/utils/examples/test.tree deleted file mode 100644 index 795cc88..0000000 --- a/BJC-Utils2/src/examples/java/bjc/utils/examples/test.tree +++ /dev/null @@ -1,13 +0,0 @@ -test 1 - 1 - 1 - 2 - 2 - 1 - -simp 1 - 2 - 3 - 4 - 3 - 2
\ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/PropertyDB.java b/BJC-Utils2/src/main/java/bjc/utils/PropertyDB.java deleted file mode 100644 index 713e1e0..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/PropertyDB.java +++ /dev/null @@ -1,160 +0,0 @@ -package bjc.utils; - -import java.util.HashMap; -import java.util.Map; -import java.util.NoSuchElementException; -import java.util.regex.Pattern; - -import bjc.utils.funcutils.LambdaLock; -import bjc.utils.ioutils.SimpleProperties; - -/** - * Database for storage of properties from external files. - * - * @author EVE - * - */ -public class PropertyDB { - private static SimpleProperties regexes; - private static Map<String, Pattern> compiledRegexes; - - private static SimpleProperties formats; - - /* - * Whether or not to log during the loading. - */ - private static final boolean LOGLOAD = false; - - /* - * The lock to use to ensure a read can't happen during a reload - */ - private static LambdaLock loadLock = new LambdaLock(); - - static { - reloadProperties(); - } - - /** - * Reload all the properties from their files. - * - * NOTE: Any attempts to read from the property DB while properties are - * being loaded will block, to prevent reads from partial states. - */ - public static void reloadProperties() { - /* - * Do the load with the write lock taken. - */ - loadLock.write(() -> { - if (LOGLOAD) { - System.out.println("Reading regex properties:"); - } - - /* - * Load regexes. - */ - regexes = new SimpleProperties(); - regexes.loadFrom(PropertyDB.class.getResourceAsStream("/regexes.sprop"), false); - if (LOGLOAD) { - regexes.outputProperties(); - System.out.println(); - } - compiledRegexes = new HashMap<>(); - - if (LOGLOAD) { - System.out.println("Reading format properties:"); - } - - /* - * Load formats. - */ - formats = new SimpleProperties(); - formats.loadFrom(PropertyDB.class.getResourceAsStream("/formats.sprop"), false); - if (LOGLOAD) { - formats.outputProperties(); - System.out.println(); - } - }); - } - - /** - * Retrieve a persisted regular expression. - * - * @param key - * The name of the regular expression. - * - * @return The regular expression with that name. - */ - public static String getRegex(final String key) { - return loadLock.read(() -> { - if (!regexes.containsKey(key)) { - final String msg = String.format("No regular expression named '%s' found", key); - - throw new NoSuchElementException(msg); - } - - return regexes.get(key); - }); - } - - /** - * Retrieve a persisted regular expression, compiled into a regular - * expression. - * - * @param key - * The name of the regular expression. - * - * @return The regular expression with that name. - */ - public static Pattern getCompiledRegex(final String key) { - return loadLock.read(() -> { - if (!regexes.containsKey(key)) { - final String msg = String.format("No regular expression named '%s' found", key); - - throw new NoSuchElementException(msg); - } - - /* - * Get the regex, and cache a compiled version. - */ - return compiledRegexes.computeIfAbsent(key, strang -> { - return Pattern.compile(regexes.get(strang)); - }); - }); - } - - /** - * Retrieve a persisted format string. - * - * @param key - * The name of the format string. - * - * @return The format string with that name. - */ - public static String getFormat(final String key) { - return loadLock.read(() -> { - if (!formats.containsKey(key)) { - final String msg = String.format("No format string named '%s' found", key); - - throw new NoSuchElementException(msg); - } - - return formats.get(key); - }); - } - - /** - * Retrieve a persisted format string, and apply it to a set of - * arguments. - * - * @param key - * The name of the format string. - * - * @param objects - * The parameters to the format string. - * - * @return The format string with that name. - */ - public static String applyFormat(final String key, final Object... objects) { - return String.format(getFormat(key), objects); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/cli/CLICommander.java b/BJC-Utils2/src/main/java/bjc/utils/cli/CLICommander.java deleted file mode 100644 index cccb255..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/cli/CLICommander.java +++ /dev/null @@ -1,134 +0,0 @@ -package bjc.utils.cli; - -import java.io.InputStream; -import java.io.OutputStream; -import java.io.PrintStream; -import java.util.Arrays; -import java.util.Scanner; - -/** - * Runs a CLI interface from the provided set of streams. - * - * @author ben - * - */ -public class CLICommander { - /* - * The streams used for input and normal/error output. - */ - private final InputStream input; - private final OutputStream output; - private final OutputStream error; - - /* - * The command mode to start execution in. - */ - private CommandMode initialMode; - - /** - * Create a new CLI interface powered by streams. - * - * @param input - * The stream to get user input from. - * @param output - * The stream to send normal output to. - * @param error - * The stream to send error output to. - */ - public CLICommander(final InputStream input, final OutputStream output, final OutputStream error) { - if (input == null) - throw new NullPointerException("Input stream must not be null"); - else if (output == null) - throw new NullPointerException("Output stream must not be null"); - else if (error == null) throw new NullPointerException("Error stream must not be null"); - - this.input = input; - this.output = output; - this.error = error; - } - - /** - * Start handling commands from the given input stream. - */ - public void runCommands() { - /* - * Setup output streams. - */ - final PrintStream normalOutput = new PrintStream(output); - final PrintStream errorOutput = new PrintStream(error); - - /* - * Set up input streams. - * - * We're suppressing the warning because we might use the input - * stream multiple times. - */ - @SuppressWarnings("resource") - final Scanner inputSource = new Scanner(input); - - /* - * The mode currently being used to handle commands. - * - * Used to preserve the initial mode. - */ - CommandMode currentMode = initialMode; - - /* - * Process commands until we're told to stop. - */ - while (currentMode != null) { - /* - * Print out the command prompt, using a custom prompt - * if one is specified. - */ - if (currentMode.isCustomPromptEnabled()) { - normalOutput.print(currentMode.getCustomPrompt()); - } else { - normalOutput.print(currentMode.getName() + ">> "); - } - - /* - * Read in a command. - */ - final String currentLine = inputSource.nextLine(); - - /* - * Handle commands we can handle. - */ - if (currentMode.canHandle(currentLine)) { - final String[] commandTokens = currentLine.split(" "); - String[] commandArgs = null; - - final int argCount = commandTokens.length; - - /* - * Parse args if they are present. - */ - if (argCount > 1) { - commandArgs = Arrays.copyOfRange(commandTokens, 1, argCount); - } - - /* - * Process command. - */ - currentMode = currentMode.process(commandTokens[0], commandArgs); - } else { - errorOutput.print("Error: Unrecognized command " + currentLine); - } - } - - normalOutput.print("Exiting now."); - } - - /** - * Set the initial command mode to use. - * - * @param initialMode - * The initial command mode to use. - */ - public void setInitialCommandMode(final CommandMode initialMode) { - if (initialMode == null) throw new NullPointerException("Initial mode must be non-zero"); - - this.initialMode = initialMode; - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/cli/Command.java b/BJC-Utils2/src/main/java/bjc/utils/cli/Command.java deleted file mode 100644 index 02bc061..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/cli/Command.java +++ /dev/null @@ -1,39 +0,0 @@ -package bjc.utils.cli; - -/** - * Represents a command that can be invoked from a {@link CommandMode} - * - * @author ben - * - */ -public interface Command { - /** - * Create a command that serves as an alias to this one - * - * @return A command that serves as an alias to this one - */ - Command aliased(); - - /** - * Get the handler that executes this command - * - * @return The handler that executes this command - */ - CommandHandler getHandler(); - - /** - * Get the help entry for this command - * - * @return The help entry for this command - */ - CommandHelp getHelp(); - - /** - * Check if this command is an alias of another command - * - * @return Whether or not this command is an alias of another - */ - default boolean isAlias() { - return false; - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/cli/CommandHandler.java b/BJC-Utils2/src/main/java/bjc/utils/cli/CommandHandler.java deleted file mode 100644 index 2548248..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/cli/CommandHandler.java +++ /dev/null @@ -1,24 +0,0 @@ -package bjc.utils.cli; - -import java.util.function.Function; - -/** - * A handler for a command - * - * @author ben - * - */ -@FunctionalInterface -public interface CommandHandler extends Function<String[], CommandMode> { - /** - * Execute this command - * - * @param args - * The arguments for this command - * @return The command mode to switch to after this command, or null to - * stop executing commands - */ - default CommandMode handle(final String[] args) { - return this.apply(args); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/cli/CommandHelp.java b/BJC-Utils2/src/main/java/bjc/utils/cli/CommandHelp.java deleted file mode 100644 index 86567a0..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/cli/CommandHelp.java +++ /dev/null @@ -1,31 +0,0 @@ -package bjc.utils.cli; - -/** - * Interface for the help entry for a command - * - * @author ben - * - */ -public interface CommandHelp { - /** - * Get the description of a command. - * - * @return The description of a command - */ - String getDescription(); - - /** - * Get the summary line for a command. - * - * A summary line should consist of a string of the following format - * - * <pre> - * "<command-name>\t<command-summary>" - * </pre> - * - * where anything in angle brackets should be filled in. - * - * @return The summary line line for a command - */ - String getSummary(); -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/cli/CommandMode.java b/BJC-Utils2/src/main/java/bjc/utils/cli/CommandMode.java deleted file mode 100644 index 39c72fc..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/cli/CommandMode.java +++ /dev/null @@ -1,72 +0,0 @@ -package bjc.utils.cli; - -/** - * A mode for determining the commands that are valid to enter, and then - * handling those commands - * - * @author ben - * - */ -public interface CommandMode extends Comparable<CommandMode> { - /** - * Check to see if this mode can handle the specified command - * - * @param command - * The command to check - * @return Whether or not this mode can handle the command. It is - * assumed not by default - */ - default boolean canHandle(final String command) { - return false; - }; - - /** - * Get the custom prompt for this mode - * - * @return the custom prompt for this mode - * - * @throws UnsupportedOperationException - * if this mode doesn't support a custom prompt - */ - default String getCustomPrompt() { - throw new UnsupportedOperationException("This mode doesn't support a custom prompt"); - } - - /** - * Get the name of this command mode - * - * @return The name of this command mode, which is the empty string by - * default - */ - public default String getName() { - return ""; - } - - /** - * Check if this mode uses a custom prompt - * - * @return Whether or not this mode uses a custom prompt - */ - default boolean isCustomPromptEnabled() { - return false; - } - - /** - * Process a command in this mode - * - * @param command - * The command to process - * @param args - * A list of arguments to the command - * @return The command mode to use for the next command. Defaults to - * returning this, and doing nothing else - */ - default CommandMode process(final String command, final String[] args) { - return this; - } - - @Override - default int compareTo(final CommandMode o) { - return getName().compareTo(o.getName()); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/cli/DelegatingCommand.java b/BJC-Utils2/src/main/java/bjc/utils/cli/DelegatingCommand.java deleted file mode 100644 index acaa3a6..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/cli/DelegatingCommand.java +++ /dev/null @@ -1,64 +0,0 @@ -package bjc.utils.cli; - -/** - * A class for a command that delegates to another command. - * - * @author ben - * - */ -class DelegatingCommand implements Command { - /* - * The command to delegate to. - */ - private final Command delegate; - - /** - * Create a new command that delegates to another command. - * - * @param delegate - * The command to delegate to. - */ - public DelegatingCommand(final Command delegate) { - this.delegate = delegate; - } - - @Override - public Command aliased() { - return new DelegatingCommand(delegate); - } - - @Override - public CommandHandler getHandler() { - return delegate.getHandler(); - } - - @Override - public CommandHelp getHelp() { - return delegate.getHelp(); - } - - @Override - public boolean isAlias() { - return true; - } - - /* - * (non-Javadoc) - * - * @see java.lang.Object#toString() - */ - @Override - public String toString() { - final StringBuilder builder = new StringBuilder(); - builder.append("DelegatingCommand ["); - - if (delegate != null) { - builder.append("delegate="); - builder.append(delegate); - } - - builder.append("]"); - - return builder.toString(); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/cli/GenericCommand.java b/BJC-Utils2/src/main/java/bjc/utils/cli/GenericCommand.java deleted file mode 100644 index 4ae4dea..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/cli/GenericCommand.java +++ /dev/null @@ -1,84 +0,0 @@ -package bjc.utils.cli; - -/** - * Generic command implementation. - * - * @author ben - * - */ -public class GenericCommand implements Command { - /* - * The behavior for invoking the command. - */ - private final CommandHandler handler; - - /* - * The help for the command. - */ - private CommandHelp help; - - /** - * Create a new generic command. - * - * @param handler - * The handler to use for the command. - * @param description - * The description of the command. May be null, in which - * case a default is provided. - * @param help - * The detailed help message for the command. May be - * null, in which case the description is repeated for - * the detailed help. - */ - public GenericCommand(final CommandHandler handler, final String description, final String help) { - if (handler == null) throw new NullPointerException("Command handler must not be null"); - - this.handler = handler; - - if (description == null) { - this.help = new NullHelp(); - } else { - this.help = new GenericHelp(description, help); - } - } - - @Override - public Command aliased() { - return new DelegatingCommand(this); - } - - @Override - public CommandHandler getHandler() { - return handler; - } - - @Override - public CommandHelp getHelp() { - return help; - } - - @Override - public boolean isAlias() { - return false; - } - - /* - * (non-Javadoc) - * - * @see java.lang.Object#toString() - */ - @Override - public String toString() { - final StringBuilder builder = new StringBuilder(); - builder.append("GenericCommand ["); - - if (help != null) { - builder.append("help="); - builder.append(help); - } - - builder.append("]"); - - return builder.toString(); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/cli/GenericCommandMode.java b/BJC-Utils2/src/main/java/bjc/utils/cli/GenericCommandMode.java deleted file mode 100644 index 8764537..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/cli/GenericCommandMode.java +++ /dev/null @@ -1,469 +0,0 @@ -package bjc.utils.cli; - -import java.util.TreeMap; -import java.util.function.BiConsumer; -import java.util.function.Consumer; - -import bjc.utils.funcdata.FunctionalMap; -import bjc.utils.funcdata.IMap; - -/** - * A general command mode, with a customizable set of commands - * - * There is a small set of commands which is handled by default. The first is - * 'list', which lists all the commands the user can input. The second is - * 'alias', which allows the user to bind a new name to a command - * - * @author ben - * - */ -public class GenericCommandMode implements CommandMode { - /* - * Contains the commands this mode handles - */ - private final IMap<String, Command> commandHandlers; - private final IMap<String, Command> defaultHandlers; - - /* - * Contains help topics without an associated command - */ - private final IMap<String, CommandHelp> helpTopics; - - /* - * The action to execute upon encountering an unknown command - */ - private BiConsumer<String, String[]> unknownCommandHandler; - - /* - * The functions to use for input/output - */ - private final Consumer<String> errorOutput; - private final Consumer<String> normalOutput; - - /* - * The name of this command mode, or null if it is unnamed - */ - private String modeName; - - /* - * The custom prompt to use, or null if none is specified - */ - private String customPrompt; - - /** - * Create a new generic command mode - * - * @param normalOutput - * The function to use for normal output - * @param errorOutput - * The function to use for error output - */ - public GenericCommandMode(final Consumer<String> normalOutput, final Consumer<String> errorOutput) { - if (normalOutput == null) - throw new NullPointerException("Normal output source must be non-null"); - else if (errorOutput == null) throw new NullPointerException("Error output source must be non-null"); - - this.normalOutput = normalOutput; - this.errorOutput = errorOutput; - - /* - * Initialize handler maps so that they sort in alphabetical - */ - /* - * order - */ - commandHandlers = new FunctionalMap<>(new TreeMap<>()); - defaultHandlers = new FunctionalMap<>(new TreeMap<>()); - helpTopics = new FunctionalMap<>(new TreeMap<>()); - - setupDefaultCommands(); - } - - /** - * Add an alias to an existing command - * - * @param commandName - * The name of the command to add an alias for - * @param aliasName - * The new alias for the command - * - * @throws IllegalArgumentException - * if the specified command doesn't have a bound - * handler, or if the alias name already has a bound - * value - */ - public void addCommandAlias(final String commandName, final String aliasName) { - if (commandName == null) - throw new NullPointerException("Command name must not be null"); - else if (aliasName == null) - throw new NullPointerException("Alias name must not be null"); - else if (!commandHandlers.containsKey(commandName) && !defaultHandlers.containsKey(commandName)) - throw new IllegalArgumentException("Cannot alias non-existant command '" + commandName + "'"); - else if (commandHandlers.containsKey(aliasName) || defaultHandlers.containsKey(aliasName)) - throw new IllegalArgumentException( - "Cannot bind alias '" + aliasName + "' to a command with a bound handler"); - else { - Command aliasedCommand; - - if (defaultHandlers.containsKey(commandName)) { - aliasedCommand = defaultHandlers.get(commandName).aliased(); - } else { - aliasedCommand = commandHandlers.get(commandName).aliased(); - } - - commandHandlers.put(aliasName, aliasedCommand); - } - } - - /** - * Add a command to this command mode - * - * @param command - * The name of the command to add - * @param handler - * The handler to use for the specified command - * - * @throws IllegalArgumentException - * if the specified command already has a handler - * registered - */ - public void addCommandHandler(final String command, final Command handler) { - if (command == null) - throw new NullPointerException("Command must not be null"); - else if (handler == null) - throw new NullPointerException("Handler must not be null"); - else if (canHandle(command)) - throw new IllegalArgumentException("Command " + command + " already has a handler registered"); - else { - commandHandlers.put(command, handler); - } - } - - /** - * Add a help topic to this command mode that isn't tied to a command - * - * @param topicName - * The name of the topic - * @param topic - * The contents of the topic - */ - public void addHelpTopic(final String topicName, final CommandHelp topic) { - helpTopics.put(topicName, topic); - } - - /* - * Default command builders - */ - - private GenericCommand buildAliasCommand() { - final String aliasShortHelp = "alias\tAlias one command to another"; - final String aliasLongHelp = "Gives a command another name it can be invoked by." - + " Invoke with two arguments: the name of the command to alias" - + "followed by the name of the alias to give that command."; - - return new GenericCommand((args) -> { - doAliasCommands(args); - - return this; - }, aliasShortHelp, aliasLongHelp); - } - - private GenericCommand buildClearCommands() { - final String clearShortHelp = "clear\tClear the screen"; - final String clearLongHelp = "Clears the screen of all the text on it," + " and prints a new prompt."; - - return new GenericCommand((args) -> { - errorOutput.accept("ERROR: This console doesn't support screen clearing"); - - return this; - }, clearShortHelp, clearLongHelp); - } - - private GenericCommand buildExitCommand() { - final String exitShortHelp = "exit\tExit the console"; - final String exitLongHelp = "First prompts the user to make sure they want to" - + " exit, then quits if they say they do"; - - return new GenericCommand((args) -> { - errorOutput.accept("ERROR: This console doesn't support auto-exiting"); - - return this; - }, exitShortHelp, exitLongHelp); - } - - private GenericCommand buildHelpCommand() { - final String helpShortHelp = "help\tConsult the help system"; - final String helpLongHelp = "Consults the internal help system." - + " Invoked in two different ways. Invoking with no arguments" - + " causes all the topics you can ask for details on to be list," - + " while invoking with the name of a topic will print the entry" + " for that topic"; - - return new GenericCommand((args) -> { - if (args == null || args.length == 0) { - /* - * Invoke general help - */ - doHelpSummary(); - } else { - /* - * Invoke help for a command - */ - doHelpCommand(args[0]); - } - - return this; - }, helpShortHelp, helpLongHelp); - } - - private GenericCommand buildListCommand() { - final String listShortHelp = "list\tList available commands"; - final String listLongHelp = "Lists all of the commands available in this mode," - + " as well as commands available in any mode"; - - return new GenericCommand((args) -> { - doListCommands(); - - return this; - }, listShortHelp, listLongHelp); - } - - @Override - public boolean canHandle(final String command) { - return commandHandlers.containsKey(command) || defaultHandlers.containsKey(command); - } - - /* - * Implement default commands - */ - - private void doAliasCommands(final String[] args) { - if (args.length != 2) { - errorOutput.accept("ERROR: Alias requires two arguments." - + " The command name, and the alias for that command"); - } else { - final String commandName = args[0]; - final String aliasName = args[1]; - - if (!canHandle(commandName)) { - errorOutput.accept("ERROR: '" + commandName + "' is not a valid command."); - } else if (canHandle(aliasName)) { - errorOutput.accept("ERROR: Cannot overwrite command '" + aliasName + "'"); - } else { - addCommandAlias(commandName, aliasName); - } - } - } - - private void doHelpCommand(final String commandName) { - if (commandHandlers.containsKey(commandName)) { - final String desc = commandHandlers.get(commandName).getHelp().getDescription(); - - normalOutput.accept("\n" + desc); - } else if (defaultHandlers.containsKey(commandName)) { - final String desc = defaultHandlers.get(commandName).getHelp().getDescription(); - - normalOutput.accept("\n" + desc); - } else if (helpTopics.containsKey(commandName)) { - normalOutput.accept("\n" + helpTopics.get(commandName).getDescription()); - } else { - errorOutput.accept( - "ERROR: I'm sorry, but there is no help available for '" + commandName + "'"); - } - } - - private void doHelpSummary() { - normalOutput.accept("Help topics for this command mode are as follows:\n"); - - if (commandHandlers.size() > 0) { - commandHandlers.forEachValue(command -> { - if (!command.isAlias()) { - normalOutput.accept("\t" + command.getHelp().getSummary() + "\n"); - } - }); - } else { - normalOutput.accept("\tNone available\n"); - } - - normalOutput.accept("\nHelp topics available in all command modes are as follows\n"); - if (defaultHandlers.size() > 0) { - defaultHandlers.forEachValue(command -> { - if (!command.isAlias()) { - normalOutput.accept("\t" + command.getHelp().getSummary() + "\n"); - } - }); - } else { - normalOutput.accept("\tNone available\n"); - } - - normalOutput.accept("\nHelp topics not associated with a command are as follows\n"); - if (helpTopics.size() > 0) { - helpTopics.forEachValue(topic -> { - normalOutput.accept("\t" + topic.getSummary() + "\n"); - }); - } else { - normalOutput.accept("\tNone available\n"); - } - } - - private void doListCommands() { - normalOutput.accept("The available commands for this mode are as follows:\n"); - - commandHandlers.keyList().forEach(commandName -> { - normalOutput.accept("\t" + commandName); - }); - - normalOutput.accept("\nThe following commands are available in all modes:\n"); - defaultHandlers.keyList().forEach(commandName -> { - normalOutput.accept("\t" + commandName); - }); - - normalOutput.accept("\n"); - } - - @Override - public String getCustomPrompt() { - if (customPrompt != null) return customPrompt; - - return CommandMode.super.getCustomPrompt(); - } - - @Override - public String getName() { - if (modeName != null) return modeName; - - return CommandMode.super.getName(); - } - - @Override - public boolean isCustomPromptEnabled() { - return customPrompt != null; - } - - @Override - public CommandMode process(final String command, final String[] args) { - normalOutput.accept("\n"); - - if (defaultHandlers.containsKey(command)) - return defaultHandlers.get(command).getHandler().handle(args); - else if (commandHandlers.containsKey(command)) - return commandHandlers.get(command).getHandler().handle(args); - else { - if (args != null) { - errorOutput.accept("ERROR: Unrecognized command " + command + String.join(" ", args)); - } else { - errorOutput.accept("ERROR: Unrecognized command " + command); - } - - if (unknownCommandHandler == null) - throw new UnsupportedOperationException("Command " + command + " is invalid."); - - unknownCommandHandler.accept(command, args); - } - - return this; - } - - /** - * Set the custom prompt for this mode - * - * @param prompt - * The custom prompt for this mode, or null to disable - * the custom prompt - */ - public void setCustomPrompt(final String prompt) { - customPrompt = prompt; - } - - /** - * Set the name of this mode - * - * @param name - * The desired name of this mode, or null to use the - * default name - */ - public void setModeName(final String name) { - modeName = name; - } - - /** - * Set the handler to use for unknown commands - * - * @param handler - * The handler to use for unknown commands, or null to - * throw on unknown commands - */ - public void setUnknownCommandHandler(final BiConsumer<String, String[]> handler) { - if (handler == null) throw new NullPointerException("Handler must not be null"); - - unknownCommandHandler = handler; - } - - private void setupDefaultCommands() { - defaultHandlers.put("list", buildListCommand()); - defaultHandlers.put("alias", buildAliasCommand()); - defaultHandlers.put("help", buildHelpCommand()); - - addCommandAlias("help", "man"); - - /* - * Add commands handled in a upper layer. - */ - - /* - * @TODO figure out a place to put commands that apply across - */ - /* - * all - */ - /* - * modes, but only apply to a specific application - */ - defaultHandlers.put("clear", buildClearCommands()); - defaultHandlers.put("exit", buildExitCommand()); - } - - /* - * (non-Javadoc) - * - * @see java.lang.Object#toString() - */ - @Override - public String toString() { - final StringBuilder builder = new StringBuilder(); - builder.append("GenericCommandMode ["); - - if (commandHandlers != null) { - builder.append("commandHandlers="); - builder.append(commandHandlers); - } - - if (defaultHandlers != null) { - builder.append(", "); - builder.append("defaultHandlers="); - builder.append(defaultHandlers); - } - - if (helpTopics != null) { - builder.append(", "); - builder.append("helpTopics="); - builder.append(helpTopics); - } - - if (modeName != null) { - builder.append(", "); - builder.append("modeName="); - builder.append(modeName); - } - - if (customPrompt != null) { - builder.append(", "); - builder.append("customPrompt="); - builder.append(customPrompt); - } - - builder.append("]"); - - return builder.toString(); - } - -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/cli/GenericHelp.java b/BJC-Utils2/src/main/java/bjc/utils/cli/GenericHelp.java deleted file mode 100644 index 38adf57..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/cli/GenericHelp.java +++ /dev/null @@ -1,63 +0,0 @@ -package bjc.utils.cli; - -/** - * Generic implementation of a help topic - * - * @author ben - * - */ -public class GenericHelp implements CommandHelp { - // The strings for this help topic - private final String summary; - private final String description; - - /** - * Create a new help topic - * - * @param summary - * The summary of this help topic - * @param description - * The description of this help topic, or null if this - * help topic doesn't have a more detailed description - */ - public GenericHelp(final String summary, final String description) { - if (summary == null) throw new NullPointerException("Help summary must be non-null"); - - this.summary = summary; - this.description = description; - } - - @Override - public String getDescription() { - if (description == null) return summary; - - return description; - } - - @Override - public String getSummary() { - return summary; - } - - @Override - public String toString() { - final StringBuilder builder = new StringBuilder(); - - builder.append("GenericHelp ["); - - if (summary != null) { - builder.append("summary="); - builder.append(summary); - } - - if (description != null) { - builder.append(", "); - builder.append("description="); - builder.append(description); - } - - builder.append("]"); - - return builder.toString(); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/cli/NullHelp.java b/BJC-Utils2/src/main/java/bjc/utils/cli/NullHelp.java deleted file mode 100644 index 6c49ae6..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/cli/NullHelp.java +++ /dev/null @@ -1,20 +0,0 @@ -package bjc.utils.cli; - -/** - * Implementation of a help topic that doesn't exist - * - * @author ben - * - */ -public class NullHelp implements CommandHelp { - @Override - public String getDescription() { - return "No description provided"; - } - - @Override - public String getSummary() { - return "No summary provided"; - } - -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/cli/objects/BlockReaderCLI.java b/BJC-Utils2/src/main/java/bjc/utils/cli/objects/BlockReaderCLI.java deleted file mode 100644 index ec66fe2..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/cli/objects/BlockReaderCLI.java +++ /dev/null @@ -1,392 +0,0 @@ -package bjc.utils.cli.objects; - -import java.io.InputStreamReader; -import java.io.Reader; - -import java.util.HashMap; -import java.util.Map; -import java.util.Scanner; -import java.util.function.Predicate; -import java.util.logging.Logger; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.regex.PatternSyntaxException; - -import bjc.utils.ioutils.Prompter; -import bjc.utils.ioutils.blocks.*; - -import static bjc.utils.cli.objects.Command.CommandStatus; -import static bjc.utils.cli.objects.Command.CommandStatus.*; - -public class BlockReaderCLI { - private final Logger LOGGER = Logger.getLogger(BlockReaderCLI.class.getName()); - - public static class BlockReaderState { - public final Map<String, BlockReader> readers; - public final Map<String, Reader> sources; - - public BlockReaderState(Map<String, BlockReader> readers, Map<String, Reader> sources) { - this.readers = readers; - this.sources = sources; - } - } - - private BlockReaderState stat; - - /** - * Create a new CLI for configuring BlockReaders. - * - * @param srcs - * The container of initial I/O sources. - */ - public BlockReaderCLI(Map<String, Reader> srcs) { - stat = new BlockReaderState(new HashMap<>(), srcs); - } - - public static void main(String[] args) { - /* - * Create/configure I/O sources. - */ - Map<String, Reader> sources = new HashMap<>(); - sources.put("stdio", new InputStreamReader(System.in)); - - BlockReaderCLI reader = new BlockReaderCLI(sources); - - reader.run(new Scanner(System.in), "console", true); - } - - /** - * Run the CLI on an input source. - * - * @param input - * The place to read input from. - * @param ioSource - * The name of the place to read input from. - * @param interactive - * Whether or not the source is interactive - */ - public void run(Scanner input, String ioSource, boolean interactive) { - int lno = 0; - while(input.hasNextLine()) { - if(interactive) - System.out.printf("reader-conf(%d)>", lno); - - String ln = input.nextLine(); - - lno += 1; - - Command com = Command.fromString(ln, lno, ioSource); - if(com == null) continue; - - CommandStatus stat = handleCommand(com, interactive); - if(stat == FINISH || stat == ERROR) { - return; - } - } - - input.close(); - } - - /* - * Handle a command. - */ - public CommandStatus handleCommand(Command com, boolean interactive) { - switch(com.nameCommand) { - case "def-filtered": - return defFiltered(com); - case "def-layered": - return defLayered(com); - case "def-pushback": - return defPushback(com); - case "def-simple": - return defSimple(com); - case "def-serial": - return defSerial(com); - case "def-toggled": - return defToggled(com); - case "}": - case "end": - case "exit": - case "quit": - if(interactive) - System.out.printf("Exiting reader-conf, %d readers configured in %d commands\n", - stat.readers.size(), com.lineNo); - return FINISH; - default: - LOGGER.severe(com.error("Unknown command '%s'\n", com.nameCommand)); - return FAIL; - } - } - - private CommandStatus defFiltered(Command com) { - String remn = com.remnCommand; - - /* - * Get the block name. - */ - int idx = remn.indexOf(' '); - if(idx == -1) { - LOGGER.severe(com.error("No name argument for def-filtered.\n")); - return FAIL; - } - String blockName = remn.substring(0, idx).trim(); - remn = remn.substring(idx).trim(); - - /* - * Check there isn't a reader already bound to this name. - */ - if(stat.readers.containsKey(blockName)) { - LOGGER.warning(com.warn("Shadowing existing reader named %s\n", blockName)); - } - - /* - * Get the reader name. - */ - idx = remn.indexOf(' '); - if(idx == -1) { - LOGGER.severe(com.error("No reader-name argument for def-filtered.\n")); - return FAIL; - } - String readerName = remn.substring(0, idx).trim(); - remn = remn.substring(idx).trim(); - - /* - * Check there is a reader bound to that name. - */ - if(!stat.readers.containsKey(readerName)) { - LOGGER.severe(com.error("No source named %s\n", readerName)); - return FAIL; - } - - /* - * Get the pattern. - */ - if(remn.equals("")) { - LOGGER.severe(com.error("No filter argument for def-filtered\n")); - return FAIL; - } - - String filter = remn; - - try { - Pattern pat = Pattern.compile(filter); - - Predicate<Block> pred = (block) -> { - Matcher mat = pat.matcher(block.contents); - - return mat.matches(); - }; - - BlockReader reader = new FilteredBlockReader(stat.readers.get(readerName), pred); - - stat.readers.put(blockName, reader); - } catch (PatternSyntaxException psex) { - LOGGER.severe(com.error("Invalid regular expression '%s' for filter. (%s)\n", filter, psex.getMessage())); - return FAIL; - } - - return SUCCESS; - } - - private CommandStatus defPushback(Command com) { - String[] parts = com.remnCommand.split(" "); - - if(parts.length != 2) { - LOGGER.severe(com.error("Incorrect number of arguments to def-pushback. Requires a block name and a reader name\n")); - return FAIL; - } - - String blockName = parts[0]; - if(stat.readers.containsKey(blockName)) { - LOGGER.warning(com.warn("Shadowing existing reader %s\n", blockName)); - return FAIL; - } - - String readerName = parts[1]; - if(!stat.readers.containsKey(readerName)) { - LOGGER.severe(com.error("No reader named %s\n", readerName)); - return FAIL; - } - - BlockReader reader = new PushbackBlockReader(stat.readers.get(readerName)); - stat.readers.put(blockName, reader); - - return SUCCESS; - } - - private CommandStatus defToggled(Command com) { - String[] parts = com.remnCommand.split(" "); - - if(parts.length != 3) { - LOGGER.severe(com.error("Incorrect number of arguments to def-toggled. Requires a block name and two reader names\n")); - return FAIL; - } - - /* - * Get the block name. - */ - String blockName = parts[0]; - if(stat.readers.containsKey(blockName)) { - LOGGER.warning(com.warn("Shadowing existing reader named %s\n", blockName)); - } - - /* - * Make sure the component readers exist. - */ - if(!stat.readers.containsKey(parts[1])) { - LOGGER.severe(com.error("No reader named %s\n", parts[1])); - return FAIL; - } - - if(!stat.readers.containsKey(parts[2])) { - LOGGER.severe(com.error("No reader named %s\n", parts[2])); - return FAIL; - } - - BlockReader reader = new ToggledBlockReader(stat.readers.get(parts[1]), stat.readers.get(parts[2])); - stat.readers.put(blockName, reader); - - return SUCCESS; - } - - private CommandStatus defLayered(Command com) { - String[] parts = com.remnCommand.split(" "); - - if(parts.length != 3) { - LOGGER.severe(com.error("Incorrect number of arguments to def-layered. Requires a block name and two reader names\n")); - return FAIL; - } - - /* - * Get the block name. - */ - String blockName = parts[0]; - if(stat.readers.containsKey(blockName)) { - LOGGER.warning(com.warn("Shadowing existing reader named %s\n", blockName)); - } - - /* - * Make sure the component readers exist. - */ - if(!stat.readers.containsKey(parts[1])) { - LOGGER.severe(com.error("No reader named %s\n", parts[1])); - return FAIL; - } - - if(!stat.readers.containsKey(parts[2])) { - LOGGER.severe(com.error("No reader named %s\n", parts[2])); - return FAIL; - } - - BlockReader reader = new LayeredBlockReader(stat.readers.get(parts[1]), stat.readers.get(parts[2])); - stat.readers.put(blockName, reader); - - return SUCCESS; - } - - private CommandStatus defSerial(Command com) { - String[] parts = com.remnCommand.split(" "); - - if(parts.length < 2) { - LOGGER.severe(com.error("Not enough arguments to def-serial. Requires at least a block name and at least one reader name\n")); - return FAIL; - } - - /* - * Get the name for this BlockReader. - */ - String blockName = parts[0]; - /* - * Check there isn't a reader already bound to this name. - */ - if(stat.readers.containsKey(blockName)) { - LOGGER.warning(com.warn("Shadowing existing reader named %s\n", blockName)); - } - - /* - * Get all of the component readers. - */ - BlockReader[] readerArr = new BlockReader[parts.length - 1]; - for(int i = 1; i < parts.length; i++) { - String readerName = parts[i]; - - /* - * Check there is a reader bound to that name. - */ - if(!stat.readers.containsKey(readerName)) { - LOGGER.severe(com.error("No reader named %s\n", readerName)); - return FAIL; - } - - readerArr[i] = stat.readers.get(readerName); - } - - BlockReader reader = new SerialBlockReader(readerArr); - - stat.readers.put(blockName, reader); - - return SUCCESS; - } - - private CommandStatus defSimple(Command com) { - String remn = com.remnCommand; - - /* - * Get the block name. - */ - int idx = remn.indexOf(' '); - if(idx == -1) { - LOGGER.severe(com.error("No name argument for def-simple.\n")); - return FAIL; - } - String blockName = remn.substring(0, idx).trim(); - remn = remn.substring(idx).trim(); - - /* - * Check there isn't a reader already bound to this name. - */ - if(stat.readers.containsKey(blockName)) { - LOGGER.warning(com.warn("Shadowing existing reader named %s\n", blockName)); - } - - /* - * Get the source name. - */ - idx = remn.indexOf(' '); - if(idx == -1) { - LOGGER.severe(com.error("No source-name argument for def-simple.\n")); - return FAIL; - } - String sourceName = remn.substring(0, idx).trim(); - remn = remn.substring(idx).trim(); - - /* - * Check there is a source bound to that name. - */ - if(!stat.sources.containsKey(sourceName)) { - LOGGER.severe(com.error("No source named %s\n", sourceName)); - return FAIL; - } - - /* - * Get the pattern. - */ - if(remn.equals("")) { - LOGGER.severe(com.error("No delimiter argument for def-simple\n")); - return FAIL; - } - - String delim = remn; - - try { - BlockReader reader = new SimpleBlockReader(delim, stat.sources.get(sourceName)); - - stat.readers.put(blockName, reader); - } catch (PatternSyntaxException psex) { - LOGGER.severe(com.error("Invalid regular expression '%s' for delimiter. (%s)\n", delim, psex.getMessage())); - return FAIL; - } - - return SUCCESS; - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/cli/objects/Command.java b/BJC-Utils2/src/main/java/bjc/utils/cli/objects/Command.java deleted file mode 100644 index e605a2b..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/cli/objects/Command.java +++ /dev/null @@ -1,87 +0,0 @@ -package bjc.utils.cli.objects; - -public class Command { - /** - * Command status values. - */ - public static enum CommandStatus { - /** - * The command succeded. - */ - SUCCESS, - /** - * The command failed non-fatally. - */ - FAIL, - /** - * The command failed fatally. - */ - ERROR, - /** - * The command was the last one. - */ - FINISH, - } - - public final int lineNo; - - public final String fullCommand; - public final String remnCommand; - public final String nameCommand; - - public final String ioSource; - - /** - * Create a new command. - * - * @param ln - * The line to get the command from. - * @param lno - * The number of the line the command came from. - * @param ioSrc - * The name of where the I/O came from. - */ - public Command(String ln, int lno, String ioSrc) { - int idx = ln.indexOf(' '); - - if(idx == -1) idx = ln.length(); - - fullCommand = ln; - nameCommand = ln.substring(0, idx).trim(); - remnCommand = ln.substring(idx).trim(); - - lineNo = lno; - - ioSource = ioSrc; - } - - public static Command fromString(String ln, int lno, String ioSource) { - /* - * Ignore blank lines and comments. - */ - if(ln.equals("")) return null; - if(ln.startsWith("#")) return null; - - /* - * Trim off comments part-way through the line. - */ - int idxHash = ln.indexOf('#'); - if(idxHash != -1) { - ln = ln.substring(0, idxHash).trim(); - } - - return new Command(ln, lno, ioSource); - } - - public String warn(String warning, Object... parms) { - String msg = String.format(warning, parms); - - return String.format("WARNING (%s:%d): %s", ioSource, lineNo, msg); - } - - public String error(String err, Object... parms) { - String msg = String.format(err, parms); - - return String.format("ERROR (%s:%d): %s", ioSource, lineNo, msg); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/cli/objects/DefineCLI.java b/BJC-Utils2/src/main/java/bjc/utils/cli/objects/DefineCLI.java deleted file mode 100644 index bb2733f..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/cli/objects/DefineCLI.java +++ /dev/null @@ -1,133 +0,0 @@ -package bjc.utils.cli.objects; - -import java.util.HashMap; -import java.util.Map; -import java.util.Scanner; -import java.util.function.UnaryOperator; -import java.util.logging.Logger; -import java.util.regex.Pattern; - -import static bjc.utils.cli.objects.Command.CommandStatus; -import static bjc.utils.cli.objects.Command.CommandStatus.*; - -public class DefineCLI { - private final Logger LOGGER = Logger.getLogger(DefineCLI.class.getName()); - - public static class DefineState { - public final Map<String, UnaryOperator<String>> defines; - - public final Map<String, String> strings; - public final Map<String, String> formats; - - public final Map<String, Pattern> patterns; - - public DefineState() { - this(new HashMap<>(), new HashMap<>(), new HashMap<>(), new HashMap<>()); - } - - public DefineState(Map<String, UnaryOperator<String>> defines, - Map<String, String> strings, Map<String, String> formats, - Map<String, Pattern> patterns) { - this.defines = defines; - - this.strings = strings; - this.formats = formats; - - this.patterns = patterns; - } - } - - private DefineState stat; - - public DefineCLI() { - stat = new DefineState(); - } - - public static void main(String[] args) { - DefineCLI defin = new DefineCLI(); - } - - /** - * Run the CLI on an input source. - * - * @param input - * The place to read input from. - * @param ioSource - * The name of the place to read input from. - * @param interactive - * Whether or not the source is interactive - */ - public void run(Scanner input, String ioSource, boolean interactive) { - int lno = 0; - while(input.hasNextLine()) { - if(interactive) - System.out.printf("define-conf(%d)>", lno); - - String ln = input.nextLine(); - - lno += 1; - - Command com = Command.fromString(ln, lno, ioSource); - if(com == null) continue; - - handleCommand(com, interactive); - } - - input.close(); - } - - public void handleCommand(Command com, boolean interactive) { - switch(com.nameCommand) { - case "def-string": - default: - LOGGER.severe(com.error("Unknown command %s\n", com.nameCommand)); - break; - } - } - - private CommandStatus defString(Command com) { - String remn = com.remnCommand; - - int idx = remn.indexOf(' '); - if(idx == -1) { - LOGGER.warning(com.warn("Binding empty string to name '%s'\n", remn)); - idx = remn.length(); - } - String name = remn.substring(0, idx); - String strang = remn.substring(idx); - - if(stat.strings.containsKey(name)) { - LOGGER.warning(com.warn("Shadowing string '%s'\n", name)); - } - - stat.strings.put(name, strang); - - return SUCCESS; - } - - private CommandStatus defFormat(Command com) { - String remn = com.remnCommand; - - int idx = remn.indexOf(' '); - if(idx == -1) { - LOGGER.warning(com.warn("Binding empty format to name '%s'\n", remn)); - idx = remn.length(); - } - String name = remn.substring(0, idx); - String fmt = remn.substring(idx); - - if(stat.formats.containsKey(name)) { - LOGGER.warning(com.warn("Shadowing format '%s'\n", name)); - } - - stat.formats.put(name, fmt); - - return SUCCESS; - } - - private CommandStatus bindFormat(Command com) { - String[] parts = com.remnCommand.split(" "); - - return SUCCESS; - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/components/ComponentDescription.java b/BJC-Utils2/src/main/java/bjc/utils/components/ComponentDescription.java deleted file mode 100644 index 28f81d1..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/components/ComponentDescription.java +++ /dev/null @@ -1,135 +0,0 @@ -package bjc.utils.components; - -/** - * Generic implementation of a description for a component - * - * @author ben - * - */ -public class ComponentDescription implements IDescribedComponent { - private static void sanityCheckArgs(final String name, final String author, final String description, - final int version) { - if (name == null) - throw new NullPointerException("Component name can't be null"); - else if (version <= 0) throw new IllegalArgumentException("Component version must be greater than 0"); - } - - /** - * The author of the component - */ - private final String author; - /** - * The description of the component - */ - private final String description; - /** - * The name of the component - */ - private final String name; - - /** - * The version of the component - */ - private final int version; - - /** - * Create a new component description - * - * @param name - * The name of the component - * @param author - * The author of the component - * @param description - * The description of the component - * @param version - * The version of the component - * @throws IllegalArgumentException - * thrown if version is less than 1 - */ - public ComponentDescription(final String name, final String author, final String description, - final int version) { - sanityCheckArgs(name, author, description, version); - - this.name = name; - this.author = author; - this.description = description; - this.version = version; - } - - @Override - public String getAuthor() { - if (author == null) return IDescribedComponent.super.getAuthor(); - - return author; - } - - @Override - public String getDescription() { - if (description == null) return IDescribedComponent.super.getDescription(); - - return description; - } - - @Override - public String getName() { - return name; - } - - @Override - public int getVersion() { - return version; - } - - @Override - public String toString() { - return name + " component v" + version + ", written by " + author; - } - - /* - * (non-Javadoc) - * - * @see java.lang.Object#hashCode() - */ - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - - result = prime * result + (author == null ? 0 : author.hashCode()); - result = prime * result + (description == null ? 0 : description.hashCode()); - result = prime * result + (name == null ? 0 : name.hashCode()); - result = prime * result + version; - - return result; - } - - /* - * (non-Javadoc) - * - * @see java.lang.Object#equals(java.lang.Object) - */ - @Override - public boolean equals(final Object obj) { - if (this == obj) return true; - if (obj == null) return false; - if (getClass() != obj.getClass()) return false; - - final ComponentDescription other = (ComponentDescription) obj; - - if (author == null) { - if (other.author != null) return false; - } else if (!author.equals(other.author)) return false; - - if (description == null) { - if (other.description != null) return false; - } else if (!description.equals(other.description)) return false; - - if (name == null) { - if (other.name != null) return false; - } else if (!name.equals(other.name)) return false; - - if (version != other.version) return false; - - return true; - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/components/ComponentDescriptionFileParser.java b/BJC-Utils2/src/main/java/bjc/utils/components/ComponentDescriptionFileParser.java deleted file mode 100644 index f7ddaff..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/components/ComponentDescriptionFileParser.java +++ /dev/null @@ -1,65 +0,0 @@ -package bjc.utils.components; - -import static bjc.utils.ioutils.RuleBasedReaderPragmas.buildInteger; -import static bjc.utils.ioutils.RuleBasedReaderPragmas.buildStringCollapser; - -import java.io.InputStream; - -import bjc.utils.ioutils.RuleBasedConfigReader; - -/** - * Read a component description from a file - * - * @author ben - * - */ -public class ComponentDescriptionFileParser { - // The reader used to read in component descriptions - private static RuleBasedConfigReader<ComponentDescriptionState> reader; - - // Initialize the reader and its pragmas - static { - // This reader works entirely off of pragmas, so no need to - // handle - // rules - reader = new RuleBasedConfigReader<>((tokenizer, statePair) -> { - // Don't need to do anything on rule start - }, (tokenizer, state) -> { - // Don't need to do anything on rule continuation - }, (state) -> { - // Don't need to do anything on rule end - }); - - setupReaderPragmas(); - } - - /** - * Parse a component description from a stream - * - * @param inputSource - * The stream to parse from - * @return The description parsed from the stream - */ - public static ComponentDescription fromStream(final InputStream inputSource) { - if (inputSource == null) throw new NullPointerException("Input source must not be null"); - - final ComponentDescriptionState readState = reader.fromStream(inputSource, - new ComponentDescriptionState()); - - return readState.toDescription(); - } - - /* - * Create all the pragmas the reader needs to function - */ - private static void setupReaderPragmas() { - reader.addPragma("name", buildStringCollapser("name", (name, state) -> state.setName(name))); - - reader.addPragma("author", buildStringCollapser("author", (author, state) -> state.setAuthor(author))); - - reader.addPragma("description", buildStringCollapser("description", - (description, state) -> state.setDescription(description))); - - reader.addPragma("version", buildInteger("version", (version, state) -> state.setVersion(version))); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/components/ComponentDescriptionState.java b/BJC-Utils2/src/main/java/bjc/utils/components/ComponentDescriptionState.java deleted file mode 100644 index 8d66f85..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/components/ComponentDescriptionState.java +++ /dev/null @@ -1,144 +0,0 @@ -package bjc.utils.components; - -/** - * Internal state of component description parser - * - * @author ben - * - */ -public class ComponentDescriptionState { - // Tentative name of this component - private String name; - - // Tentative description of this componet - private String description; - - // Tentative author of this component - private String author; - - // Tentative version of this component - private int version; - - /** - * Set the author of this component - * - * @param author - * The author of this component - */ - public void setAuthor(final String author) { - this.author = author; - } - - /** - * Set the description of this component - * - * @param description - * The description of this component - */ - public void setDescription(final String description) { - this.description = description; - } - - /** - * Set the name of this component - * - * @param name - * The name of this component - */ - public void setName(final String name) { - this.name = name; - } - - /** - * Set the version of this component - * - * @param version - * The version of this component - */ - public void setVersion(final int version) { - this.version = version; - } - - /** - * Convert this state into the description it represents - * - * @return The description represented by this state - */ - public ComponentDescription toDescription() { - return new ComponentDescription(name, author, description, version); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - - result = prime * result + (author == null ? 0 : author.hashCode()); - result = prime * result + (description == null ? 0 : description.hashCode()); - result = prime * result + (name == null ? 0 : name.hashCode()); - result = prime * result + version; - - return result; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) return true; - if (obj == null) return false; - if (getClass() != obj.getClass()) return false; - - final ComponentDescriptionState other = (ComponentDescriptionState) obj; - - if (author == null) { - if (other.author != null) return false; - } else if (!author.equals(other.author)) return false; - - if (description == null) { - if (other.description != null) return false; - } else if (!description.equals(other.description)) return false; - - if (name == null) { - if (other.name != null) return false; - } else if (!name.equals(other.name)) return false; - - if (version != other.version) return false; - - return true; - } - - /* - * (non-Javadoc) - * - * @see java.lang.Object#toString() - */ - @Override - public String toString() { - final StringBuilder builder = new StringBuilder(); - builder.append("ComponentDescriptionState ["); - - if (name != null) { - builder.append("name="); - builder.append(name); - builder.append(", "); - } - - if (description != null) { - builder.append("description="); - builder.append(description); - builder.append(", "); - } - - if (author != null) { - builder.append("author="); - builder.append(author); - builder.append(", "); - } - - builder.append("version="); - builder.append(version); - builder.append("]"); - - return builder.toString(); - } - -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/components/FileComponentRepository.java b/BJC-Utils2/src/main/java/bjc/utils/components/FileComponentRepository.java deleted file mode 100644 index efde5c7..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/components/FileComponentRepository.java +++ /dev/null @@ -1,181 +0,0 @@ -package bjc.utils.components; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Path; -import java.nio.file.attribute.BasicFileAttributes; -import java.util.function.BiPredicate; -import java.util.function.Function; -import java.util.logging.Level; -import java.util.logging.Logger; - -import bjc.utils.data.IHolder; -import bjc.utils.data.Identity; -import bjc.utils.funcdata.FunctionalMap; -import bjc.utils.funcdata.IList; -import bjc.utils.funcdata.IMap; -import bjc.utils.funcutils.FileUtils; - -/** - * A component repository that loads its components from files in a directory - * - * @author ben - * - * @param <ComponentType> - * The type of component being read in - */ -public class FileComponentRepository<ComponentType extends IDescribedComponent> - implements IComponentRepository<ComponentType> { - // The logger to use for storing data about this class - private static final Logger CLASS_LOGGER = Logger.getLogger("FileComponentRepository"); - - // The internal storage of components - private IMap<String, ComponentType> components; - - // The path that all the components came from - private Path sourceDirectory; - - /** - * Create a new component repository sourcing components from files in a - * directory - * - * An exception thrown during the loading of a component will only cause - * the loading of that component to fail, but a warning will be logged. - * - * @param directory - * The directory to read component files from - * @param componentReader - * The function to use to convert files to components - */ - public FileComponentRepository(final File directory, - final Function<File, ? extends ComponentType> componentReader) { - // Make sure we have valid arguments - if (directory == null) - throw new NullPointerException("Directory must not be null"); - else if (!directory.isDirectory()) - throw new IllegalArgumentException("File " + directory + " is not a directory.\n" - + "Components can only be read from a directory"); - else if (componentReader == null) throw new NullPointerException("Component reader must not be null"); - - // Initialize our fields - components = new FunctionalMap<>(); - sourceDirectory = directory.toPath().toAbsolutePath(); - - // Marker for making sure we don't skip the parent - final IHolder<Boolean> isFirstDir = new Identity<>(true); - - // Predicate to use to traverse all the files in a directory, - // but - // not recurse into sub-directories - final BiPredicate<Path, BasicFileAttributes> firstLevelTraverser = (pth, attr) -> { - if (attr.isDirectory() && !isFirstDir.getValue()) /* - * Skip - * directories, - * they - * probably - * have - * component - * support - * files. - */ - return false; - - /* - * Don't skip the first directory, that's the parent - * directory - */ - isFirstDir.replace(false); - - return true; - }; - - // Try reading components - try { - FileUtils.traverseDirectory(sourceDirectory, firstLevelTraverser, (pth, attr) -> { - loadComponent(componentReader, pth); - - // Keep loading components, even if this one - // failed - return true; - }); - } catch (final IOException ioex) { - CLASS_LOGGER.log(Level.WARNING, ioex, () -> "Error found reading component from file."); - } - } - - @Override - public IMap<String, ComponentType> getAll() { - return components; - } - - @Override - public ComponentType getByName(final String name) { - return components.get(name); - } - - @Override - public IList<ComponentType> getList() { - return components.valueList(); - } - - @Override - public String getSource() { - return "Components read from directory " + sourceDirectory + "."; - } - - /* - * Load a component from a file - */ - private void loadComponent(final Function<File, ? extends ComponentType> componentReader, final Path pth) { - try { - // Try to load the component - final ComponentType component = componentReader.apply(pth.toFile()); - - if (component == null) - throw new NullPointerException("Component reader read null component"); - else if (!components.containsKey(component.getName())) { - // We only care about the latest version of a - // component - final ComponentType oldComponent = components.put(component.getName(), component); - - if (oldComponent.getVersion() > component.getVersion()) { - components.put(oldComponent.getName(), oldComponent); - } - } else { - CLASS_LOGGER.warning("Found a duplicate component.\n" - + "Multiple versions of the same component are not currently supported.\n" - + "Only the latest version of the component" + component - + " will be registered ."); - } - } catch (final Exception ex) { - CLASS_LOGGER.log(Level.WARNING, ex, () -> "Error found reading component from file " - + pth.toString() + ". This component will not be loaded"); - } - } - - /* - * (non-Javadoc) - * - * @see java.lang.Object#toString() - */ - @Override - public String toString() { - final StringBuilder builder = new StringBuilder(); - builder.append("FileComponentRepository ["); - - if (components != null) { - builder.append("components="); - builder.append(components); - builder.append(", "); - } - - if (sourceDirectory != null) { - builder.append("sourceDirectory="); - builder.append(sourceDirectory); - } - - builder.append("]"); - - return builder.toString(); - } -}
\ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/components/IComponentRepository.java b/BJC-Utils2/src/main/java/bjc/utils/components/IComponentRepository.java deleted file mode 100644 index 6ee51f3..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/components/IComponentRepository.java +++ /dev/null @@ -1,49 +0,0 @@ -package bjc.utils.components; - -import bjc.utils.funcdata.IList; -import bjc.utils.funcdata.IMap; - -/** - * A collection of implementations of a particular type of - * {@link IDescribedComponent} - * - * @author ben - * - * @param <ComponentType> - * The type of components contained in this repository - */ -public interface IComponentRepository<ComponentType extends IDescribedComponent> { - /** - * Get all of the components this repository knows about - * - * @return A map from component name to component, containing all of the - * components in the repositories - */ - public IMap<String, ComponentType> getAll(); - - /** - * Get a component with a specific name - * - * @param name - * The name of the component to retrieve - * @return The named component, or null if no component with that name - * exists - */ - public ComponentType getByName(String name); - - /** - * Get a list of all the registered components - * - * @return A list of all the registered components - */ - public default IList<ComponentType> getList() { - return getAll().valueList(); - } - - /** - * Get the source from which these components came - * - * @return The source from which these components came - */ - public String getSource(); -}
\ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/components/IDescribedComponent.java b/BJC-Utils2/src/main/java/bjc/utils/components/IDescribedComponent.java deleted file mode 100644 index 952b375..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/components/IDescribedComponent.java +++ /dev/null @@ -1,64 +0,0 @@ -package bjc.utils.components; - -/** - * Represents a optional component that has status information associated with - * it - * - * @author ben - * - */ -public interface IDescribedComponent extends Comparable<IDescribedComponent> { - /** - * Get the author of this component - * - * Providing this is optional, with "Anonymous" as the default author - * - * @return The author of the component - */ - default String getAuthor() { - return "Anonymous"; - } - - /** - * Get the description of this component - * - * Providing this is optional, with the default being a note that no - * description was provided - * - * @return The description of the component - */ - default String getDescription() { - return "No description provided."; - } - - /** - * Get the name of this component. - * - * This is the only thing required of all components - * - * @return The name of the component - */ - String getName(); - - /** - * Get the version of this component - * - * Providing this is optional, with "1" as the default version - * - * @return The version of this component - */ - default int getVersion() { - return 1; - } - - @Override - default int compareTo(final IDescribedComponent o) { - int res = getName().compareTo(o.getName()); - - if (res == 0) { - res = getVersion() - o.getVersion(); - } - - return res; - } -}
\ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/BooleanToggle.java b/BJC-Utils2/src/main/java/bjc/utils/data/BooleanToggle.java deleted file mode 100644 index 12e3b2e..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/data/BooleanToggle.java +++ /dev/null @@ -1,76 +0,0 @@ -package bjc.utils.data; - -/** - * A simple {@link ValueToggle} that swaps between true and false. - * - * @author EVE - * - */ -public class BooleanToggle implements Toggle<Boolean> { - private boolean val; - - /** - * Create a new, initially false, flip-flop. - */ - public BooleanToggle() { - this(false); - } - - /** - * Create a flip-flop with the specified initial value. - * - * @param initial - * The initial value of the flip-flop. - */ - public BooleanToggle(final boolean initial) { - val = initial; - } - - @Override - public Boolean get() { - final boolean res = val; - - val = !res; - - return res; - } - - @Override - public Boolean peek() { - return val; - } - - @Override - public void set(final boolean vl) { - val = vl; - } - - @Override - public int hashCode() { - final int prime = 31; - - int result = 1; - - result = prime * result + (val ? 1231 : 1237); - - return result; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) return true; - if (obj == null) return false; - if (!(obj instanceof BooleanToggle)) return false; - - final BooleanToggle other = (BooleanToggle) obj; - - if (val != other.val) return false; - - return true; - } - - @Override - public String toString() { - return String.format("BooleanToggle [val=%s]", val); - } -}
\ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/CircularIterator.java b/BJC-Utils2/src/main/java/bjc/utils/data/CircularIterator.java deleted file mode 100644 index a708eba..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/data/CircularIterator.java +++ /dev/null @@ -1,81 +0,0 @@ -package bjc.utils.data; - -import java.util.Iterator; - -/** - * An iterator that repeats elements from a provided iterable. - * - * @author EVE - * - * @param <E> - * The type of the iterable. - */ -public class CircularIterator<E> implements Iterator<E> { - /* - * The iterable, and our current iterator into it. - */ - private Iterable<E> source; - private Iterator<E> curr; - - /* - * Our current element. - */ - private E curElm; - - /* - * Should we actually get new iterators, or just repeat the last - * element? - */ - private boolean doCircle; - - /** - * Create a new circular iterator. - * - * @param src - * The iterable to iterate from. - * - * @param circ - * Should we actually do circular iteration, or just - * repeat the terminal element? - */ - public CircularIterator(final Iterable<E> src, final boolean circ) { - source = src; - curr = source.iterator(); - - doCircle = circ; - } - - /** - * Create a new circular iterator that does actual circular iteration. - * - * @param src - * The iterable to iterate from. - */ - public CircularIterator(final Iterable<E> src) { - this(src, true); - } - - @Override - public boolean hasNext() { - // We always have something - return true; - } - - @Override - public E next() { - if (!curr.hasNext()) { - if (doCircle) { - curr = source.iterator(); - } else return curElm; - } - - curElm = curr.next(); - - return curElm; - } - - @Override - public void remove() { - curr.remove(); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/Either.java b/BJC-Utils2/src/main/java/bjc/utils/data/Either.java deleted file mode 100644 index 36b3324..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/data/Either.java +++ /dev/null @@ -1,173 +0,0 @@ -package bjc.utils.data; - -import java.util.function.BiFunction; -import java.util.function.Function; - -/** - * Represents a pair where only one side has a value - * - * @author ben - * @param <LeftType> - * The type that could be on the left - * @param <RightType> - * The type that could be on the right - * - */ -public class Either<LeftType, RightType> implements IPair<LeftType, RightType> { - /** - * Create a new either with the left value occupied - * - * @param <LeftType> - * The type of the left value - * @param <RightType> - * The type of the empty right value - * @param left - * The value to put on the left - * @return An either with the left side occupied - */ - public static <LeftType, RightType> Either<LeftType, RightType> left(final LeftType left) { - return new Either<>(left, null); - } - - /** - * Create a new either with the right value occupied - * - * @param <LeftType> - * The type of the empty left value - * @param <RightType> - * The type of the right value - * @param right - * The value to put on the right - * @return An either with the right side occupied - */ - public static <LeftType, RightType> Either<LeftType, RightType> right(final RightType right) { - return new Either<>(null, right); - } - - private LeftType leftVal; - - private RightType rightVal; - - private boolean isLeft; - - private Either(final LeftType left, final RightType right) { - if (left == null) { - rightVal = right; - } else { - leftVal = left; - - isLeft = true; - } - } - - @Override - public <BoundLeft, BoundRight> IPair<BoundLeft, BoundRight> bind( - final BiFunction<LeftType, RightType, IPair<BoundLeft, BoundRight>> binder) { - if (binder == null) throw new NullPointerException("Binder must not be null"); - - return binder.apply(leftVal, rightVal); - } - - @Override - public <BoundLeft> IPair<BoundLeft, RightType> bindLeft( - final Function<LeftType, IPair<BoundLeft, RightType>> leftBinder) { - if (leftBinder == null) throw new NullPointerException("Left binder must not be null"); - - if (isLeft) return leftBinder.apply(leftVal); - - return new Either<>(null, rightVal); - } - - @Override - public <BoundRight> IPair<LeftType, BoundRight> bindRight( - final Function<RightType, IPair<LeftType, BoundRight>> rightBinder) { - if (rightBinder == null) throw new NullPointerException("Right binder must not be null"); - - if (isLeft) return new Either<>(leftVal, null); - - return rightBinder.apply(rightVal); - } - - @Override - public <OtherLeft, OtherRight, CombinedLeft, CombinedRight> IPair<CombinedLeft, CombinedRight> combine( - final IPair<OtherLeft, OtherRight> otherPair, - final BiFunction<LeftType, OtherLeft, CombinedLeft> leftCombiner, - final BiFunction<RightType, OtherRight, CombinedRight> rightCombiner) { - if (otherPair == null) - throw new NullPointerException("Other pair must not be null"); - else if (leftCombiner == null) - throw new NullPointerException("Left combiner must not be null"); - else if (rightCombiner == null) throw new NullPointerException("Right combiner must not be null"); - - if (isLeft) return otherPair.bind((otherLeft, otherRight) -> { - return new Either<>(leftCombiner.apply(leftVal, otherLeft), null); - }); - - return otherPair.bind((otherLeft, otherRight) -> { - return new Either<>(null, rightCombiner.apply(rightVal, otherRight)); - }); - } - - @Override - public <NewLeft> IPair<NewLeft, RightType> mapLeft(final Function<LeftType, NewLeft> mapper) { - if (mapper == null) throw new NullPointerException("Mapper must not be null"); - - if (isLeft) return new Either<>(mapper.apply(leftVal), null); - - return new Either<>(null, rightVal); - } - - @Override - public <NewRight> IPair<LeftType, NewRight> mapRight(final Function<RightType, NewRight> mapper) { - if (mapper == null) throw new NullPointerException("Mapper must not be null"); - - if (isLeft) return new Either<>(leftVal, null); - - return new Either<>(null, mapper.apply(rightVal)); - } - - @Override - public <MergedType> MergedType merge(final BiFunction<LeftType, RightType, MergedType> merger) { - if (merger == null) throw new NullPointerException("Merger must not be null"); - - return merger.apply(leftVal, rightVal); - } - - @Override - public int hashCode() { - final int prime = 31; - - int result = 1; - result = prime * result + (isLeft ? 1231 : 1237); - result = prime * result + (leftVal == null ? 0 : leftVal.hashCode()); - result = prime * result + (rightVal == null ? 0 : rightVal.hashCode()); - - return result; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) return true; - if (obj == null) return false; - if (!(obj instanceof Either<?, ?>)) return false; - - final Either<?, ?> other = (Either<?, ?>) obj; - - if (isLeft != other.isLeft) return false; - - if (leftVal == null) { - if (other.leftVal != null) return false; - } else if (!leftVal.equals(other.leftVal)) return false; - - if (rightVal == null) { - if (other.rightVal != null) return false; - } else if (!rightVal.equals(other.rightVal)) return false; - - return true; - } - - @Override - public String toString() { - return String.format("Either [leftVal='%s', rightVal='%s', isLeft=%s]", leftVal, rightVal, isLeft); - } -}
\ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/GeneratingIterator.java b/BJC-Utils2/src/main/java/bjc/utils/data/GeneratingIterator.java deleted file mode 100644 index 9abca7c..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/data/GeneratingIterator.java +++ /dev/null @@ -1,53 +0,0 @@ -package bjc.utils.data; - -import java.util.Iterator; -import java.util.function.Predicate; -import java.util.function.UnaryOperator; - -/** - * An iterator that generates a series of elements from a single element. - * - * @author bjculkin - * - * @param <E> - * The type of element generated. - */ -public class GeneratingIterator<E> implements Iterator<E> { - private E state; - - private UnaryOperator<E> transtion; - - private Predicate<E> stpper; - - /** - * Create a new generative iterator. - * - * @param initial - * The initial state of the generator. - * - * @param transition - * The function to apply to the state. - * - * @param stopper - * The predicate applied to the current state to - * determine when to stop. - */ - public GeneratingIterator(E initial, UnaryOperator<E> transition, Predicate<E> stopper) { - state = initial; - transtion = transition; - stpper = stopper; - } - - @Override - public boolean hasNext() { - return stpper.test(state); - } - - @Override - public E next() { - state = transtion.apply(state); - - return state; - } - -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/IHolder.java b/BJC-Utils2/src/main/java/bjc/utils/data/IHolder.java deleted file mode 100644 index ca0b2ba..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/data/IHolder.java +++ /dev/null @@ -1,153 +0,0 @@ -package bjc.utils.data; - -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.UnaryOperator; - -import bjc.utils.data.internals.BoundListHolder; -import bjc.utils.data.internals.WrappedLazy; -import bjc.utils.data.internals.WrappedOption; -import bjc.utils.funcdata.FunctionalList; -import bjc.utils.funcdata.theory.Functor; - -/** - * A holder of a single value. - * - * @author ben - * - * @param <ContainedType> - * The type of value held - */ -public interface IHolder<ContainedType> extends Functor<ContainedType> { - /** - * Bind a function across the value in this container - * - * @param <BoundType> - * The type of value in this container - * @param binder - * The function to bind to the value - * @return A holder from binding the value - */ - public <BoundType> IHolder<BoundType> bind(Function<ContainedType, IHolder<BoundType>> binder); - - /** - * Apply an action to the value - * - * @param action - * The action to apply to the value - */ - public default void doWith(final Consumer<? super ContainedType> action) { - transform(value -> { - action.accept(value); - - return value; - }); - } - - @Override - default <ArgType, ReturnType> Function<Functor<ArgType>, Functor<ReturnType>> fmap( - final Function<ArgType, ReturnType> func) { - return argumentFunctor -> { - if (!(argumentFunctor instanceof IHolder<?>)) { - final String msg = "This functor only supports mapping over instances of IHolder"; - - throw new IllegalArgumentException(msg); - } - - final IHolder<ArgType> holder = (IHolder<ArgType>) argumentFunctor; - - return holder.map(func); - }; - } - - @Override - public default ContainedType getValue() { - return unwrap(value -> value); - } - - /** - * Lifts a function to bind over this holder - * - * @param <NewType> - * The type of the functions return - * @param func - * The function to lift over the holder - * @return The function lifted over the holder - */ - public <NewType> Function<ContainedType, IHolder<NewType>> lift(Function<ContainedType, NewType> func); - - /** - * Make this holder lazy - * - * @return A lazy version of this holder - */ - public default IHolder<ContainedType> makeLazy() { - return new WrappedLazy<>(this); - } - - /** - * Make this holder a list - * - * @return A list version of this holder - */ - public default IHolder<ContainedType> makeList() { - return new BoundListHolder<>(new FunctionalList<>(this)); - } - - /** - * Make this holder optional - * - * @return An optional version of this holder - */ - public default IHolder<ContainedType> makeOptional() { - return new WrappedOption<>(this); - } - - /** - * Create a new holder with a mapped version of the value in this - * holder. - * - * Does not change the internal state of this holder - * - * @param <MappedType> - * The type of the mapped value - * @param mapper - * The function to do mapping with - * @return A holder with the mapped value - */ - public <MappedType> IHolder<MappedType> map(Function<ContainedType, MappedType> mapper); - - /** - * Replace the held value with a new one - * - * @param newValue - * The value to hold instead - * @return The holder itself - */ - public default IHolder<ContainedType> replace(final ContainedType newValue) { - return transform(oldValue -> { - return newValue; - }); - } - - /** - * Transform the value held in this holder - * - * @param transformer - * The function to transform the value with - * @return The holder itself, for easy chaining - */ - public IHolder<ContainedType> transform(UnaryOperator<ContainedType> transformer); - - /** - * Unwrap the value contained in this holder so that it is no longer - * held - * - * @param <UnwrappedType> - * The type of the unwrapped value - * @param unwrapper - * The function to use to unwrap the value - * @return The unwrapped held value - */ - public <UnwrappedType> UnwrappedType unwrap(Function<ContainedType, UnwrappedType> unwrapper); -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/IPair.java b/BJC-Utils2/src/main/java/bjc/utils/data/IPair.java deleted file mode 100644 index db8a1cb..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/data/IPair.java +++ /dev/null @@ -1,200 +0,0 @@ -package bjc.utils.data; - -import java.util.function.BiConsumer; -import java.util.function.BiFunction; -import java.util.function.Function; - -import bjc.utils.funcdata.theory.Bifunctor; - -/** - * Represents a pair of values - * - * @author ben - * @param <LeftType> - * The type of the left side of the pair - * @param <RightType> - * The type of the right side of the pair - * - */ -public interface IPair<LeftType, RightType> extends Bifunctor<LeftType, RightType> { - /** - * Bind a function across the values in this pair - * - * @param <BoundLeft> - * The type of the bound left - * @param <BoundRight> - * The type of the bound right - * @param binder - * The function to bind with - * @return The bound pair - */ - public <BoundLeft, BoundRight> IPair<BoundLeft, BoundRight> bind( - BiFunction<LeftType, RightType, IPair<BoundLeft, BoundRight>> binder); - - /** - * Bind a function to the left value in this pair - * - * @param <BoundLeft> - * The type of the bound value - * @param leftBinder - * The function to use to bind - * @return A pair with the left type bound - */ - public <BoundLeft> IPair<BoundLeft, RightType> bindLeft( - Function<LeftType, IPair<BoundLeft, RightType>> leftBinder); - - /** - * Bind a function to the right value in this pair - * - * @param <BoundRight> - * The type of the bound value - * @param rightBinder - * The function to use to bind - * @return A pair with the right type bound - */ - public <BoundRight> IPair<LeftType, BoundRight> bindRight( - Function<RightType, IPair<LeftType, BoundRight>> rightBinder); - - /** - * Pairwise combine two pairs together - * - * @param <OtherLeft> - * The left type of the other pair - * @param <OtherRight> - * The right type of the other pair - * @param otherPair - * The pair to combine with - * @return The pairs, pairwise combined together - */ - public default <OtherLeft, OtherRight> IPair<IPair<LeftType, OtherLeft>, IPair<RightType, OtherRight>> combine( - final IPair<OtherLeft, OtherRight> otherPair) { - return combine(otherPair, Pair<LeftType, OtherLeft>::new, Pair<RightType, OtherRight>::new); - } - - /** - * Combine the contents of two pairs together - * - * @param <OtherLeft> - * The type of the left value of the other pair - * @param <OtherRight> - * The type of the right value of the other pair - * @param <CombinedLeft> - * The type of the left value of the combined pair - * @param <CombinedRight> - * The type of the right value of the combined pair - * @param otherPair - * The other pair to combine with - * @param leftCombiner - * @param rightCombiner - * @return A pair with its values combined - */ - public <OtherLeft, OtherRight, CombinedLeft, CombinedRight> IPair<CombinedLeft, CombinedRight> combine( - IPair<OtherLeft, OtherRight> otherPair, - BiFunction<LeftType, OtherLeft, CombinedLeft> leftCombiner, - BiFunction<RightType, OtherRight, CombinedRight> rightCombiner); - - /** - * Immediately perfom the specified action with the contents of this - * pair - * - * @param consumer - * The action to perform on the pair - */ - public default void doWith(final BiConsumer<LeftType, RightType> consumer) { - merge((leftValue, rightValue) -> { - consumer.accept(leftValue, rightValue); - - return null; - }); - } - - @Override - default <OldLeft, OldRight, NewLeft> LeftBifunctorMap<OldLeft, OldRight, NewLeft> fmapLeft( - final Function<OldLeft, NewLeft> func) { - return argumentPair -> { - if (!(argumentPair instanceof IPair<?, ?>)) { - final String msg = "This function can only be applied to instances of IPair"; - - throw new IllegalArgumentException(msg); - } - - final IPair<OldLeft, OldRight> argPair = (IPair<OldLeft, OldRight>) argumentPair; - - return argPair.mapLeft(func); - }; - } - - @Override - default <OldLeft, OldRight, NewRight> RightBifunctorMap<OldLeft, OldRight, NewRight> - - fmapRight(final Function<OldRight, NewRight> func) { - return argumentPair -> { - if (!(argumentPair instanceof IPair<?, ?>)) { - final String msg = "This function can only be applied to instances of IPair"; - - throw new IllegalArgumentException(msg); - } - - final IPair<OldLeft, OldRight> argPair = (IPair<OldLeft, OldRight>) argumentPair; - - return argPair.mapRight(func); - }; - } - - /** - * Get the value on the left side of the pair - * - * @return The value on the left side of the pair - */ - @Override - public default LeftType getLeft() { - return merge((leftValue, rightValue) -> leftValue); - } - - /** - * Get the value on the right side of the pair - * - * @return The value on the right side of the pair - */ - @Override - public default RightType getRight() { - return merge((leftValue, rightValue) -> rightValue); - } - - /** - * Transform the value on the left side of the pair. Doesn't modify the - * pair - * - * @param <NewLeft> - * The new type of the left part of the pair - * @param mapper - * The function to use to transform the left part of the - * pair - * @return The pair, with its left part transformed - */ - public <NewLeft> IPair<NewLeft, RightType> mapLeft(Function<LeftType, NewLeft> mapper); - - /** - * Transform the value on the right side of the pair. Doesn't modify the - * pair - * - * @param <NewRight> - * The new type of the right part of the pair - * @param mapper - * The function to use to transform the right part of the - * pair - * @return The pair, with its right part transformed - */ - public <NewRight> IPair<LeftType, NewRight> mapRight(Function<RightType, NewRight> mapper); - - /** - * Merge the two values in this pair into a single value - * - * @param <MergedType> - * The type of the single value - * @param merger - * The function to use for merging - * @return The pair, merged into a single value - */ - public <MergedType> MergedType merge(BiFunction<LeftType, RightType, MergedType> merger); -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/ITree.java b/BJC-Utils2/src/main/java/bjc/utils/data/ITree.java deleted file mode 100644 index ff374e8..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/data/ITree.java +++ /dev/null @@ -1,234 +0,0 @@ -package bjc.utils.data; - -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Predicate; -import java.util.function.UnaryOperator; - -import bjc.utils.funcdata.bst.TreeLinearizationMethod; -import bjc.utils.functypes.ListFlattener; - -/** - * A node in a homogeneous tree with a unlimited amount of children. - * - * @author ben - * - * @param <ContainedType> - * The type of data contained in the tree nodes. - * - */ -public interface ITree<ContainedType> { - /** - * Append a child to this node. - * - * @param child - * The child to append to this node. - */ - void addChild(ITree<ContainedType> child); - - /** - * Prepend a child to this node. - * - * @param child - * The child to prepend to this node. - */ - void prependChild(ITree<ContainedType> child); - - /** - * Collapse a tree into a single version. - * - * @param <NewType> - * The intermediate type being folded. - * - * @param <ReturnedType> - * The type that is the end result. - * - * @param leafTransform - * The function to use to convert leaf values. - * - * @param nodeCollapser - * The function to use to convert internal nodes and - * their children. - * - * @param resultTransformer - * The function to use to convert a state to the returned - * version. - * - * @return The final transformed state. - */ - <NewType, ReturnedType> ReturnedType collapse(Function<ContainedType, NewType> leafTransform, - Function<ContainedType, ListFlattener<NewType>> nodeCollapser, - Function<NewType, ReturnedType> resultTransformer); - - /** - * Execute a given action for each of this tree's children. - * - * @param action - * The action to execute for each child. - */ - void doForChildren(Consumer<ITree<ContainedType>> action); - - /** - * Expand the nodes of a tree into trees, and then merge the contents of - * those trees into a single tree. - * - * @param mapper - * The function to use to map values into trees. - * - * @return A tree, with some nodes expanded into trees. - */ - default ITree<ContainedType> flatMapTree(final Function<ContainedType, ITree<ContainedType>> mapper) { - return topDownTransform(dat -> TopDownTransformResult.PUSHDOWN, node -> { - if (node.getChildrenCount() > 0) { - final ITree<ContainedType> parent = node.transformHead(mapper); - - node.doForChildren(parent::addChild); - - return parent; - } - - return node.transformHead(mapper); - }); - } - - /** - * Get the specified child of this tree. - * - * @param childNo - * The number of the child to get. - * - * @return The specified child of this tree. - */ - default ITree<ContainedType> getChild(final int childNo) { - return transformChild(childNo, child -> child); - } - - /** - * Get a count of the number of direct children this node has. - * - * @return The number of direct children this node has. - */ - int getChildrenCount(); - - /** - * Get the data stored in this node. - * - * @return The data stored in this node. - */ - default ContainedType getHead() { - return transformHead(head -> head); - } - - /** - * Rebuild the tree with the same structure, but different nodes. - * - * @param <MappedType> - * The type of the new tree. - * - * @param leafTransformer - * The function to use to transform leaf tokens. - * - * @param operatorTransformer - * The function to use to transform internal tokens. - * - * @return The tree, with the nodes changed. - */ - <MappedType> ITree<MappedType> rebuildTree(Function<ContainedType, MappedType> leafTransformer, - Function<ContainedType, MappedType> operatorTransformer); - - /** - * Transform some of the nodes in this tree. - * - * @param nodePicker - * The predicate to use to pick nodes to transform. - * - * @param transformer - * The function to use to transform picked nodes. - */ - void selectiveTransform(Predicate<ContainedType> nodePicker, UnaryOperator<ContainedType> transformer); - - /** - * Do a top-down transform of the tree. - * - * @param transformPicker - * The function to use to pick how to progress. - * - * @param transformer - * The function used to transform picked subtrees. - * - * @return The tree with the transform applied to picked subtrees. - */ - ITree<ContainedType> topDownTransform(Function<ContainedType, TopDownTransformResult> transformPicker, - UnaryOperator<ITree<ContainedType>> transformer); - - /** - * Transform one of this nodes children. - * - * @param <TransformedType> - * The type of the transformed value. - * - * @param childNo - * The number of the child to transform. - * - * @param transformer - * The function to use to transform the value. - * - * @return The transformed value. - * - * @throws IllegalArgumentException - * if the childNo is out of bounds (0 <= childNo <= - * childCount()). - */ - <TransformedType> TransformedType transformChild(int childNo, - Function<ITree<ContainedType>, TransformedType> transformer); - - /** - * Transform the value that is the head of this node. - * - * @param <TransformedType> - * The type of the transformed value. - * - * @param transformer - * The function to use to transform the value. - * - * @return The transformed value. - */ - <TransformedType> TransformedType transformHead(Function<ContainedType, TransformedType> transformer); - - /** - * Transform the tree into a tree with a different type of token. - * - * @param <MappedType> - * The type of the new tree. - * - * @param transformer - * The function to use to transform tokens. - * - * @return A tree with the token types transformed. - */ - default <MappedType> ITree<MappedType> transformTree(final Function<ContainedType, MappedType> transformer) { - return rebuildTree(transformer, transformer); - } - - /** - * Perform an action on each part of the tree. - * - * @param linearizationMethod - * The way to traverse the tree. - * - * @param action - * The action to perform on each tree node. - */ - void traverse(TreeLinearizationMethod linearizationMethod, Consumer<ContainedType> action); - - /** - * Find the farthest to right child that satisfies the given predicate. - * - * @param childPred - * The predicate to satisfy. - * - * @return The index of the right-most child that satisfies the - * predicate, or -1 if one doesn't exist. - */ - int revFind(Predicate<ITree<ContainedType>> childPred); -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/Identity.java b/BJC-Utils2/src/main/java/bjc/utils/data/Identity.java deleted file mode 100644 index a8c8d70..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/data/Identity.java +++ /dev/null @@ -1,118 +0,0 @@ -package bjc.utils.data; - -import java.util.function.Function; -import java.util.function.UnaryOperator; - -/** - * @author ben - * - * @param <ContainedType> - */ -/** - * Simple implementation of IHolder that has no hidden behavior - * - * @author ben - * - * @param <ContainedType> - * The type contained in the holder - */ -public class Identity<ContainedType> implements IHolder<ContainedType> { - private ContainedType heldValue; - - /** - * Create a holder holding null - */ - public Identity() { - heldValue = null; - } - - /** - * Create a holder holding the specified value - * - * @param value - * The value to hold - */ - public Identity(final ContainedType value) { - heldValue = value; - } - - @Override - public <BoundType> IHolder<BoundType> bind(final Function<ContainedType, IHolder<BoundType>> binder) { - return binder.apply(heldValue); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - - result = prime * result + (heldValue == null ? 0 : heldValue.hashCode()); - - return result; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) return true; - if (obj == null) return false; - if (!(obj instanceof Identity)) return false; - - final Identity<?> other = (Identity<?>) obj; - - if (heldValue == null) { - if (other.heldValue != null) return false; - } else if (!heldValue.equals(other.heldValue)) return false; - - return true; - } - - @Override - public <NewType> Function<ContainedType, IHolder<NewType>> lift(final Function<ContainedType, NewType> func) { - return (val) -> { - return new Identity<>(func.apply(val)); - }; - } - - @Override - public <MappedType> IHolder<MappedType> map(final Function<ContainedType, MappedType> mapper) { - return new Identity<>(mapper.apply(heldValue)); - } - - @Override - public String toString() { - return String.format("Identity [heldValue=%s]", heldValue); - } - - @Override - public IHolder<ContainedType> transform(final UnaryOperator<ContainedType> transformer) { - heldValue = transformer.apply(heldValue); - - return this; - } - - @Override - public <UnwrappedType> UnwrappedType unwrap(final Function<ContainedType, UnwrappedType> unwrapper) { - return unwrapper.apply(heldValue); - } - - /** - * Create a new identity container. - * - * @param val - * The contained value. - * - * @return A new identity container. - */ - public static <ContainedType> Identity<ContainedType> id(final ContainedType val) { - return new Identity<>(val); - } - - /** - * Create a new empty identity container. - * - * @return A new empty identity container. - */ - public static <ContainedType> Identity<ContainedType> id() { - return new Identity<>(); - } -}
\ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/Lazy.java b/BJC-Utils2/src/main/java/bjc/utils/data/Lazy.java deleted file mode 100644 index ca41b62..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/data/Lazy.java +++ /dev/null @@ -1,194 +0,0 @@ -package bjc.utils.data; - -import java.util.function.Function; -import java.util.function.Supplier; -import java.util.function.UnaryOperator; - -import bjc.utils.data.internals.BoundLazy; -import bjc.utils.funcdata.FunctionalList; -import bjc.utils.funcdata.IList; - -/** - * A holder that holds a means to create a value, but doesn't actually compute - * the value until it's needed - * - * @author ben - * - * @param <ContainedType> - */ -public class Lazy<ContainedType> implements IHolder<ContainedType> { - private Supplier<ContainedType> valueSupplier; - - private IList<UnaryOperator<ContainedType>> actions = new FunctionalList<>(); - - private boolean valueMaterialized; - - private ContainedType heldValue; - - /** - * Create a new lazy value from the specified seed value - * - * @param value - * The seed value to use - */ - public Lazy(final ContainedType value) { - heldValue = value; - - valueMaterialized = true; - } - - /** - * Create a new lazy value from the specified value source - * - * @param supp - * The source of a value to use - */ - public Lazy(final Supplier<ContainedType> supp) { - valueSupplier = new SingleSupplier<>(supp); - - valueMaterialized = false; - } - - private Lazy(final Supplier<ContainedType> supp, final IList<UnaryOperator<ContainedType>> pendingActions) { - valueSupplier = supp; - - actions = pendingActions; - } - - @Override - public <BoundType> IHolder<BoundType> bind(final Function<ContainedType, IHolder<BoundType>> binder) { - final IList<UnaryOperator<ContainedType>> pendingActions = new FunctionalList<>(); - - actions.forEach(pendingActions::add); - - final Supplier<ContainedType> supplier = () -> { - if (valueMaterialized) return heldValue; - - return valueSupplier.get(); - }; - - return new BoundLazy<>(() -> { - return new Lazy<>(supplier, pendingActions); - }, binder); - } - - @Override - public <NewType> Function<ContainedType, IHolder<NewType>> lift(final Function<ContainedType, NewType> func) { - return val -> { - return new Lazy<>(func.apply(val)); - }; - } - - @Override - public <MappedType> IHolder<MappedType> map(final Function<ContainedType, MappedType> mapper) { - final IList<UnaryOperator<ContainedType>> pendingActions = new FunctionalList<>(); - - actions.forEach(pendingActions::add); - - return new Lazy<>(() -> { - ContainedType currVal = heldValue; - - if (!valueMaterialized) { - currVal = valueSupplier.get(); - } - - return pendingActions.reduceAux(currVal, UnaryOperator<ContainedType>::apply, - value -> mapper.apply(value)); - }); - } - - @Override - public String toString() { - if (valueMaterialized) { - if (actions.isEmpty()) - return String.format("value[v='%s']", heldValue); - else return String.format("value[v='%s'] (has pending transforms)", heldValue); - } - - return "(unmaterialized)"; - } - - @Override - public IHolder<ContainedType> transform(final UnaryOperator<ContainedType> transformer) { - actions.add(transformer); - - return this; - } - - @Override - public <UnwrappedType> UnwrappedType unwrap(final Function<ContainedType, UnwrappedType> unwrapper) { - if (!valueMaterialized) { - heldValue = valueSupplier.get(); - - valueMaterialized = true; - } - - actions.forEach(action -> { - heldValue = action.apply(heldValue); - }); - - actions = new FunctionalList<>(); - - return unwrapper.apply(heldValue); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - - result = prime * result + (actions == null ? 0 : actions.hashCode()); - result = prime * result + (heldValue == null ? 0 : heldValue.hashCode()); - result = prime * result + (valueMaterialized ? 1231 : 1237); - - return result; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) return true; - if (obj == null) return false; - if (!(obj instanceof Lazy<?>)) return false; - - final Lazy<?> other = (Lazy<?>) obj; - - if (valueMaterialized != other.valueMaterialized) return false; - - if (valueMaterialized) { - if (heldValue == null) { - if (other.heldValue != null) return false; - } else if (!heldValue.equals(other.heldValue)) return false; - } else return false; - - if (actions == null) { - if (other.actions != null) return false; - } else if (actions.getSize() > 0 || other.actions.getSize() > 0) return false; - - return true; - } - - /** - * Create a new lazy container with an already present value. - * - * @param val - * The value for the lazy container. - * - * @return A new lazy container holding that value. - */ - public static <ContainedType> Lazy<ContainedType> lazy(final ContainedType val) { - return new Lazy<>(val); - } - - /** - * Create a new lazy container with a suspended value. - * - * @param supp - * The suspended value for the lazy container. - * - * @return A new lazy container that will un-suspend the value when - * necessary. - */ - public static <ContainedType> Lazy<ContainedType> lazy(final Supplier<ContainedType> supp) { - return new Lazy<>(supp); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/LazyPair.java b/BJC-Utils2/src/main/java/bjc/utils/data/LazyPair.java deleted file mode 100644 index 5cb85f3..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/data/LazyPair.java +++ /dev/null @@ -1,240 +0,0 @@ -package bjc.utils.data; - -import java.util.function.BiFunction; -import java.util.function.Function; -import java.util.function.Supplier; - -import bjc.utils.data.internals.BoundLazyPair; -import bjc.utils.data.internals.HalfBoundLazyPair; - -/** - * A lazy implementation of a pair - * - * @author ben - * - * @param <LeftType> - * The type on the left side of the pair - * @param <RightType> - * The type on the right side of the pair - * - */ -public class LazyPair<LeftType, RightType> implements IPair<LeftType, RightType> { - private LeftType leftValue; - private RightType rightValue; - - private Supplier<LeftType> leftSupplier; - private Supplier<RightType> rightSupplier; - - private boolean leftMaterialized; - private boolean rightMaterialized; - - /** - * Create a new lazy pair, using the set values - * - * @param leftVal - * The value for the left side of the pair - * @param rightVal - * The value for the right side of the pair - */ - public LazyPair(final LeftType leftVal, final RightType rightVal) { - leftValue = leftVal; - rightValue = rightVal; - - leftMaterialized = true; - rightMaterialized = true; - } - - /** - * Create a new lazy pair from the given value sources - * - * @param leftSupp - * The source for a value on the left side of the pair - * @param rightSupp - * The source for a value on the right side of the pair - */ - public LazyPair(final Supplier<LeftType> leftSupp, final Supplier<RightType> rightSupp) { - // Use single suppliers to catch double-instantiation bugs - leftSupplier = new SingleSupplier<>(leftSupp); - rightSupplier = new SingleSupplier<>(rightSupp); - - leftMaterialized = false; - rightMaterialized = false; - } - - @Override - public <BoundLeft, BoundRight> IPair<BoundLeft, BoundRight> bind( - final BiFunction<LeftType, RightType, IPair<BoundLeft, BoundRight>> binder) { - return new BoundLazyPair<>(leftSupplier, rightSupplier, binder); - } - - @Override - public <BoundLeft> IPair<BoundLeft, RightType> bindLeft( - final Function<LeftType, IPair<BoundLeft, RightType>> leftBinder) { - final Supplier<LeftType> leftSupp = () -> { - if (leftMaterialized) return leftValue; - - return leftSupplier.get(); - }; - - return new HalfBoundLazyPair<>(leftSupp, leftBinder); - } - - @Override - public <BoundRight> IPair<LeftType, BoundRight> bindRight( - final Function<RightType, IPair<LeftType, BoundRight>> rightBinder) { - final Supplier<RightType> rightSupp = () -> { - if (rightMaterialized) return rightValue; - - return rightSupplier.get(); - }; - - return new HalfBoundLazyPair<>(rightSupp, rightBinder); - } - - @Override - public <OtherLeft, OtherRight, CombinedLeft, CombinedRight> IPair<CombinedLeft, CombinedRight> combine( - final IPair<OtherLeft, OtherRight> otherPair, - final BiFunction<LeftType, OtherLeft, CombinedLeft> leftCombiner, - final BiFunction<RightType, OtherRight, CombinedRight> rightCombiner) { - return otherPair.bind((otherLeft, otherRight) -> { - return bind((leftVal, rightVal) -> { - final CombinedLeft left = leftCombiner.apply(leftVal, otherLeft); - final CombinedRight right = rightCombiner.apply(rightVal, otherRight); - - return new LazyPair<>(left, right); - }); - }); - } - - @Override - public LeftType getLeft() { - if (!leftMaterialized) { - leftValue = leftSupplier.get(); - - leftMaterialized = true; - } - - return leftValue; - } - - @Override - public RightType getRight() { - if (!rightMaterialized) { - rightValue = rightSupplier.get(); - - rightMaterialized = true; - } - - return rightValue; - } - - @Override - public <NewLeft> IPair<NewLeft, RightType> mapLeft(final Function<LeftType, NewLeft> mapper) { - final Supplier<NewLeft> leftSupp = () -> { - if (leftMaterialized) return mapper.apply(leftValue); - - return mapper.apply(leftSupplier.get()); - }; - - final Supplier<RightType> rightSupp = () -> { - if (rightMaterialized) return rightValue; - - return rightSupplier.get(); - }; - - return new LazyPair<>(leftSupp, rightSupp); - } - - @Override - public <NewRight> IPair<LeftType, NewRight> mapRight(final Function<RightType, NewRight> mapper) { - final Supplier<LeftType> leftSupp = () -> { - if (leftMaterialized) return leftValue; - - return leftSupplier.get(); - }; - - final Supplier<NewRight> rightSupp = () -> { - if (rightMaterialized) return mapper.apply(rightValue); - - return mapper.apply(rightSupplier.get()); - }; - - return new LazyPair<>(leftSupp, rightSupp); - } - - @Override - public <MergedType> MergedType merge(final BiFunction<LeftType, RightType, MergedType> merger) { - if (!leftMaterialized) { - leftValue = leftSupplier.get(); - - leftMaterialized = true; - } - - if (!rightMaterialized) { - rightValue = rightSupplier.get(); - - rightMaterialized = true; - } - - return merger.apply(leftValue, rightValue); - } - - @Override - public String toString() { - String leftVal; - String rightVal; - - if (leftMaterialized) { - leftVal = leftValue.toString(); - } else { - leftVal = "(un-materialized)"; - } - - if (rightMaterialized) { - rightVal = rightValue.toString(); - } else { - rightVal = "(un-materialized)"; - } - - return String.format("pair[l=%s,r=%s]", leftVal, rightVal); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - - result = prime * result + (leftMaterialized ? 1231 : 1237); - result = prime * result + (leftValue == null ? 0 : leftValue.hashCode()); - result = prime * result + (rightMaterialized ? 1231 : 1237); - result = prime * result + (rightValue == null ? 0 : rightValue.hashCode()); - - return result; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) return true; - if (obj == null) return false; - if (!(obj instanceof LazyPair<?, ?>)) return false; - - final LazyPair<?, ?> other = (LazyPair<?, ?>) obj; - - if (leftMaterialized != other.leftMaterialized) return false; - - if (leftMaterialized) { - if (leftValue == null) { - if (other.leftValue != null) return false; - } else if (!leftValue.equals(other.leftValue)) return false; - } else return false; - - if (rightMaterialized != other.rightMaterialized) return false; - if (rightMaterialized) { - if (rightValue == null) { - if (other.rightValue != null) return false; - } else if (!rightValue.equals(other.rightValue)) return false; - } else return false; - - return true; - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/ListHolder.java b/BJC-Utils2/src/main/java/bjc/utils/data/ListHolder.java deleted file mode 100644 index 142057c..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/data/ListHolder.java +++ /dev/null @@ -1,104 +0,0 @@ -package bjc.utils.data; - -import java.util.function.Function; -import java.util.function.UnaryOperator; - -import bjc.utils.data.internals.BoundListHolder; -import bjc.utils.funcdata.FunctionalList; -import bjc.utils.funcdata.IList; - -/** - * A holder that represents a set of non-deterministic computations - * - * @author ben - * - * @param <ContainedType> - * The type of contained value - */ -public class ListHolder<ContainedType> implements IHolder<ContainedType> { - private IList<ContainedType> heldValues; - - /** - * Create a new list holder - * - * @param values - * The possible values for the computation - */ - @SafeVarargs - public ListHolder(final ContainedType... values) { - heldValues = new FunctionalList<>(); - - if (values != null) { - for (final ContainedType containedValue : values) { - heldValues.add(containedValue); - } - } - } - - private ListHolder(final IList<ContainedType> toHold) { - heldValues = toHold; - } - - @Override - public <BoundType> IHolder<BoundType> bind(final Function<ContainedType, IHolder<BoundType>> binder) { - final IList<IHolder<BoundType>> boundValues = heldValues.map(binder); - - return new BoundListHolder<>(boundValues); - } - - @Override - public <NewType> Function<ContainedType, IHolder<NewType>> lift(final Function<ContainedType, NewType> func) { - return val -> { - return new ListHolder<>(new FunctionalList<>(func.apply(val))); - }; - } - - @Override - public <MappedType> IHolder<MappedType> map(final Function<ContainedType, MappedType> mapper) { - final IList<MappedType> mappedValues = heldValues.map(mapper); - - return new ListHolder<>(mappedValues); - } - - @Override - public IHolder<ContainedType> transform(final UnaryOperator<ContainedType> transformer) { - heldValues = heldValues.map(transformer); - - return this; - } - - @Override - public <UnwrappedType> UnwrappedType unwrap(final Function<ContainedType, UnwrappedType> unwrapper) { - return unwrapper.apply(heldValues.randItem()); - } - - @Override - public String toString() { - return String.format("ListHolder [heldValues=%s]", heldValues); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - - result = prime * result + (heldValues == null ? 0 : heldValues.hashCode()); - - return result; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) return true; - if (obj == null) return false; - if (!(obj instanceof ListHolder<?>)) return false; - - final ListHolder<?> other = (ListHolder<?>) obj; - - if (heldValues == null) { - if (other.heldValues != null) return false; - } else if (!heldValues.equals(other.heldValues)) return false; - - return true; - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/Option.java b/BJC-Utils2/src/main/java/bjc/utils/data/Option.java deleted file mode 100644 index 37e0cde..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/data/Option.java +++ /dev/null @@ -1,93 +0,0 @@ -package bjc.utils.data; - -import java.util.function.Function; -import java.util.function.UnaryOperator; - -/** - * A holder that may or may not contain a value - * - * @author ben - * - * @param <ContainedType> - * The type of the value that may or may not be held - */ -public class Option<ContainedType> implements IHolder<ContainedType> { - private ContainedType held; - - /** - * Create a new optional, using the given initial value - * - * @param seed - * The initial value for the optional - */ - public Option(final ContainedType seed) { - held = seed; - } - - @Override - public <BoundType> IHolder<BoundType> bind(final Function<ContainedType, IHolder<BoundType>> binder) { - if (held == null) return new Option<>(null); - - return binder.apply(held); - } - - @Override - public <NewType> Function<ContainedType, IHolder<NewType>> lift(final Function<ContainedType, NewType> func) { - return val -> { - return new Option<>(func.apply(val)); - }; - } - - @Override - public <MappedType> IHolder<MappedType> map(final Function<ContainedType, MappedType> mapper) { - if (held == null) return new Option<>(null); - - return new Option<>(mapper.apply(held)); - } - - @Override - public IHolder<ContainedType> transform(final UnaryOperator<ContainedType> transformer) { - if (held != null) { - held = transformer.apply(held); - } - - return this; - } - - @Override - public <UnwrappedType> UnwrappedType unwrap(final Function<ContainedType, UnwrappedType> unwrapper) { - if (held == null) return null; - - return unwrapper.apply(held); - } - - @Override - public String toString() { - return String.format("Option [held='%s']", held); - } - - @Override - public int hashCode() { - final int prime = 31; - - int result = 1; - result = prime * result + (held == null ? 0 : held.hashCode()); - - return result; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) return true; - if (obj == null) return false; - if (!(obj instanceof Option<?>)) return false; - - final Option<?> other = (Option<?>) obj; - - if (held == null) { - if (other.held != null) return false; - } else if (!held.equals(other.held)) return false; - - return true; - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/Pair.java b/BJC-Utils2/src/main/java/bjc/utils/data/Pair.java deleted file mode 100644 index e6796ba..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/data/Pair.java +++ /dev/null @@ -1,135 +0,0 @@ -package bjc.utils.data; - -import java.util.function.BiFunction; -import java.util.function.Function; - -/** - * A pair of values, with nothing special about them. - * - * @author ben - * - * @param <LeftType> - * The type of the left value - * @param <RightType> - * The type of the right value - */ -public class Pair<LeftType, RightType> implements IPair<LeftType, RightType> { - // The left value - private LeftType leftValue; - - // The right value - private RightType rightValue; - - /** - * Create a new pair with both sides set to null - */ - public Pair() { - - } - - /** - * Create a new pair with both sides set to the specified values - * - * @param left - * The value of the left side - * @param right - * The value of the right side - */ - public Pair(final LeftType left, final RightType right) { - leftValue = left; - rightValue = right; - } - - @Override - public <BoundLeft, BoundRight> IPair<BoundLeft, BoundRight> bind( - final BiFunction<LeftType, RightType, IPair<BoundLeft, BoundRight>> binder) { - if (binder == null) throw new NullPointerException("Binder must not be null."); - - return binder.apply(leftValue, rightValue); - } - - @Override - public <BoundLeft> IPair<BoundLeft, RightType> bindLeft( - final Function<LeftType, IPair<BoundLeft, RightType>> leftBinder) { - if (leftBinder == null) throw new NullPointerException("Binder must not be null"); - - return leftBinder.apply(leftValue); - } - - @Override - public <BoundRight> IPair<LeftType, BoundRight> bindRight( - final Function<RightType, IPair<LeftType, BoundRight>> rightBinder) { - if (rightBinder == null) throw new NullPointerException("Binder must not be null"); - - return rightBinder.apply(rightValue); - } - - @Override - public <OtherLeft, OtherRight, CombinedLeft, CombinedRight> IPair<CombinedLeft, CombinedRight> combine( - final IPair<OtherLeft, OtherRight> otherPair, - final BiFunction<LeftType, OtherLeft, CombinedLeft> leftCombiner, - final BiFunction<RightType, OtherRight, CombinedRight> rightCombiner) { - return otherPair.bind((otherLeft, otherRight) -> { - final CombinedLeft left = leftCombiner.apply(leftValue, otherLeft); - final CombinedRight right = rightCombiner.apply(rightValue, otherRight); - - return new Pair<>(left, right); - }); - } - - @Override - public <NewLeft> IPair<NewLeft, RightType> mapLeft(final Function<LeftType, NewLeft> mapper) { - if (mapper == null) throw new NullPointerException("Mapper must not be null"); - - return new Pair<>(mapper.apply(leftValue), rightValue); - } - - @Override - public <NewRight> IPair<LeftType, NewRight> mapRight(final Function<RightType, NewRight> mapper) { - if (mapper == null) throw new NullPointerException("Mapper must not be null"); - - return new Pair<>(leftValue, mapper.apply(rightValue)); - } - - @Override - public <MergedType> MergedType merge(final BiFunction<LeftType, RightType, MergedType> merger) { - if (merger == null) throw new NullPointerException("Merger must not be null"); - - return merger.apply(leftValue, rightValue); - } - - @Override - public String toString() { - return String.format("Pair [leftValue='%s', rightValue='%s']", leftValue, rightValue); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - - result = prime * result + (leftValue == null ? 0 : leftValue.hashCode()); - result = prime * result + (rightValue == null ? 0 : rightValue.hashCode()); - - return result; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) return true; - if (obj == null) return false; - if (!(obj instanceof Pair<?, ?>)) return false; - - final Pair<?, ?> other = (Pair<?, ?>) obj; - - if (leftValue == null) { - if (other.leftValue != null) return false; - } else if (!leftValue.equals(other.leftValue)) return false; - - if (rightValue == null) { - if (other.rightValue != null) return false; - } else if (!rightValue.equals(other.rightValue)) return false; - - return true; - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/SingleIterator.java b/BJC-Utils2/src/main/java/bjc/utils/data/SingleIterator.java deleted file mode 100644 index 4069c3f..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/data/SingleIterator.java +++ /dev/null @@ -1,41 +0,0 @@ -package bjc.utils.data; - -import java.util.Iterator; - -/** - * An iterator that will only ever yield one item. - * - * @author EVE - * - * @param <T> - * The type of the item. - */ -public class SingleIterator<T> implements Iterator<T> { - private final T itm; - - private boolean yielded; - - /** - * Create a iterator that yields a single item. - * - * @param item - * The item to yield. - */ - public SingleIterator(final T item) { - itm = item; - - yielded = false; - } - - @Override - public boolean hasNext() { - return !yielded; - } - - @Override - public T next() { - yielded = true; - - return itm; - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/SingleSupplier.java b/BJC-Utils2/src/main/java/bjc/utils/data/SingleSupplier.java deleted file mode 100644 index c675ebf..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/data/SingleSupplier.java +++ /dev/null @@ -1,72 +0,0 @@ -package bjc.utils.data; - -import java.util.function.Supplier; - -/** - * A supplier that can only supply one value. - * - * Attempting to retrieve another value will cause an exception to be thrown. - * - * @author ben - * - * @param <T> - * The supplied type - */ -public class SingleSupplier<T> implements Supplier<T> { - private static long nextID = 0; - - private final Supplier<T> source; - - private boolean gotten; - - private final long id; - - /* - * This is bad practice, but I want to know where the single - * instantiation was, in case of duplicate initiations. - */ - private Exception instSite; - - /** - * Create a new single supplier from an existing value - * - * @param supp - * The supplier to give a single value from - */ - public SingleSupplier(final Supplier<T> supp) { - source = supp; - - gotten = false; - - id = nextID++; - } - - @Override - public T get() { - if (gotten == true) { - final String msg = String.format( - "Attempted to retrieve value more than once from single supplier #%d", id); - - final IllegalStateException isex = new IllegalStateException(msg); - - isex.initCause(instSite); - - throw isex; - } - - gotten = true; - - try { - throw new IllegalStateException("Previous instantiation here."); - } catch (final IllegalStateException isex) { - instSite = isex; - } - - return source.get(); - } - - @Override - public String toString() { - return String.format("SingleSupplier [source='%s', gotten=%s, id=%s]", source, gotten, id); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/Toggle.java b/BJC-Utils2/src/main/java/bjc/utils/data/Toggle.java deleted file mode 100644 index 1e10dae..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/data/Toggle.java +++ /dev/null @@ -1,35 +0,0 @@ -package bjc.utils.data; - -/** - * A stateful holder that swaps between two values of the same type. - * - * @author EVE - * - * @param <E> - * The value stored in the toggle. - */ -public interface Toggle<E> { - /** - * Retrieve the currently-aligned value of this toggle, and swap the - * alignment. - * - * @return The previously-aligned value. - */ - E get(); - - /** - * Retrieve the currently-aligned value without altering the alignment. - * - * @return The currently-aligned value. - */ - E peek(); - - /** - * Change the alignment of the toggle. - * - * @param isLeft - * Whether the toggle should be left-aligned or not. - */ - void set(boolean isLeft); - -}
\ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/TopDownTransformIterator.java b/BJC-Utils2/src/main/java/bjc/utils/data/TopDownTransformIterator.java deleted file mode 100644 index 1b87e52..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/data/TopDownTransformIterator.java +++ /dev/null @@ -1,208 +0,0 @@ -package bjc.utils.data; - -import static bjc.utils.data.TopDownTransformResult.RTRANSFORM; - -import java.util.Deque; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.NoSuchElementException; -import java.util.function.BiFunction; -import java.util.function.Consumer; -import java.util.function.Function; - -/* - * FIXME something is broken in here. fix it. - */ -public class TopDownTransformIterator<ContainedType> implements Iterator<ITree<ContainedType>> { - private final Function<ContainedType, TopDownTransformResult> picker; - private final BiFunction<ITree<ContainedType>, Consumer<Iterator<ITree<ContainedType>>>, ITree<ContainedType>> transform; - - private ITree<ContainedType> preParent; - private ITree<ContainedType> postParent; - - private final Deque<ITree<ContainedType>> preChildren; - private final Deque<ITree<ContainedType>> postChildren; - - private TopDownTransformIterator<ContainedType> curChild; - - private boolean done; - private boolean initial; - - private final Deque<Iterator<ITree<ContainedType>>> toYield; - private Iterator<ITree<ContainedType>> curYield; - - public TopDownTransformIterator(final Function<ContainedType, TopDownTransformResult> pickr, - final BiFunction<ITree<ContainedType>, Consumer<Iterator<ITree<ContainedType>>>, ITree<ContainedType>> transfrm, - final ITree<ContainedType> tree) { - preParent = tree; - - preChildren = new LinkedList<>(); - postChildren = new LinkedList<>(); - toYield = new LinkedList<>(); - - picker = pickr; - transform = transfrm; - - done = false; - initial = true; - } - - public void addYield(final Iterator<ITree<ContainedType>> src) { - if (curYield != null) { - toYield.push(curYield); - } - - curYield = src; - } - - @Override - public boolean hasNext() { - return !done; - } - - public ITree<ContainedType> flushYields(final ITree<ContainedType> val) { - if (curYield != null) { - toYield.add(new SingleIterator<>(val)); - - if (curYield.hasNext()) - return curYield.next(); - else { - while (toYield.size() != 0 && !curYield.hasNext()) { - curYield = toYield.pop(); - } - - if (toYield.size() == 0 && !curYield.hasNext()) { - curYield = null; - return val; - } else return curYield.next(); - } - } else return val; - } - - @Override - public ITree<ContainedType> next() { - if (done) throw new NoSuchElementException(); - - if (curYield != null) { - if (curYield.hasNext()) - return curYield.next(); - else { - while (toYield.size() != 0 && !curYield.hasNext()) { - curYield = toYield.pop(); - } - - if (toYield.size() == 0 && !curYield.hasNext()) { - curYield = null; - } else return curYield.next(); - } - } - - if (initial) { - final TopDownTransformResult res = picker.apply(preParent.getHead()); - - switch (res) { - case PASSTHROUGH: - postParent = new Tree<>(preParent.getHead()); - - if (preParent.getChildrenCount() != 0) { - for (int i = 0; i < preParent.getChildrenCount(); i++) { - preChildren.add(preParent.getChild(i)); - } - - // Return whatever the first child is - break; - } else { - done = true; - return flushYields(postParent); - } - case SKIP: - done = true; - return flushYields(preParent); - case TRANSFORM: - done = true; - return flushYields(transform.apply(preParent, this::addYield)); - case RTRANSFORM: - preParent = transform.apply(preParent, this::addYield); - return flushYields(preParent); - case PUSHDOWN: - if (preParent.getChildrenCount() != 0) { - for (int i = 0; i < preParent.getChildrenCount(); i++) { - preChildren.add(preParent.getChild(i)); - } - - // Return whatever the first child is - break; - } else { - done = true; - return flushYields(transform.apply(new Tree<>(preParent.getHead()), - this::addYield)); - } - case PULLUP: - final ITree<ContainedType> intRes = transform.apply(preParent, this::addYield); - - postParent = new Tree<>(intRes.getHead()); - - if (intRes.getChildrenCount() != 0) { - for (int i = 0; i < intRes.getChildrenCount(); i++) { - preChildren.add(intRes.getChild(i)); - } - - // Return whatever the first child is - break; - } else { - done = true; - return flushYields(postParent); - } - default: - throw new IllegalArgumentException("Unknown result type " + res); - } - - if (res != RTRANSFORM) { - initial = false; - } - } - - if (curChild == null || !curChild.hasNext()) { - if (preChildren.size() != 0) { - curChild = new TopDownTransformIterator<>(picker, transform, preChildren.pop()); - - final ITree<ContainedType> res = curChild.next(); - System.out.println("\t\tTRACE: adding node " + res + " to children"); - postChildren.add(res); - - return flushYields(res); - } else { - ITree<ContainedType> res = null; - - if (postParent == null) { - res = new Tree<>(preParent.getHead()); - - System.out.println("\t\tTRACE: adding nodes " + postChildren + " to " + res); - - for (final ITree<ContainedType> child : postChildren) { - res.addChild(child); - } - - // res = transform.apply(res, - // this::addYield); - } else { - res = postParent; - - System.out.println("\t\tTRACE: adding nodes " + postChildren + " to " + res); - for (final ITree<ContainedType> child : postChildren) { - res.addChild(child); - } - } - - done = true; - return flushYields(res); - } - } else { - final ITree<ContainedType> res = curChild.next(); - System.out.println("\t\tTRACE: adding node " + res + " to children"); - postChildren.add(res); - - return flushYields(res); - } - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/TopDownTransformResult.java b/BJC-Utils2/src/main/java/bjc/utils/data/TopDownTransformResult.java deleted file mode 100644 index ed41eae..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/data/TopDownTransformResult.java +++ /dev/null @@ -1,34 +0,0 @@ -package bjc.utils.data; - -/** - * Represents the results for doing a top-down transform of a tree - * - * @author ben - * - */ -public enum TopDownTransformResult { - /** - * Do not do anything to this node, and ignore its children - */ - SKIP, - /** - * Transform this node, and don't touch its children - */ - TRANSFORM, - /** - * Transform this node, then do a top-down transform on the result - */ - RTRANSFORM, - /** - * Ignore this node, and traverse its children - */ - PASSTHROUGH, - /** - * Traverse the nodes of this children, then transform it - */ - PUSHDOWN, - /** - * Transform this node, then traverse its children - */ - PULLUP; -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/TransformIterator.java b/BJC-Utils2/src/main/java/bjc/utils/data/TransformIterator.java deleted file mode 100644 index 50f28b1..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/data/TransformIterator.java +++ /dev/null @@ -1,46 +0,0 @@ -package bjc.utils.data; - -import java.util.Iterator; -import java.util.function.Function; - -/** - * An iterator that transforms values from one type to another. - * - * @author EVE - * - * @param <S> - * The source iterator type. - * - * @param <D> - * The destination iterator type. - */ -public class TransformIterator<S, D> implements Iterator<D> { - private final Iterator<S> source; - - private final Function<S, D> transform; - - /** - * Create a new transform iterator. - * - * @param source - * The source iterator to use. - * - * @param transform - * The transform to apply. - */ - public TransformIterator(final Iterator<S> source, final Function<S, D> transform) { - this.source = source; - this.transform = transform; - } - - @Override - public boolean hasNext() { - return source.hasNext(); - } - - @Override - public D next() { - return transform.apply(source.next()); - } - -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/Tree.java b/BJC-Utils2/src/main/java/bjc/utils/data/Tree.java deleted file mode 100644 index a52f699..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/data/Tree.java +++ /dev/null @@ -1,390 +0,0 @@ -package bjc.utils.data; - -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Predicate; -import java.util.function.UnaryOperator; - -import bjc.utils.funcdata.FunctionalList; -import bjc.utils.funcdata.IList; -import bjc.utils.funcdata.bst.TreeLinearizationMethod; -import bjc.utils.functypes.ListFlattener; - -/** - * A node in a homogeneous tree. - * - * @author ben - * - * @param <ContainedType> - */ -public class Tree<ContainedType> implements ITree<ContainedType> { - private ContainedType data; - - private IList<ITree<ContainedType>> children; - private boolean hasChildren; - private int childCount = 0; - - private int ID; - private static int nextID = 0; - - /** - * Create a new leaf node in a tree. - * - * @param leaf - * The data to store as a leaf node. - */ - public Tree(final ContainedType leaf) { - data = leaf; - - hasChildren = false; - - ID = nextID++; - } - - /** - * Create a new tree node with the specified children. - * - * @param leaf - * The data to hold in this node. - * - * @param childrn - * A list of children for this node. - */ - public Tree(final ContainedType leaf, final IList<ITree<ContainedType>> childrn) { - this(leaf); - - hasChildren = true; - - childCount = childrn.getSize(); - - children = childrn; - } - - /** - * Create a new tree node with the specified children. - * - * @param leaf - * The data to hold in this node. - * - * @param childrn - * A list of children for this node. - */ - @SafeVarargs - public Tree(final ContainedType leaf, final ITree<ContainedType>... childrn) { - this(leaf); - - hasChildren = true; - - childCount = 0; - - children = new FunctionalList<>(); - - for (final ITree<ContainedType> child : childrn) { - children.add(child); - - childCount++; - } - } - - @Override - public void addChild(final ITree<ContainedType> child) { - if (hasChildren == false) { - hasChildren = true; - - children = new FunctionalList<>(); - } - - childCount++; - - children.add(child); - } - - @Override - public void prependChild(final ITree<ContainedType> child) { - if (hasChildren == false) { - hasChildren = true; - - children = new FunctionalList<>(); - } - - childCount++; - - children.prepend(child); - } - - @Override - public void doForChildren(final Consumer<ITree<ContainedType>> action) { - if (childCount > 0) { - children.forEach(action); - } - } - - @Override - public int getChildrenCount() { - return childCount; - } - - @Override - public int revFind(final Predicate<ITree<ContainedType>> childPred) { - if (childCount == 0) - return -1; - else { - for (int i = childCount - 1; i >= 0; i--) { - if (childPred.test(getChild(i))) return i; - } - } - - return -1; - } - - @Override - public void traverse(final TreeLinearizationMethod linearizationMethod, final Consumer<ContainedType> action) { - if (hasChildren) { - switch (linearizationMethod) { - case INORDER: - if (childCount != 2) { - final String msg = "Can only do in-order traversal for binary trees."; - - throw new IllegalArgumentException(msg); - } - - children.getByIndex(0).traverse(linearizationMethod, action); - - action.accept(data); - - children.getByIndex(1).traverse(linearizationMethod, action); - break; - case POSTORDER: - children.forEach((child) -> child.traverse(linearizationMethod, action)); - - action.accept(data); - break; - case PREORDER: - action.accept(data); - - children.forEach((child) -> child.traverse(linearizationMethod, action)); - break; - default: - break; - - } - } else { - action.accept(data); - } - } - - @Override - public <NewType, ReturnedType> ReturnedType collapse(final Function<ContainedType, NewType> leafTransform, - final Function<ContainedType, ListFlattener<NewType>> nodeCollapser, - final Function<NewType, ReturnedType> resultTransformer) { - return resultTransformer.apply(internalCollapse(leafTransform, nodeCollapser)); - } - - @Override - public ITree<ContainedType> flatMapTree(final Function<ContainedType, ITree<ContainedType>> mapper) { - if (hasChildren) { - final ITree<ContainedType> flatMappedData = mapper.apply(data); - - final IList<ITree<ContainedType>> mappedChildren = children - .map(child -> child.flatMapTree(mapper)); - - mappedChildren.forEach(child -> flatMappedData.addChild(child)); - - return flatMappedData; - } - - return mapper.apply(data); - } - - protected <NewType> NewType internalCollapse(final Function<ContainedType, NewType> leafTransform, - final Function<ContainedType, ListFlattener<NewType>> nodeCollapser) { - if (hasChildren) { - final Function<IList<NewType>, NewType> nodeTransformer = nodeCollapser.apply(data); - - final IList<NewType> collapsedChildren = children.map(child -> { - final NewType collapsed = child.collapse(leafTransform, nodeCollapser, - subTreeVal -> subTreeVal); - - return collapsed; - }); - - return nodeTransformer.apply(collapsedChildren); - } - - return leafTransform.apply(data); - } - - protected void internalToString(final StringBuilder builder, final int indentLevel, final boolean initial) { - for (int i = 0; i < indentLevel; i++) { - builder.append(">\t"); - } - - builder.append("Node #"); - builder.append(ID); - builder.append(": "); - builder.append(data == null ? "(null)" : data.toString()); - builder.append("\n"); - - if (hasChildren) { - children.forEach(child -> { - if (child instanceof Tree<?>) { - final Tree<ContainedType> kid = (Tree<ContainedType>) child; - - kid.internalToString(builder, indentLevel + 1, false); - } else { - for (int i = 0; i < indentLevel + 1; i++) { - builder.append(">\t"); - } - - builder.append("Unknown node\n"); - } - }); - } - } - - @Override - public <MappedType> ITree<MappedType> rebuildTree(final Function<ContainedType, MappedType> leafTransformer, - final Function<ContainedType, MappedType> operatorTransformer) { - if (hasChildren) { - final IList<ITree<MappedType>> mappedChildren = children.map(child -> { - return child.rebuildTree(leafTransformer, operatorTransformer); - }); - - return new Tree<>(operatorTransformer.apply(data), mappedChildren); - } - - return new Tree<>(leafTransformer.apply(data)); - } - - @Override - public void selectiveTransform(final Predicate<ContainedType> nodePicker, - final UnaryOperator<ContainedType> transformer) { - if (hasChildren) { - children.forEach(child -> child.selectiveTransform(nodePicker, transformer)); - } else { - data = transformer.apply(data); - } - } - - @Override - public ITree<ContainedType> topDownTransform( - final Function<ContainedType, TopDownTransformResult> transformPicker, - final UnaryOperator<ITree<ContainedType>> transformer) { - final TopDownTransformResult transformResult = transformPicker.apply(data); - - switch (transformResult) { - case PASSTHROUGH: - ITree<ContainedType> result = new Tree<>(data); - - if (hasChildren) { - children.forEach(child -> { - final ITree<ContainedType> kid = child.topDownTransform(transformPicker, - transformer); - - result.addChild(kid); - }); - } - - return result; - case SKIP: - return this; - case TRANSFORM: - return transformer.apply(this); - case RTRANSFORM: - return transformer.apply(this).topDownTransform(transformPicker, transformer); - case PUSHDOWN: - result = new Tree<>(data); - - if (hasChildren) { - children.forEach(child -> { - final ITree<ContainedType> kid = child.topDownTransform(transformPicker, - transformer); - - result.addChild(kid); - }); - } - - return transformer.apply(result); - case PULLUP: - final ITree<ContainedType> intermediateResult = transformer.apply(this); - - result = new Tree<>(intermediateResult.getHead()); - - intermediateResult.doForChildren(child -> { - final ITree<ContainedType> kid = child.topDownTransform(transformPicker, transformer); - - result.addChild(kid); - }); - - return result; - default: - final String msg = String.format("Recieved unknown transform result %s", transformResult); - - throw new IllegalArgumentException(msg); - } - } - - @Override - public <TransformedType> TransformedType transformChild(final int childNo, - final Function<ITree<ContainedType>, TransformedType> transformer) { - if (childNo < 0 || childNo > childCount - 1) { - final String msg = String.format("Child index #%d is invalid", childNo); - - throw new IllegalArgumentException(msg); - } - - final ITree<ContainedType> selectedKid = children.getByIndex(childNo); - - return transformer.apply(selectedKid); - } - - @Override - public <TransformedType> TransformedType transformHead( - final Function<ContainedType, TransformedType> transformer) { - return transformer.apply(data); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - - result = prime * result + childCount; - result = prime * result + (children == null ? 0 : children.hashCode()); - result = prime * result + (data == null ? 0 : data.hashCode()); - - return result; - } - - @Override - public String toString() { - final StringBuilder builder = new StringBuilder(); - - internalToString(builder, 1, true); - - builder.deleteCharAt(builder.length() - 1); - - return builder.toString(); - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) return true; - if (obj == null) return false; - if (!(obj instanceof Tree<?>)) return false; - - final Tree<?> other = (Tree<?>) obj; - - if (data == null) { - if (other.data != null) return false; - } else if (!data.equals(other.data)) return false; - - if (childCount != other.childCount) return false; - - if (children == null) { - if (other.children != null) return false; - } else if (!children.equals(other.children)) return false; - - return true; - } -}
\ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/ValueToggle.java b/BJC-Utils2/src/main/java/bjc/utils/data/ValueToggle.java deleted file mode 100644 index 9193896..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/data/ValueToggle.java +++ /dev/null @@ -1,54 +0,0 @@ -package bjc.utils.data; - -/** - * A simple implementation of {@link Toggle}. - * - * @author EVE - * - * @param <E> - * The type of value to toggle between. - */ -public class ValueToggle<E> implements Toggle<E> { - private final E lft; - private final E rght; - - private final BooleanToggle alignment; - - /** - * Create a new toggle. - * - * All toggles start right-aligned. - * - * @param left - * The value when the toggle is left-aligned. - * - * @param right - * The value when the toggle is right-aligned. - */ - public ValueToggle(final E left, final E right) { - lft = left; - - rght = right; - - alignment = new BooleanToggle(); - } - - @Override - public E get() { - if (alignment.get()) - return lft; - else return rght; - } - - @Override - public E peek() { - if (alignment.peek()) - return lft; - else return rght; - } - - @Override - public void set(final boolean isLeft) { - alignment.set(isLeft); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/internals/BoundLazy.java b/BJC-Utils2/src/main/java/bjc/utils/data/internals/BoundLazy.java deleted file mode 100644 index f71d32b..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/data/internals/BoundLazy.java +++ /dev/null @@ -1,145 +0,0 @@ -package bjc.utils.data.internals; - -import java.util.function.Function; -import java.util.function.Supplier; -import java.util.function.UnaryOperator; - -import bjc.utils.data.IHolder; -import bjc.utils.data.Lazy; -import bjc.utils.funcdata.FunctionalList; -import bjc.utils.funcdata.IList; - -/* - * Implements a lazy holder that has been bound - */ -public class BoundLazy<OldType, BoundContainedType> implements IHolder<BoundContainedType> { - /* - * The old value - */ - private final Supplier<IHolder<OldType>> oldSupplier; - - /* - * The function to use to transform the old value into a new value - */ - private final Function<OldType, IHolder<BoundContainedType>> binder; - - /* - * The bound value being held - */ - private IHolder<BoundContainedType> boundHolder; - - /* - * Whether the bound value has been actualized or not - */ - private boolean holderBound; - - /* - * Transformations currently pending on the bound value - */ - private final IList<UnaryOperator<BoundContainedType>> actions = new FunctionalList<>(); - - /* - * Create a new bound lazy value - */ - public BoundLazy(final Supplier<IHolder<OldType>> supp, - final Function<OldType, IHolder<BoundContainedType>> binder) { - oldSupplier = supp; - this.binder = binder; - } - - @Override - public <BoundType> IHolder<BoundType> bind(final Function<BoundContainedType, IHolder<BoundType>> bindr) { - if (bindr == null) throw new NullPointerException("Binder must not be null"); - - /* - * Prepare a list of pending actions - */ - final IList<UnaryOperator<BoundContainedType>> pendingActions = new FunctionalList<>(); - actions.forEach(pendingActions::add); - - /* - * Create the new supplier of a value - */ - final Supplier<IHolder<BoundContainedType>> typeSupplier = () -> { - IHolder<BoundContainedType> oldHolder = boundHolder; - - /* - * Bind the value if it hasn't been bound before - */ - if (!holderBound) { - oldHolder = oldSupplier.get().unwrap(binder); - } - - /* - * Apply all the pending actions - */ - return pendingActions.reduceAux(oldHolder, (action, state) -> { - return state.transform(action); - }, (value) -> value); - }; - - return new BoundLazy<>(typeSupplier, bindr); - } - - @Override - public <NewType> Function<BoundContainedType, IHolder<NewType>> lift( - final Function<BoundContainedType, NewType> func) { - if (func == null) throw new NullPointerException("Function to lift must not be null"); - - return (val) -> { - return new Lazy<>(func.apply(val)); - }; - } - - @Override - public <MappedType> IHolder<MappedType> map(final Function<BoundContainedType, MappedType> mapper) { - if (mapper == null) throw new NullPointerException("Mapper must not be null"); - - // Prepare a list of pending actions - final IList<UnaryOperator<BoundContainedType>> pendingActions = new FunctionalList<>(); - actions.forEach(pendingActions::add); - - // Prepare the new supplier - final Supplier<MappedType> typeSupplier = () -> { - IHolder<BoundContainedType> oldHolder = boundHolder; - - // Bound the value if it hasn't been bound - if (!holderBound) { - oldHolder = oldSupplier.get().unwrap(binder); - } - - return pendingActions.reduceAux(oldHolder.getValue(), (action, state) -> { - return action.apply(state); - }, (value) -> mapper.apply(value)); - }; - - return new Lazy<>(typeSupplier); - } - - @Override - public String toString() { - if (holderBound) return boundHolder.toString(); - - return "(unmaterialized)"; - } - - @Override - public IHolder<BoundContainedType> transform(final UnaryOperator<BoundContainedType> transformer) { - if (transformer == null) throw new NullPointerException("Transformer must not be null"); - - actions.add(transformer); - - return this; - } - - @Override - public <UnwrappedType> UnwrappedType unwrap(final Function<BoundContainedType, UnwrappedType> unwrapper) { - if (unwrapper == null) throw new NullPointerException("Unwrapper must not be null"); - - if (!holderBound) { - boundHolder = oldSupplier.get().unwrap(binder::apply); - } - - return boundHolder.unwrap(unwrapper); - } -}
\ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/internals/BoundLazyPair.java b/BJC-Utils2/src/main/java/bjc/utils/data/internals/BoundLazyPair.java deleted file mode 100644 index df6e60b..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/data/internals/BoundLazyPair.java +++ /dev/null @@ -1,199 +0,0 @@ -package bjc.utils.data.internals; - -import java.util.function.BiFunction; -import java.util.function.Function; -import java.util.function.Supplier; - -import bjc.utils.data.IHolder; -import bjc.utils.data.IPair; -import bjc.utils.data.Identity; -import bjc.utils.data.LazyPair; - -/* - * Implements a lazy pair that has been bound - */ -public class BoundLazyPair<OldLeft, OldRight, NewLeft, NewRight> implements IPair<NewLeft, NewRight> { - /* - * The supplier of the left value - */ - private final Supplier<OldLeft> leftSupplier; - /* - * The supplier of the right value - */ - private final Supplier<OldRight> rightSupplier; - - /* - * The binder to transform values - */ - private final BiFunction<OldLeft, OldRight, IPair<NewLeft, NewRight>> binder; - - /* - * The bound pair - */ - private IPair<NewLeft, NewRight> boundPair; - - /* - * Whether the pair has been bound yet - */ - private boolean pairBound; - - public BoundLazyPair(final Supplier<OldLeft> leftSupp, final Supplier<OldRight> rightSupp, - final BiFunction<OldLeft, OldRight, IPair<NewLeft, NewRight>> bindr) { - leftSupplier = leftSupp; - rightSupplier = rightSupp; - binder = bindr; - } - - @Override - public <BoundLeft, BoundRight> IPair<BoundLeft, BoundRight> bind( - final BiFunction<NewLeft, NewRight, IPair<BoundLeft, BoundRight>> bindr) { - if (bindr == null) throw new NullPointerException("Binder must not be null"); - - final IHolder<IPair<NewLeft, NewRight>> newPair = new Identity<>(boundPair); - final IHolder<Boolean> newPairMade = new Identity<>(pairBound); - - final Supplier<NewLeft> leftSupp = () -> { - if (!newPairMade.getValue()) { - newPair.replace(binder.apply(leftSupplier.get(), rightSupplier.get())); - - newPairMade.replace(true); - } - - return newPair.unwrap((pair) -> pair.getLeft()); - }; - - final Supplier<NewRight> rightSupp = () -> { - if (!newPairMade.getValue()) { - newPair.replace(binder.apply(leftSupplier.get(), rightSupplier.get())); - - newPairMade.replace(true); - } - - return newPair.unwrap((pair) -> pair.getRight()); - }; - - return new BoundLazyPair<>(leftSupp, rightSupp, bindr); - } - - @Override - public <BoundLeft> IPair<BoundLeft, NewRight> bindLeft( - final Function<NewLeft, IPair<BoundLeft, NewRight>> leftBinder) { - if (leftBinder == null) throw new NullPointerException("Left binder must not be null"); - - final Supplier<NewLeft> leftSupp = () -> { - IPair<NewLeft, NewRight> newPair = boundPair; - - if (!pairBound) { - newPair = binder.apply(leftSupplier.get(), rightSupplier.get()); - } - - return newPair.getLeft(); - }; - - return new HalfBoundLazyPair<>(leftSupp, leftBinder); - } - - @Override - public <BoundRight> IPair<NewLeft, BoundRight> bindRight( - final Function<NewRight, IPair<NewLeft, BoundRight>> rightBinder) { - if (rightBinder == null) throw new NullPointerException("Right binder must not be null"); - - final Supplier<NewRight> rightSupp = () -> { - IPair<NewLeft, NewRight> newPair = boundPair; - - if (!pairBound) { - newPair = binder.apply(leftSupplier.get(), rightSupplier.get()); - } - - return newPair.getRight(); - }; - - return new HalfBoundLazyPair<>(rightSupp, rightBinder); - } - - @Override - public <OtherLeft, OtherRight, CombinedLeft, CombinedRight> IPair<CombinedLeft, CombinedRight> combine( - final IPair<OtherLeft, OtherRight> otherPair, - final BiFunction<NewLeft, OtherLeft, CombinedLeft> leftCombiner, - final BiFunction<NewRight, OtherRight, CombinedRight> rightCombiner) { - if (otherPair == null) - throw new NullPointerException("Other pair must not be null"); - else if (leftCombiner == null) - throw new NullPointerException("Left combiner must not be null"); - else if (rightCombiner == null) throw new NullPointerException("Right combiner must not be null"); - - return otherPair.bind((otherLeft, otherRight) -> { - return bind((leftVal, rightVal) -> { - return new LazyPair<>(leftCombiner.apply(leftVal, otherLeft), - rightCombiner.apply(rightVal, otherRight)); - }); - }); - } - - @Override - public <NewLeftType> IPair<NewLeftType, NewRight> mapLeft(final Function<NewLeft, NewLeftType> mapper) { - if (mapper == null) throw new NullPointerException("Mapper must not be null"); - - final Supplier<NewLeftType> leftSupp = () -> { - if (!pairBound) { - final NewLeft leftVal = binder.apply(leftSupplier.get(), rightSupplier.get()).getLeft(); - - return mapper.apply(leftVal); - } - - return mapper.apply(boundPair.getLeft()); - }; - - final Supplier<NewRight> rightSupp = () -> { - if (!pairBound) return binder.apply(leftSupplier.get(), rightSupplier.get()).getRight(); - - return boundPair.getRight(); - }; - - return new LazyPair<>(leftSupp, rightSupp); - } - - @Override - public <NewRightType> IPair<NewLeft, NewRightType> mapRight(final Function<NewRight, NewRightType> mapper) { - if (mapper == null) throw new NullPointerException("Mapper must not be null"); - - final Supplier<NewLeft> leftSupp = () -> { - if (!pairBound) return binder.apply(leftSupplier.get(), rightSupplier.get()).getLeft(); - - return boundPair.getLeft(); - }; - - final Supplier<NewRightType> rightSupp = () -> { - if (!pairBound) { - final NewRight rightVal = binder.apply(leftSupplier.get(), rightSupplier.get()) - .getRight(); - - return mapper.apply(rightVal); - } - - return mapper.apply(boundPair.getRight()); - }; - - return new LazyPair<>(leftSupp, rightSupp); - } - - @Override - public <MergedType> MergedType merge(final BiFunction<NewLeft, NewRight, MergedType> merger) { - if (merger == null) throw new NullPointerException("Merger must not be null"); - - if (!pairBound) { - boundPair = binder.apply(leftSupplier.get(), rightSupplier.get()); - - pairBound = true; - } - - return boundPair.merge(merger); - } - - @Override - public String toString() { - if (pairBound) return boundPair.toString(); - - return "(un-materialized)"; - } -}
\ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/internals/BoundListHolder.java b/BJC-Utils2/src/main/java/bjc/utils/data/internals/BoundListHolder.java deleted file mode 100644 index f3799fd..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/data/internals/BoundListHolder.java +++ /dev/null @@ -1,68 +0,0 @@ -package bjc.utils.data.internals; - -import java.util.function.Function; -import java.util.function.UnaryOperator; - -import bjc.utils.data.IHolder; -import bjc.utils.data.ListHolder; -import bjc.utils.funcdata.IList; - -/* - * Holds a list, converted into a holder - */ -public class BoundListHolder<ContainedType> implements IHolder<ContainedType> { - private final IList<IHolder<ContainedType>> heldHolders; - - public BoundListHolder(final IList<IHolder<ContainedType>> toHold) { - heldHolders = toHold; - } - - @Override - public <BoundType> IHolder<BoundType> bind(final Function<ContainedType, IHolder<BoundType>> binder) { - if (binder == null) throw new NullPointerException("Binder must not be null"); - - final IList<IHolder<BoundType>> boundHolders = heldHolders.map((containedHolder) -> { - return containedHolder.bind(binder); - }); - - return new BoundListHolder<>(boundHolders); - } - - @Override - public <NewType> Function<ContainedType, IHolder<NewType>> lift(final Function<ContainedType, NewType> func) { - if (func == null) throw new NullPointerException("Function to lift must not be null"); - - return (val) -> { - return new ListHolder<>(func.apply(val)); - }; - } - - @Override - public <MappedType> IHolder<MappedType> map(final Function<ContainedType, MappedType> mapper) { - if (mapper == null) throw new NullPointerException("Mapper must not be null"); - - final IList<IHolder<MappedType>> mappedHolders = heldHolders.map((containedHolder) -> { - return containedHolder.map(mapper); - }); - - return new BoundListHolder<>(mappedHolders); - } - - @Override - public IHolder<ContainedType> transform(final UnaryOperator<ContainedType> transformer) { - if (transformer == null) throw new NullPointerException("Transformer must not be null"); - - heldHolders.forEach((containedHolder) -> { - containedHolder.transform(transformer); - }); - - return this; - } - - @Override - public <UnwrappedType> UnwrappedType unwrap(final Function<ContainedType, UnwrappedType> unwrapper) { - if (unwrapper == null) throw new NullPointerException("Unwrapper must not be null"); - - return heldHolders.randItem().unwrap(unwrapper); - } -}
\ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/internals/HalfBoundLazyPair.java b/BJC-Utils2/src/main/java/bjc/utils/data/internals/HalfBoundLazyPair.java deleted file mode 100644 index 8cac38b..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/data/internals/HalfBoundLazyPair.java +++ /dev/null @@ -1,149 +0,0 @@ -package bjc.utils.data.internals; - -import java.util.function.BiFunction; -import java.util.function.Function; -import java.util.function.Supplier; - -import bjc.utils.data.IHolder; -import bjc.utils.data.IPair; -import bjc.utils.data.Identity; -import bjc.utils.data.LazyPair; - -/* - * A lazy pair, with only one side bound - */ -public class HalfBoundLazyPair<OldType, NewLeft, NewRight> implements IPair<NewLeft, NewRight> { - private final Supplier<OldType> oldSupplier; - - private final Function<OldType, IPair<NewLeft, NewRight>> binder; - - private IPair<NewLeft, NewRight> boundPair; - private boolean pairBound; - - public HalfBoundLazyPair(final Supplier<OldType> oldSupp, - final Function<OldType, IPair<NewLeft, NewRight>> bindr) { - oldSupplier = oldSupp; - binder = bindr; - } - - @Override - public <BoundLeft, BoundRight> IPair<BoundLeft, BoundRight> bind( - final BiFunction<NewLeft, NewRight, IPair<BoundLeft, BoundRight>> bindr) { - final IHolder<IPair<NewLeft, NewRight>> newPair = new Identity<>(boundPair); - final IHolder<Boolean> newPairMade = new Identity<>(pairBound); - - final Supplier<NewLeft> leftSupp = () -> { - if (!newPairMade.getValue()) { - newPair.replace(binder.apply(oldSupplier.get())); - newPairMade.replace(true); - } - - return newPair.unwrap((pair) -> pair.getLeft()); - }; - - final Supplier<NewRight> rightSupp = () -> { - if (!newPairMade.getValue()) { - newPair.replace(binder.apply(oldSupplier.get())); - newPairMade.replace(true); - } - - return newPair.unwrap((pair) -> pair.getRight()); - }; - - return new BoundLazyPair<>(leftSupp, rightSupp, bindr); - } - - @Override - public <BoundLeft> IPair<BoundLeft, NewRight> bindLeft( - final Function<NewLeft, IPair<BoundLeft, NewRight>> leftBinder) { - final Supplier<NewLeft> leftSupp = () -> { - IPair<NewLeft, NewRight> newPair = boundPair; - - if (!pairBound) { - newPair = binder.apply(oldSupplier.get()); - } - - return newPair.getLeft(); - }; - - return new HalfBoundLazyPair<>(leftSupp, leftBinder); - } - - @Override - public <BoundRight> IPair<NewLeft, BoundRight> bindRight( - final Function<NewRight, IPair<NewLeft, BoundRight>> rightBinder) { - final Supplier<NewRight> rightSupp = () -> { - IPair<NewLeft, NewRight> newPair = boundPair; - - if (!pairBound) { - newPair = binder.apply(oldSupplier.get()); - } - - return newPair.getRight(); - }; - - return new HalfBoundLazyPair<>(rightSupp, rightBinder); - } - - @Override - public <OtherLeft, OtherRight, CombinedLeft, CombinedRight> IPair<CombinedLeft, CombinedRight> combine( - final IPair<OtherLeft, OtherRight> otherPair, - final BiFunction<NewLeft, OtherLeft, CombinedLeft> leftCombiner, - final BiFunction<NewRight, OtherRight, CombinedRight> rightCombiner) { - return otherPair.bind((otherLeft, otherRight) -> { - return bind((leftVal, rightVal) -> { - return new LazyPair<>(leftCombiner.apply(leftVal, otherLeft), - rightCombiner.apply(rightVal, otherRight)); - }); - }); - } - - @Override - public <NewLeftType> IPair<NewLeftType, NewRight> mapLeft(final Function<NewLeft, NewLeftType> mapper) { - final Supplier<NewLeftType> leftSupp = () -> { - if (pairBound) return mapper.apply(boundPair.getLeft()); - - final NewLeft leftVal = binder.apply(oldSupplier.get()).getLeft(); - - return mapper.apply(leftVal); - }; - - final Supplier<NewRight> rightSupp = () -> { - if (pairBound) return boundPair.getRight(); - - return binder.apply(oldSupplier.get()).getRight(); - }; - - return new LazyPair<>(leftSupp, rightSupp); - } - - @Override - public <NewRightType> IPair<NewLeft, NewRightType> mapRight(final Function<NewRight, NewRightType> mapper) { - final Supplier<NewLeft> leftSupp = () -> { - if (pairBound) return boundPair.getLeft(); - - return binder.apply(oldSupplier.get()).getLeft(); - }; - - final Supplier<NewRightType> rightSupp = () -> { - if (pairBound) return mapper.apply(boundPair.getRight()); - - final NewRight rightVal = binder.apply(oldSupplier.get()).getRight(); - - return mapper.apply(rightVal); - }; - - return new LazyPair<>(leftSupp, rightSupp); - } - - @Override - public <MergedType> MergedType merge(final BiFunction<NewLeft, NewRight, MergedType> merger) { - if (!pairBound) { - boundPair = binder.apply(oldSupplier.get()); - - pairBound = true; - } - - return boundPair.merge(merger); - } -}
\ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/internals/WrappedLazy.java b/BJC-Utils2/src/main/java/bjc/utils/data/internals/WrappedLazy.java deleted file mode 100644 index 4175724..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/data/internals/WrappedLazy.java +++ /dev/null @@ -1,62 +0,0 @@ -package bjc.utils.data.internals; - -import java.util.function.Function; -import java.util.function.UnaryOperator; - -import bjc.utils.data.IHolder; -import bjc.utils.data.Lazy; - -public class WrappedLazy<ContainedType> implements IHolder<ContainedType> { - private final IHolder<IHolder<ContainedType>> held; - - public WrappedLazy(final IHolder<ContainedType> wrappedHolder) { - held = new Lazy<>(wrappedHolder); - } - - // This has an extra parameter, because otherwise it erases to the same - // as the public one - private WrappedLazy(final IHolder<IHolder<ContainedType>> wrappedHolder, final boolean dummy) { - held = wrappedHolder; - } - - @Override - public <BoundType> IHolder<BoundType> bind(final Function<ContainedType, IHolder<BoundType>> binder) { - final IHolder<IHolder<BoundType>> newHolder = held.map((containedHolder) -> { - return containedHolder.bind(binder); - }); - - return new WrappedLazy<>(newHolder, false); - } - - @Override - public <NewType> Function<ContainedType, IHolder<NewType>> lift(final Function<ContainedType, NewType> func) { - return (val) -> { - return new Lazy<>(func.apply(val)); - }; - } - - @Override - public <MappedType> IHolder<MappedType> map(final Function<ContainedType, MappedType> mapper) { - final IHolder<IHolder<MappedType>> newHolder = held.map((containedHolder) -> { - return containedHolder.map(mapper); - }); - - return new WrappedLazy<>(newHolder, false); - } - - @Override - public IHolder<ContainedType> transform(final UnaryOperator<ContainedType> transformer) { - held.transform((containedHolder) -> { - return containedHolder.transform(transformer); - }); - - return this; - } - - @Override - public <UnwrappedType> UnwrappedType unwrap(final Function<ContainedType, UnwrappedType> unwrapper) { - return held.unwrap((containedHolder) -> { - return containedHolder.unwrap(unwrapper); - }); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/internals/WrappedOption.java b/BJC-Utils2/src/main/java/bjc/utils/data/internals/WrappedOption.java deleted file mode 100644 index 512c699..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/data/internals/WrappedOption.java +++ /dev/null @@ -1,76 +0,0 @@ -package bjc.utils.data.internals; - -import java.util.function.Function; -import java.util.function.UnaryOperator; - -import bjc.utils.data.IHolder; -import bjc.utils.data.Option; - -public class WrappedOption<ContainedType> implements IHolder<ContainedType> { - private final IHolder<IHolder<ContainedType>> held; - - public WrappedOption(final IHolder<ContainedType> seedValue) { - held = new Option<>(seedValue); - } - - private WrappedOption(final IHolder<IHolder<ContainedType>> toHold, final boolean dummy) { - held = toHold; - } - - @Override - public <BoundType> IHolder<BoundType> bind(final Function<ContainedType, IHolder<BoundType>> binder) { - final IHolder<IHolder<BoundType>> newHolder = held.map((containedHolder) -> { - return containedHolder.bind((containedValue) -> { - if (containedValue == null) return new Option<>(null); - - return binder.apply(containedValue); - }); - }); - - return new WrappedOption<>(newHolder, false); - } - - @Override - public <NewType> Function<ContainedType, IHolder<NewType>> lift(final Function<ContainedType, NewType> func) { - return (val) -> { - return new Option<>(func.apply(val)); - }; - } - - @Override - public <MappedType> IHolder<MappedType> map(final Function<ContainedType, MappedType> mapper) { - final IHolder<IHolder<MappedType>> newHolder = held.map((containedHolder) -> { - return containedHolder.map((containedValue) -> { - if (containedValue == null) return null; - - return mapper.apply(containedValue); - }); - }); - - return new WrappedOption<>(newHolder, false); - } - - @Override - public IHolder<ContainedType> transform(final UnaryOperator<ContainedType> transformer) { - held.transform((containedHolder) -> { - return containedHolder.transform((containedValue) -> { - if (containedValue == null) return null; - - return transformer.apply(containedValue); - }); - }); - - return this; - } - - @Override - public <UnwrappedType> UnwrappedType unwrap(final Function<ContainedType, UnwrappedType> unwrapper) { - return held.unwrap((containedHolder) -> { - return containedHolder.unwrap((containedValue) -> { - if (containedValue == null) return null; - - return unwrapper.apply(containedValue); - }); - }); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/esodata/AbbrevMap.java b/BJC-Utils2/src/main/java/bjc/utils/esodata/AbbrevMap.java deleted file mode 100644 index 0d54471..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/esodata/AbbrevMap.java +++ /dev/null @@ -1,227 +0,0 @@ -package bjc.utils.esodata; - -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; - -import com.google.common.collect.HashMultimap; -import com.google.common.collect.SetMultimap; - -import bjc.utils.funcdata.FunctionalMap; -import bjc.utils.funcdata.IMap; - -/** - * Represents a mapping from a set of strings to a mapping of all unambiguous - * prefixes of their respective strings. - * - * This works the same as Ruby's Abbrev. - * - * @author EVE - * - */ -public class AbbrevMap { - /* - * All of the words we have abbreviations for. - */ - private final Set<String> wrds; - - /* - * Maps abbreviations to their strings. - */ - private IMap<String, String> abbrevMap; - - /* - * Counts how many times we've seen a substring. - */ - private Set<String> seen; - - /* - * Maps ambiguous abbreviations to the strings they could be. - */ - private SetMultimap<String, String> ambMap; - - /** - * Create a new abbreviation map. - * - * @param words - * The initial set of words to put in the map. - */ - public AbbrevMap(final String... words) { - wrds = new HashSet<>(Arrays.asList(words)); - - recalculate(); - } - - /** - * Recalculate all the abbreviations in this map. - */ - public void recalculate() { - abbrevMap = new FunctionalMap<>(); - - ambMap = HashMultimap.create(); - - seen = new HashSet<>(); - - for (final String word : wrds) { - /* - * A word always abbreviates to itself. - */ - abbrevMap.put(word, word); - - intAddWord(word); - } - } - - /** - * Adds words to the abbreviation map. - * - * @param words - * The words to add to the abbreviation map. - */ - public void addWords(final String... words) { - wrds.addAll(Arrays.asList(words)); - - for (final String word : words) { - /* - * A word always abbreviates to itself. - */ - abbrevMap.put(word, word); - - intAddWord(word); - } - } - - /* - * Actually add abbreviations of a word. - */ - private void intAddWord(final String word) { - /* - * Skip blank words. - */ - if (word.equals("")) return; - - /* - * Handle each possible abbreviation. - */ - for (int i = word.length(); i > 0; i--) { - final String subword = word.substring(0, i); - - if (seen.contains(subword)) { - /* - * Remove a mapping if its ambiguous and not a - * whole word. - */ - if (abbrevMap.containsKey(subword) && !wrds.contains(subword)) { - final String oldword = abbrevMap.remove(subword); - - ambMap.put(subword, oldword); - ambMap.put(subword, word); - } else if (!wrds.contains(subword)) { - ambMap.put(subword, word); - } - } else { - seen.add(subword); - - abbrevMap.put(subword, word); - } - } - } - - /** - * Removes words from the abbreviation map. - * - * NOTE: There may be inconsistent behavior after removing a word from - * the map. Use {@link AbbrevMap#recalculate()} to fix it if it occurs. - * - * @param words - * The words to remove. - */ - public void removeWords(final String... words) { - wrds.removeAll(Arrays.asList(words)); - - for (final String word : words) { - intRemoveWord(word); - } - } - - /* - * Actually remove a word. - */ - private void intRemoveWord(final String word) { - /* - * Skip blank words. - */ - if (word.equals("")) return; - - /* - * Handle each possible abbreviation. - */ - for (int i = word.length(); i > 0; i--) { - final String subword = word.substring(0, i); - - if (abbrevMap.containsKey(subword)) { - abbrevMap.remove(subword); - } else { - ambMap.remove(subword, word); - - final Set<String> possWords = ambMap.get(subword); - - if (possWords.size() == 0) { - seen.remove(subword); - } else if (possWords.size() == 1) { - final String newWord = possWords.iterator().next(); - - abbrevMap.put(subword, newWord); - ambMap.remove(subword, newWord); - } - } - } - } - - /** - * Convert an abbreviation into all the strings it could abbreviate - * into. - * - * @param abbrev - * The abbreviation to convert. - * - * @return All the expansions for the provided abbreviation. - */ - public String[] deabbrev(final String abbrev) { - if (abbrevMap.containsKey(abbrev)) - return new String[] { abbrevMap.get(abbrev) }; - else return ambMap.get(abbrev).toArray(new String[0]); - } - - @Override - public int hashCode() { - final int prime = 31; - - int result = 1; - result = prime * result + (wrds == null ? 0 : wrds.hashCode()); - - return result; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) return true; - if (obj == null) return false; - if (!(obj instanceof AbbrevMap)) return false; - - final AbbrevMap other = (AbbrevMap) obj; - - if (wrds == null) { - if (other.wrds != null) return false; - } else if (!wrds.equals(other.wrds)) return false; - - return true; - } - - @Override - public String toString() { - final String fmt = "AbbrevMap [wrds=%s, abbrevMap=%s, seen=%s, ambMap=%s]"; - - return String.format(fmt, wrds, abbrevMap, seen, ambMap); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/esodata/Directory.java b/BJC-Utils2/src/main/java/bjc/utils/esodata/Directory.java deleted file mode 100644 index 17b70f5..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/esodata/Directory.java +++ /dev/null @@ -1,106 +0,0 @@ -package bjc.utils.esodata;
-
-/**
- * Represents a hierarchical map.
- *
- * What's useful about this is that you can hand sub-directories to people and
- * be able to ensure that they can't write outside of it.
- *
- * @param <K>
- * The key type of the map.
- * @param <V>
- * The value type of the map.
- */
-public interface Directory<K, V> {
- /**
- * Retrieves a given sub-directory.
- *
- * @param key
- * The key to retrieve the sub-directory for.
- *
- * @return The sub-directory under that name.
- *
- * @throws IllegalArgumentException
- * If the given sub-directory doesn't exist.
- */
- Directory<K, V> getSubdirectory(K key);
-
- /**
- * Check if a given sub-directory exists.
- *
- * @param key
- * The key to look for the sub-directory under.
- *
- * @return Whether or not a sub-directory of that name exists.
- */
- boolean hasSubdirectory(K key);
-
- /**
- * Insert a sub-directory into the dictionary.
- *
- * @param key
- * The name of the new sub-directory
- * @param value
- * The sub-directory to insert
- *
- * @return The old sub-directory attached to this key, or null if such a
- * sub-directory didn't exist
- */
- Directory<K, V> putSubdirectory(K key, Directory<K, V> value);
-
- /**
- * Create a new sub-directory.
- *
- * Will fail if a sub-directory of that name already exists.
- *
- * @param key
- * The name of the new sub-directory.
- *
- * @return The new sub-directory, or null if one by that name already
- * exists.
- */
- default Directory<K, V> newSubdirectory(final K key) {
- if (hasSubdirectory(key)) return null;
-
- final Directory<K, V> dir = new SimpleDirectory<>();
-
- putSubdirectory(key, dir);
-
- return dir;
- }
-
- /**
- * Check if the directory contains a data-item under the given key.
- *
- * @param key
- * The key to check for.
- *
- * @return Whether or not there is a data item for the given key.
- */
- boolean containsKey(K key);
-
- /**
- * Retrieve a given data-item from the directory.
- *
- * @param key
- * The key to retrieve data for.
- *
- * @return The value for the given key.
- *
- * @throws IllegalArgumentException
- * If no value exists for the given key.
- */
- V getKey(K key);
-
- /**
- * Insert a data-item into the directory.
- *
- * @param key
- * The key to insert into.
- * @param val
- * The value to insert.
- *
- * @return The old value of key, or null if such a value didn't exist.
- */
- V putKey(K key, V val);
-}
\ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/esodata/DoubleTape.java b/BJC-Utils2/src/main/java/bjc/utils/esodata/DoubleTape.java deleted file mode 100644 index 5c463c6..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/esodata/DoubleTape.java +++ /dev/null @@ -1,258 +0,0 @@ -package bjc.utils.esodata; - -/** - * Double-sided tape is essentially two tapes stuck together with a shared - * cursor. - * - * The main way a double-sided tape differs is that it can be flipped, allowing - * access to another set of data. - * - * However, there is only one cursor, and the position of the cursor on one side - * is the inverse of the position on the other side. - * - * When one side is extended, a null will be inserted into the inactive side - * regardless of the auto-extension policy of the tape. The policy will still be - * respected for the active side. - * - * All operations that refer to the tape refer to the currently active side of - * the tape, except for flip. - * - * Flip refers to the entire tape for 'obvious' reasons. - * - * @param <T> - * The element type of the tape. - * @author bjculkin - */ -public class DoubleTape<T> implements Tape<T> { - private Tape<T> front; - private Tape<T> back; - - /** - * Create a new empty double-sided tape that doesn't autoextend. - */ - public DoubleTape() { - this(false); - } - - /** - * Create a new empty double-sided tape that follows the specified - * auto-extension policy. - * - * @param autoExtnd - * Whether or not to auto-extend the tape to the right w/ - * nulls. - */ - public DoubleTape(final boolean autoExtnd) { - front = new SingleTape<>(autoExtnd); - back = new SingleTape<>(autoExtnd); - } - - /** - * Get the item the tape is currently on. - * - * @return The item the tape is on. - */ - @Override - public T item() { - return front.item(); - } - - /** - * Set the item the tape is currently on. - * - * @param itm - * The new value for the tape item. - */ - @Override - public void item(final T itm) { - front.item(itm); - } - - /** - * Get the current number of elements in the tape. - * - * @return The current number of elements in the tape. - */ - @Override - public int size() { - return front.size(); - } - - @Override - public int position() { - return front.position(); - } - - /** - * Insert an element before the current item. - * - * @param itm - * The item to add. - */ - @Override - public void insertBefore(final T itm) { - front.insertBefore(itm); - back.insertAfter(null); - } - - /** - * Insert an element after the current item. - */ - @Override - public void insertAfter(final T itm) { - front.insertAfter(itm); - back.insertBefore(itm); - } - - /** - * Remove the current element. - * - * Also moves the cursor back one step if possible to maintain relative - * position, and removes the corresponding item from the non-active side - * - * @return The removed item from the active side. - */ - @Override - public T remove() { - back.remove(); - - return front.remove(); - } - - /** - * Move the cursor to the left-most position. - */ - @Override - public void first() { - front.first(); - back.last(); - } - - /** - * Move the cursor the right-most position. - */ - @Override - public void last() { - front.last(); - back.first(); - } - - /** - * Move the cursor one space left. - * - * The cursor can't go past zero. - * - * @return True if the cursor was moved left. - */ - @Override - public boolean left() { - return left(1); - } - - /** - * Move the cursor the specified amount left. - * - * The cursor can't go past zero. Attempts to move the cursor by amounts - * that would exceed zero don't move the cursor at all. - * - * @param amt - * The amount to attempt to move the cursor left. - * - * @return True if the cursor was moved left. - */ - @Override - public boolean left(final int amt) { - final boolean succ = front.left(amt); - - if (succ) { - back.right(amt); - } - - return succ; - } - - /** - * Move the cursor one space right. - * - * Moving the cursor right will auto-extend the tape if that is enabled. - * - * @return Whether the cursor was moved right. - */ - @Override - public boolean right() { - return right(1); - } - - /** - * Move the cursor the specified amount right. - * - * Moving the cursor right will auto-extend the tape if that is enabled. - * - * @param amt - * The amount to move the cursor right by. - * - * @return Whether the cursor was moved right. - */ - @Override - public boolean right(final int amt) { - final boolean succ = front.right(amt); - - if (succ) { - back.left(amt); - } - - return succ; - } - - /** - * Flips the tape. - * - * The active side becomes inactive, and the inactive side becomes - * active. - */ - public void flip() { - final Tape<T> tmp = front; - - front = back; - - back = tmp; - } - - @Override - public boolean isDoubleSided() { - return true; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + (back == null ? 0 : back.hashCode()); - result = prime * result + (front == null ? 0 : front.hashCode()); - return result; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) return true; - if (obj == null) return false; - if (!(obj instanceof DoubleTape<?>)) return false; - - final DoubleTape<?> other = (DoubleTape<?>) obj; - - if (back == null) { - if (other.back != null) return false; - } else if (!back.equals(other.back)) return false; - - if (front == null) { - if (other.front != null) return false; - } else if (!front.equals(other.front)) return false; - - return true; - } - - @Override - public String toString() { - return String.format("DoubleTape [front=%s, back=%s]", front, back); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/esodata/PushdownMap.java b/BJC-Utils2/src/main/java/bjc/utils/esodata/PushdownMap.java deleted file mode 100644 index a631704..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/esodata/PushdownMap.java +++ /dev/null @@ -1,148 +0,0 @@ -package bjc.utils.esodata; - -import java.util.function.BiConsumer; -import java.util.function.Consumer; -import java.util.function.Function; - -import bjc.utils.funcdata.FunctionalMap; -import bjc.utils.funcdata.IList; -import bjc.utils.funcdata.IMap; - -/** - * A variant of a map where inserting a duplicate key shadows the existing value - * instead of replacing it. - * - * @author EVE - * - * @param <KeyType> - * The key of the map. - * @param <ValueType> - * The values in the map. - */ -public class PushdownMap<KeyType, ValueType> implements IMap<KeyType, ValueType> { - private final IMap<KeyType, Stack<ValueType>> backing; - - /** - * Create a new empty stack-based map. - */ - public PushdownMap() { - backing = new FunctionalMap<>(); - } - - private PushdownMap(final IMap<KeyType, Stack<ValueType>> back) { - backing = back; - } - - @Override - public void clear() { - backing.clear(); - } - - @Override - public boolean containsKey(final KeyType key) { - return backing.containsKey(key); - } - - @Override - public IMap<KeyType, ValueType> extend() { - return new PushdownMap<>(backing.extend()); - } - - @Override - public void forEach(final BiConsumer<KeyType, ValueType> action) { - backing.forEach((key, stk) -> action.accept(key, stk.top())); - } - - @Override - public void forEachKey(final Consumer<KeyType> action) { - backing.forEachKey(action); - } - - @Override - public void forEachValue(final Consumer<ValueType> action) { - backing.forEachValue(stk -> action.accept(stk.top())); - } - - @Override - public ValueType get(final KeyType key) { - return backing.get(key).top(); - } - - @Override - public int size() { - return backing.size(); - } - - @Override - public IList<KeyType> keyList() { - return backing.keyList(); - } - - @Override - public <V2> IMap<KeyType, V2> transform(final Function<ValueType, V2> transformer) { - throw new UnsupportedOperationException("Cannot transform pushdown maps."); - } - - @Override - public ValueType put(final KeyType key, final ValueType val) { - if (backing.containsKey(key)) { - final Stack<ValueType> stk = backing.get(key); - - final ValueType vl = stk.top(); - - stk.push(val); - - return vl; - } else { - final Stack<ValueType> stk = new SimpleStack<>(); - - stk.push(val); - - return null; - } - } - - @Override - public ValueType remove(final KeyType key) { - final Stack<ValueType> stk = backing.get(key); - - if (stk.size() > 1) - return stk.pop(); - else return backing.remove(key).top(); - } - - @Override - public IList<ValueType> valueList() { - return backing.valueList().map(stk -> stk.top()); - } - - @Override - public int hashCode() { - final int prime = 31; - - int result = 1; - result = prime * result + (backing == null ? 0 : backing.hashCode()); - - return result; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) return true; - if (obj == null) return false; - if (!(obj instanceof PushdownMap<?, ?>)) return false; - - final PushdownMap<?, ?> other = (PushdownMap<?, ?>) obj; - - if (backing == null) { - if (other.backing != null) return false; - } else if (!backing.equals(other.backing)) return false; - - return true; - } - - @Override - public String toString() { - return String.format("PushdownMap [backing=%s]", backing); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/esodata/QueueStack.java b/BJC-Utils2/src/main/java/bjc/utils/esodata/QueueStack.java deleted file mode 100644 index 850598a..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/esodata/QueueStack.java +++ /dev/null @@ -1,88 +0,0 @@ -package bjc.utils.esodata; - -import java.util.Deque; -import java.util.LinkedList; - -/** - * A FIFO implementation of a stack. - * - * @param <T> - * The datatype stored in the stack. - * @author Ben Culkin - */ -public class QueueStack<T> extends Stack<T> { - private final Deque<T> backing; - - /** - * Create a new empty stack queue. - * - */ - public QueueStack() { - backing = new LinkedList<>(); - } - - @Override - public void push(final T elm) { - backing.add(elm); - } - - @Override - public T pop() { - if (backing.isEmpty()) throw new StackUnderflowException(); - - return backing.remove(); - } - - @Override - public T top() { - if (backing.isEmpty()) throw new StackUnderflowException(); - - return backing.peek(); - } - - @Override - public int size() { - return backing.size(); - } - - @Override - public boolean empty() { - return backing.size() == 0; - } - - @SuppressWarnings("unchecked") - @Override - public T[] toArray() { - return (T[]) backing.toArray(); - } - - @Override - public String toString() { - return String.format("QueueStack [backing=%s]", backing); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - - result = prime * result + (backing == null ? 0 : backing.hashCode()); - - return result; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) return true; - if (obj == null) return false; - if (!(obj instanceof QueueStack<?>)) return false; - - final QueueStack<?> other = (QueueStack<?>) obj; - - if (backing == null) { - if (other.backing != null) return false; - } else if (!backing.equals(other.backing)) return false; - - return true; - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/esodata/SimpleDirectory.java b/BJC-Utils2/src/main/java/bjc/utils/esodata/SimpleDirectory.java deleted file mode 100644 index 69fd019..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/esodata/SimpleDirectory.java +++ /dev/null @@ -1,95 +0,0 @@ -package bjc.utils.esodata; - -import bjc.utils.funcdata.FunctionalMap; -import bjc.utils.funcdata.IMap; - -/** - * Simple implementation of {@link Directory}. - * - * Has a split namespace for data and children. - * - * @author EVE - * - * @param <K> - * The key type of the directory. - * @param <V> - * The value type of the directory. - */ -public class SimpleDirectory<K, V> implements Directory<K, V> { - private final IMap<K, Directory<K, V>> children; - - private final IMap<K, V> data; - - /** - * Create a new directory. - */ - public SimpleDirectory() { - children = new FunctionalMap<>(); - data = new FunctionalMap<>(); - } - - @Override - public Directory<K, V> getSubdirectory(final K key) { - return children.get(key); - } - - @Override - public boolean hasSubdirectory(final K key) { - return children.containsKey(key); - } - - @Override - public Directory<K, V> putSubdirectory(final K key, final Directory<K, V> val) { - return children.put(key, val); - } - - @Override - public boolean containsKey(final K key) { - return data.containsKey(key); - } - - @Override - public V getKey(final K key) { - return data.get(key); - } - - @Override - public V putKey(final K key, final V val) { - return data.put(key, val); - } - - @Override - public int hashCode() { - final int prime = 31; - - int result = 1; - result = prime * result + (children == null ? 0 : children.hashCode()); - result = prime * result + (data == null ? 0 : data.hashCode()); - - return result; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) return true; - if (obj == null) return false; - if (!(obj instanceof SimpleDirectory<?, ?>)) return false; - - final SimpleDirectory<?, ?> other = (SimpleDirectory<?, ?>) obj; - - if (children == null) { - if (other.children != null) return false; - } else if (!children.equals(other.children)) return false; - - if (data == null) { - if (other.data != null) return false; - } else if (!data.equals(other.data)) return false; - - return true; - } - - @Override - public String toString() { - return String.format("SimpleDirectory [children=%s, data=%s]", children, data); - } -}
\ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/esodata/SimpleStack.java b/BJC-Utils2/src/main/java/bjc/utils/esodata/SimpleStack.java deleted file mode 100644 index fdb3300..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/esodata/SimpleStack.java +++ /dev/null @@ -1,88 +0,0 @@ -package bjc.utils.esodata; - -import java.util.Deque; -import java.util.LinkedList; - -/** - * Simple implementation of a stack. - * - * @param <T> - * The datatype stored in the stack. - * @author Ben Culkin - */ -public class SimpleStack<T> extends Stack<T> { - private final Deque<T> backing; - - /** - * Create a new empty stack. - * - */ - public SimpleStack() { - backing = new LinkedList<>(); - } - - @Override - public void push(final T elm) { - backing.push(elm); - } - - @Override - public T pop() { - if (backing.isEmpty()) throw new StackUnderflowException(); - - return backing.pop(); - } - - @Override - public T top() { - if (backing.isEmpty()) throw new StackUnderflowException(); - - return backing.peek(); - } - - @Override - public int size() { - return backing.size(); - } - - @Override - public boolean empty() { - return backing.size() == 0; - } - - @Override - @SuppressWarnings("unchecked") - public T[] toArray() { - return (T[]) backing.toArray(); - } - - @Override - public int hashCode() { - final int prime = 31; - - int result = 1; - result = prime * result + (backing == null ? 0 : backing.hashCode()); - - return result; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) return true; - if (obj == null) return false; - if (!(obj instanceof SimpleStack<?>)) return false; - - final SimpleStack<?> other = (SimpleStack<?>) obj; - - if (backing == null) { - if (other.backing != null) return false; - } else if (!backing.equals(other.backing)) return false; - - return true; - } - - @Override - public String toString() { - return String.format("SimpleStack [backing=%s]", backing); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/esodata/SingleTape.java b/BJC-Utils2/src/main/java/bjc/utils/esodata/SingleTape.java deleted file mode 100644 index c50be92..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/esodata/SingleTape.java +++ /dev/null @@ -1,255 +0,0 @@ -package bjc.utils.esodata; - -import java.util.ArrayList; - -/** - * A tape is a one-dimensional array that can only be accessed in one position - * at a time. - * - * A tape is essentially a 1D array with a cursor attached to it, and you can - * only affect elements at that cursor. The size of the array is theoretically - * unbounded to the right, but in practice bounded by available memory. - * - * You can choose whether or not you want the tape to automatically extend - * itself to the right with null elements by specifying its auto-extension - * policy. - * - * @param <T> - * The element type of the tape. - * - * @author bjculkin - */ -public class SingleTape<T> implements Tape<T> { - protected ArrayList<T> backing; - protected int pos; - - protected boolean autoExtend; - - /** - * Create a new tape with the specified contents that doesn't - * autoextend. - */ - public SingleTape(T... vals) { - autoExtend = false; - - backing = new ArrayList(vals.length); - - for(T val : vals) { - backing.add(val); - } - } - /** - * Create a new empty tape that doesn't autoextend. - */ - public SingleTape() { - this(false); - } - - /** - * Create a new empty tape that follows the specified auto-extension - * policy. - * - * @param autoExtnd - * Whether or not to auto-extend the tape to the right w/ - * nulls. - */ - public SingleTape(final boolean autoExtnd) { - autoExtend = autoExtnd; - - backing = new ArrayList<>(); - } - - /** - * Get the item the tape is currently on. - * - * @return The item the tape is on. - */ - @Override - public T item() { - return backing.get(pos); - } - - /** - * Set the item the tape is currently on. - * - * @param itm - * The new value for the tape item. - */ - @Override - public void item(final T itm) { - backing.set(pos, itm); - } - - /** - * Get the current number of elements in the tape. - * - * @return The current number of elements in the tape. - */ - @Override - public int size() { - return backing.size(); - } - - @Override - public int position() { - return pos; - } - - /** - * Insert an element before the current item. - * - * @param itm - * The item to add. - */ - @Override - public void insertBefore(final T itm) { - backing.add(pos, itm); - } - - /** - * Insert an element after the current item. - */ - @Override - public void insertAfter(final T itm) { - if (pos == backing.size() - 1) { - backing.add(itm); - } else { - backing.add(pos + 1, itm); - } - } - - /** - * Remove the current element. - * - * Also moves the cursor back one step if possible to maintain relative - * position. - * - * @return The removed item. - */ - @Override - public T remove() { - final T res = backing.remove(pos); - if (pos != 0) { - pos -= 1; - } - return res; - } - - /** - * Move the cursor to the left-most position. - */ - @Override - public void first() { - pos = 0; - } - - /** - * Move the cursor the right-most position. - */ - @Override - public void last() { - pos = backing.size() - 1; - } - - /** - * Move the cursor one space left. - * - * The cursor can't go past zero. - * - * @return True if the cursor was moved left. - */ - @Override - public boolean left() { - return left(1); - } - - /** - * Move the cursor the specified amount left. - * - * The cursor can't go past zero. Attempts to move the cursor by amounts - * that would exceed zero don't move the cursor at all. - * - * @param amt - * The amount to attempt to move the cursor left. - * - * @return True if the cursor was moved left. - */ - @Override - public boolean left(final int amt) { - if (pos - amt < 0) return false; - - pos -= amt; - return true; - } - - /** - * Move the cursor one space right. - * - * Moving the cursor right will auto-extend the tape if that is enabled. - * - * @return Whether the cursor was moved right. - */ - @Override - public boolean right() { - return right(1); - } - - /** - * Move the cursor the specified amount right. - * - * Moving the cursor right will auto-extend the tape if that is enabled. - * - * @param amt - * The amount to move the cursor right by. - * - * @return Whether the cursor was moved right. - */ - @Override - public boolean right(final int amt) { - if (pos + amt >= backing.size() - 1) { - if (autoExtend) { - while (pos + amt >= backing.size() - 1) { - backing.add(null); - } - } else return false; - } - - pos += amt; - return true; - } - - @Override - public boolean isDoubleSided() { - return false; - } - - @Override - public int hashCode() { - final int prime = 31; - - int result = 1; - result = prime * result + (backing == null ? 0 : backing.hashCode()); - - return result; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) return true; - if (obj == null) return false; - if (!(obj instanceof SingleTape<?>)) return false; - - final SingleTape<?> other = (SingleTape<?>) obj; - - if (backing == null) { - if (other.backing != null) return false; - } else if (!backing.equals(other.backing)) return false; - - return true; - } - - @Override - public String toString() { - return String.format("SingleTape [backing=%s, pos=%s, autoExtend=%s]", backing, pos, autoExtend); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/esodata/SpaghettiStack.java b/BJC-Utils2/src/main/java/bjc/utils/esodata/SpaghettiStack.java deleted file mode 100644 index 7c8c757..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/esodata/SpaghettiStack.java +++ /dev/null @@ -1,99 +0,0 @@ -package bjc.utils.esodata; - -import java.util.Arrays; -import java.util.stream.Stream; - -/* - * Implements a spaghetti stack, which is a stack that is branched off of a - * parent stack. - * - * @param T The datatype stored in the stack. - * @author Ben Culkin - */ -class SpaghettiStack<T> extends Stack<T> { - private final Stack<T> backing; - - private final Stack<T> parent; - - /** - * Create a new empty spaghetti stack, off of the specified parent. - * - * @param par - * The parent stack - */ - public SpaghettiStack(final Stack<T> par) { - backing = new SimpleStack<>(); - - parent = par; - } - - @Override - public void push(final T elm) { - backing.push(elm); - } - - @Override - public T pop() { - if (backing.empty()) return parent.pop(); - - return backing.pop(); - } - - @Override - public T top() { - if (backing.empty()) return parent.top(); - - return backing.top(); - } - - @Override - public int size() { - return parent.size() + backing.size(); - } - - @Override - public boolean empty() { - return backing.empty() && parent.empty(); - } - - @SuppressWarnings("unchecked") - @Override - public T[] toArray() { - return (T[]) Stream.concat(Arrays.stream(parent.toArray()), Arrays.stream(backing.toArray())).toArray(); - } - - @Override - public int hashCode() { - final int prime = 31; - - int result = 1; - result = prime * result + (backing == null ? 0 : backing.hashCode()); - result = prime * result + (parent == null ? 0 : parent.hashCode()); - - return result; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) return true; - if (obj == null) return false; - if (!(obj instanceof SpaghettiStack<?>)) return false; - - final SpaghettiStack<?> other = (SpaghettiStack<?>) obj; - - if (backing == null) { - if (other.backing != null) return false; - } else if (!backing.equals(other.backing)) return false; - - if (parent == null) { - if (other.parent != null) return false; - } else if (!parent.equals(other.parent)) return false; - - return true; - } - - @Override - public String toString() { - return String.format("SpaghettiStack [backing=%s, parent=%s]", backing, parent); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/esodata/Stack.java b/BJC-Utils2/src/main/java/bjc/utils/esodata/Stack.java deleted file mode 100644 index 9d74e9a..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/esodata/Stack.java +++ /dev/null @@ -1,459 +0,0 @@ -package bjc.utils.esodata; - -import java.util.ArrayList; -import java.util.List; -import java.util.function.Consumer; - -/** - * A stack, with support for combinators. - * - * A FILO stack with support for forth/factor style combinators. - * - * <p> - * <h2>Stack underflow</h2> - * <p> - * NOTE: In general, using any operation that attempts to remove more data from - * the stack than exists will cause a {@link StackUnderflowException} to be - * thrown. Check the size of the stack if you want to avoid this. - * <p> - * </p> - * - * @param <T> - * The datatype stored in the stack. - * - * @author Ben Culkin - */ -public abstract class Stack<T> { - /** - * The exception thrown when attempting to access an element from the - * stack that isn't there. - * - * @author EVE - * - */ - public static class StackUnderflowException extends RuntimeException { - - /** - * - */ - private static final long serialVersionUID = 1423867176204571539L; - } - - /** - * Push an element onto the stack. - * - * @param elm - * The element to insert. - */ - public abstract void push(T elm); - - /** - * Pop an element off of the stack. - * - * @return The element on top of the stack. - */ - public abstract T pop(); - - /** - * Retrieve the top element of this stack without removing it from the - * stack. - * - * @return The top element of this stack. - */ - public abstract T top(); - - /** - * Get the number of elements in the stack. - * - * @return the number of elements in the stack. - */ - public abstract int size(); - - /** - * Check if the stack is empty. - * - * @return Whether or not the stack is empty. - */ - public abstract boolean empty(); - - /** - * Create a spaghetti stack branching off of this one. - * - * @return A spaghetti stack with this stack as a parent. - */ - public Stack<T> spaghettify() { - return new SpaghettiStack<>(this); - } - - /* - * Basic combinators - */ - - /** - * Drop n items from the stack. - * - * @param n - * The number of items to drop. - */ - public void drop(final int n) { - for (int i = 0; i < n; i++) { - pop(); - } - } - - /** - * Drop one item from the stack. - */ - public void drop() { - drop(1); - } - - /** - * Delete n items below the current one. - * - * @param n - * The number of items below the top to delete. - */ - public void nip(final int n) { - final T elm = pop(); - - drop(n); - - push(elm); - } - - /** - * Delete the second element in the stack. - */ - public void nip() { - nip(1); - } - - /** - * Replicate the top n items of the stack m times. - * - * @param n - * The number of items to duplicate. - * @param m - * The number of times to duplicate items. - */ - public void multidup(final int n, final int m) { - final List<T> lst = new ArrayList<>(n); - - for (int i = n; i > 0; i--) { - lst.set(i - 1, pop()); - } - - for (int i = 0; i < m; i++) { - for (final T elm : lst) { - push(elm); - } - } - } - - /** - * Duplicate the top n items of the stack. - * - * @param n - * The number of items to duplicate. - */ - public void dup(final int n) { - multidup(n, 2); - } - - /** - * Duplicate the top item on the stack. - */ - public void dup() { - dup(1); - } - - /** - * Replicate the n elements below the top one m times. - * - * @param n - * The number of items to duplicate. - * @param m - * The number of times to duplicate items. - */ - public void multiover(final int n, final int m) { - final List<T> lst = new ArrayList<>(n); - - final T elm = pop(); - - for (int i = n; i > 0; i--) { - lst.set(i - 1, pop()); - } - - for (final T nelm : lst) { - push(nelm); - } - push(elm); - - for (int i = 1; i < m; i++) { - for (final T nelm : lst) { - push(nelm); - } - } - } - - /** - * Duplicate the n elements below the top one. - * - * @param n - * The number of items to duplicate. - */ - public void over(final int n) { - multiover(n, 2); - } - - /** - * Duplicate the second item in the stack. - */ - public void over() { - over(1); - } - - /** - * Duplicate the third item in the stack. - */ - public void pick() { - final T z = pop(); - final T y = pop(); - final T x = pop(); - - push(x); - push(y); - push(z); - push(x); - } - - /** - * Swap the top two items on the stack. - */ - public void swap() { - final T y = pop(); - final T x = pop(); - - push(y); - push(x); - } - - /** - * Duplicate the second item below the first item. - */ - public void deepdup() { - final T y = pop(); - final T x = pop(); - - push(x); - push(x); - push(y); - } - - /** - * Swap the second and third items in the stack. - */ - public void deepswap() { - final T z = pop(); - final T y = pop(); - final T x = pop(); - - push(y); - push(x); - push(z); - } - - /** - * Rotate the top three items on the stack - */ - public void rot() { - final T z = pop(); - final T y = pop(); - final T x = pop(); - - push(y); - push(z); - push(x); - } - - /** - * Inversely rotate the top three items on the stack - */ - public void invrot() { - final T z = pop(); - final T y = pop(); - final T x = pop(); - - push(z); - push(x); - push(y); - } - - /* - * Dataflow Combinators - */ - /** - * Hides the top n elements on the stack from cons. - * - * @param n - * The number of elements to hide. - * @param cons - * The action to hide the elements from - */ - public void dip(final int n, final Consumer<Stack<T>> cons) { - final List<T> elms = new ArrayList<>(n); - - for (int i = n; i > 0; i--) { - elms.set(i - 1, pop()); - } - - cons.accept(this); - - for (final T elm : elms) { - push(elm); - } - } - - /** - * Hide the top element of the stack from cons. - * - * @param cons - * The action to hide the top from - */ - public void dip(final Consumer<Stack<T>> cons) { - dip(1, cons); - } - - /** - * Copy the top n elements on the stack, replacing them once cons is - * done. - * - * @param n - * The number of elements to copy. - * @param cons - * The action to execute. - */ - public void keep(final int n, final Consumer<Stack<T>> cons) { - dup(n); - dip(n, cons); - } - - /** - * Apply all the actions in conses to the top n elements of the stack. - * - * @param n - * The number of elements to give to cons. - * @param conses - * The actions to execute. - */ - public void multicleave(final int n, final List<Consumer<Stack<T>>> conses) { - final List<T> elms = new ArrayList<>(n); - - for (int i = n; i > 0; i--) { - elms.set(i - 1, pop()); - } - - for (final Consumer<Stack<T>> cons : conses) { - for (final T elm : elms) { - push(elm); - } - - cons.accept(this); - } - } - - /** - * Apply all the actions in conses to the top element of the stack. - * - * @param conses - * The actions to execute. - */ - public void cleave(final List<Consumer<Stack<T>>> conses) { - multicleave(1, conses); - } - - /** - * Apply every action in cons to n arguments. - * - * @param n - * The number of parameters each action takes. - * @param conses - * The actions to execute. - */ - public void multispread(final int n, final List<Consumer<Stack<T>>> conses) { - final List<List<T>> nelms = new ArrayList<>(conses.size()); - - for (int i = conses.size(); i > 0; i--) { - final List<T> elms = new ArrayList<>(n); - - for (int j = n; j > 0; j--) { - elms.set(j, pop()); - } - - nelms.set(i, elms); - } - - int i = 0; - for (final List<T> elms : nelms) { - for (final T elm : elms) { - push(elm); - } - - conses.get(i).accept(this); - i += 1; - } - } - - /** - * Apply the actions in cons to corresponding elements from the stack. - * - * @param conses - * The actions to execute. - */ - public void spread(final List<Consumer<Stack<T>>> conses) { - multispread(1, conses); - } - - /** - * Apply the action in cons to the first m groups of n arguments. - * - * @param n - * The number of arguments cons takes. - * @param m - * The number of time to call cons. - * @param cons - * The action to execute. - */ - public void multiapply(final int n, final int m, final Consumer<Stack<T>> cons) { - final List<Consumer<Stack<T>>> conses = new ArrayList<>(m); - - for (int i = 0; i < m; i++) { - conses.add(cons); - } - - multispread(n, conses); - } - - /** - * Apply cons n times to the corresponding elements in the stack. - * - * @param n - * The number of times to execute cons. - * @param cons - * The action to execute. - */ - public void apply(final int n, final Consumer<Stack<T>> cons) { - multiapply(1, n, cons); - } - - /* - * Misc. functions - */ - /** - * Get an array representing this stack. - * - * @return The stack as an array. - */ - public abstract T[] toArray(); -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/esodata/Tape.java b/BJC-Utils2/src/main/java/bjc/utils/esodata/Tape.java deleted file mode 100644 index b6a2c01..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/esodata/Tape.java +++ /dev/null @@ -1,126 +0,0 @@ -package bjc.utils.esodata; - -/** - * Interface for something that acts like a tape. - * - * A tape is essentially a 1D array with a cursor attached to it, and you can - * only affect elements at that cursor. The size of the array is theoretically - * unbounded to the right, but in practice bounded by available memory. - * - * @param <T> - * The element type of the tape. - * - * @author bjculkin - */ -public interface Tape<T> { - /** - * Get the item the tape is currently on. - * - * @return The item the tape is on. - */ - T item(); - - /** - * Set the item the tape is currently on. - * - * @param itm - * The new value for the tape item. - */ - void item(T itm); - - /** - * Get the current number of elements in the tape. - * - * @return The current number of elements in the tape. - */ - int size(); - - /** - * Get the position of the current item. - * - * @return The position of the current item. - */ - int position(); - - /** - * Insert an element before the current item. - * - * @param itm - * The item to add. - */ - void insertBefore(T itm); - - /** - * Insert an element after the current item. - * - * @param itm - * The item to insert. - */ - void insertAfter(T itm); - - /** - * Remove the current element. - * - * Also moves the cursor back one step if possible to maintain relative - * position. - * - * @return The removed item. - */ - T remove(); - - /** - * Move the cursor to the left-most position. - */ - void first(); - - /** - * Move the cursor the right-most position. - */ - void last(); - - /** - * Move the cursor one space left. - * - * The cursor can't go past zero. - * - * @return True if the cursor was moved left. - */ - boolean left(); - - /** - * Move the cursor the specified amount left. - * - * The cursor can't go past zero. Attempts to move the cursor by amounts - * that would exceed zero don't move the cursor at all. - * - * @param amt - * The amount to attempt to move the cursor left. - * - * @return True if the cursor was moved left. - */ - boolean left(int amt); - - /** - * Move the cursor one space right. - * - * @return Whether the cursor was moved right. - */ - boolean right(); - - /** - * Move the cursor the specified amount right. - * - * @param amt - * The amount to move the cursor right by. - * - * @return Whether the cursor was moved right. - */ - boolean right(int amt); - - /** - * Is this tape double sided? - * - * @return Whether or not this tape is double-sided. - */ - boolean isDoubleSided(); -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/esodata/TapeChanger.java b/BJC-Utils2/src/main/java/bjc/utils/esodata/TapeChanger.java deleted file mode 100644 index dc885bc..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/esodata/TapeChanger.java +++ /dev/null @@ -1,363 +0,0 @@ -package bjc.utils.esodata; - -/** - * A tape changer is essentially a tape of tapes. - * - * It has a current tape that you can do operations to, but also operations to - * add/remove other tapes. - * - * If there is no tape currently loaded into the changer, all the methods will - * either return null/false. - * - * @param <T> - * The element type of the tapes. - */ -public class TapeChanger<T> implements Tape<T> { - private Tape<Tape<T>> tapes; - private Tape<T> currentTape; - - /** - * Create a new empty tape changer. - */ - public TapeChanger() { - tapes = new SingleTape<>(); - } - - /** - * Create a new tape changer with the specified tapes. - * - * @param current - * The tape to mount first. - * @param others - * The tapes to put in this tape changer. - */ - @SafeVarargs - public TapeChanger(final Tape<T> current, final Tape<T>... others) { - this(); - - tapes.insertBefore(current); - - for (final Tape<T> tp : others) { - tapes.insertAfter(tp); - tapes.right(); - } - - tapes.first(); - currentTape = tapes.item(); - } - - /** - * Get the item the tape is currently on. - * - * @return The item the tape is on. - */ - @Override - public T item() { - if (currentTape == null) return null; - - return currentTape.item(); - } - - /** - * Set the item the tape is currently on. - * - * @param itm - * The new value for the tape item. - */ - @Override - public void item(final T itm) { - if (currentTape == null) return; - - currentTape.item(itm); - } - - /** - * Get the current number of elements in the tape. - * - * @return The current number of elements in the tape. - */ - @Override - public int size() { - if (currentTape == null) return 0; - - return currentTape.size(); - } - - @Override - public int position() { - if (currentTape == null) return 0; - - return currentTape.position(); - } - - /** - * Insert an element before the current item. - * - * @param itm - * The item to add. - */ - @Override - public void insertBefore(final T itm) { - if (currentTape == null) return; - - currentTape.insertBefore(itm); - } - - /** - * Insert an element after the current item. - */ - @Override - public void insertAfter(final T itm) { - if (currentTape == null) return; - - currentTape.insertAfter(itm); - } - - /** - * Remove the current element. - * - * Also moves the cursor back one step if possible to maintain relative - * position, and removes the corresponding item from the non-active side - * - * @return The removed item from the active side. - */ - @Override - public T remove() { - if (currentTape == null) return null; - - return currentTape.remove(); - } - - /** - * Move the cursor to the left-most position. - */ - @Override - public void first() { - if (currentTape == null) return; - - currentTape.first(); - } - - /** - * Move the cursor the right-most position. - */ - @Override - public void last() { - if (currentTape == null) return; - - currentTape.last(); - } - - /** - * Move the cursor one space left. - * - * The cursor can't go past zero. - * - * @return True if the cursor was moved left. - */ - @Override - public boolean left() { - return left(1); - } - - /** - * Move the cursor the specified amount left. - * - * The cursor can't go past zero. Attempts to move the cursor by amounts - * that would exceed zero don't move the cursor at all. - * - * @param amt - * The amount to attempt to move the cursor left. - * - * @return True if the cursor was moved left. - */ - @Override - public boolean left(final int amt) { - if (currentTape == null) return false; - - return currentTape.left(amt); - } - - /** - * Move the cursor one space right. - * - * Moving the cursor right will auto-extend the tape if that is enabled. - * - * @return Whether the cursor was moved right. - */ - @Override - public boolean right() { - return right(1); - } - - /** - * Move the cursor the specified amount right. - * - * Moving the cursor right will auto-extend the tape if that is enabled. - * - * @param amt - * The amount to move the cursor right by. - * - * @return Whether the cursor was moved right. - */ - @Override - public boolean right(final int amt) { - if (currentTape == null) return false; - - return currentTape.right(amt); - } - - /** - * Flips the tape. - * - * The active side becomes inactive, and the inactive side becomes - * active. - * - * If the current tape is not double-sided, does nothing. - */ - public void flip() { - if (currentTape == null) return; - - if (currentTape.isDoubleSided()) { - ((DoubleTape<T>) currentTape).flip(); - } - } - - @Override - public boolean isDoubleSided() { - if (currentTape == null) return false; - - return currentTape.isDoubleSided(); - } - - /** - * Check if a tape is currently loaded. - * - * @return Whether or not a tape is loaded. - */ - public boolean isLoaded() { - return currentTape != null; - } - - /** - * Move to the next tape in the changer. - * - * Attempting to load a tape that isn't there won't eject the current - * tape. - * - * @return Whether or not the next tape was loaded. - */ - public boolean nextTape() { - final boolean succ = tapes.right(); - - if (succ) { - currentTape = tapes.item(); - } - - return succ; - } - - /** - * Move to the previous tape in the changer. - * - * Attempting to load a tape that isn't there won't eject the current - * tape. - * - * @return Whether or not the previous tape was loaded. - */ - public boolean prevTape() { - final boolean succ = tapes.left(); - - if (succ) { - currentTape = tapes.item(); - } - - return succ; - } - - /** - * Inserts a tape into the tape changer. - * - * Any currently loaded tape is ejected, and becomes the previous tape. - * - * The specified tape is loaded. - * - * @param tp - * The tape to insert and load. - */ - public void insertTape(final Tape<T> tp) { - tapes.insertAfter(tp); - tapes.right(); - - currentTape = tapes.item(); - } - - /** - * Removes the current tape. - * - * Does nothing if there is not a tape loaded. - * - * Loads the previous tape, if there is one. - * - * @return The removed tape. - */ - public Tape<T> removeTape() { - if (currentTape == null) return null; - - final Tape<T> tp = tapes.remove(); - currentTape = tapes.item(); - - return tp; - } - - /** - * Ejects the current tape. - * - * Does nothing if no tape is loaded. - */ - public void eject() { - currentTape = null; - } - - /** - * Get how many tapes are currently in the changer. - * - * @return How many tapes are currently in the changer. - */ - public int tapeCount() { - return tapes.size(); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + (currentTape == null ? 0 : currentTape.hashCode()); - result = prime * result + (tapes == null ? 0 : tapes.hashCode()); - return result; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) return true; - if (obj == null) return false; - if (!(obj instanceof TapeChanger<?>)) return false; - - final TapeChanger<?> other = (TapeChanger<?>) obj; - - if (currentTape == null) { - if (other.currentTape != null) return false; - } else if (!currentTape.equals(other.currentTape)) return false; - - if (tapes == null) { - if (other.tapes != null) return false; - } else if (!tapes.equals(other.tapes)) return false; - - return true; - } - - @Override - public String toString() { - return String.format("TapeChanger [tapes=%s, currentTape='%s']", tapes, currentTape); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/esodata/TapeLibrary.java b/BJC-Utils2/src/main/java/bjc/utils/esodata/TapeLibrary.java deleted file mode 100644 index 2dbc70b..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/esodata/TapeLibrary.java +++ /dev/null @@ -1,340 +0,0 @@ -package bjc.utils.esodata; - -import java.util.HashMap; -import java.util.Map; - -/** - * A tape changer is essentially a map of tapes. - * - * It has a current tape that you can do operations to, but also operations to - * add/remove other tapes. - * - * If there is no tape currently loaded into the changer, all the methods will - * either return null/false. - * - * @param <T> - * The element type of the tapes. - */ -public class TapeLibrary<T> implements Tape<T> { - private final Map<String, Tape<T>> tapes; - private Tape<T> currentTape; - - /** - * Create a new empty tape library. - */ - public TapeLibrary() { - tapes = new HashMap<>(); - } - - /** - * Get the item the tape is currently on. - * - * @return The item the tape is on. - */ - @Override - public T item() { - if (currentTape == null) return null; - - return currentTape.item(); - } - - /** - * Set the item the tape is currently on. - * - * @param itm - * The new value for the tape item. - */ - @Override - public void item(final T itm) { - if (currentTape == null) return; - - currentTape.item(itm); - } - - /** - * Get the current number of elements in the tape. - * - * @return The current number of elements in the tape. - */ - @Override - public int size() { - if (currentTape == null) return 0; - - return currentTape.size(); - } - - @Override - public int position() { - if (currentTape == null) return 0; - - return currentTape.position(); - } - /** - * Insert an element before the current item. - * - * @param itm - * The item to add. - */ - @Override - public void insertBefore(final T itm) { - if (currentTape == null) return; - - currentTape.insertBefore(itm); - } - - /** - * Insert an element after the current item. - */ - @Override - public void insertAfter(final T itm) { - if (currentTape == null) return; - - currentTape.insertAfter(itm); - } - - /** - * Remove the current element. - * - * Also moves the cursor back one step if possible to maintain relative - * position, and removes the corresponding item from the non-active side - * - * @return The removed item from the active side. - */ - @Override - public T remove() { - if (currentTape == null) return null; - - return currentTape.remove(); - } - - /** - * Move the cursor to the left-most position. - */ - @Override - public void first() { - if (currentTape == null) return; - - currentTape.first(); - } - - /** - * Move the cursor the right-most position. - */ - @Override - public void last() { - if (currentTape == null) return; - - currentTape.last(); - } - - /** - * Move the cursor one space left. - * - * The cursor can't go past zero. - * - * @return True if the cursor was moved left. - */ - @Override - public boolean left() { - return left(1); - } - - /** - * Move the cursor the specified amount left. - * - * The cursor can't go past zero. Attempts to move the cursor by amounts - * that would exceed zero don't move the cursor at all. - * - * @param amt - * The amount to attempt to move the cursor left. - * - * @return True if the cursor was moved left. - */ - @Override - public boolean left(final int amt) { - if (currentTape == null) return false; - - return currentTape.left(amt); - } - - /** - * Move the cursor one space right. - * - * Moving the cursor right will auto-extend the tape if that is enabled. - * - * @return Whether the cursor was moved right. - */ - @Override - public boolean right() { - return right(1); - } - - /** - * Move the cursor the specified amount right. - * - * Moving the cursor right will auto-extend the tape if that is enabled. - * - * @param amt - * The amount to move the cursor right by. - * - * @return Whether the cursor was moved right. - */ - @Override - public boolean right(final int amt) { - if (currentTape == null) return false; - - return currentTape.right(amt); - } - - /** - * Flips the tape. - * - * The active side becomes inactive, and the inactive side becomes - * active. - * - * If the current tape is not double-sided, does nothing. - */ - public void flip() { - if (currentTape == null) return; - - if (currentTape.isDoubleSided()) { - ((DoubleTape<T>) currentTape).flip(); - } - } - - @Override - public boolean isDoubleSided() { - if (currentTape == null) return false; - - return currentTape.isDoubleSided(); - } - - /** - * Check if a tape is currently loaded. - * - * @return Whether or not a tape is loaded. - */ - public boolean isLoaded() { - return currentTape != null; - } - - /** - * Move to the specified tape in the library. - * - * Attempting to load a tape that isn't there won't eject the current - * tape. - * - * @param label - * The label of the tape to load. - * - * @return Whether or not the next tape was loaded. - */ - public boolean switchTape(final String label) { - if (tapes.containsKey(label)) { - currentTape = tapes.get(label); - return true; - } - - return false; - } - - /** - * Inserts a tape into the tape library. - * - * Any currently loaded tape is ejected. - * - * The specified tape is loaded. - * - * Adding a duplicate tape will overwrite any existing types. - * - * @param label - * The label of the tape to add. - * - * @param tp - * The tape to insert and load. - */ - public void insertTape(final String label, final Tape<T> tp) { - tapes.put(label, tp); - - currentTape = tp; - } - - /** - * Remove a tape from the library. - * - * Does nothing if there is not a tape of that name loaded. - * - * @param label - * The tape to remove. - * - * @return The removed tape. - */ - public Tape<T> removeTape(final String label) { - return tapes.remove(label); - } - - /** - * Ejects the current tape. - * - * Does nothing if no tape is loaded. - */ - public void eject() { - currentTape = null; - } - - /** - * Get how many tapes are currently in the library. - * - * @return How many tapes are currently in the library. - */ - public int tapeCount() { - return tapes.size(); - } - - /** - * Check if a specific tape is loaded into the library. - * - * @param label - * The tape to check for. - * - * @return Whether or not a tape of that name exists - */ - public boolean hasTape(final String label) { - return tapes.containsKey(label); - } - - @Override - public int hashCode() { - final int prime = 31; - - int result = 1; - result = prime * result + (currentTape == null ? 0 : currentTape.hashCode()); - result = prime * result + (tapes == null ? 0 : tapes.hashCode()); - - return result; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) return true; - if (obj == null) return false; - if (!(obj instanceof TapeLibrary<?>)) return false; - - final TapeLibrary<?> other = (TapeLibrary<?>) obj; - - if (currentTape == null) { - if (other.currentTape != null) return false; - } else if (!currentTape.equals(other.currentTape)) return false; - - if (tapes == null) { - if (other.tapes != null) return false; - } else if (!tapes.equals(other.tapes)) return false; - - return true; - } - - @Override - public String toString() { - return String.format("TapeLibrary [tapes=%s, currentTape='%s']", tapes, currentTape); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/esodata/UnifiedDirectory.java b/BJC-Utils2/src/main/java/bjc/utils/esodata/UnifiedDirectory.java deleted file mode 100644 index ffb639f..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/esodata/UnifiedDirectory.java +++ /dev/null @@ -1,105 +0,0 @@ -package bjc.utils.esodata; - -import bjc.utils.funcdata.FunctionalMap; -import bjc.utils.funcdata.IMap; - -/** - * Simple implementation of {@link Directory}. - * - * Has a unified namespace for data and children. - * - * @author EVE - * - * @param <K> - * The key type of the directory. - * @param <V> - * The value type of the directory. - */ -public class UnifiedDirectory<K, V> implements Directory<K, V> { - private final IMap<K, Directory<K, V>> children; - - private final IMap<K, V> data; - - /** - * Create a new directory. - */ - public UnifiedDirectory() { - children = new FunctionalMap<>(); - data = new FunctionalMap<>(); - } - - @Override - public Directory<K, V> getSubdirectory(final K key) { - return children.get(key); - } - - @Override - public boolean hasSubdirectory(final K key) { - return children.containsKey(key); - } - - @Override - public Directory<K, V> putSubdirectory(final K key, final Directory<K, V> val) { - if (data.containsKey(key)) { - final String msg = String.format("Key %s is already used for data", key); - - throw new IllegalArgumentException(msg); - } - - return children.put(key, val); - } - - @Override - public boolean containsKey(final K key) { - return data.containsKey(key); - } - - @Override - public V getKey(final K key) { - return data.get(key); - } - - @Override - public V putKey(final K key, final V val) { - if (children.containsKey(key)) { - final String msg = String.format("Key %s is already used for sub-directories.", key); - - throw new IllegalArgumentException(msg); - } - - return data.put(key, val); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + (children == null ? 0 : children.hashCode()); - result = prime * result + (data == null ? 0 : data.hashCode()); - return result; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) return true; - if (obj == null) return false; - if (!(obj instanceof UnifiedDirectory<?, ?>)) return false; - - final UnifiedDirectory<?, ?> other = (UnifiedDirectory<?, ?>) obj; - - if (children == null) { - if (other.children != null) return false; - } else if (!children.equals(other.children)) return false; - - if (data == null) { - if (other.data != null) return false; - } else if (!data.equals(other.data)) return false; - - return true; - } - - @Override - public String toString() { - return String.format("UnifiedDirectory [children=%s, data=%s]", children, data); - } -}
\ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/exceptions/FileNotChosenException.java b/BJC-Utils2/src/main/java/bjc/utils/exceptions/FileNotChosenException.java deleted file mode 100644 index 6f5a68a..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/exceptions/FileNotChosenException.java +++ /dev/null @@ -1,31 +0,0 @@ -package bjc.utils.exceptions; - -import java.io.IOException; - -/** - * Represents the user failing to choose a file. - * - * @author ben - * - */ -public class FileNotChosenException extends IOException { - // Version ID for serialization - private static final long serialVersionUID = -8753348705210831096L; - - /** - * Create a new exception - */ - public FileNotChosenException() { - super(); - } - - /** - * Create a new exception with the given cause - * - * @param cause - * The cause of why the exception was thrown - */ - public FileNotChosenException(final String cause) { - super(cause); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/exceptions/PragmaFormatException.java b/BJC-Utils2/src/main/java/bjc/utils/exceptions/PragmaFormatException.java deleted file mode 100644 index 1ad339d..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/exceptions/PragmaFormatException.java +++ /dev/null @@ -1,31 +0,0 @@ -package bjc.utils.exceptions; - -import java.util.InputMismatchException; - -/** - * The exception to throw whenever a pragma is used with invalid syntax - * - * @author ben - * - */ -public class PragmaFormatException extends InputMismatchException { - // Version ID for serialization - private static final long serialVersionUID = 1288536477368021069L; - - /** - * Create a new exception - */ - public PragmaFormatException() { - super(); - } - - /** - * Create a new exception with the given message - * - * @param message - * The message to explain why the exception was thrown - */ - public PragmaFormatException(final String message) { - super(message); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/exceptions/UnknownPragmaException.java b/BJC-Utils2/src/main/java/bjc/utils/exceptions/UnknownPragmaException.java deleted file mode 100644 index 6fc9113..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/exceptions/UnknownPragmaException.java +++ /dev/null @@ -1,25 +0,0 @@ -package bjc.utils.exceptions; - -import java.util.InputMismatchException; - -/** - * Represents a error from encountering a unknown pragma - * - * @author ben - * - */ -public class UnknownPragmaException extends InputMismatchException { - // Version ID for serialization - private static final long serialVersionUID = -4277573484926638662L; - - /** - * Create a new exception with the given cause - * - * @param cause - * The cause for throwing this exception - */ - public UnknownPragmaException(final String cause) { - super(cause); - } - -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcdata/ExtendedMap.java b/BJC-Utils2/src/main/java/bjc/utils/funcdata/ExtendedMap.java deleted file mode 100644 index 909c5e9..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/funcdata/ExtendedMap.java +++ /dev/null @@ -1,127 +0,0 @@ -package bjc.utils.funcdata; - -import java.util.function.BiConsumer; -import java.util.function.Consumer; -import java.util.function.Function; - -import bjc.utils.funcutils.ListUtils; - -class ExtendedMap<KeyType, ValueType> implements IMap<KeyType, ValueType> { - private final IMap<KeyType, ValueType> delegate; - - private final IMap<KeyType, ValueType> store; - - public ExtendedMap(final IMap<KeyType, ValueType> delegate, final IMap<KeyType, ValueType> store) { - this.delegate = delegate; - this.store = store; - } - - @Override - public void clear() { - store.clear(); - } - - @Override - public boolean containsKey(final KeyType key) { - if (store.containsKey(key)) return true; - - return delegate.containsKey(key); - } - - @Override - public IMap<KeyType, ValueType> extend() { - return new ExtendedMap<>(this, new FunctionalMap<>()); - } - - @Override - public void forEach(final BiConsumer<KeyType, ValueType> action) { - store.forEach(action); - - delegate.forEach(action); - } - - @Override - public void forEachKey(final Consumer<KeyType> action) { - store.forEachKey(action); - - delegate.forEachKey(action); - } - - @Override - public void forEachValue(final Consumer<ValueType> action) { - store.forEachValue(action); - - delegate.forEachValue(action); - } - - @Override - public ValueType get(final KeyType key) { - if (store.containsKey(key)) return store.get(key); - - return delegate.get(key); - } - - @Override - public int size() { - return store.size() + delegate.size(); - } - - @Override - public IList<KeyType> keyList() { - return ListUtils.mergeLists(store.keyList(), delegate.keyList()); - } - - @Override - public <MappedValue> IMap<KeyType, MappedValue> transform(final Function<ValueType, MappedValue> transformer) { - return new TransformedValueMap<>(this, transformer); - } - - @Override - public ValueType put(final KeyType key, final ValueType val) { - return store.put(key, val); - } - - @Override - public ValueType remove(final KeyType key) { - if (!store.containsKey(key)) return delegate.remove(key); - - return store.remove(key); - } - - @Override - public IList<ValueType> valueList() { - return ListUtils.mergeLists(store.valueList(), delegate.valueList()); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + (delegate == null ? 0 : delegate.hashCode()); - result = prime * result + (store == null ? 0 : store.hashCode()); - return result; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) return true; - if (obj == null) return false; - if (!(obj instanceof ExtendedMap)) return false; - - final ExtendedMap<?, ?> other = (ExtendedMap<?, ?>) obj; - - if (delegate == null) { - if (other.delegate != null) return false; - } else if (!delegate.equals(other.delegate)) return false; - if (store == null) { - if (other.store != null) return false; - } else if (!store.equals(other.store)) return false; - - return true; - } - - @Override - public String toString() { - return String.format("ExtendedMap [delegate=%s, store=%s]", delegate, store); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcdata/FunctionalList.java b/BJC-Utils2/src/main/java/bjc/utils/funcdata/FunctionalList.java deleted file mode 100644 index 55ea7ff..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/funcdata/FunctionalList.java +++ /dev/null @@ -1,423 +0,0 @@ -package bjc.utils.funcdata; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.Iterator; -import java.util.List; -import java.util.NoSuchElementException; -import java.util.function.BiConsumer; -import java.util.function.BiFunction; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Predicate; - -import bjc.utils.data.IHolder; -import bjc.utils.data.IPair; -import bjc.utils.data.Identity; -import bjc.utils.data.Pair; - -/** - * A wrapper over another list that provides eager functional operations over - * it. - * - * Differs from a stream in every way except for the fact that they both provide - * functional operations. - * - * @author ben - * - * @param <E> - * The type in this list - */ -public class FunctionalList<E> implements Cloneable, IList<E> { - /* - * The list used as a backing store - */ - private final List<E> wrapped; - - /** - * Create a new empty functional list. - */ - public FunctionalList() { - wrapped = new ArrayList<>(); - } - - /** - * Create a new functional list containing the specified items. - * - * Takes O(n) time, where n is the number of items specified - * - * @param items - * The items to put into this functional list. - */ - @SafeVarargs - public FunctionalList(final E... items) { - wrapped = new ArrayList<>(items.length); - - for (final E item : items) { - wrapped.add(item); - } - } - - /** - * Create a new functional list with the specified size. - * - * @param size - * The size of the backing list . - */ - private FunctionalList(final int size) { - wrapped = new ArrayList<>(size); - } - - /** - * Create a new functional list as a wrapper of a existing list. - * - * Takes O(1) time, since it doesn't copy the list. - * - * @param backing - * The list to use as a backing list. - */ - public FunctionalList(final List<E> backing) { - if (backing == null) throw new NullPointerException("Backing list must be non-null"); - - wrapped = backing; - } - - @Override - public boolean add(final E item) { - return wrapped.add(item); - } - - @Override - public boolean allMatch(final Predicate<E> predicate) { - if (predicate == null) throw new NullPointerException("Predicate must be non-null"); - - for (final E item : wrapped) { - if (!predicate.test(item)) - // We've found a non-matching item - return false; - } - - // All of the items matched - return true; - } - - @Override - public boolean anyMatch(final Predicate<E> predicate) { - if (predicate == null) throw new NullPointerException("Predicate must be not null"); - - for (final E item : wrapped) { - if (predicate.test(item)) - // We've found a matching item - return true; - } - - // We didn't find a matching item - return false; - } - - /** - * Clone this list into a new one, and clone the backing list as well - * - * Takes O(n) time, where n is the number of elements in the list - * - * @return A list - */ - @Override - public IList<E> clone() { - final IList<E> cloned = new FunctionalList<>(); - - for (final E element : wrapped) { - cloned.add(element); - } - - return cloned; - } - - @Override - public <T, F> IList<F> combineWith(final IList<T> rightList, final BiFunction<E, T, F> itemCombiner) { - if (rightList == null) - throw new NullPointerException("Target combine list must not be null"); - else if (itemCombiner == null) throw new NullPointerException("Combiner must not be null"); - - final IList<F> returned = new FunctionalList<>(); - - // Get the iterator for the other list - final Iterator<T> rightIterator = rightList.toIterable().iterator(); - - for (final Iterator<E> leftIterator = wrapped.iterator(); leftIterator.hasNext() - && rightIterator.hasNext();) { - // Add the transformed items to the result list - final E leftVal = leftIterator.next(); - final T rightVal = rightIterator.next(); - - returned.add(itemCombiner.apply(leftVal, rightVal)); - } - - return returned; - } - - @Override - public boolean contains(final E item) { - // Check if any items in the list match the provided item - return this.anyMatch(item::equals); - } - - @Override - public E first() { - if (wrapped.size() < 1) - throw new NoSuchElementException("Attempted to get first element of empty list"); - - return wrapped.get(0); - } - - @Override - public <T> IList<T> flatMap(final Function<E, IList<T>> expander) { - if (expander == null) throw new NullPointerException("Expander must not be null"); - - final IList<T> returned = new FunctionalList<>(this.wrapped.size()); - - forEach(element -> { - final IList<T> expandedElement = expander.apply(element); - - if (expandedElement == null) throw new NullPointerException("Expander returned null list"); - - // Add each element to the returned list - expandedElement.forEach(returned::add); - }); - - return returned; - } - - @Override - public void forEach(final Consumer<? super E> action) { - if (action == null) throw new NullPointerException("Action is null"); - - wrapped.forEach(action); - } - - @Override - public void forEachIndexed(final BiConsumer<Integer, E> indexedAction) { - if (indexedAction == null) throw new NullPointerException("Action must not be null"); - - // This is held b/c ref'd variables must be final/effectively - // final - final IHolder<Integer> currentIndex = new Identity<>(0); - - wrapped.forEach((element) -> { - // Call the action with the index and the value - indexedAction.accept(currentIndex.unwrap(index -> index), element); - - // Increment the value - currentIndex.transform((index) -> index + 1); - }); - } - - @Override - public E getByIndex(final int index) { - return wrapped.get(index); - } - - /** - * Get the internal backing list. - * - * @return The backing list this list is based off of. - */ - public List<E> getInternal() { - return wrapped; - } - - @Override - public IList<E> getMatching(final Predicate<E> predicate) { - if (predicate == null) throw new NullPointerException("Predicate must not be null"); - - final IList<E> returned = new FunctionalList<>(); - - wrapped.forEach((element) -> { - if (predicate.test(element)) { - // The item matches, so add it to the returned - // list - returned.add(element); - } - }); - - return returned; - } - - @Override - public int getSize() { - return wrapped.size(); - } - - @Override - public boolean isEmpty() { - return wrapped.isEmpty(); - } - - /* - * Check if a partition has room for another item - */ - private Boolean isPartitionFull(final int numberPerPartition, final IHolder<IList<E>> currentPartition) { - return currentPartition.unwrap((partition) -> partition.getSize() >= numberPerPartition); - } - - @Override - public <T> IList<T> map(final Function<E, T> elementTransformer) { - if (elementTransformer == null) throw new NullPointerException("Transformer must be not null"); - - final IList<T> returned = new FunctionalList<>(this.wrapped.size()); - - forEach(element -> { - // Add the transformed item to the result - returned.add(elementTransformer.apply(element)); - }); - - return returned; - } - - @Override - public <T> IList<IPair<E, T>> pairWith(final IList<T> rightList) { - return combineWith(rightList, Pair<E, T>::new); - } - - @Override - public IList<IList<E>> partition(final int numberPerPartition) { - if (numberPerPartition < 1 || numberPerPartition > wrapped.size()) { - final String fmt = "%s is an invalid partition size. Must be between 1 and %d"; - final String msg = String.format(fmt, numberPerPartition, wrapped.size()); - - throw new IllegalArgumentException(msg); - } - - final IList<IList<E>> returned = new FunctionalList<>(); - - // The current partition being filled - final IHolder<IList<E>> currentPartition = new Identity<>(new FunctionalList<>()); - - this.forEach(element -> { - if (isPartitionFull(numberPerPartition, currentPartition)) { - // Add the partition to the list - returned.add(currentPartition.unwrap(partition -> partition)); - - // Start a new partition - currentPartition.transform(partition -> new FunctionalList<>()); - } else { - // Add the element to the current partition - currentPartition.unwrap(partition -> partition.add(element)); - } - }); - - return returned; - } - - @Override - public void prepend(final E item) { - wrapped.add(0, item); - } - - @Override - public E randItem(final Function<Integer, Integer> rnd) { - if (rnd == null) throw new NullPointerException("Random source must not be null"); - - final int randomIndex = rnd.apply(wrapped.size()); - - return wrapped.get(randomIndex); - } - - @Override - public <T, F> F reduceAux(final T initialValue, final BiFunction<E, T, T> stateAccumulator, - final Function<T, F> resultTransformer) { - if (stateAccumulator == null) - throw new NullPointerException("Accumulator must not be null"); - else if (resultTransformer == null) throw new NullPointerException("Transformer must not be null"); - - // The current collapsed list - final IHolder<T> currentState = new Identity<>(initialValue); - - wrapped.forEach(element -> { - // Accumulate a new value into the state - currentState.transform(state -> stateAccumulator.apply(element, state)); - }); - - // Convert the state to its final value - return currentState.unwrap(resultTransformer); - } - - @Override - public boolean removeIf(final Predicate<E> removePredicate) { - if (removePredicate == null) throw new NullPointerException("Predicate must be non-null"); - - return wrapped.removeIf(removePredicate); - } - - @Override - public void removeMatching(final E desiredElement) { - removeIf(element -> element.equals(desiredElement)); - } - - @Override - public void reverse() { - Collections.reverse(wrapped); - } - - @Override - public E search(final E searchKey, final Comparator<E> comparator) { - // Search our internal list - final int foundIndex = Collections.binarySearch(wrapped, searchKey, comparator); - - if (foundIndex >= 0) // We found a matching element - return wrapped.get(foundIndex); - - // We didn't find an element - return null; - } - - @Override - public void sort(final Comparator<E> comparator) { - // sb.deleteCharAt(sb.length() - 2); - Collections.sort(wrapped, comparator); - } - - @Override - public IList<E> tail() { - return new FunctionalList<>(wrapped.subList(1, getSize())); - } - - @Override - public E[] toArray(final E[] arrType) { - return wrapped.toArray(arrType); - } - - @Override - public Iterable<E> toIterable() { - return wrapped; - } - - @Override - public String toString() { - final int lSize = getSize(); - - if (lSize == 0) return "()"; - - final StringBuilder sb = new StringBuilder("("); - final Iterator<E> itr = toIterable().iterator(); - final E itm = itr.next(); - int i = 0; - - if (lSize == 1) return "(" + itm + ")"; - - for (final E item : toIterable()) { - sb.append(item.toString()); - - if (i < lSize - 1) { - sb.append(", "); - } - - i += 1; - } - - sb.append(")"); - - return sb.toString(); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcdata/FunctionalMap.java b/BJC-Utils2/src/main/java/bjc/utils/funcdata/FunctionalMap.java deleted file mode 100644 index c4f0ff1..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/funcdata/FunctionalMap.java +++ /dev/null @@ -1,175 +0,0 @@ -package bjc.utils.funcdata; - -import java.util.HashMap; -import java.util.Map; -import java.util.function.BiConsumer; -import java.util.function.Consumer; -import java.util.function.Function; - -import bjc.utils.data.IPair; - -/** - * Basic implementation of {@link IMap} - * - * @author ben - * - * @param <KeyType> - * The type of the map's keys - * @param <ValueType> - * The type of the map's values - */ -public class FunctionalMap<KeyType, ValueType> implements IMap<KeyType, ValueType> { - private Map<KeyType, ValueType> wrappedMap; - - /** - * Create a new blank functional map - */ - public FunctionalMap() { - wrappedMap = new HashMap<>(); - } - - /** - * Create a new functional map with the specified entries - * - * @param entries - * The entries to put into the map - */ - @SafeVarargs - public FunctionalMap(final IPair<KeyType, ValueType>... entries) { - this(); - - for (final IPair<KeyType, ValueType> entry : entries) { - entry.doWith((key, val) -> { - wrappedMap.put(key, val); - }); - } - } - - /** - * Create a new functional map wrapping the specified map - * - * @param wrap - * The map to wrap - */ - public FunctionalMap(final Map<KeyType, ValueType> wrap) { - if (wrap == null) throw new NullPointerException("Map to wrap must not be null"); - - wrappedMap = wrap; - } - - @Override - public void clear() { - wrappedMap.clear(); - } - - @Override - public boolean containsKey(final KeyType key) { - return wrappedMap.containsKey(key); - } - - @Override - public IMap<KeyType, ValueType> extend() { - return new ExtendedMap<>(this, new FunctionalMap<>()); - } - - @Override - public void forEach(final BiConsumer<KeyType, ValueType> action) { - wrappedMap.forEach(action); - } - - @Override - public void forEachKey(final Consumer<KeyType> action) { - wrappedMap.keySet().forEach(action); - } - - @Override - public void forEachValue(final Consumer<ValueType> action) { - wrappedMap.values().forEach(action); - } - - @Override - public ValueType get(final KeyType key) { - if (key == null) throw new NullPointerException("Key must not be null"); - - if (!wrappedMap.containsKey(key)) { - final String msg = String.format("Key %s is not present in the map", key); - - throw new IllegalArgumentException(msg); - } - - return wrappedMap.get(key); - } - - @Override - public int size() { - return wrappedMap.size(); - } - - @Override - public IList<KeyType> keyList() { - final FunctionalList<KeyType> keys = new FunctionalList<>(); - - wrappedMap.keySet().forEach(key -> { - keys.add(key); - }); - - return keys; - } - - @Override - public <MappedValue> IMap<KeyType, MappedValue> transform(final Function<ValueType, MappedValue> transformer) { - if (transformer == null) throw new NullPointerException("Transformer must not be null"); - - return new TransformedValueMap<>(this, transformer); - } - - @Override - public ValueType put(final KeyType key, final ValueType val) { - if (key == null) throw new NullPointerException("Key must not be null"); - - return wrappedMap.put(key, val); - } - - @Override - public ValueType remove(final KeyType key) { - return wrappedMap.remove(key); - } - - @Override - public String toString() { - return wrappedMap.toString(); - } - - @Override - public IList<ValueType> valueList() { - final FunctionalList<ValueType> values = new FunctionalList<>(); - - wrappedMap.values().forEach(value -> { - values.add(value); - }); - - return values; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + (wrappedMap == null ? 0 : wrappedMap.hashCode()); - return result; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) return true; - if (obj == null) return false; - if (!(obj instanceof FunctionalMap)) return false; - - final FunctionalMap<?, ?> other = (FunctionalMap<?, ?>) obj; - - if (wrappedMap == null) { - if (other.wrappedMap != null) return false; - } else if (!wrappedMap.equals(other.wrappedMap)) return false; - return true; - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcdata/FunctionalStringTokenizer.java b/BJC-Utils2/src/main/java/bjc/utils/funcdata/FunctionalStringTokenizer.java deleted file mode 100644 index e068b46..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/funcdata/FunctionalStringTokenizer.java +++ /dev/null @@ -1,159 +0,0 @@ -package bjc.utils.funcdata; - -import java.util.StringTokenizer; -import java.util.function.Consumer; -import java.util.function.Function; - -/** - * A string tokenizer that exposes a functional interface - * - * @author ben - * - */ -public class FunctionalStringTokenizer { - /** - * Create a new tokenizer from the specified string. - * - * @param strang - * The string to create a tokenizer from. - * @return A new tokenizer that splits the provided string on spaces. - */ - public static FunctionalStringTokenizer fromString(final String strang) { - if (strang == null) throw new NullPointerException("String to tokenize must be non-null"); - - return new FunctionalStringTokenizer(new StringTokenizer(strang, " ")); - } - - /* - * The string tokenizer being driven - */ - private final StringTokenizer input; - - /** - * Create a functional string tokenizer from a given string - * - * @param inp - * The string to tokenize - */ - public FunctionalStringTokenizer(final String inp) { - if (inp == null) throw new NullPointerException("String to tokenize must be non-null"); - - this.input = new StringTokenizer(inp); - } - - /** - * Create a functional string tokenizer from a given string and set of - * separators - * - * @param input - * The string to tokenize - * @param seperators - * The set of separating tokens to use for splitting - */ - public FunctionalStringTokenizer(final String input, final String seperators) { - if (input == null) - throw new NullPointerException("String to tokenize must not be null"); - else if (seperators == null) throw new NullPointerException("Tokens to split on must not be null"); - - this.input = new StringTokenizer(input, seperators); - } - - /** - * Create a functional string tokenizer from a non-functional one - * - * @param toWrap - * The non-functional string tokenizer to wrap - */ - public FunctionalStringTokenizer(final StringTokenizer toWrap) { - if (toWrap == null) throw new NullPointerException("Wrapped tokenizer must not be null"); - - this.input = toWrap; - } - - /** - * Execute a provided action for each of the remaining tokens - * - * @param action - * The action to execute for each token - */ - public void forEachToken(final Consumer<String> action) { - if (action == null) throw new NullPointerException("Action must not be null"); - - while (input.hasMoreTokens()) { - action.accept(input.nextToken()); - } - } - - /** - * Get the string tokenizer encapsulated by this tokenizer - * - * @return The encapsulated tokenizer - */ - public StringTokenizer getInternal() { - return input; - } - - /** - * Check if this tokenizer has more tokens - * - * @return Whether or not this tokenizer has more tokens - */ - public boolean hasMoreTokens() { - return input.hasMoreTokens(); - } - - /** - * Return the next token from the tokenizer. - * - * Returns null if no more tokens are available - * - * @return The next token from the tokenizer - */ - public String nextToken() { - if (input.hasMoreTokens()) // Return the next available token - return input.nextToken(); - - // Return no token - return null; - } - - /** - * Convert this tokenizer into a list of strings - * - * @return This tokenizer, converted into a list of strings - */ - public IList<String> toList() { - return toList((final String element) -> element); - } - - /** - * Convert the contents of this tokenizer into a list. Consumes all of - * the input from this tokenizer. - * - * @param <E> - * The type of the converted tokens - * - * @param transformer - * The function to use to convert tokens. - * @return A list containing all of the converted tokens. - */ - public <E> IList<E> toList(final Function<String, E> transformer) { - if (transformer == null) throw new NullPointerException("Transformer must not be null"); - - final IList<E> returned = new FunctionalList<>(); - - // Add each token to the list after transforming it - forEachToken(token -> { - final E transformedToken = transformer.apply(token); - - returned.add(transformedToken); - }); - - return returned; - } - - @Override - public String toString() { - return String.format("FunctionalStringTokenizer [input=%s]", input); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcdata/IList.java b/BJC-Utils2/src/main/java/bjc/utils/funcdata/IList.java deleted file mode 100644 index 28c09d0..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/funcdata/IList.java +++ /dev/null @@ -1,416 +0,0 @@ -package bjc.utils.funcdata; - -import java.util.Comparator; -import java.util.Iterator; -import java.util.function.BiConsumer; -import java.util.function.BiFunction; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Predicate; -import java.util.stream.Collector; - -import bjc.utils.data.IPair; -import bjc.utils.functypes.ID; - -/** - * A wrapper over another list that provides functional operations over it. - * - * @author ben - * - * @param <ContainedType> - * The type in this list - */ -public interface IList<ContainedType> extends Iterable<ContainedType> { - /** - * Add an item to this list - * - * @param item - * The item to add to this list. - * @return Whether the item was added to the list successfully. - */ - boolean add(ContainedType item); - - /** - * Add all of the elements in the provided list to this list - * - * @param items - * The list of items to add - * @return True if every item was successfully added to the list, false - * otherwise - */ - default boolean addAll(final IList<ContainedType> items) { - return items.map(this::add).anyMatch(bl -> bl == false); - } - - /** - * Add all of the elements in the provided array to this list. - * - * @param items - * The array of items to add. - * - * @return True if every item was successfully added to the list, false - * otherwise. - */ - @SuppressWarnings("unchecked") - default boolean addAll(final ContainedType... items) { - boolean succ = true; - - for (final ContainedType item : items) { - final boolean addSucc = add(item); - - succ = succ ? addSucc : false; - } - - return succ; - } - - /** - * Check if all of the elements of this list match the specified - * predicate. - * - * @param matcher - * The predicate to use for checking. - * @return Whether all of the elements of the list match the specified - * predicate. - */ - boolean allMatch(Predicate<ContainedType> matcher); - - /** - * Check if any of the elements in this list match the specified list. - * - * @param matcher - * The predicate to use for checking. - * @return Whether any element in the list matches the provided - * predicate. - */ - boolean anyMatch(Predicate<ContainedType> matcher); - - /** - * Reduce the contents of this list using a collector - * - * @param <StateType> - * The intermediate accumulation type - * @param <ReducedType> - * The final, reduced type - * @param collector - * The collector to use for reduction - * @return The reduced list - */ - default <StateType, ReducedType> ReducedType collect( - final Collector<ContainedType, StateType, ReducedType> collector) { - final BiConsumer<StateType, ContainedType> accumulator = collector.accumulator(); - - final StateType initial = collector.supplier().get(); - return reduceAux(initial, (value, state) -> { - accumulator.accept(state, value); - - return state; - }, collector.finisher()); - } - - /** - * Combine this list with another one into a new list and merge the - * results. - * - * Works sort of like a combined zip/map over resulting pairs. Does not - * change the underlying list. - * - * NOTE: The returned list will have the length of the shorter of this - * list and the combined one. - * - * @param <OtherType> - * The type of the second list - * @param <CombinedType> - * The type of the combined list - * - * @param list - * The list to combine with - * @param combiner - * The function to use for combining element pairs. - * @return A new list containing the merged pairs of lists. - */ - <OtherType, CombinedType> IList<CombinedType> combineWith(IList<OtherType> list, - BiFunction<ContainedType, OtherType, CombinedType> combiner); - - /** - * Check if the list contains the specified item - * - * @param item - * The item to see if it is contained - * @return Whether or not the specified item is in the list - */ - boolean contains(ContainedType item); - - /** - * Get the first element in the list - * - * @return The first element in this list. - */ - ContainedType first(); - - /** - * Apply a function to each member of the list, then flatten the - * results. - * - * Does not change the underlying list. - * - * @param <MappedType> - * The type of the flattened list - * - * @param expander - * The function to apply to each member of the list. - * @return A new list containing the flattened results of applying the - * provided function. - */ - <MappedType> IList<MappedType> flatMap(Function<ContainedType, IList<MappedType>> expander); - - /** - * Apply a given action for each member of the list - * - * @param action - * The action to apply to each member of the list. - */ - @Override - void forEach(Consumer<? super ContainedType> action); - - /** - * Apply a given function to each element in the list and its index. - * - * @param action - * The function to apply to each element in the list and - * its index. - */ - void forEachIndexed(BiConsumer<Integer, ContainedType> action); - - /** - * Retrieve a value in the list by its index. - * - * @param index - * The index to retrieve a value from. - * @return The value at the specified index in the list. - */ - ContainedType getByIndex(int index); - - /** - * Retrieve a list containing all elements matching a predicate - * - * @param predicate - * The predicate to match by - * @return A list containing all elements that match the predicate - */ - IList<ContainedType> getMatching(Predicate<ContainedType> predicate); - - /** - * Retrieve the size of the wrapped list - * - * @return The size of the wrapped list - */ - int getSize(); - - /** - * Check if this list is empty. - * - * @return Whether or not this list is empty. - */ - boolean isEmpty(); - - /** - * Create a new list by applying the given function to each element in - * the list. - * - * Does not change the underlying list. - * - * @param <MappedType> - * The type of the transformed list - * - * @param transformer - * The function to apply to each element in the list - * @return A new list containing the mapped elements of this list. - */ - <MappedType> IList<MappedType> map(Function<ContainedType, MappedType> transformer); - - /** - * Zip two lists into a list of pairs - * - * @param <OtherType> - * The type of the second list - * - * @param list - * The list to use as the left side of the pair - * @return A list containing pairs of this element and the specified - * list - */ - <OtherType> IList<IPair<ContainedType, OtherType>> pairWith(IList<OtherType> list); - - /** - * Partition this list into a list of sublists - * - * @param partitionSize - * The size of elements to put into each one of the - * sublists - * @return A list partitioned into partitions of size nPerPart - */ - IList<IList<ContainedType>> partition(int partitionSize); - - /** - * Prepend an item to the list - * - * @param item - * The item to prepend to the list - */ - void prepend(ContainedType item); - - /** - * Prepend an array of items to the list. - * - * @param items - * The items to prepend to the list. - */ - @SuppressWarnings("unchecked") - default void prependAll(final ContainedType... items) { - for (final ContainedType item : items) { - prepend(item); - } - } - - /** - * Select a random item from the list, using a default random number - * generator - * - * @return A random item from the list - */ - default ContainedType randItem() { - return randItem(num -> (int) (Math.random() * num)); - } - - /** - * Select a random item from this list, using the provided random number - * generator. - * - * @param rnd - * The random number generator to use. - * @return A random element from this list. - */ - ContainedType randItem(Function<Integer, Integer> rnd); - - /** - * Reduce this list to a single value, using a accumulative approach. - * - * @param <StateType> - * The in-between type of the values - * @param <ReducedType> - * The final value type - * - * @param initial - * The initial value of the accumulative state. - * @param accumulator - * The function to use to combine a list element with the - * accumulative state. - * @param transformer - * The function to use to convert the accumulative state - * into a final result. - * @return A single value condensed from this list and transformed into - * its final state. - */ - <StateType, ReducedType> ReducedType reduceAux(StateType initial, - BiFunction<ContainedType, StateType, StateType> accumulator, - Function<StateType, ReducedType> transformer); - - /** - * Reduce this list to a single value, using a accumulative approach. - * - * @param <StateType> - * The in-between type of the values. - * - * @param initial - * The initial value of the accumulative state. - * - * @param accumulator - * The function to use to combine a list element with the - * accumulative state. - * - * @return A single value condensed from this list. - */ - default <StateType> StateType reduceAux(StateType initial, - BiFunction<ContainedType, StateType, StateType> accumulator) { - return reduceAux(initial, accumulator, ID.id()); - } - - /** - * Remove all elements that match a given predicate - * - * @param predicate - * The predicate to use to determine elements to delete - * @return Whether there was anything that satisfied the predicate - */ - boolean removeIf(Predicate<ContainedType> predicate); - - /** - * Remove all parameters that match a given parameter - * - * @param element - * The object to remove all matching copies of - */ - void removeMatching(ContainedType element); - - /** - * Reverse the contents of this list in place - */ - void reverse(); - - /** - * Perform a binary search for the specified key using the provided - * means of comparing elements. - * - * Since this IS a binary search, the list must have been sorted before - * hand. - * - * @param key - * The key to search for. - * @param comparator - * The way to compare elements for searching. Pass null - * to use the natural ordering for E - * @return The element if it is in this list, or null if it is not. - */ - ContainedType search(ContainedType key, Comparator<ContainedType> comparator); - - /** - * Sort the elements of this list using the provided way of comparing - * elements. - * - * Does change the underlying list. - * - * @param comparator - * The way to compare elements for sorting. Pass null to - * use E's natural ordering - */ - void sort(Comparator<ContainedType> comparator); - - /** - * Get the tail of this list (the list without the first element - * - * @return The list without the first element - */ - IList<ContainedType> tail(); - - /** - * Convert this list into an array - * - * @param type - * The type of array to return - * @return The list, as an array - */ - ContainedType[] toArray(ContainedType[] type); - - /** - * Convert the list into a Iterable - * - * @return An iterable view onto the list - */ - Iterable<ContainedType> toIterable(); - - @Override - default Iterator<ContainedType> iterator() { - return toIterable().iterator(); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcdata/IMap.java b/BJC-Utils2/src/main/java/bjc/utils/funcdata/IMap.java deleted file mode 100644 index 0ee7375..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/funcdata/IMap.java +++ /dev/null @@ -1,188 +0,0 @@ -package bjc.utils.funcdata; - -import java.util.function.BiConsumer; -import java.util.function.Consumer; -import java.util.function.Function; - -/** - * Functional wrapper over map providing some useful things. - * - * @author ben - * - * @param <KeyType> - * The type of this map's keys. - * - * @param <ValueType> - * The type of this map's values. - */ -public interface IMap<KeyType, ValueType> { - /** - * Execute an action for each entry in the map. - * - * @param action - * the action to execute for each entry in the map. - */ - void forEach(BiConsumer<KeyType, ValueType> action); - - /** - * Perform an action for each key in the map. - * - * @param action - * The action to perform on each key in the map. - */ - default void forEachKey(final Consumer<KeyType> action) { - forEach((key, val) -> action.accept(key)); - } - - /** - * Perform an action for each value in the map. - * - * @param action - * The action to perform on each value in the map. - */ - default void forEachValue(final Consumer<ValueType> action) { - forEach((key, val) -> action.accept(val)); - } - - /** - * Check if this map contains the specified key. - * - * @param key - * The key to check. - * - * @return Whether or not the map contains the key. - */ - boolean containsKey(KeyType key); - - /** - * Get the value assigned to the given key. - * - * @param key - * The key to look for a value under. - * - * @return The value of the key. - */ - ValueType get(KeyType key); - - /** - * Get a value from the map, and return a default value if the key - * doesn't exist. - * - * @param key - * The key to attempt to retrieve. - * - * @param defaultValue - * The value to return if the key doesn't exist. - * - * @return The value associated with the key, or the default value if - * the key doesn't exist. - */ - default ValueType getOrDefault(final KeyType key, final ValueType defaultValue) { - try { - return get(key); - } catch (final IllegalArgumentException iaex) { - /* - * We don't care about this, because it indicates a key - * is missing. - */ - return defaultValue; - } - } - - /** - * Add an entry to the map. - * - * @param key - * The key to put the value under. - * - * @param val - * The value to add. - * - * @return The previous value of the key in the map, or null if the key - * wasn't in the map. However, note that it may also return null - * if the key was set to null. - * - * @throws UnsupportedOperationException - * if the map implementation doesn't support modifying - * the map - */ - ValueType put(KeyType key, ValueType val); - - /** - * Delete all the values in the map. - */ - default void clear() { - keyList().forEach(key -> remove(key)); - } - - /** - * Get the number of entries in this map. - * - * @return The number of entries in this map. - */ - default int size() { - return keyList().getSize(); - } - - /** - * Transform the values returned by this map. - * - * NOTE: This transform is applied once for each lookup of a value, so - * the transform passed should be a proper function, or things will - * likely not work as expected. - * - * @param <V2> - * The new type of returned values. - * - * @param transformer - * The function to use to transform values. - * - * @return The map where each value will be transformed after lookup. - */ - default <V2> IMap<KeyType, V2> transform(final Function<ValueType, V2> transformer) { - return new TransformedValueMap<>(this, transformer); - } - - /** - * Extends this map, creating a new map that will delegate queries to - * the map, but store any added values itself. - * - * @return An extended map. - */ - IMap<KeyType, ValueType> extend(); - - /** - * Remove the value bound to the key. - * - * @param key - * The key to remove from the map. - * - * @return The previous value for the key in the map, or null if the key - * wasn't in the class. NOTE: Just because you received null, - * doesn't mean the map wasn't changed. It may mean that someone - * put a null value for that key into the map. - */ - ValueType remove(KeyType key); - - /** - * Get a list of all the keys in this map. - * - * @return A list of all the keys in this map. - */ - IList<KeyType> keyList(); - - /** - * Get a list of the values in this map. - * - * @return A list of values in this map. - */ - default IList<ValueType> valueList() { - final IList<ValueType> returns = new FunctionalList<>(); - - for (final KeyType key : keyList()) { - returns.add(get(key)); - } - - return returns; - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcdata/SentryList.java b/BJC-Utils2/src/main/java/bjc/utils/funcdata/SentryList.java deleted file mode 100644 index c322743..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/funcdata/SentryList.java +++ /dev/null @@ -1,41 +0,0 @@ -package bjc.utils.funcdata; - -import java.util.List; - -/** - * A list that logs when items are inserted into it. - * - * @author bjculkin - * - * @param <T> - * The type of item in the list. - */ -public class SentryList<T> extends FunctionalList<T> { - /** - * Create a new sentry list. - */ - public SentryList() { - super(); - } - - /** - * Create a new sentry list backed by an existing list. - * - * @param backing - * The backing list. - */ - public SentryList(final List<T> backing) { - super(backing); - } - - @Override - public boolean add(final T item) { - final boolean val = super.add(item); - - if (val) { - System.out.println("Added item (" + item + ") to list"); - } - - return val; - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcdata/TransformedValueMap.java b/BJC-Utils2/src/main/java/bjc/utils/funcdata/TransformedValueMap.java deleted file mode 100644 index 0ca1fdc..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/funcdata/TransformedValueMap.java +++ /dev/null @@ -1,102 +0,0 @@ -package bjc.utils.funcdata; - -import java.util.function.BiConsumer; -import java.util.function.Consumer; -import java.util.function.Function; - -/** - * A map that transforms values from one type to another - * - * @author ben - * - * @param <OldKey> - * The type of the map's keys - * @param <OldValue> - * The type of the map's values - * @param <NewValue> - * The type of the transformed values - */ -final class TransformedValueMap<OldKey, OldValue, NewValue> implements IMap<OldKey, NewValue> { - private final IMap<OldKey, OldValue> backing; - private final Function<OldValue, NewValue> transformer; - - public TransformedValueMap(final IMap<OldKey, OldValue> backingMap, - final Function<OldValue, NewValue> transform) { - backing = backingMap; - transformer = transform; - } - - @Override - public void clear() { - backing.clear(); - } - - @Override - public boolean containsKey(final OldKey key) { - return backing.containsKey(key); - } - - @Override - public IMap<OldKey, NewValue> extend() { - return new ExtendedMap<>(this, new FunctionalMap<>()); - } - - @Override - public void forEach(final BiConsumer<OldKey, NewValue> action) { - backing.forEach((key, value) -> { - action.accept(key, transformer.apply(value)); - }); - } - - @Override - public void forEachKey(final Consumer<OldKey> action) { - backing.forEachKey(action); - } - - @Override - public void forEachValue(final Consumer<NewValue> action) { - backing.forEachValue(value -> { - action.accept(transformer.apply(value)); - }); - } - - @Override - public NewValue get(final OldKey key) { - return transformer.apply(backing.get(key)); - } - - @Override - public int size() { - return backing.size(); - } - - @Override - public IList<OldKey> keyList() { - return backing.keyList(); - } - - @Override - public <MappedValue> IMap<OldKey, MappedValue> transform(final Function<NewValue, MappedValue> transform) { - return new TransformedValueMap<>(this, transform); - } - - @Override - public NewValue put(final OldKey key, final NewValue value) { - throw new UnsupportedOperationException("Can't add items to transformed map"); - } - - @Override - public NewValue remove(final OldKey key) { - return transformer.apply(backing.remove(key)); - } - - @Override - public String toString() { - return backing.toString(); - } - - @Override - public IList<NewValue> valueList() { - return backing.valueList().map(transformer); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcdata/bst/BinarySearchTree.java b/BJC-Utils2/src/main/java/bjc/utils/funcdata/bst/BinarySearchTree.java deleted file mode 100644 index 8acd477..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/funcdata/bst/BinarySearchTree.java +++ /dev/null @@ -1,221 +0,0 @@ -package bjc.utils.funcdata.bst; - -import java.util.ArrayList; -import java.util.Comparator; -import java.util.List; -import java.util.function.Predicate; - -import bjc.utils.funcdata.FunctionalList; -import bjc.utils.funcdata.IList; - -/** - * A binary search tree, with some mild support for functional traversal. - * - * @author ben - * - * @param <T> - * The data type stored in the node. - */ -public class BinarySearchTree<T> { - /* - * The comparator for use in ordering items - */ - private final Comparator<T> comparator; - - /* - * The current count of elements in the tree - */ - private int elementCount; - - /* - * The root element of the tree - */ - private ITreePart<T> root; - - /** - * Create a new tree using the specified way to compare elements. - * - * @param cmp - * The thing to use for comparing elements - */ - public BinarySearchTree(final Comparator<T> cmp) { - if (cmp == null) throw new NullPointerException("Comparator must not be null"); - - elementCount = 0; - comparator = cmp; - } - - /** - * Add a node to the binary search tree. - * - * @param element - * The data to add to the binary search tree. - */ - public void addNode(final T element) { - elementCount++; - - if (root == null) { - root = new BinarySearchTreeNode<>(element, null, null); - } else { - root.add(element, comparator); - } - } - - /** - * Check if an adjusted pivot falls with the bounds of a list - * - * @param elements - * The list to get bounds from - * @param pivot - * The pivot - * @param pivotAdjustment - * The distance from the pivot - * @return Whether the adjusted pivot is with the list - */ - private boolean adjustedPivotInBounds(final IList<T> elements, final int pivot, final int pivotAdjustment) { - return pivot - pivotAdjustment >= 0 && pivot + pivotAdjustment < elements.getSize(); - } - - /** - * Balance the tree, and remove soft-deleted nodes for free. - * - * Takes O(N) time, but also O(N) space. - */ - public void balance() { - final IList<T> elements = new FunctionalList<>(); - - // Add each element to the list in sorted order - root.forEach(TreeLinearizationMethod.INORDER, element -> elements.add(element)); - - // Clear the tree - root = null; - - // Set up the pivot and adjustment for readding elements - final int pivot = elements.getSize() / 2; - int pivotAdjustment = 0; - - // Add elements until there aren't any left - while (adjustedPivotInBounds(elements, pivot, pivotAdjustment)) { - if (root == null) { - // Create a new root element - root = new BinarySearchTreeNode<>(elements.getByIndex(pivot), null, null); - } else { - // Add the left and right elements in a balanced - // manner - root.add(elements.getByIndex(pivot + pivotAdjustment), comparator); - - root.add(elements.getByIndex(pivot - pivotAdjustment), comparator); - } - - // Increase the distance from the pivot - pivotAdjustment++; - } - - // Add any trailing unbalanced elements - if (pivot - pivotAdjustment >= 0) { - root.add(elements.getByIndex(pivot - pivotAdjustment), comparator); - } else if (pivot + pivotAdjustment < elements.getSize()) { - root.add(elements.getByIndex(pivot + pivotAdjustment), comparator); - } - } - - /** - * Soft-delete a node from the tree. - * - * Soft-deleted nodes stay in the tree until trim()/balance() is - * invoked, and are not included in traversals/finds. - * - * @param element - * The node to delete - */ - public void deleteNode(final T element) { - elementCount--; - - root.delete(element, comparator); - } - - /** - * Get the root of the tree. - * - * @return The root of the tree. - */ - public ITreePart<T> getRoot() { - return root; - } - - /** - * Check if a node is in the tree - * - * @param element - * The node to check the presence of for the tree. - * @return Whether or not the node is in the tree. - */ - public boolean isInTree(final T element) { - return root.contains(element, comparator); - } - - /** - * Traverse the tree in a specified way until the function fails - * - * @param linearizationMethod - * The way to linearize the tree for traversal - * @param traversalPredicate - * The function to use until it fails - */ - public void traverse(final TreeLinearizationMethod linearizationMethod, final Predicate<T> traversalPredicate) { - if (linearizationMethod == null) - throw new NullPointerException("Linearization method must not be null"); - else if (traversalPredicate == null) throw new NullPointerException("Predicate must not be nulls"); - - root.forEach(linearizationMethod, traversalPredicate); - } - - /** - * Remove all soft-deleted nodes from the tree. - */ - public void trim() { - final List<T> nodes = new ArrayList<>(elementCount); - - // Add all non-soft deleted nodes to the tree in insertion order - traverse(TreeLinearizationMethod.PREORDER, node -> { - nodes.add(node); - return true; - }); - - // Clear the tree - root = null; - - // Add the nodes to the tree in the order they were inserted - nodes.forEach(node -> addNode(node)); - } - - @Override - public String toString() { - return String.format("BinarySearchTree [elementCount=%s, root='%s']", elementCount, root); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + elementCount; - result = prime * result + (root == null ? 0 : root.hashCode()); - return result; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) return true; - if (obj == null) return false; - if (!(obj instanceof BinarySearchTree<?>)) return false; - - final BinarySearchTree<?> other = (BinarySearchTree<?>) obj; - - if (elementCount != other.elementCount) return false; - if (root == null) { - if (other.root != null) return false; - } else if (!root.equals(other.root)) return false; - - return true; - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcdata/bst/BinarySearchTreeLeaf.java b/BJC-Utils2/src/main/java/bjc/utils/funcdata/bst/BinarySearchTreeLeaf.java deleted file mode 100644 index 8c4f3f0..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/funcdata/bst/BinarySearchTreeLeaf.java +++ /dev/null @@ -1,119 +0,0 @@ -package bjc.utils.funcdata.bst; - -import java.util.Comparator; -import java.util.function.BiFunction; -import java.util.function.Function; -import java.util.function.Predicate; - -/** - * A leaf in a tree. - * - * @author ben - * - * @param <T> - * The data stored in the tree. - */ -public class BinarySearchTreeLeaf<T> implements ITreePart<T> { - /** - * The data held in this tree leaf - */ - protected T data; - - /** - * Whether this node is soft-deleted or not - */ - protected boolean isDeleted; - - /** - * Create a new leaf holding the specified data. - * - * @param element - * The data for the leaf to hold. - */ - public BinarySearchTreeLeaf(final T element) { - data = element; - } - - @Override - public void add(final T element, final Comparator<T> comparator) { - throw new IllegalArgumentException("Can't add to a leaf."); - } - - @Override - public <E> E collapse(final Function<T, E> leafTransformer, final BiFunction<E, E, E> branchCollapser) { - if (leafTransformer == null) throw new NullPointerException("Transformer must not be null"); - - return leafTransformer.apply(data); - } - - @Override - public boolean contains(final T element, final Comparator<T> comparator) { - return this.data.equals(element); - } - - @Override - public T data() { - return data; - } - - @Override - public void delete(final T element, final Comparator<T> comparator) { - if (data.equals(element)) { - isDeleted = true; - } - } - - @Override - public boolean directedWalk(final DirectedWalkFunction<T> treeWalker) { - if (treeWalker == null) throw new NullPointerException("Tree walker must not be null"); - - switch (treeWalker.walk(data)) { - case SUCCESS: - return true; - // We don't have any children to care about - case FAILURE: - case LEFT: - case RIGHT: - default: - return false; - } - } - - @Override - public boolean forEach(final TreeLinearizationMethod linearizationMethod, - final Predicate<T> traversalPredicate) { - if (traversalPredicate == null) throw new NullPointerException("Predicate must not be null"); - - return traversalPredicate.test(data); - } - - @Override - public String toString() { - return String.format("BinarySearchTreeLeaf [data='%s', isDeleted=%s]", data, isDeleted); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + (data == null ? 0 : data.hashCode()); - result = prime * result + (isDeleted ? 1231 : 1237); - return result; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) return true; - if (obj == null) return false; - if (!(obj instanceof BinarySearchTreeLeaf<?>)) return false; - - final BinarySearchTreeLeaf<?> other = (BinarySearchTreeLeaf<?>) obj; - - if (data == null) { - if (other.data != null) return false; - } else if (!data.equals(other.data)) return false; - if (isDeleted != other.isDeleted) return false; - - return true; - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcdata/bst/BinarySearchTreeNode.java b/BJC-Utils2/src/main/java/bjc/utils/funcdata/bst/BinarySearchTreeNode.java deleted file mode 100644 index 9f45c17..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/funcdata/bst/BinarySearchTreeNode.java +++ /dev/null @@ -1,287 +0,0 @@ -package bjc.utils.funcdata.bst; - -import static bjc.utils.funcdata.bst.DirectedWalkFunction.DirectedWalkResult.FAILURE; -import static bjc.utils.funcdata.bst.DirectedWalkFunction.DirectedWalkResult.LEFT; -import static bjc.utils.funcdata.bst.DirectedWalkFunction.DirectedWalkResult.RIGHT; -import static bjc.utils.funcdata.bst.DirectedWalkFunction.DirectedWalkResult.SUCCESS; - -import java.util.Comparator; -import java.util.function.BiFunction; -import java.util.function.Function; -import java.util.function.Predicate; - -/** - * A binary node in a tree. - * - * @author ben - * - * @param <T> - * The data type stored in the tree. - */ -public class BinarySearchTreeNode<T> extends BinarySearchTreeLeaf<T> { - /* - * The left child of this node - */ - private ITreePart<T> left; - - /* - * The right child of this node - */ - private ITreePart<T> right; - - /** - * Create a new node with the specified data and children. - * - * @param element - * The data to store in this node. - * @param lft - * The left child of this node. - * @param rght - * The right child of this node. - */ - public BinarySearchTreeNode(final T element, final ITreePart<T> lft, final ITreePart<T> rght) { - super(element); - this.left = lft; - this.right = rght; - } - - @Override - public void add(final T element, final Comparator<T> comparator) { - if (comparator == null) throw new NullPointerException("Comparator must not be null"); - - switch (comparator.compare(data, element)) { - case -1: - if (left == null) { - left = new BinarySearchTreeNode<>(element, null, null); - } else { - left.add(element, comparator); - } - break; - case 0: - if (isDeleted) { - isDeleted = false; - } else throw new IllegalArgumentException("Can't add duplicate values"); - break; - case 1: - if (right == null) { - right = new BinarySearchTreeNode<>(element, null, null); - } else { - right.add(element, comparator); - } - break; - default: - throw new IllegalStateException("Error: Comparator yielded invalid value"); - } - } - - @Override - public <E> E collapse(final Function<T, E> nodeCollapser, final BiFunction<E, E, E> branchCollapser) { - if (nodeCollapser == null || branchCollapser == null) - throw new NullPointerException("Collapser must not be null"); - - final E collapsedNode = nodeCollapser.apply(data); - - if (left != null) { - final E collapsedLeftBranch = left.collapse(nodeCollapser, branchCollapser); - - if (right != null) { - final E collapsedRightBranch = right.collapse(nodeCollapser, branchCollapser); - - final E collapsedBranches = branchCollapser.apply(collapsedLeftBranch, - collapsedRightBranch); - - return branchCollapser.apply(collapsedNode, collapsedBranches); - } - - return branchCollapser.apply(collapsedNode, collapsedLeftBranch); - } - - if (right != null) { - final E collapsedRightBranch = right.collapse(nodeCollapser, branchCollapser); - - return branchCollapser.apply(collapsedNode, collapsedRightBranch); - } - - return collapsedNode; - } - - @Override - public boolean contains(final T element, final Comparator<T> comparator) { - if (comparator == null) throw new NullPointerException("Comparator must not be null"); - - return directedWalk(currentElement -> { - switch (comparator.compare(element, currentElement)) { - case -1: - return LEFT; - case 0: - return isDeleted ? FAILURE : SUCCESS; - case 1: - return RIGHT; - default: - return FAILURE; - } - }); - } - - @Override - public void delete(final T element, final Comparator<T> comparator) { - if (comparator == null) throw new NullPointerException("Comparator must not be null"); - - directedWalk(currentElement -> { - switch (comparator.compare(data, element)) { - case -1: - return left == null ? FAILURE : LEFT; - case 0: - isDeleted = true; - return FAILURE; - case 1: - return right == null ? FAILURE : RIGHT; - default: - return FAILURE; - } - }); - } - - @Override - public boolean directedWalk(final DirectedWalkFunction<T> treeWalker) { - if (treeWalker == null) throw new NullPointerException("Walker must not be null"); - - switch (treeWalker.walk(data)) { - case SUCCESS: - return true; - case LEFT: - return left.directedWalk(treeWalker); - case RIGHT: - return right.directedWalk(treeWalker); - case FAILURE: - return false; - default: - return false; - } - } - - @Override - public boolean forEach(final TreeLinearizationMethod linearizationMethod, - final Predicate<T> traversalPredicate) { - if (linearizationMethod == null) - throw new NullPointerException("Linearization method must not be null"); - else if (traversalPredicate == null) throw new NullPointerException("Predicate must not be null"); - - switch (linearizationMethod) { - case PREORDER: - return preorderTraverse(linearizationMethod, traversalPredicate); - case INORDER: - return inorderTraverse(linearizationMethod, traversalPredicate); - case POSTORDER: - return postorderTraverse(linearizationMethod, traversalPredicate); - default: - throw new IllegalArgumentException( - "Passed an incorrect TreeLinearizationMethod " + linearizationMethod + ". WAT"); - } - } - - private boolean inorderTraverse(final TreeLinearizationMethod linearizationMethod, - final Predicate<T> traversalPredicate) { - if (!traverseLeftBranch(linearizationMethod, traversalPredicate)) return false; - - if (!traverseElement(traversalPredicate)) return false; - - if (!traverseRightBranch(linearizationMethod, traversalPredicate)) return false; - - return true; - } - - private boolean postorderTraverse(final TreeLinearizationMethod linearizationMethod, - final Predicate<T> traversalPredicate) { - if (!traverseLeftBranch(linearizationMethod, traversalPredicate)) return false; - - if (!traverseRightBranch(linearizationMethod, traversalPredicate)) return false; - - if (!traverseElement(traversalPredicate)) return false; - - return true; - - } - - private boolean preorderTraverse(final TreeLinearizationMethod linearizationMethod, - final Predicate<T> traversalPredicate) { - if (!traverseElement(traversalPredicate)) return false; - - if (!traverseLeftBranch(linearizationMethod, traversalPredicate)) return false; - - if (!traverseRightBranch(linearizationMethod, traversalPredicate)) return false; - - return true; - } - - private boolean traverseElement(final Predicate<T> traversalPredicate) { - boolean nodeSuccesfullyTraversed; - - if (isDeleted) { - nodeSuccesfullyTraversed = true; - } else { - nodeSuccesfullyTraversed = traversalPredicate.test(data); - } - - return nodeSuccesfullyTraversed; - } - - private boolean traverseLeftBranch(final TreeLinearizationMethod linearizationMethod, - final Predicate<T> traversalPredicate) { - boolean leftSuccesfullyTraversed; - - if (left == null) { - leftSuccesfullyTraversed = true; - } else { - leftSuccesfullyTraversed = left.forEach(linearizationMethod, traversalPredicate); - } - - return leftSuccesfullyTraversed; - } - - private boolean traverseRightBranch(final TreeLinearizationMethod linearizationMethod, - final Predicate<T> traversalPredicate) { - boolean rightSuccesfullyTraversed; - - if (right == null) { - rightSuccesfullyTraversed = true; - } else { - rightSuccesfullyTraversed = right.forEach(linearizationMethod, traversalPredicate); - } - - return rightSuccesfullyTraversed; - } - - @Override - public String toString() { - return String.format("BinarySearchTreeNode [left='%s', right='%s']", left, right); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = super.hashCode(); - result = prime * result + (left == null ? 0 : left.hashCode()); - result = prime * result + (right == null ? 0 : right.hashCode()); - return result; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) return true; - if (!super.equals(obj)) return false; - if (!(obj instanceof BinarySearchTreeNode<?>)) return false; - - final BinarySearchTreeNode<?> other = (BinarySearchTreeNode<?>) obj; - - if (left == null) { - if (other.left != null) return false; - } else if (!left.equals(other.left)) return false; - - if (right == null) { - if (other.right != null) return false; - } else if (!right.equals(other.right)) return false; - - return true; - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcdata/bst/DirectedWalkFunction.java b/BJC-Utils2/src/main/java/bjc/utils/funcdata/bst/DirectedWalkFunction.java deleted file mode 100644 index e11524a..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/funcdata/bst/DirectedWalkFunction.java +++ /dev/null @@ -1,49 +0,0 @@ -package bjc.utils.funcdata.bst; - -/** - * Represents a function for doing a directed walk of a binary tree. - * - * @author ben - * - * @param <T> - * The type of element stored in the walked tree - */ -@FunctionalInterface -public interface DirectedWalkFunction<T> { - /** - * Represents the results used to direct a walk in a binary tree. - * - * @author ben - * - */ - public enum DirectedWalkResult { - /** - * Specifies that the function has failed. - */ - FAILURE, - /** - * Specifies that the function wants to move left in the tree - * next. - */ - LEFT, - /** - * Specifies that the function wants to move right in the tree - * next. - */ - RIGHT, - /** - * Specifies that the function has succesfully completed - * - */ - SUCCESS - } - - /** - * Perform a directed walk on a node of a tree. - * - * @param element - * The data stored in the node currently being visited - * @return The way the function wants the walk to go next. - */ - public DirectedWalkResult walk(T element); -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcdata/bst/ITreePart.java b/BJC-Utils2/src/main/java/bjc/utils/funcdata/bst/ITreePart.java deleted file mode 100644 index 3aa8880..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/funcdata/bst/ITreePart.java +++ /dev/null @@ -1,96 +0,0 @@ -package bjc.utils.funcdata.bst; - -import java.util.Comparator; -import java.util.function.BiFunction; -import java.util.function.Function; -import java.util.function.Predicate; - -/** - * A interface for the fundamental things that want to be part of a tree. - * - * @author ben - * - * @param <T> - * The data contained in this part of the tree. - */ -public interface ITreePart<T> { - /** - * Add a element below this tree part somewhere. - * - * @param element - * The element to add below this tree part - * @param comparator - * The thing to use for comparing values to find where to - * insert the tree part. - */ - public void add(T element, Comparator<T> comparator); - - /** - * Collapses this tree part into a single value. Does not change the - * underlying tree. - * - * @param <E> - * The type of the final collapsed value - * - * @param nodeCollapser - * The function to use to transform data into mapped - * form. - * @param branchCollapser - * The function to use to collapse data in mapped form - * into a single value. - * @return A single value from collapsing the tree. - */ - public <E> E collapse(Function<T, E> nodeCollapser, BiFunction<E, E, E> branchCollapser); - - /** - * Check if this tre part or below it contains the specified data item - * - * @param element - * The data item to look for. - * @param comparator - * The comparator to use to search for the data item - * @return Whether or not the given item is contained in this tree part - * or its children. - */ - public boolean contains(T element, Comparator<T> comparator); - - /** - * Get the data associated with this tree part. - * - * @return The data associated with this tree part. - */ - public T data(); - - /** - * Remove the given node from this tree part and any of its children. - * - * @param element - * The data item to remove. - * @param comparator - * The comparator to use to search for the data item. - */ - public void delete(T element, Comparator<T> comparator); - - /** - * Execute a directed walk through the tree. - * - * @param walker - * The function to use to direct the walk through the - * tree. - * @return Whether the directed walk finished successfully. - */ - public boolean directedWalk(DirectedWalkFunction<T> walker); - - /** - * Execute a provided function for each element of tree it succesfully - * completes for - * - * @param linearizationMethod - * The way to linearize the tree for executing - * @param predicate - * The predicate to apply to each element, where it - * returning false terminates traversal early - * @return Whether the traversal finished succesfully - */ - public boolean forEach(TreeLinearizationMethod linearizationMethod, Predicate<T> predicate); -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcdata/bst/TreeLinearizationMethod.java b/BJC-Utils2/src/main/java/bjc/utils/funcdata/bst/TreeLinearizationMethod.java deleted file mode 100644 index 0c83867..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/funcdata/bst/TreeLinearizationMethod.java +++ /dev/null @@ -1,25 +0,0 @@ -package bjc.utils.funcdata.bst; - -/** - * Represents the ways to linearize a tree for traversal. - * - * @author ben - * - */ -public enum TreeLinearizationMethod { - /** - * Visit the left side of this tree part, the tree part itself, and then - * the right part. - */ - INORDER, - /** - * Visit the left side of this tree part, the right side, and then the - * tree part itself. - */ - POSTORDER, - /** - * Visit the tree part itself, then the left side of tthis tree part and - * then the right part. - */ - PREORDER -}
\ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcdata/theory/Bifunctor.java b/BJC-Utils2/src/main/java/bjc/utils/funcdata/theory/Bifunctor.java deleted file mode 100644 index 13c1709..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/funcdata/theory/Bifunctor.java +++ /dev/null @@ -1,139 +0,0 @@ -package bjc.utils.funcdata.theory; - -import java.util.function.Function; - -/** - * A functor over a pair of heterogeneous types - * - * @author ben - * @param <LeftType> - * The type stored on the 'left' of the pair - * @param <RightType> - * The type stored on the 'right' of the pair - * - */ -public interface Bifunctor<LeftType, RightType> { - /** - * Alias for functor mapping. - * - * @author EVE - * - * @param <OldLeft> - * @param <OldRight> - * @param <NewLeft> - * @param <NewRight> - */ - public interface BifunctorMap<OldLeft, OldRight, NewLeft, NewRight> - extends Function<Bifunctor<OldLeft, OldRight>, Bifunctor<NewLeft, NewRight>> { - - } - - /** - * Alias for left functor mapping. - * - * @author EVE - * - * @param <OldLeft> - * @param <OldRight> - * @param <NewLeft> - */ - public interface LeftBifunctorMap<OldLeft, OldRight, NewLeft> - extends BifunctorMap<OldLeft, OldRight, NewLeft, OldRight> { - - } - - /** - * Alias for right functor mapping. - * - * @author EVE - * - * @param <OldLeft> - * @param <OldRight> - * @param <NewRight> - */ - public interface RightBifunctorMap<OldLeft, OldRight, NewRight> - extends BifunctorMap<OldLeft, OldRight, OldLeft, NewRight> { - - } - - /** - * Lift a pair of functions to a single function that maps over both - * parts of a pair - * - * @param <OldLeft> - * The old left type of the pair - * @param <OldRight> - * The old right type of the pair - * @param <NewLeft> - * The new left type of the pair - * @param <NewRight> - * The new right type of the pair - * @param leftFunc - * The function that maps over the left of the pair - * @param rightFunc - * The function that maps over the right of the pair - * @return A function that maps over both parts of the pair - */ - public default <OldLeft, OldRight, NewLeft, NewRight> BifunctorMap<OldLeft, OldRight, NewLeft, NewRight> bimap( - final Function<OldLeft, NewLeft> leftFunc, final Function<OldRight, NewRight> rightFunc) { - final BifunctorMap<OldLeft, OldRight, NewLeft, NewRight> bimappedFunc = (argPair) -> { - final LeftBifunctorMap<OldLeft, OldRight, NewLeft> leftMapper = argPair.fmapLeft(leftFunc); - - final Bifunctor<NewLeft, OldRight> leftMappedFunctor = leftMapper.apply(argPair); - final RightBifunctorMap<NewLeft, OldRight, NewRight> rightMapper = leftMappedFunctor - .fmapRight(rightFunc); - - return rightMapper.apply(leftMappedFunctor); - }; - - return bimappedFunc; - } - - /** - * Lift a function to operate over the left part of this pair - * - * @param <OldLeft> - * The old left type of the pair - * @param <OldRight> - * The old right type of the pair - * @param <NewLeft> - * The new left type of the pair - * @param func - * The function to lift to work over the left side of the - * pair - * @return The function lifted to work over the left side of bifunctors - */ - public <OldLeft, OldRight, NewLeft> LeftBifunctorMap<OldLeft, OldRight, NewLeft> fmapLeft( - Function<OldLeft, NewLeft> func); - - /** - * Lift a function to operate over the right part of this pair - * - * @param <OldLeft> - * The old left type of the pair - * @param <OldRight> - * The old right type of the pair - * @param <NewRight> - * The new right type of the pair - * @param func - * The function to lift to work over the right side of - * the pair - * @return The function lifted to work over the right side of bifunctors - */ - public <OldLeft, OldRight, NewRight> RightBifunctorMap<OldLeft, OldRight, NewRight> fmapRight( - Function<OldRight, NewRight> func); - - /** - * Get the value contained on the left of this bifunctor - * - * @return The value on the left side of this bifunctor - */ - public LeftType getLeft(); - - /** - * Get the value contained on the right of this bifunctor - * - * @return The value on the right of this bifunctor - */ - public RightType getRight(); -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcdata/theory/Functor.java b/BJC-Utils2/src/main/java/bjc/utils/funcdata/theory/Functor.java deleted file mode 100644 index 1c53284..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/funcdata/theory/Functor.java +++ /dev/null @@ -1,39 +0,0 @@ -package bjc.utils.funcdata.theory; - -import java.util.function.Function; - -/** - * Represents a container or context some sort usually, but the precise - * definition is that it represents exactly what it is defined as - * - * @author ben - * @param <ContainedType> - * The value inside the functor - */ -public interface Functor<ContainedType> { - /** - * Converts a normal function to operate over values in a functor. - * - * N.B: Even though the type signature implies that you can apply the - * resulting function to any type of functor, it is only safe to call it - * on instances of the type of functor you called fmap on. - * - * @param <ArgType> - * The argument of the function - * @param <ReturnType> - * The return type of the function - * @param func - * The function to convert - * @return The passed in function converted to work over a particular - * type of functors - */ - public <ArgType, ReturnType> Function<Functor<ArgType>, Functor<ReturnType>> fmap( - Function<ArgType, ReturnType> func); - - /** - * Retrieve the thing inside this functor - * - * @return The thing inside this functor - */ - public ContainedType getValue(); -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/functypes/ID.java b/BJC-Utils2/src/main/java/bjc/utils/functypes/ID.java deleted file mode 100644 index d3197e2..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/functypes/ID.java +++ /dev/null @@ -1,20 +0,0 @@ -package bjc.utils.functypes;
-
-import java.util.function.UnaryOperator;
-
-/**
- * Identity function.
- *
- * @author bjculkin
- *
- */
-public class ID {
- /**
- * Create an identity function.
- *
- * @return A identity function.
- */
- public static <A> UnaryOperator<A> id() {
- return (x) -> x;
- }
-}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/functypes/ListFlattener.java b/BJC-Utils2/src/main/java/bjc/utils/functypes/ListFlattener.java deleted file mode 100644 index cfa0c8b..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/functypes/ListFlattener.java +++ /dev/null @@ -1,17 +0,0 @@ -package bjc.utils.functypes; - -import java.util.function.Function; - -import bjc.utils.funcdata.IList; - -/** - * A function that flattens a list. - * - * @author bjculkin - * - * @param <S> - * The type of value in the list. - */ -public interface ListFlattener<S> extends Function<IList<S>, S> { - -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcutils/CollectorUtils.java b/BJC-Utils2/src/main/java/bjc/utils/funcutils/CollectorUtils.java deleted file mode 100644 index a044bfd..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/funcutils/CollectorUtils.java +++ /dev/null @@ -1,39 +0,0 @@ -package bjc.utils.funcutils; - -import java.util.stream.Collector; - -import bjc.utils.data.IHolder; -import bjc.utils.data.IPair; - -/** - * Utilities for producing implementations of {@link Collector} - * - * @author ben - * - */ -public class CollectorUtils { - /** - * Create a collector that applies two collectors at once - * - * @param <InitialType> - * The type of the collection to collect from - * @param <AuxType1> - * The intermediate type of the first collector - * @param <AuxType2> - * The intermediate type of the second collector - * @param <FinalType1> - * The final type of the first collector - * @param <FinalType2> - * The final type of the second collector - * @param first - * The first collector to use - * @param second - * The second collector to use - * @return A collector that functions as mentioned above - */ - public static <InitialType, AuxType1, AuxType2, FinalType1, FinalType2> Collector<InitialType, IHolder<IPair<AuxType1, AuxType2>>, IPair<FinalType1, FinalType2>> compoundCollect( - final Collector<InitialType, AuxType1, FinalType1> first, - final Collector<InitialType, AuxType2, FinalType2> second) { - return new CompoundCollector<>(first, second); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcutils/CompoundCollector.java b/BJC-Utils2/src/main/java/bjc/utils/funcutils/CompoundCollector.java deleted file mode 100644 index 35695bc..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/funcutils/CompoundCollector.java +++ /dev/null @@ -1,89 +0,0 @@ -package bjc.utils.funcutils; - -import java.util.Set; -import java.util.function.BiConsumer; -import java.util.function.BinaryOperator; -import java.util.function.Function; -import java.util.function.Supplier; -import java.util.stream.Collector; - -import bjc.utils.data.IHolder; -import bjc.utils.data.IPair; -import bjc.utils.data.Identity; -import bjc.utils.data.Pair; - -final class CompoundCollector<InitialType, AuxType1, AuxType2, FinalType1, FinalType2> - implements Collector<InitialType, IHolder<IPair<AuxType1, AuxType2>>, IPair<FinalType1, FinalType2>> { - - private final Set<java.util.stream.Collector.Characteristics> characteristicSet; - - private final Collector<InitialType, AuxType1, FinalType1> first; - private final Collector<InitialType, AuxType2, FinalType2> second; - - public CompoundCollector(final Collector<InitialType, AuxType1, FinalType1> first, - final Collector<InitialType, AuxType2, FinalType2> second) { - this.first = first; - this.second = second; - - characteristicSet = first.characteristics(); - characteristicSet.addAll(second.characteristics()); - } - - @Override - public BiConsumer<IHolder<IPair<AuxType1, AuxType2>>, InitialType> accumulator() { - final BiConsumer<AuxType1, InitialType> firstAccumulator = first.accumulator(); - final BiConsumer<AuxType2, InitialType> secondAccumulator = second.accumulator(); - - return (state, value) -> { - state.doWith(statePair -> { - statePair.doWith((left, right) -> { - firstAccumulator.accept(left, value); - secondAccumulator.accept(right, value); - }); - }); - }; - } - - @Override - public Set<java.util.stream.Collector.Characteristics> characteristics() { - return characteristicSet; - } - - @Override - public BinaryOperator<IHolder<IPair<AuxType1, AuxType2>>> combiner() { - final BinaryOperator<AuxType1> firstCombiner = first.combiner(); - final BinaryOperator<AuxType2> secondCombiner = second.combiner(); - - return (leftState, rightState) -> { - return leftState.unwrap(leftPair -> { - return rightState.transform(rightPair -> { - return leftPair.combine(rightPair, firstCombiner, secondCombiner); - }); - }); - }; - } - - @Override - public Function<IHolder<IPair<AuxType1, AuxType2>>, IPair<FinalType1, FinalType2>> finisher() { - return state -> { - return state.unwrap(pair -> { - return pair.bind((left, right) -> { - final FinalType1 finalLeft = first.finisher().apply(left); - final FinalType2 finalRight = second.finisher().apply(right); - - return new Pair<>(finalLeft, finalRight); - }); - }); - }; - } - - @Override - public Supplier<IHolder<IPair<AuxType1, AuxType2>>> supplier() { - return () -> { - final AuxType1 initialLeft = first.supplier().get(); - final AuxType2 initialRight = second.supplier().get(); - - return new Identity<>(new Pair<>(initialLeft, initialRight)); - }; - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcutils/EnumUtils.java b/BJC-Utils2/src/main/java/bjc/utils/funcutils/EnumUtils.java deleted file mode 100644 index e4c0bda..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/funcutils/EnumUtils.java +++ /dev/null @@ -1,63 +0,0 @@ -package bjc.utils.funcutils; - -import java.util.Random; -import java.util.function.Consumer; - -import bjc.utils.funcdata.FunctionalList; -import bjc.utils.funcdata.IList; - -/** - * Utility methods on enums - * - * @author ben - * - */ -public class EnumUtils { - /** - * Do an action for a random number of enum values - * - * @param <E> - * The type of the enum - * @param clasz - * The enum class - * @param nValues - * The number of values to execute the action on - * @param action - * The action to perform on random values - * @param rnd - * The source of randomness to use - */ - public static <E extends Enum<E>> void doForValues(final Class<E> clasz, final int nValues, - final Consumer<E> action, final Random rnd) { - final E[] enumValues = clasz.getEnumConstants(); - - final IList<E> valueList = new FunctionalList<>(enumValues); - - final int randomValueCount = enumValues.length - nValues; - - for (int i = 0; i <= randomValueCount; i++) { - final E rDir = valueList.randItem(rnd::nextInt); - - valueList.removeMatching(rDir); - } - - valueList.forEach(action); - } - - /** - * Get a random value from an enum - * - * @param <E> - * The type of the enum - * @param clasz - * The class of the enum - * @param rnd - * The random source to use - * @return A random value from the specified enum - */ - public static <E extends Enum<E>> E getRandomValue(final Class<E> clasz, final Random rnd) { - final E[] enumValues = clasz.getEnumConstants(); - - return new FunctionalList<>(enumValues).randItem(rnd::nextInt); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcutils/FileUtils.java b/BJC-Utils2/src/main/java/bjc/utils/funcutils/FileUtils.java deleted file mode 100644 index 87199b1..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/funcutils/FileUtils.java +++ /dev/null @@ -1,40 +0,0 @@ -package bjc.utils.funcutils; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.attribute.BasicFileAttributes; -import java.util.function.BiPredicate; - -/** - * Utilities for doing things with files - * - * @author ben - * - */ -public class FileUtils { - /** - * Traverse a directory recursively. This is a depth-first traversal - * - * - * @param root - * The directory to start the traversal at - * @param predicate - * The predicate to determine whether or not to traverse - * a directory - * @param action - * The action to invoke upon each file in the directory. - * Returning true means to continue the traversal, - * returning false stops it - * @throws IOException - * if the walk throws an exception - * - * TODO If it becomes necessary, write another overload - * for this with all the buttons and knobs from - * walkFileTree - */ - public static void traverseDirectory(final Path root, final BiPredicate<Path, BasicFileAttributes> predicate, - final BiPredicate<Path, BasicFileAttributes> action) throws IOException { - Files.walkFileTree(root, new FunctionalFileVisitor(predicate, action)); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcutils/FuncUtils.java b/BJC-Utils2/src/main/java/bjc/utils/funcutils/FuncUtils.java deleted file mode 100644 index 9950add..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/funcutils/FuncUtils.java +++ /dev/null @@ -1,76 +0,0 @@ -package bjc.utils.funcutils; - -import java.util.function.BiFunction; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.UnaryOperator; - -/** - * Utility things for functions - * - * @author ben - * - */ -public class FuncUtils { - /** - * Convert a binary function into a unary function that returns a - * function - * - * @param <A> - * The initial type of the function - * @param <B> - * The intermediate type of the function - * @param <C> - * The terminal type of the function - * @param func - * The function to transform - * @return The function transformed into a unary function returning a - * function - */ - public static <A, B, C> Function<A, Function<B, C>> curry2(final BiFunction<A, B, C> func) { - return arg1 -> arg2 -> { - return func.apply(arg1, arg2); - }; - } - - /** - * Do the specified action the specified number of times - * - * @param nTimes - * The number of times to do the action - * @param cons - * The action to perform - */ - public static void doTimes(final int nTimes, final Consumer<Integer> cons) { - for (int i = 0; i < nTimes; i++) { - cons.accept(i); - } - } - - /** - * Return an operator that executes until it converges. - * - * @param op - * The operator to execute. - * @param maxTries - * The maximum amount of times to apply the function in an - * attempt to cause it to converge. - */ - public static <T> UnaryOperator<T> converge(final UnaryOperator<T> op, final int maxTries) { - return (val) -> { - T newVal = op.apply(val); - T oldVal; - - int tries = 0; - - do { - oldVal = newVal; - newVal = op.apply(newVal); - - tries += 1; - } while(!newVal.equals(oldVal) && tries < maxTries); - - return newVal; - }; - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcutils/FunctionalFileVisitor.java b/BJC-Utils2/src/main/java/bjc/utils/funcutils/FunctionalFileVisitor.java deleted file mode 100644 index db6c43b..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/funcutils/FunctionalFileVisitor.java +++ /dev/null @@ -1,36 +0,0 @@ -package bjc.utils.funcutils; - -import java.io.IOException; -import java.nio.file.FileVisitResult; -import java.nio.file.Path; -import java.nio.file.SimpleFileVisitor; -import java.nio.file.attribute.BasicFileAttributes; -import java.util.function.BiPredicate; - -/* - * Functional implementation of a file visitor. - */ -final class FunctionalFileVisitor extends SimpleFileVisitor<Path> { - private final BiPredicate<Path, BasicFileAttributes> predicate; - private final BiPredicate<Path, BasicFileAttributes> action; - - public FunctionalFileVisitor(final BiPredicate<Path, BasicFileAttributes> predicate, - final BiPredicate<Path, BasicFileAttributes> action) { - this.predicate = predicate; - this.action = action; - } - - @Override - public FileVisitResult preVisitDirectory(final Path dir, final BasicFileAttributes attrs) throws IOException { - if (predicate.test(dir, attrs)) return FileVisitResult.CONTINUE; - - return FileVisitResult.SKIP_SUBTREE; - } - - @Override - public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs) throws IOException { - if (action.test(file, attrs)) return FileVisitResult.CONTINUE; - - return FileVisitResult.TERMINATE; - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcutils/GroupPartIteration.java b/BJC-Utils2/src/main/java/bjc/utils/funcutils/GroupPartIteration.java deleted file mode 100644 index f3b2254..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/funcutils/GroupPartIteration.java +++ /dev/null @@ -1,62 +0,0 @@ -package bjc.utils.funcutils; - -import java.util.function.Consumer; -import java.util.function.Function; - -import bjc.utils.funcdata.FunctionalList; -import bjc.utils.funcdata.IList; - -/** - * Implements a single group partitioning pass on a list - * - * @author ben - * - * @param <E> - * The type of element in the list being partitioned - */ -final class GroupPartIteration<E> implements Consumer<E> { - private final IList<IList<E>> returnedList; - - public IList<E> currentPartition; - private final IList<E> rejectedItems; - - private int numberInCurrentPartition; - private final int numberPerPartition; - - private final Function<E, Integer> elementCounter; - - public GroupPartIteration(final IList<IList<E>> returned, final IList<E> rejects, final int nPerPart, - final Function<E, Integer> eleCount) { - this.returnedList = returned; - this.rejectedItems = rejects; - this.numberPerPartition = nPerPart; - this.elementCounter = eleCount; - - this.currentPartition = new FunctionalList<>(); - this.numberInCurrentPartition = 0; - } - - @Override - public void accept(final E value) { - final boolean shouldStartPartition = numberInCurrentPartition >= numberPerPartition; - - if (shouldStartPartition) { - returnedList.add(currentPartition); - - currentPartition = new FunctionalList<>(); - numberInCurrentPartition = 0; - } else { - final int currentElementCount = elementCounter.apply(value); - - final boolean shouldReject = numberInCurrentPartition - + currentElementCount >= numberPerPartition; - - if (shouldReject) { - rejectedItems.add(value); - } else { - currentPartition.add(value); - numberInCurrentPartition += currentElementCount; - } - } - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcutils/IBuilder.java b/BJC-Utils2/src/main/java/bjc/utils/funcutils/IBuilder.java deleted file mode 100644 index a96a4d6..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/funcutils/IBuilder.java +++ /dev/null @@ -1,31 +0,0 @@ -package bjc.utils.funcutils; - -/** - * Generic interface for objects that implement the builder pattern - * - * @author ben - * - * @param <E> - * The type of object being built - */ -public interface IBuilder<E> { - /** - * Build the object this builder is building - * - * @return The built object - * @throws IllegalStateException - * if the data in the builder cannot be built into its - * corresponding object at this point in time - */ - public E build(); - - /** - * Reset the state of this builder to its initial state - * - * @throws UnsupportedOperationException - * if the builder doesn't support resetting its state - */ - public default void reset() { - throw new UnsupportedOperationException("Builder doesn't support state resetting"); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcutils/Isomorphism.java b/BJC-Utils2/src/main/java/bjc/utils/funcutils/Isomorphism.java deleted file mode 100644 index 2d3655e..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/funcutils/Isomorphism.java +++ /dev/null @@ -1,60 +0,0 @@ -package bjc.utils.funcutils; - -import java.util.function.Function; - -/** - * A pair of functions to transform between a pair of types. - * - * @author bjculkin - * - * @param <S> - * The source type of the isomorphism. - * - * @param <D> - * The destination type of isomorphism. - * - */ -public class Isomorphism<S, D> { - private Function<S, D> toFunc; - private Function<D, S> fromFunc; - - /** - * Create a new isomorphism. - * - * @param to - * The 'forward' function, from the source to the - * definition. - * - * @param from - * The 'backward' function, from the definition to the - * source. - */ - public Isomorphism(Function<S, D> to, Function<D, S> from) { - toFunc = to; - fromFunc = from; - } - - /** - * Apply the isomorphism forward. - * - * @param val - * The source value. - * - * @return The destination value. - */ - public D to(S val) { - return toFunc.apply(val); - } - - /** - * Apply the isomorphism backward. - * - * @param val - * The destination value. - * - * @return The source value. - */ - public S from(D val) { - return fromFunc.apply(val); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcutils/LambdaLock.java b/BJC-Utils2/src/main/java/bjc/utils/funcutils/LambdaLock.java deleted file mode 100644 index 62c5d32..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/funcutils/LambdaLock.java +++ /dev/null @@ -1,105 +0,0 @@ -package bjc.utils.funcutils; - -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; -import java.util.function.Supplier; - -/** - * A wrapper around a {@link ReadWriteLock} to ensure that the lock is used - * properly. - * - * @author EVE - * - */ -public class LambdaLock { - private final Lock readLock; - private final Lock writeLock; - - /** - * Create a new lambda-enabled lock around a new lock. - */ - public LambdaLock() { - this(new ReentrantReadWriteLock()); - } - - /** - * Create a new lambda-enabled lock. - * - * @param lck - * The lock to wrap. - */ - public LambdaLock(final ReadWriteLock lck) { - readLock = lck.readLock(); - writeLock = lck.writeLock(); - } - - /** - * Execute an action with the read lock taken. - * - * @param supp - * The action to call. - * - * @return The result of the action. - */ - public <T> T read(final Supplier<T> supp) { - readLock.lock(); - - try { - return supp.get(); - } finally { - readLock.unlock(); - } - } - - /** - * Execute an action with the write lock taken. - * - * @param supp - * The action to call. - * - * @return The result of the action. - */ - public <T> T write(final Supplier<T> supp) { - writeLock.lock(); - - try { - return supp.get(); - } finally { - writeLock.unlock(); - } - } - - /** - * Execute an action with the read lock taken. - * - * @param action - * The action to call. - * - */ - public void read(final Runnable action) { - readLock.lock(); - - try { - action.run(); - } finally { - readLock.unlock(); - } - } - - /** - * Execute an action with the write lock taken. - * - * @param action - * The action to call. - */ - public void write(final Runnable action) { - writeLock.lock(); - - try { - action.run(); - } finally { - writeLock.unlock(); - } - } -}
\ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcutils/ListUtils.java b/BJC-Utils2/src/main/java/bjc/utils/funcutils/ListUtils.java deleted file mode 100644 index c0daa1e..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/funcutils/ListUtils.java +++ /dev/null @@ -1,294 +0,0 @@ -package bjc.utils.funcutils; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.function.Function; -import java.util.function.Supplier; - -import bjc.utils.funcdata.FunctionalList; -import bjc.utils.funcdata.IList; - -/** - * Utilities for manipulating FunctionalLists that don't belong in the class - * itself - * - * @author ben - * - */ -public class ListUtils { - private static final int MAX_NTRIESPART = 50; - - /** - * Collapse a string of tokens into a single string without adding any - * spaces - * - * @param input - * The list of tokens to collapse - * @return The collapsed string of tokens - */ - public static String collapseTokens(final IList<String> input) { - if (input == null) throw new NullPointerException("Input must not be null"); - - return collapseTokens(input, ""); - } - - /** - * Collapse a string of tokens into a single string, adding the desired - * separator after each token - * - * @param input - * The list of tokens to collapse - * @param seperator - * The separator to use for separating tokens - * @return The collapsed string of tokens - */ - public static String collapseTokens(final IList<String> input, final String seperator) { - if (input == null) - throw new NullPointerException("Input must not be null"); - else if (seperator == null) throw new NullPointerException("Seperator must not be null"); - - if (input.getSize() < 1) - return ""; - else if (input.getSize() == 1) - return input.first(); - else { - final StringBuilder state = new StringBuilder(); - - int i = 1; - for (final String itm : input.toIterable()) { - state.append(itm); - - if (i != input.getSize()) { - state.append(seperator); - } - - i += 1; - } - - return state.toString(); - } - } - - /** - * Select a number of random items from the list without replacement - * - * @param <E> - * The type of items to select - * @param list - * The list to select from - * @param number - * The number of items to selet - * @param rng - * A function that creates a random number from 0 to the - * desired number - * @return A new list containing the desired number of items randomly - * selected from the specified list without replacement - */ - - public static <E> IList<E> drawWithoutReplacement(final IList<E> list, final int number, - final Function<Integer, Integer> rng) { - final IList<E> selected = new FunctionalList<>(new ArrayList<>(number)); - - final int total = list.getSize(); - - final Iterator<E> itr = list.toIterable().iterator(); - E element = null; - - for (final int index = 0; itr.hasNext(); element = itr.next()) { - /* - * n - m - */ - final int winningChance = number - selected.getSize(); - - /* - * N - t - */ - final int totalChance = total - (index - 1); - - /* - * Probability of selecting the t+1'th element - */ - if (NumberUtils.isProbable(winningChance, totalChance, rng)) { - selected.add(element); - } - } - - return selected; - } - - /** - * Select a number of random items from the list, with replacement - * - * @param <E> - * The type of items to select - * @param list - * The list to select from - * @param number - * The number of items to selet - * @param rng - * A function that creates a random number from 0 to the - * desired number - * @return A new list containing the desired number of items randomly - * selected from the specified list - */ - public static <E> IList<E> drawWithReplacement(final IList<E> list, final int number, - final Function<Integer, Integer> rng) { - final IList<E> selected = new FunctionalList<>(new ArrayList<>(number)); - - for (int i = 0; i < number; i++) { - selected.add(list.randItem(rng)); - } - - return selected; - } - - /** - * Partition a list into a list of lists, where each element can count - * for more than one element in a partition - * - * @param <E> - * The type of elements in the list to partition - * - * @param input - * The list to partition - * @param counter - * The function to determine the count for each element - * for - * @param partitionSize - * The number of elements to put in each partition - * - * @return A list partitioned according to the above rules - */ - public static <E> IList<IList<E>> groupPartition(final IList<E> input, final Function<E, Integer> counter, - final int partitionSize) { - if (input == null) - throw new NullPointerException("Input list must not be null"); - else if (counter == null) - throw new NullPointerException("Counter must not be null"); - else if (partitionSize < 1 || partitionSize > input.getSize()) { - final String fmt = "%d is not a valid partition size. Must be between 1 and %d"; - final String msg = String.format(fmt, partitionSize, input.getSize()); - - throw new IllegalArgumentException(msg); - } - - /* - * List that holds our results - */ - final IList<IList<E>> returned = new FunctionalList<>(); - - /* - * List that holds elements rejected during current pass - */ - final IList<E> rejected = new FunctionalList<>(); - - final GroupPartIteration<E> it = new GroupPartIteration<>(returned, rejected, partitionSize, counter); - - /* - * Run up to a certain number of passes - */ - for (int numberOfIterations = 0; numberOfIterations < MAX_NTRIESPART - && !rejected.isEmpty(); numberOfIterations++) { - input.forEach(it); - - if (rejected.isEmpty()) { - /* - * Nothing was rejected, so we're done - */ - return returned; - } - } - - - final String fmt = "Heuristic (more than %d iterations of partitioning) detected an unpartitionable list. (%s)\nThe following elements were not partitioned: %s\nCurrent group in formation: %s\nPreviously formed groups: %s\n"; - - final String msg = String.format(fmt, MAX_NTRIESPART, input.toString(), rejected.toString(), it.currentPartition.toString(), returned.toString()); - - throw new IllegalArgumentException(msg); - } - - /** - * Merge the contents of a bunch of lists together into a single list - * - * @param <E> - * The type of value in this lists - * @param lists - * The values in the lists to merge - * @return A list containing all the elements of the lists - */ - @SafeVarargs - public static <E> IList<E> mergeLists(final IList<E>... lists) { - final IList<E> returned = new FunctionalList<>(); - - for (final IList<E> list : lists) { - for (final E itm : list.toIterable()) { - returned.add(itm); - } - } - - return returned; - } - - /** - * Pad the provided list out to the desired size - * - * @param <E> - * The type of elements in the list - * @param list - * The list to pad out - * @param counter - * The function to count elements with - * @param size - * The desired size of the list - * @param padder - * The function to get elements to pad with - * @return The list, padded to the desired size - * @throws IllegalArgumentException - * if the list couldn't be padded to the desired size - */ - public static <E> IList<E> padList(final IList<E> list, final Function<E, Integer> counter, final int size, - final Supplier<E> padder) { - int count = 0; - - final IList<E> returned = new FunctionalList<>(); - - for (final E itm : list.toIterable()) { - count += counter.apply(itm); - - returned.add(itm); - } - - if (count % size != 0) { - /* - * We need to pad - */ - int needed = count % size; - int threshold = 0; - - while (needed > 0 && threshold <= MAX_NTRIESPART) { - final E val = padder.get(); - final int newCount = counter.apply(val); - - if (newCount <= needed) { - returned.add(val); - - threshold = 0; - - needed -= newCount; - } else { - threshold += 1; - } - } - - if (threshold > MAX_NTRIESPART) { - final String fmt = "Heuristic (more than %d iterations of attempting to pad) detected an unpaddable list. (%s)\nPartially padded list: %S"; - - final String msg = String.format(fmt, MAX_NTRIESPART, list.toString(), returned.toString()); - - throw new IllegalArgumentException(msg); - } - } - - return returned; - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcutils/NumberUtils.java b/BJC-Utils2/src/main/java/bjc/utils/funcutils/NumberUtils.java deleted file mode 100644 index 770d3a5..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/funcutils/NumberUtils.java +++ /dev/null @@ -1,69 +0,0 @@ -package bjc.utils.funcutils; - -import java.util.function.Function; - -/** - * Utility functions for dealing with numbers - * - * @author ben - * - */ -public class NumberUtils { - /** - * Compute the falling factorial of a number - * - * @param value - * The number to compute - * @param power - * The power to do the falling factorial for - * @return The falling factorial of the number to the power - */ - public static int fallingFactorial(final int value, final int power) { - if (power == 0) - return 1; - else if (power == 1) - return value; - else { - int result = 1; - - for (int currentSub = 0; currentSub < power + 1; currentSub++) { - result *= value - currentSub; - } - - return result; - } - } - - /** - * Evaluates a linear probability distribution - * - * @param winning - * The number of winning possibilities - * @param total - * The number of total possibilities - * @param rng - * The function to use to generate a random possibility - * @return Whether or not a random possibility was a winning one - */ - public static boolean isProbable(final int winning, final int total, final Function<Integer, Integer> rng) { - return rng.apply(total) < winning; - } - - /** - * Check if a number is in an inclusive range. - * - * @param min - * The minimum value of the range. - * - * @param max - * The maximum value of the range. - * - * @param i - * The number to check. - * - * @return Whether the number is in the range. - */ - public static boolean between(final int min, final int max, final int i) { - return i >= min && i <= max; - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcutils/StringUtils.java b/BJC-Utils2/src/main/java/bjc/utils/funcutils/StringUtils.java deleted file mode 100644 index 62f78f5..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/funcutils/StringUtils.java +++ /dev/null @@ -1,196 +0,0 @@ -package bjc.utils.funcutils; - -import java.util.Deque; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import com.ibm.icu.text.BreakIterator; - -/** - * Utility methods for operations on strings - * - * @author ben - * - */ -public class StringUtils { - /** - * Check if a string consists only of one or more matches of a regular - * expression - * - * @param input - * The string to check - * @param rRegex - * The regex to see if the string only contains matches - * of - * @return Whether or not the string consists only of multiple matches - * of the provided regex - */ - public static boolean containsOnly(final String input, final String rRegex) { - if (input == null) - throw new NullPointerException("Input must not be null"); - else if (rRegex == null) throw new NullPointerException("Regex must not be null"); - - /* - * This regular expression is fairly simple. - * - * First, we match the beginning of the string. Then, we start a - * non-capturing group whose contents are the passed in regex. - * That group is then matched one or more times and the pattern - * matches to the end of the string - */ - return input.matches("\\A(?:" + rRegex + ")+\\Z"); - } - - /** - * Indent the string being built in a StringBuilder n levels - * - * @param builder - * The builder to indent in - * @param levels - * The number of levels to indent - */ - public static void indentNLevels(final StringBuilder builder, final int levels) { - for (int i = 0; i < levels; i++) { - builder.append("\t"); - } - } - - /** - * Print out a deque with a special case for easily showing a deque is - * empty - * - * @param <ContainedType> - * The type in the deque - * @param queue - * The deque to print - * @return A string version of the deque, with allowance for an empty - * deque - */ - public static <ContainedType> String printDeque(final Deque<ContainedType> queue) { - return queue.isEmpty() ? "(none)" : queue.toString(); - } - - /** - * Converts a sequence to an English list. - * - * @param objects - * The sequence to convert to an English list. - * @param join - * The string to use for separating the last element from - * the rest. - * @param comma - * The string to use as a comma - * - * @return The sequence as an English list. - */ - public static String toEnglishList(final Object[] objects, final String join, final String comma) { - if (objects == null) throw new NullPointerException("Sequence must not be null"); - - final StringBuilder sb = new StringBuilder(); - - final String joiner = join; - final String coma = comma; - - switch (objects.length) { - case 0: - /* - * Empty list. - */ - break; - case 1: - /* - * One item. - */ - sb.append(objects[0].toString()); - break; - case 2: - /* - * Two items. - */ - sb.append(objects[0].toString()); - sb.append(" " + joiner + " "); - sb.append(objects[1].toString()); - break; - default: - /* - * Three or more items. - */ - for (int i = 0; i < objects.length - 1; i++) { - sb.append(objects[i].toString()); - sb.append(coma + " "); - } - /* - * Uncomment this to remove serial commas. - * - * int lc = sb.length() - 1; - * - * sb.delete(lc - coma.length(), lc); - */ - sb.append(joiner + " "); - sb.append(objects[objects.length - 1].toString()); - } - - return sb.toString(); - } - - /** - * Converts a sequence to an English list. - * - * @param objects - * The sequence to convert to an English list. - * @param join - * The string to use for separating the last element from - * the rest. - * - * @return The sequence as an English list. - */ - public static String toEnglishList(final Object[] objects, final String join) { - return toEnglishList(objects, join, ","); - } - - /** - * Converts a sequence to an English list. - * - * @param objects - * The sequence to convert to an English list. - * @param and - * Whether to use 'and' or 'or'. - * - * @return The sequence as an English list. - */ - public static String toEnglishList(final Object[] objects, final boolean and) { - if (and) - return toEnglishList(objects, "and"); - else return toEnglishList(objects, "or"); - } - - /** - * Count the number of graphemes in a string. - * - * @param value - * The string to check. - * - * @return The number of graphemes in the string. - */ - public static int graphemeCount(final String value) { - final BreakIterator it = BreakIterator.getCharacterInstance(); - it.setText(value); - - int count = 0; - while (it.next() != BreakIterator.DONE) { - count++; - } - - return count; - } - - public static int countMatches(final String value, final String pattern) { - Matcher mat = Pattern.compile(pattern).matcher(value); - - int num = 0; - while(mat.find()) - num += 1; - - return num; - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcutils/TreeUtils.java b/BJC-Utils2/src/main/java/bjc/utils/funcutils/TreeUtils.java deleted file mode 100644 index dcd5738..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/funcutils/TreeUtils.java +++ /dev/null @@ -1,56 +0,0 @@ -package bjc.utils.funcutils; - -import java.util.LinkedList; -import java.util.function.Predicate; - -import bjc.utils.data.ITree; -import bjc.utils.funcdata.FunctionalList; -import bjc.utils.funcdata.IList; - -/** - * Implements various utilities for trees. - * - * @author Benjamin Culkin - */ -public class TreeUtils { - /* - * Convert a tree into a list of outline nodes that match a certain - * path. - */ - public static <T> IList<IList<T>> outlineTree(ITree<T> tre, Predicate<T> leafMarker) { - IList<IList<T>> paths = new FunctionalList<>(); - - LinkedList<T> path = new LinkedList<>(); - path.add(tre.getHead()); - - tre.doForChildren((child) -> findPath(child, path, leafMarker, paths)); - - return paths; - } - - private static <T> void findPath(ITree<T> subtree, LinkedList<T> path, Predicate<T> leafMarker, IList<IList<T>> paths) { - if(subtree.getChildrenCount() == 0 && leafMarker.test(subtree.getHead())) { - /* - * We're at a matching leaf node. Add it. - */ - IList<T> finalPath = new FunctionalList<>(); - - for(T ePath : path) { - finalPath.add(ePath); - } - - finalPath.add(subtree.getHead()); - - paths.add(finalPath); - } else { - /* - * Check the children of this node. - */ - path.add(subtree.getHead()); - - subtree.doForChildren((child) -> findPath(child, path, leafMarker, paths)); - - path.removeLast(); - } - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcutils/TriConsumer.java b/BJC-Utils2/src/main/java/bjc/utils/funcutils/TriConsumer.java deleted file mode 100644 index f30386c..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/funcutils/TriConsumer.java +++ /dev/null @@ -1,31 +0,0 @@ -package bjc.utils.funcutils; - -/** - * Consumer that takes three arguments. - * - * @author EVE - * - * @param <A> - * Type of the first argument. - * @param <B> - * Type of the second argument. - * @param <C> - * Type of the third argument. - * - */ -@FunctionalInterface -public interface TriConsumer<A, B, C> { - /** - * Perform the action. - * - * @param a - * The first parameter. - * - * @param b - * The second parameter. - * - * @param c - * The third parameter. - */ - public void accept(A a, B b, C c); -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/gen/RandomGrammar.java b/BJC-Utils2/src/main/java/bjc/utils/gen/RandomGrammar.java deleted file mode 100644 index 3de08d6..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/gen/RandomGrammar.java +++ /dev/null @@ -1,69 +0,0 @@ -package bjc.utils.gen; - -import bjc.utils.funcdata.FunctionalMap; -import bjc.utils.funcdata.IList; - -/** - * A weighted grammar where all the rules have a equal chance of occuring. - * - * @author ben - * - * @param <E> - * The type of grammar elements to use. - */ -public class RandomGrammar<E> extends WeightedGrammar<E> { - /** - * Create a new random grammar. - */ - public RandomGrammar() { - rules = new FunctionalMap<>(); - } - - /** - * Add cases to a specified rule. - * - * @param rule - * The name of the rule to add cases to. - * @param cases - * The cases to add for this rule. - */ - @SafeVarargs - public final void addCases(final E rule, final IList<E>... cases) { - for (final IList<E> currentCase : cases) { - super.addCase(rule, 1, currentCase); - } - } - - /** - * Create a rule with the specified name and cases. - * - * @param rule - * The name of the rule to add. - * @param cases - * The cases to add for this rule. - */ - @SafeVarargs - public final void makeRule(final E rule, final IList<E>... cases) { - super.addRule(rule); - - for (final IList<E> currentCase : cases) { - super.addCase(rule, 1, currentCase); - } - } - - /** - * Create a rule with the specified name and cases. - * - * @param rule - * The name of the rule to add. - * @param cases - * The cases to add for this rule. - */ - public void makeRule(final E rule, final IList<IList<E>> cases) { - if (cases == null) throw new NullPointerException("Cases must not be null"); - - super.addRule(rule); - - cases.forEach(currentCase -> super.addCase(rule, 1, currentCase)); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/gen/WeightedGrammar.java b/BJC-Utils2/src/main/java/bjc/utils/gen/WeightedGrammar.java deleted file mode 100644 index 7777ad8..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/gen/WeightedGrammar.java +++ /dev/null @@ -1,573 +0,0 @@ -package bjc.utils.gen; - -import java.util.Random; -import java.util.function.BiFunction; -import java.util.function.Function; -import java.util.function.Predicate; -import java.util.function.Supplier; - -import bjc.utils.data.IPair; -import bjc.utils.data.Pair; -import bjc.utils.funcdata.FunctionalList; -import bjc.utils.funcdata.FunctionalMap; -import bjc.utils.funcdata.IList; -import bjc.utils.funcdata.IMap; - -/** - * A random grammar, where certain rules will come up more often than others. - * - * @author ben - * - * @param <E> - * The values that make up sentences of this grammar. - */ -public class WeightedGrammar<E> { - /** - * The initial rule of the grammar - */ - protected String initialRule; - - /** - * The rules currently in this grammar - */ - protected IMap<E, WeightedRandom<IList<E>>> rules; - - /** - * The random number generator used for random numbers - */ - private Random rng; - - /** - * All of the subgrammars of this grammar - */ - protected IMap<E, WeightedGrammar<E>> subgrammars; - - /** - * Rules that require special handling - */ - private IMap<E, Supplier<IList<E>>> specialRules; - - /** - * Predicate for marking special tokens - */ - - private Predicate<E> specialMarker; - - /** - * Action for special tokens - */ - private BiFunction<E, WeightedGrammar<E>, IList<E>> specialAction; - - /** - * Create a new weighted grammar. - */ - public WeightedGrammar() { - rules = new FunctionalMap<>(); - subgrammars = new FunctionalMap<>(); - specialRules = new FunctionalMap<>(); - } - - /** - * Create a new weighted grammar that uses the specified source of - * randomness. - * - * @param source - * The source of randomness to use - */ - public WeightedGrammar(final Random source) { - this(); - - if (source == null) throw new NullPointerException("Source of randomness must be non-null"); - - rng = source; - } - - /** - * Configure the action to perform on special tokens. - * - * @param marker - * The marker to find special tokens. - * - * @param action - * The action to take on those tokens. - */ - public void configureSpecial(final Predicate<E> marker, - final BiFunction<E, WeightedGrammar<E>, IList<E>> action) { - specialMarker = marker; - specialAction = action; - } - - /** - * Adds a special rule to the grammar. - * - * @param ruleName - * The name of the special rule. - * - * @param cse - * The case for the rule. - */ - public void addSpecialRule(final E ruleName, final Supplier<IList<E>> cse) { - if (ruleName == null) - throw new NullPointerException("Rule name must not be null"); - else if (cse == null) throw new NullPointerException("Case must not be null"); - - specialRules.put(ruleName, cse); - } - - /** - * Add a case to an already existing rule. - * - * @param ruleName - * The rule to add a case to. - * @param probability - * The probability for this rule to be chosen. - * @param cse - * The case being added. - */ - public void addCase(final E ruleName, final int probability, final IList<E> cse) { - if (ruleName == null) - throw new NullPointerException("Rule name must be not null"); - else if (cse == null) throw new NullPointerException("Case body must not be null"); - - rules.get(ruleName).addProbability(probability, cse); - } - - /** - * Add a alias for an existing subgrammar - * - * @param name - * The name of the subgrammar to alias - * @param alias - * The alias of the subgrammar - * @return Whether the alias was succesfully created - */ - public boolean addGrammarAlias(final E name, final E alias) { - if (name == null) - throw new NullPointerException("Subgrammar name must not be null"); - else if (alias == null) throw new NullPointerException("Subgrammar alias must not be null"); - - if (subgrammars.containsKey(alias)) return false; - - if (subgrammars.containsKey(name)) { - subgrammars.put(alias, subgrammars.get(name)); - return true; - } - - return false; - } - - /** - * Add a new rule with no cases. - * - * @param name - * The name of the rule to add. - * @return Whether or not the rule was successfully added. - */ - public boolean addRule(final E name) { - if (rng == null) { - rng = new Random(); - } - - if (name == null) throw new NullPointerException("Rule name must not be null"); - - return addRule(name, new WeightedRandom<>(rng)); - } - - /** - * Add a new rule with a set of cases. - * - * @param name - * The name of the rule to add. - * @param cases - * The set of cases for the rule. - * @return Whether or not the rule was succesfully added. - */ - public boolean addRule(final E name, final WeightedRandom<IList<E>> cases) { - if (name == null) - throw new NullPointerException("Name must not be null"); - else if (cases == null) throw new NullPointerException("Cases must not be null"); - - if (rules.containsKey(name)) return false; - - rules.put(name, cases); - return true; - } - - /** - * Add a subgrammar. - * - * @param name - * The name of the subgrammar. - * @param subgrammar - * The subgrammar to add. - * @return Whether or not the subgrammar was succesfully added. - */ - public boolean addSubgrammar(final E name, final WeightedGrammar<E> subgrammar) { - if (name == null) - throw new NullPointerException("Subgrammar name must not be null"); - else if (subgrammar == null) throw new NullPointerException("Subgrammar must not be null"); - - if (subgrammars.containsKey(name)) return false; - - subgrammars.put(name, subgrammar); - return true; - } - - /** - * Remove a rule with the specified name. - * - * @param name - * The name of the rule to remove. - */ - public void deleteRule(final E name) { - if (name == null) throw new NullPointerException("Rule name must not be null"); - - rules.remove(name); - } - - /** - * Remove a subgrammar with the specified name. - * - * @param name - * The name of the subgrammar to remove. - */ - public void deleteSubgrammar(final E name) { - if (name == null) throw new NullPointerException("Rule name must not be null"); - - subgrammars.remove(name); - } - - /** - * Generate a set of debug sentences for the specified rule. - * - * Only generates sentences one layer deep. - * - * @param ruleName - * The rule to test. - * @return A set of sentences generated by the specified rule. - */ - public IList<IList<E>> generateDebugValues(final E ruleName) { - if (ruleName == null) throw new NullPointerException("Rule name must not be null"); - - final IList<IList<E>> returnedList = new FunctionalList<>(); - - final WeightedRandom<IList<E>> ruleGenerator = rules.get(ruleName); - - for (int i = 0; i < 10; i++) { - returnedList.add(ruleGenerator.generateValue()); - } - - return returnedList; - } - - /** - * Generate a generic sentence from a initial rule. - * - * @param <T> - * The type of the transformed output - * - * @param initRules - * The initial rule to start with. - * - * @param tokenTransformer - * The function to transform grammar output into - * something. - * - * @param spacer - * The spacer element to add in between output tokens. - * - * @return A randomly generated sentence from the specified initial - * rule. - */ - public <T> IList<T> generateGenericValues(final E initRules, final Function<E, T> tokenTransformer, - final T spacer) { - if (initRules == null) - throw new NullPointerException("Initial rule must not be null"); - else if (tokenTransformer == null) - throw new NullPointerException("Transformer must not be null"); - else if (spacer == null) throw new NullPointerException("Spacer must not be null"); - - final IList<T> returnedList = new FunctionalList<>(); - - IList<E> genRules = new FunctionalList<>(initRules); - - if (specialMarker != null) { - if (specialMarker.test(initRules)) { - genRules = specialAction.apply(initRules, this); - } - } - - for (final E initRule : genRules.toIterable()) { - if (specialRules.containsKey(initRule)) { - for (final E rulePart : specialRules.get(initRule).get().toIterable()) { - final Iterable<T> generatedRuleParts = generateGenericValues(rulePart, - tokenTransformer, spacer).toIterable(); - - for (final T generatedRulePart : generatedRuleParts) { - returnedList.add(generatedRulePart); - returnedList.add(spacer); - } - } - } else if (subgrammars.containsKey(initRule)) { - final Iterable<T> ruleParts = subgrammars.get(initRule) - .generateGenericValues(initRule, tokenTransformer, spacer).toIterable(); - - for (final T rulePart : ruleParts) { - returnedList.add(rulePart); - returnedList.add(spacer); - } - } else if (rules.containsKey(initRule)) { - final Iterable<E> ruleParts = rules.get(initRule).generateValue().toIterable(); - - for (final E rulePart : ruleParts) { - final Iterable<T> generatedRuleParts = generateGenericValues(rulePart, - tokenTransformer, spacer).toIterable(); - - for (final T generatedRulePart : generatedRuleParts) { - returnedList.add(generatedRulePart); - returnedList.add(spacer); - } - } - } else { - final T transformedToken = tokenTransformer.apply(initRule); - - if (transformedToken == null) - throw new NullPointerException("Transformer created null token"); - - returnedList.add(transformedToken); - returnedList.add(spacer); - } - } - - return returnedList; - } - - /** - * Generate a random list of grammar elements from a given initial rule. - * - * @param initRule - * The initial rule to start with. - * @param spacer - * The item to use to space the list. - * @return A list of random grammar elements generated by the specified - * rule. - */ - public IList<E> generateListValues(final E initRule, final E spacer) { - final IList<E> retList = generateGenericValues(initRule, strang -> strang, spacer); - - return retList; - } - - /** - * Get the initial rule of this grammar - * - * @return The initial rule of this grammar - */ - public String getInitialRule() { - return initialRule; - } - - /** - * Returns the number of rules in this grammar - * - * @return The number of rules in this grammar - */ - public int getRuleCount() { - return rules.size(); - } - - /** - * Returns a set containing all of the rules in this grammar - * - * @return The set of all rule names in this grammar - */ - public IList<E> getRuleNames() { - final IList<E> ruleNames = new FunctionalList<>(); - - ruleNames.addAll(rules.keyList()); - ruleNames.addAll(specialRules.keyList()); - - return ruleNames; - } - - /** - * Get the subgrammar with the specified name. - * - * @param name - * The name of the subgrammar to get. - * @return The subgrammar with the specified name. - */ - public WeightedGrammar<E> getSubgrammar(final E name) { - if (name == null) throw new NullPointerException("Subgrammar name must not be null"); - - return subgrammars.get(name); - } - - /** - * Check if this grammar has an initial rule - * - * @return Whether or not this grammar has an initial rule - */ - public boolean hasInitialRule() { - return initialRule != null && !initialRule.equalsIgnoreCase(""); - } - - /** - * Check if this grammar has a given rule. - * - * @param ruleName - * The rule to check for. - * - * @return Whether or not the grammar has a rule by that name. - */ - public boolean hasRule(final E ruleName) { - return rules.containsKey(ruleName) || specialRules.containsKey(ruleName); - } - - /** - * Prefix a given rule with a token multiple times - * - * @param ruleName - * The name of the rule to prefix - * @param prefixToken - * The token to prefix to the rules - * @param additionalProbability - * The additional probability of the tokens - * @param numberOfTimes - * The number of times to prefix the token - */ - public void multiPrefixRule(final E ruleName, final E prefixToken, final int additionalProbability, - final int numberOfTimes) { - if (ruleName == null) - throw new NullPointerException("Rule name must not be null"); - else if (prefixToken == null) - throw new NullPointerException("Prefix token must not be null"); - else if (numberOfTimes < 1) - throw new IllegalArgumentException("Number of times to prefix must be positive."); - - final WeightedRandom<IList<E>> rule = rules.get(ruleName); - - final IList<IPair<Integer, IList<E>>> newResults = new FunctionalList<>(); - - rule.getValues().forEach((pair) -> { - final IList<IList<E>> newRule = new FunctionalList<>(); - - for (int i = 1; i <= numberOfTimes; i++) { - final IList<E> newCase = pair.merge((left, right) -> { - final IList<E> returnVal = new FunctionalList<>(); - - for (final E val : right.toIterable()) { - returnVal.add(val); - } - - return returnVal; - }); - - for (int j = 1; j <= i; j++) { - newCase.prepend(prefixToken); - } - - newRule.add(newCase); - } - - newRule.forEach((list) -> { - final Integer currentProb = pair.merge((left, right) -> left); - - newResults.add(new Pair<>(currentProb + additionalProbability, list)); - }); - }); - - newResults.forEach((pair) -> { - pair.doWith((left, right) -> { - addCase(ruleName, left, right); - }); - }); - } - - /** - * Create a series of alternatives for a rule by prefixing them with a - * given token - * - * @param additionalProbability - * The amount to adjust the probability by - * @param ruleName - * The name of the rule to prefix - * @param prefixToken - * The token to prefix to the rule - */ - public void prefixRule(final E ruleName, final E prefixToken, final int additionalProbability) { - if (ruleName == null) - throw new NullPointerException("Rule name must not be null"); - else if (prefixToken == null) throw new NullPointerException("Prefix token must not be null"); - - final WeightedRandom<IList<E>> rule = rules.get(ruleName); - - final IList<IPair<Integer, IList<E>>> newResults = new FunctionalList<>(); - - rule.getValues().forEach((pair) -> { - final IList<E> newCase = pair.merge((left, right) -> { - final IList<E> returnVal = new FunctionalList<>(); - - for (final E val : right.toIterable()) { - returnVal.add(val); - } - - return returnVal; - }); - - newCase.prepend(prefixToken); - - newResults.add(new Pair<>(pair.merge((left, right) -> left) + additionalProbability, newCase)); - }); - - newResults.forEach((pair) -> pair.doWith((left, right) -> addCase(ruleName, left, right))); - } - - /** - * Set the initial rule of the graphic - * - * @param initRule - * The initial rule of this grammar - */ - public void setInitialRule(final String initRule) { - this.initialRule = initRule; - } - - /** - * Suffix a token to a rule - * - * @param ruleName - * The rule to suffix - * @param suffixToken - * The token to prefix to the rule - * @param additionalProbability - * Additional probability of the prefixed rule - */ - public void suffixRule(final E ruleName, final E suffixToken, final int additionalProbability) { - if (ruleName == null) - throw new NullPointerException("Rule name must not be null"); - else if (suffixToken == null) throw new NullPointerException("Prefix token must not be null"); - - final WeightedRandom<IList<E>> rule = rules.get(ruleName); - - final IList<IPair<Integer, IList<E>>> newResults = new FunctionalList<>(); - - rule.getValues().forEach((par) -> { - final IList<E> newCase = par.merge((left, right) -> { - final IList<E> returnVal = new FunctionalList<>(); - - for (final E val : right.toIterable()) { - returnVal.add(val); - } - - return returnVal; - }); - - newCase.add(suffixToken); - - newResults.add(new Pair<>(par.merge((left, right) -> left) + additionalProbability, newCase)); - }); - - newResults.forEach((pair) -> pair.doWith((left, right) -> addCase(ruleName, left, right))); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/gen/WeightedRandom.java b/BJC-Utils2/src/main/java/bjc/utils/gen/WeightedRandom.java deleted file mode 100644 index 18225ef..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/gen/WeightedRandom.java +++ /dev/null @@ -1,112 +0,0 @@ -package bjc.utils.gen; - -import java.util.Random; - -import bjc.utils.data.IHolder; -import bjc.utils.data.IPair; -import bjc.utils.data.Identity; -import bjc.utils.funcdata.FunctionalList; -import bjc.utils.funcdata.IList; - -/** - * Represents a random number generator where certain results are weighted more - * heavily than others. - * - * @author ben - * - * @param <E> - * The type of values that are randomly selected. - */ -public class WeightedRandom<E> { - /* - * The list of probabilities for each result - */ - private final IList<Integer> probabilities; - - /* - * The list of possible results to pick from - */ - private final IList<E> results; - - /* - * The source for any needed random numbers - */ - private final Random source; - - private int totalChance; - - /** - * Create a new weighted random generator with the specified source of - * randomness - * - * @param src - * The source of randomness to use. - */ - public WeightedRandom(final Random src) { - probabilities = new FunctionalList<>(); - results = new FunctionalList<>(); - - if (src == null) throw new NullPointerException("Source of randomness must not be null"); - - source = src; - } - - /** - * Add a probability for a specific result to be given. - * - * @param chance - * The chance to get this result. - * @param result - * The result to get when the chance comes up. - */ - public void addProbability(final int chance, final E result) { - probabilities.add(chance); - results.add(result); - - totalChance += chance; - } - - /** - * Generate a weighted random value. - * - * @return A random value selected in a weighted fashion. - */ - public E generateValue() { - final IHolder<Integer> value = new Identity<>(source.nextInt(totalChance)); - final IHolder<E> current = new Identity<>(); - final IHolder<Boolean> picked = new Identity<>(true); - - probabilities.forEachIndexed((index, probability) -> { - if (picked.unwrap(bool -> bool)) { - if (value.unwrap((number) -> number < probability)) { - current.transform((result) -> results.getByIndex(index)); - - picked.transform((bool) -> false); - } else { - value.transform((number) -> number - probability); - } - } - }); - - return current.unwrap((result) -> result); - } - - /** - * Return a list of values that can be generated by this generator - * - * @return A list of all the values that can be generated - */ - public IList<E> getResults() { - return results; - } - - /** - * Return a list containing values that can be generated paired with the - * probability of those values being generated - * - * @return A list of pairs of values and value probabilities - */ - public IList<IPair<Integer, E>> getValues() { - return probabilities.pairWith(results); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/graph/AdjacencyMap.java b/BJC-Utils2/src/main/java/bjc/utils/graph/AdjacencyMap.java deleted file mode 100644 index 446ab5b..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/graph/AdjacencyMap.java +++ /dev/null @@ -1,216 +0,0 @@ -package bjc.utils.graph; - -import java.io.InputStream; -import java.io.OutputStream; -import java.io.PrintStream; -import java.util.InputMismatchException; -import java.util.Scanner; - -import bjc.utils.data.IHolder; -import bjc.utils.data.Identity; -import bjc.utils.funcdata.FunctionalList; -import bjc.utils.funcdata.FunctionalMap; -import bjc.utils.funcdata.IList; -import bjc.utils.funcdata.IMap; -import bjc.utils.funcutils.FuncUtils; - -/** - * An adjacency map representing a graph - * - * @author ben - * - * @param <T> - * The type of the nodes in the graph - */ -public class AdjacencyMap<T> { - /** - * Create an adjacency map from a stream of text - * - * @param stream - * The stream of text to read in - * @return An adjacency map defined by the text - */ - public static AdjacencyMap<Integer> fromStream(final InputStream stream) { - if (stream == null) throw new NullPointerException("Input source must not be null"); - - // Create the adjacency map - AdjacencyMap<Integer> adjacency; - - try (Scanner input = new Scanner(stream)) { - input.useDelimiter("\n"); - - int vertexCount; - - final String possible = input.next(); - - try { - // First, read in number of vertices - vertexCount = Integer.parseInt(possible); - } catch (final NumberFormatException nfex) { - final InputMismatchException imex = new InputMismatchException( - "The first line must contain the number of vertices. " + possible - + " is not a valid number"); - - imex.initCause(nfex); - - throw imex; - } - - if (vertexCount <= 0) - throw new InputMismatchException("The number of vertices must be greater than 0"); - - final IList<Integer> vertices = new FunctionalList<>(); - - FuncUtils.doTimes(vertexCount, (vertexNo) -> vertices.add(vertexNo)); - - adjacency = new AdjacencyMap<>(vertices); - - final IHolder<Integer> row = new Identity<>(0); - - input.forEachRemaining((strang) -> { - readRow(adjacency, vertexCount, row, strang); - }); - } - - return adjacency; - } - - private static void readRow(final AdjacencyMap<Integer> adjacency, final int vertexCount, - final IHolder<Integer> row, final String strang) { - final String[] parts = strang.split(" "); - - if (parts.length != vertexCount) - throw new InputMismatchException("Must specify a weight for all " + vertexCount + " vertices"); - - int column = 0; - - for (final String part : parts) { - int weight; - - try { - weight = Integer.parseInt(part); - } catch (final NumberFormatException nfex) { - final InputMismatchException imex = new InputMismatchException( - "" + part + " is not a valid weight."); - - imex.initCause(nfex); - - throw imex; - } - - adjacency.setWeight(row.getValue(), column, weight); - - column++; - } - - row.transform((rowNumber) -> rowNumber + 1); - } - - /** - * The backing storage of the map - */ - private final IMap<T, IMap<T, Integer>> adjacency = new FunctionalMap<>(); - - /** - * Create a new map from a set of vertices - * - * @param vertices - * The set of vertices to create a map from - */ - public AdjacencyMap(final IList<T> vertices) { - if (vertices == null) throw new NullPointerException("Vertices must not be null"); - - vertices.forEach(vertex -> { - final IMap<T, Integer> row = new FunctionalMap<>(); - - vertices.forEach(target -> { - row.put(target, 0); - }); - - adjacency.put(vertex, row); - }); - } - - /** - * Check if the graph is directed - * - * @return Whether or not the graph is directed - */ - public boolean isDirected() { - final IHolder<Boolean> result = new Identity<>(true); - - adjacency.forEach((sourceKey, sourceValue) -> { - sourceValue.forEach((targetKey, targetValue) -> { - final int inverseValue = adjacency.get(targetKey).get(sourceKey); - - if (targetValue != inverseValue) { - result.replace(false); - } - }); - }); - - return result.getValue(); - } - - /** - * Set the weight of an edge - * - * @param source - * The source node of the edge - * @param target - * The target node of the edge - * @param weight - * The weight of the edge - */ - public void setWeight(final T source, final T target, final int weight) { - if (source == null) - throw new NullPointerException("Source vertex must not be null"); - else if (target == null) throw new NullPointerException("Target vertex must not be null"); - - if (!adjacency.containsKey(source)) - throw new IllegalArgumentException("Source vertex " + source + " isn't present in map"); - else if (!adjacency.containsKey(target)) - throw new IllegalArgumentException("Target vertex " + target + " isn't present in map"); - - adjacency.get(source).put(target, weight); - } - - /** - * Convert this to a different graph representation - * - * @return The new representation of this graph - */ - public Graph<T> toGraph() { - final Graph<T> ret = new Graph<>(); - - adjacency.forEach((sourceKey, sourceValue) -> { - sourceValue.forEach((targetKey, targetValue) -> { - ret.addEdge(sourceKey, targetKey, targetValue, true); - }); - }); - - return ret; - } - - /** - * Convert an adjacency map back into a stream - * - * @param sink - * The stream to convert to - */ - public void toStream(final OutputStream sink) { - if (sink == null) throw new NullPointerException("Output source must not be null"); - - final PrintStream outputPrinter = new PrintStream(sink); - - adjacency.forEach((sourceKey, sourceValue) -> { - sourceValue.forEach((targetKey, targetValue) -> { - outputPrinter.printf("%d", targetValue); - }); - - outputPrinter.println(); - }); - - outputPrinter.close(); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/graph/Edge.java b/BJC-Utils2/src/main/java/bjc/utils/graph/Edge.java deleted file mode 100644 index 0152e3d..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/graph/Edge.java +++ /dev/null @@ -1,112 +0,0 @@ -package bjc.utils.graph; - -/** - * An edge in a weighted graph - * - * @author ben - * - * @param <T> - * The type of the nodes in the graph - */ -public class Edge<T> { - /* - * The distance from initial to terminal node - */ - private final int distance; - - /* - * The initial and terminal nodes of this edge - */ - private final T source, target; - - /** - * Create a new edge with set parameters - * - * @param initial - * The initial node of the edge - * @param terminal - * The terminal node of the edge - * @param distance - * The distance between initial and terminal edge - */ - public Edge(final T initial, final T terminal, final int distance) { - if (initial == null) - throw new NullPointerException("Initial node must not be null"); - else if (terminal == null) throw new NullPointerException("Terminal node must not be null"); - - this.source = initial; - this.target = terminal; - this.distance = distance; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) - return true; - else if (obj == null) - return false; - else if (getClass() != obj.getClass()) - return false; - else { - final Edge<?> other = (Edge<?>) obj; - - if (distance != other.distance) - return false; - else if (source == null) { - if (other.source != null) return false; - } else if (!source.equals(other.source)) - return false; - else if (target == null) { - if (other.target != null) return false; - } else if (!target.equals(other.target)) return false; - - return true; - } - } - - /** - * Get the distance in this edge - * - * @return The distance between the initial and terminal nodes of this - * edge - */ - public int getDistance() { - return distance; - } - - /** - * Get the initial node of an edge - * - * @return The initial node of this edge - */ - public T getSource() { - return source; - } - - /** - * Get the target node of an edge - * - * @return The target node of this edge - */ - public T getTarget() { - return target; - } - - @Override - public int hashCode() { - final int prime = 31; - - int result = 1; - - result = prime * result + distance; - result = prime * result + (source == null ? 0 : source.hashCode()); - result = prime * result + (target == null ? 0 : target.hashCode()); - - return result; - } - - @Override - public String toString() { - return " first vertex " + source + " to vertex " + target + " with distance: " + distance; - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/graph/Graph.java b/BJC-Utils2/src/main/java/bjc/utils/graph/Graph.java deleted file mode 100644 index 280a7f5..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/graph/Graph.java +++ /dev/null @@ -1,267 +0,0 @@ -package bjc.utils.graph; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.NoSuchElementException; -import java.util.PriorityQueue; -import java.util.Queue; -import java.util.Set; -import java.util.function.BiConsumer; -import java.util.function.BiPredicate; - -import bjc.utils.data.IHolder; -import bjc.utils.data.Identity; -import bjc.utils.funcdata.FunctionalMap; -import bjc.utils.funcdata.IList; -import bjc.utils.funcdata.IMap; - -/** - * A directed weighted graph, where the vertices have some arbitrary label - * - * @author ben - * - * @param <T> - * The label for vertices - */ -public class Graph<T> { - /** - * Create a graph from a list of edges - * - * @param <E> - * The type of data stored in the edges - * - * @param edges - * The list of edges to build from - * @return A graph built from the provided edge-list - */ - public static <E> Graph<E> fromEdgeList(final List<Edge<E>> edges) { - final Graph<E> g = new Graph<>(); - - edges.forEach(edge -> { - g.addEdge(edge.getSource(), edge.getTarget(), edge.getDistance(), true); - }); - - return g; - } - - /** - * The backing representation of the graph - */ - private final IMap<T, IMap<T, Integer>> backing; - - /** - * Create a new graph - */ - public Graph() { - backing = new FunctionalMap<>(); - } - - /** - * Add a edge to the graph - * - * @param source - * The source vertex for this edge - * @param target - * The target vertex for this edge - * @param distance - * The distance from the source vertex to the target - * vertex - * @param directed - * Whether or not - */ - public void addEdge(final T source, final T target, final int distance, final boolean directed) { - // Can't add edges with a null source or target - if (source == null) - throw new NullPointerException("The source vertex cannot be null"); - else if (target == null) throw new NullPointerException("The target vertex cannot be null"); - - // Initialize adjacency list for vertices if necessary - if (!backing.containsKey(source)) { - backing.put(source, new FunctionalMap<T, Integer>()); - } - - // Add the edge to the graph - backing.get(source).put(target, distance); - - // Handle possible directed edges - if (!directed) { - if (!backing.containsKey(target)) { - backing.put(target, new FunctionalMap<T, Integer>()); - } - - backing.get(target).put(source, distance); - } - } - - /** - * Execute an action for all edges of a specific vertex matching - * conditions - * - * @param source - * The vertex to test edges for - * @param matcher - * The conditions an edge must match - * @param action - * The action to execute for matching edges - */ - public void forAllEdgesMatchingAt(final T source, final BiPredicate<T, Integer> matcher, - final BiConsumer<T, Integer> action) { - if (matcher == null) - throw new NullPointerException("Matcher must not be null"); - else if (action == null) throw new NullPointerException("Action must not be null"); - - getEdges(source).forEach((target, weight) -> { - if (matcher.test(target, weight)) { - action.accept(target, weight); - } - }); - } - - /** - * Get all the edges that begin at a particular source vertex - * - * @param source - * The vertex to use as a source - * @return All of the edges with the specified vertex as a source - */ - public IMap<T, Integer> getEdges(final T source) { - // Can't find edges for a null source - if (source == null) - throw new NullPointerException("The source cannot be null."); - else if (!backing.containsKey(source)) - throw new IllegalArgumentException("Vertex " + source + " is not in graph"); - - return backing.get(source); - } - - /** - * Get the initial vertex of the graph - * - * @return The initial vertex of the graph - */ - public T getInitial() { - return backing.keyList().first(); - } - - /** - * Uses Prim's algorothm 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 List<Edge<T>> getMinimumSpanningTree() { - // Set of all of the currently available edges - final Queue<Edge<T>> available = new PriorityQueue<>(10, - (left, right) -> left.getDistance() - right.getDistance()); - - // The MST of the graph - final List<Edge<T>> 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 IHolder<T> source = new Identity<>(getInitial()); - - visited.add(source.getValue()); - - // Make sure we visit all the nodes - while (visited.size() != getVertexCount()) { - // Grab all edges adjacent to the provided edge - - forAllEdgesMatchingAt(source.getValue(), (target, weight) -> { - return !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 IHolder<Edge<T>> 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; - } - - /** - * Get the count of the vertices in this graph - * - * @return A count of the vertices in this graph - */ - public int getVertexCount() { - return backing.size(); - } - - /** - * Get all of the vertices in this graph. - * - * @return A unmodifiable set of all the vertices in the graph. - */ - public IList<T> getVertices() { - return backing.keyList(); - } - - /** - * Remove the edge starting at the source and ending at the target - * - * @param source - * The source vertex for the edge - * @param target - * The target vertex for the edge - */ - public void removeEdge(final T source, final T target) { - // Can't remove things w/ null vertices - if (source == null) - throw new NullPointerException("The source vertex cannot be null"); - else if (target == null) throw new NullPointerException("The target vertex cannot be null"); - - // Can't remove if one vertice doesn't exists - if (!backing.containsKey(source)) - throw new NoSuchElementException("vertex " + source + " does not exist."); - - if (!backing.containsKey(target)) - throw new NoSuchElementException("vertex " + target + " does not exist."); - - backing.get(source).remove(target); - - // Uncomment this to turn the graph undirected - // graph.get(target).remove(source); - } - - /** - * Convert a graph into a adjacency map/matrix - * - * @return A adjacency map representing this graph - */ - public AdjacencyMap<T> toAdjacencyMap() { - final AdjacencyMap<T> adjacency = new AdjacencyMap<>(backing.keyList()); - - backing.forEach((sourceKey, sourceValue) -> { - sourceValue.forEach((targetKey, targetValue) -> { - adjacency.setWeight(sourceKey, targetKey, targetValue); - }); - }); - - return adjacency; - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/gui/ExtensionFileFilter.java b/BJC-Utils2/src/main/java/bjc/utils/gui/ExtensionFileFilter.java deleted file mode 100644 index 7c487eb..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/gui/ExtensionFileFilter.java +++ /dev/null @@ -1,56 +0,0 @@ -package bjc.utils.gui; - -import java.io.File; -import java.util.List; - -import javax.swing.filechooser.FileFilter; - -import bjc.utils.funcdata.FunctionalList; -import bjc.utils.funcdata.IList; - -/** - * A file filter based on extensions. - * - * Built for Swing. - * - * @author ben - * - */ -public class ExtensionFileFilter extends FileFilter { - /** - * The list holding all filtered extensions - */ - private final IList<String> extensions; - - /** - * Create a new filter only showing files with the specified extensions. - * - * @param exts - * The extensions to show in this filter. - */ - public ExtensionFileFilter(final List<String> exts) { - extensions = new FunctionalList<>(exts); - } - - /** - * Create a new filter only showing files with the specified extensions. - * - * @param exts - * The extensions to show in this filter. - */ - public ExtensionFileFilter(final String... exts) { - extensions = new FunctionalList<>(exts); - } - - @Override - public boolean accept(final File pathname) { - if (pathname == null) throw new NullPointerException("Pathname must not be null"); - - return extensions.anyMatch(pathname.getName()::endsWith); - } - - @Override - public String getDescription() { - return extensions.toString(); - } -}
\ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/gui/SimpleDialogs.java b/BJC-Utils2/src/main/java/bjc/utils/gui/SimpleDialogs.java deleted file mode 100644 index 59eb1c3..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/gui/SimpleDialogs.java +++ /dev/null @@ -1,269 +0,0 @@ -package bjc.utils.gui; - -import java.awt.Component; -import java.awt.Frame; -import java.util.function.Function; -import java.util.function.Predicate; - -import javax.swing.JButton; -import javax.swing.JComboBox; -import javax.swing.JDialog; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.JPanel; - -import bjc.utils.gui.layout.VLayout; - -/** - * Utility class for getting simple input from the user. - * - * @author ben - * - */ -public class SimpleDialogs { - /** - * Get a bounded integer from the user. - * - * @param parent - * The parent component for the dialogs. - * @param title - * The title for the dialogs. - * @param prompt - * The prompt to tell the user what to enter. - * @param lowerBound - * The lower integer bound to accept. - * @param upperBound - * The upper integer bound to accept. - * @return A int within the specified bounds. - */ - public static int getBoundedInt(final Component parent, final String title, final String prompt, - final int lowerBound, final int upperBound) { - return getValue(parent, title, prompt, (strang) -> { - try { - final int value = Integer.parseInt(strang); - - return value < upperBound && value > lowerBound; - } catch (final NumberFormatException nfex) { - // We don't care about the specifics of the - // exception, just - // that this value isn't good - return false; - } - }, Integer::parseInt); - } - - /** - * Asks the user to pick an option from a series of choices. - * - * @param <E> - * The type of choices for the user to pick - * - * @param parent - * The parent frame for this dialog - * @param title - * The title of this dialog - * @param question - * The question being asked - * @param choices - * The available choices for the question - * @return The choice the user picked, or null if they didn't pick one - */ - @SuppressWarnings("unchecked") - public static <E> E getChoice(final Frame parent, final String title, final String question, - final E... choices) { - if (parent == null) - throw new NullPointerException("Parent must not be null"); - else if (title == null) - throw new NullPointerException("Title must not be null"); - else if (question == null) throw new NullPointerException("Question must not be null"); - - final JDialog chooser = new JDialog(parent, title, true); - chooser.setLayout(new VLayout(2)); - - final JPanel questionPane = new JPanel(); - - final JLabel questionText = new JLabel(question); - final JComboBox<E> questionChoices = new JComboBox<>(choices); - - questionPane.add(questionText); - questionPane.add(questionChoices); - - final JPanel buttonPane = new JPanel(); - - final JButton okButton = new JButton("Ok"); - final JButton cancelButton = new JButton("Cancel"); - - okButton.addActionListener((event) -> chooser.dispose()); - cancelButton.addActionListener((event) -> chooser.dispose()); - - buttonPane.add(cancelButton); - buttonPane.add(okButton); - - chooser.add(questionPane); - chooser.add(buttonPane); - - chooser.pack(); - chooser.setVisible(true); - - return (E) questionChoices.getSelectedItem(); - } - - /** - * Get a integer from the user - * - * @param parent - * The parent component for dialogs. - * @param title - * The title for dialogs. - * @param prompt - * The prompt to tell the user what to enter. - * @return A int. - */ - public static int getInt(final Component parent, final String title, final String prompt) { - return getValue(parent, title, prompt, strang -> { - try { - Integer.parseInt(strang); - return true; - } catch (final NumberFormatException nfex) { - // We don't care about this exception, just mark - // the value - // as not good - return false; - } - }, Integer::parseInt); - } - - /** - * Get a string from the user - * - * @param parent - * The parent component for dialogs. - * @param title - * The title for the dialogs. - * @param prompt - * The prompt to tell the user what to enter. - * @return A string. - */ - public static String getString(final Component parent, final String title, final String prompt) { - if (parent == null) - throw new NullPointerException("Parent must not be null"); - else if (title == null) - throw new NullPointerException("Title must not be null"); - else if (prompt == null) throw new NullPointerException("Prompt must not be null"); - - return JOptionPane.showInputDialog(parent, prompt, title, JOptionPane.QUESTION_MESSAGE); - } - - /** - * Get a value parsable from a string from the user. - * - * @param <E> - * The type of the value parsed from the string - * - * @param parent - * The parent component for dialogs. - * @param title - * The title for dialogs. - * @param prompt - * The prompt to tell the user what to enter. - * @param validator - * A predicate to determine if a input is valid. - * @param transformer - * The function to transform the string into a value. - * @return The value parsed from a string. - */ - public static <E> E getValue(final Component parent, final String title, final String prompt, - final Predicate<String> validator, final Function<String, E> transformer) { - if (validator == null) - throw new NullPointerException("Validator must not be null"); - else if (transformer == null) throw new NullPointerException("Transformer must not be null"); - - String input = getString(parent, title, prompt); - - while (!validator.test(input)) { - showError(parent, "I/O Error", "Please enter a valid value"); - - input = getString(parent, title, prompt); - } - - return transformer.apply(input); - } - - /** - * Get a whole number from the user. - * - * @param parent - * The parent component for dialogs. - * @param title - * The title for dialogs. - * @param prompt - * The prompt to tell the user what to enter. - * @return A whole number. - */ - public static int getWhole(final Component parent, final String title, final String prompt) { - return getBoundedInt(parent, title, prompt, 0, Integer.MAX_VALUE); - } - - /** - * Ask the user a Yes/No question. - * - * @param parent - * The parent component for dialogs. - * @param title - * The title for dialogs. - * @param question - * The question to ask the user. - * @return True if the user said yes, false otherwise. - */ - public static boolean getYesNo(final Component parent, final String title, final String question) { - if (parent == null) - throw new NullPointerException("Parent must not be null"); - else if (title == null) - throw new NullPointerException("Title must not be null"); - else if (question == null) throw new NullPointerException("Question must not be null"); - - final int result = JOptionPane.showConfirmDialog(parent, question, title, JOptionPane.YES_NO_OPTION); - - return result == JOptionPane.YES_OPTION ? true : false; - } - - /** - * Show a error message to the user - * - * @param parent - * The parent component for dialogs. - * @param title - * The title for dialogs. - * @param message - * The error to show the user. - */ - public static void showError(final Component parent, final String title, final String message) { - if (parent == null) - throw new NullPointerException("Parent must not be null"); - else if (title == null) - throw new NullPointerException("Title must not be null"); - else if (message == null) throw new NullPointerException("Error message must not be null"); - - JOptionPane.showMessageDialog(parent, message, title, JOptionPane.ERROR_MESSAGE); - } - - /** - * Show an informative message to the user - * - * @param parent - * The parent for this dialog - * @param title - * Show the title for this dialog - * @param message - * Show the message for this dialog - */ - public static void showMessage(final Component parent, final String title, final String message) { - if (parent == null) - throw new NullPointerException("Parent must not be null"); - else if (title == null) - throw new NullPointerException("Title must not be null"); - else if (message == null) throw new NullPointerException("Message must not be null"); - - JOptionPane.showMessageDialog(parent, title, message, JOptionPane.INFORMATION_MESSAGE); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/gui/SimpleFileChooser.java b/BJC-Utils2/src/main/java/bjc/utils/gui/SimpleFileChooser.java deleted file mode 100644 index 7da0bd8..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/gui/SimpleFileChooser.java +++ /dev/null @@ -1,198 +0,0 @@ -package bjc.utils.gui; - -import java.awt.Component; -import java.io.File; - -import javax.swing.JFileChooser; - -import bjc.utils.exceptions.FileNotChosenException; - -/** - * Utility class for easily prompting user for files. - * - * Built for Swing. - * - * @author ben - * - */ -public class SimpleFileChooser { - private static File doOpenFile(final Component parent, final String title, final JFileChooser files) { - if (title == null) throw new NullPointerException("Title must not be null"); - - files.setDialogTitle(title); - - boolean success = false; - - while (!success) { - try { - maybeDoOpenFile(parent, files); - - success = true; - } catch (final FileNotChosenException fncx) { - // We don't care about specifics - SimpleDialogs.showError(parent, "I/O Error", "Please pick a file to open"); - } - } - - return files.getSelectedFile(); - } - - private static File doSaveFile(final Component parent, final String title, final JFileChooser files) { - if (title == null) throw new NullPointerException("Title must not be null"); - - files.setDialogTitle(title); - - final boolean success = false; - - while (!success) { - try { - maybeDoSaveFile(parent, files); - - return files.getSelectedFile(); - } catch (final FileNotChosenException fncex) { - // We don't care about specifics - SimpleDialogs.showError(parent, "I/O Error", "Please pick a file to save to"); - } - } - } - - /** - * Prompt the user with a "Open File..." dialog. Keeps prompting them - * until they pick a file. - * - * @param parent - * The component to use as the parent for the dialog. - * @param title - * The title of the dialog to prompt with. - * @return The file the user has chosen. - */ - public static File getOpenFile(final Component parent, final String title) { - final JFileChooser files = new JFileChooser(); - - return doOpenFile(parent, title, files); - } - - /** - * Prompt the user with a "Open File..." dialog. Keeps prompting them - * until they pick a file. - * - * @param parent - * The component to use as the parent for the dialog. - * @param title - * The title of the dialog to prompt with. - * @param extensions - * The list of file extensions the file should have. - * @return The file the user has chosen. - */ - public static File getOpenFile(final Component parent, final String title, final String... extensions) { - final JFileChooser files = new JFileChooser(); - - files.addChoosableFileFilter(new ExtensionFileFilter(extensions)); - - return doOpenFile(parent, title, files); - } - - /** - * Prompt the user with a "Save File..." dialog. - * - * @param parent - * The component to use as the parent for the dialog. - * @param title - * The title of the dialog to prompt with. - * @return The file the user chose. - */ - public static File getSaveFile(final Component parent, final String title) { - final JFileChooser files = new JFileChooser(); - - return doSaveFile(parent, title, files); - } - - /** - * Prompt the user with a "Save File..." dialog. - * - * @param parent - * The component to use as the parent for the dialog. - * @param title - * The title of the dialog to prompt with. - * @param extensions - * The extensions of the files the user can choose. - * @return The file the user chose. - */ - public static File getSaveFile(final Component parent, final String title, final String... extensions) { - final JFileChooser files = new JFileChooser(); - - files.addChoosableFileFilter(new ExtensionFileFilter(extensions)); - - return doSaveFile(parent, title, files); - } - - private static void maybeDoOpenFile(final Component parent, final JFileChooser files) - throws FileNotChosenException { - if (parent == null) - throw new NullPointerException("Parent must not be null"); - else if (files == null) throw new NullPointerException("File chooser must not be null"); - - final int result = files.showSaveDialog(parent); - - if (result != JFileChooser.APPROVE_OPTION) throw new FileNotChosenException(); - } - - private static void maybeDoSaveFile(final Component parent, final JFileChooser files) - throws FileNotChosenException { - if (parent == null) - throw new NullPointerException("Parent must not be null"); - else if (files == null) throw new NullPointerException("File chooser must not be null"); - - final int result = files.showSaveDialog(parent); - - if (result != JFileChooser.APPROVE_OPTION) throw new FileNotChosenException(); - } - - /** - * Prompt the user with a "Open File..." dialog. - * - * @param parent - * The component to use as the parent for the dialog. - * @param title - * The title of the dialog to prompt with. - * @return The file if the user chose one or null if they didn't. - */ - public static File maybeOpenFile(final Component parent, final String title) { - if (title == null) throw new NullPointerException("Title must not be null"); - - final JFileChooser files = new JFileChooser(); - files.setDialogTitle(title); - - try { - maybeDoOpenFile(parent, files); - } catch (final FileNotChosenException fncex) { - // We don't care about specifics - } - - return files.getSelectedFile(); - } - - /** - * Prompt the user with a "Save File..." dialog. - * - * @param parent - * The component to use as the parent for the dialog. - * @param title - * The title of the dialog to prompt with. - * @return The file if the user chose one or null if they didn't. - */ - public static File maybeSaveFile(final Component parent, final String title) { - if (title == null) throw new NullPointerException("Title must not be null"); - - final JFileChooser files = new JFileChooser(); - files.setDialogTitle(title); - - try { - maybeDoSaveFile(parent, files); - } catch (final FileNotChosenException fncex) { - // We don't care about specifics - } - - return files.getSelectedFile(); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/gui/SimpleInternalDialogs.java b/BJC-Utils2/src/main/java/bjc/utils/gui/SimpleInternalDialogs.java deleted file mode 100644 index 5237557..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/gui/SimpleInternalDialogs.java +++ /dev/null @@ -1,208 +0,0 @@ -package bjc.utils.gui; - -import java.awt.Component; -import java.util.function.Function; -import java.util.function.Predicate; - -import javax.swing.JOptionPane; - -/** - * Utility class for getting simple input from the user. - * - * Modified to work with JDesktopPanes - * - * @author ben - * - */ -public class SimpleInternalDialogs { - /** - * Get a bounded integer from the user. - * - * @param parent - * The parent component for the dialogs. - * @param title - * The title for the dialogs. - * @param prompt - * The prompt to tell the user what to enter. - * @param lowerBound - * The lower integer bound to accept. - * @param upperBound - * The upper integer bound to accept. - * @return A int within the specified bounds. - */ - public static int getBoundedInt(final Component parent, final String title, final String prompt, - final int lowerBound, final int upperBound) { - return getValue(parent, title, prompt, (strang) -> { - try { - final int value = Integer.parseInt(strang); - - return value < upperBound && value > lowerBound; - } catch (final NumberFormatException nfex) { - // We don't care about the specifics of the - // exception, just - // that this value isn't good - return false; - } - }, Integer::parseInt); - } - - /** - * Get a integer from the user - * - * @param parent - * The parent component for dialogs. - * @param title - * The title for dialogs. - * @param prompt - * The prompt to tell the user what to enter. - * @return A int. - */ - public static int getInt(final Component parent, final String title, final String prompt) { - return getValue(parent, title, prompt, strang -> { - try { - Integer.parseInt(strang); - return true; - } catch (final NumberFormatException nfex) { - // We don't care about this exception, just mark - // the value - // as not good - return false; - } - }, Integer::parseInt); - } - - /** - * Get a string from the user - * - * @param parent - * The parent component for dialogs. - * @param title - * The title for the dialogs. - * @param prompt - * The prompt to tell the user what to enter. - * @return A string. - */ - public static String getString(final Component parent, final String title, final String prompt) { - if (parent == null) - throw new NullPointerException("Parent must not be null"); - else if (title == null) - throw new NullPointerException("Title must not be null"); - else if (prompt == null) throw new NullPointerException("Prompt must not be null"); - - return JOptionPane.showInternalInputDialog(parent, prompt, title, JOptionPane.QUESTION_MESSAGE); - } - - /** - * Get a value parsable from a string from the user. - * - * @param <E> - * The type of the value parsed from the string - * - * @param parent - * The parent component for dialogs. - * @param title - * The title for dialogs. - * @param prompt - * The prompt to tell the user what to enter. - * @param validator - * A predicate to determine if a input is valid. - * @param transformer - * The function to transform the string into a value. - * @return The value parsed from a string. - */ - public static <E> E getValue(final Component parent, final String title, final String prompt, - final Predicate<String> validator, final Function<String, E> transformer) { - if (validator == null) - throw new NullPointerException("Validator must not be null"); - else if (transformer == null) throw new NullPointerException("Transformer must not be null"); - - String strang = getString(parent, title, prompt); - - while (!validator.test(strang)) { - showError(parent, "I/O Error", "Please enter a valid value"); - - strang = getString(parent, title, prompt); - } - - return transformer.apply(strang); - } - - /** - * Get a whole number from the user. - * - * @param parent - * The parent component for dialogs. - * @param title - * The title for dialogs. - * @param prompt - * The prompt to tell the user what to enter. - * @return A whole number. - */ - public static int getWhole(final Component parent, final String title, final String prompt) { - return getBoundedInt(parent, title, prompt, 0, Integer.MAX_VALUE); - } - - /** - * Ask the user a Yes/No question. - * - * @param parent - * The parent component for dialogs. - * @param title - * The title for dialogs. - * @param question - * The question to ask the user. - * @return True if the user said yes, false otherwise. - */ - public static boolean getYesNo(final Component parent, final String title, final String question) { - if (parent == null) - throw new NullPointerException("Parent must not be null"); - else if (title == null) - throw new NullPointerException("Title must not be null"); - else if (question == null) throw new NullPointerException("Question must not be null"); - - final int result = JOptionPane.showInternalConfirmDialog(parent, question, title, - JOptionPane.YES_NO_OPTION); - - return result == JOptionPane.YES_OPTION ? true : false; - } - - /** - * Show a error message to the user - * - * @param parent - * The parent component for dialogs. - * @param title - * The title for dialogs. - * @param message - * The error to show the user. - */ - public static void showError(final Component parent, final String title, final String message) { - if (parent == null) - throw new NullPointerException("Parent must not be null"); - else if (title == null) - throw new NullPointerException("Title must not be null"); - else if (message == null) throw new NullPointerException("Error message must not be null"); - - JOptionPane.showInternalMessageDialog(parent, message, title, JOptionPane.ERROR_MESSAGE); - } - - /** - * Show an informative message to the user - * - * @param parent - * The parent for this dialog - * @param title - * Show the title for this dialog - * @param message - * Show the message for this dialog - */ - public static void showMessage(final Component parent, final String title, final String message) { - if (parent == null) - throw new NullPointerException("Parent must not be null"); - else if (title == null) - throw new NullPointerException("Title must not be null"); - else if (message == null) throw new NullPointerException("Message must not be null"); - - JOptionPane.showInternalMessageDialog(parent, title, message, JOptionPane.INFORMATION_MESSAGE); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/gui/SimpleInternalFrame.java b/BJC-Utils2/src/main/java/bjc/utils/gui/SimpleInternalFrame.java deleted file mode 100644 index afb498e..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/gui/SimpleInternalFrame.java +++ /dev/null @@ -1,40 +0,0 @@ -package bjc.utils.gui; - -import javax.swing.JInternalFrame; - -/** - * A simple internal frame class - * - * @author ben - * - */ -public class SimpleInternalFrame extends JInternalFrame { - private static final long serialVersionUID = -2966801321260716617L; - - /** - * Create a new blank internal frame - */ - public SimpleInternalFrame() { - super(); - } - - /** - * Create a new blank internal frame with a specific title - * - * @param title - * The title of the internal frame - */ - public SimpleInternalFrame(final String title) { - super(title); - } - - protected void setupFrame() { - setSize(320, 240); - - setResizable(true); - - setClosable(true); - setMaximizable(true); - setIconifiable(true); - } -}
\ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/gui/SimpleJList.java b/BJC-Utils2/src/main/java/bjc/utils/gui/SimpleJList.java deleted file mode 100644 index 411d0db..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/gui/SimpleJList.java +++ /dev/null @@ -1,49 +0,0 @@ -package bjc.utils.gui; - -import javax.swing.DefaultListModel; -import javax.swing.JList; -import javax.swing.ListModel; - -/** - * Utility class for making JLists and their models. - * - * @author ben - * - */ -public class SimpleJList { - /** - * Create a new JList from a given list. - * - * @param <E> - * The type of data in the JList - * - * @param source - * The list to populate the JList with. - * @return A JList populated with the elements from ls. - */ - public static <E> JList<E> buildFromList(final Iterable<E> source) { - if (source == null) throw new NullPointerException("Source must not be null"); - - return new JList<>(buildModel(source)); - } - - /** - * Create a new list model from a given list. - * - * @param <E> - * The type of data in the list model - * - * @param source - * The list to fill the list model from. - * @return A list model populated with the elements from ls. - */ - public static <E> ListModel<E> buildModel(final Iterable<E> source) { - if (source == null) throw new NullPointerException("Source must not be null"); - - final DefaultListModel<E> defaultModel = new DefaultListModel<>(); - - source.forEach(defaultModel::addElement); - - return defaultModel; - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/gui/SimpleTitledBorder.java b/BJC-Utils2/src/main/java/bjc/utils/gui/SimpleTitledBorder.java deleted file mode 100644 index 9b01507..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/gui/SimpleTitledBorder.java +++ /dev/null @@ -1,25 +0,0 @@ -package bjc.utils.gui; - -import javax.swing.border.EtchedBorder; -import javax.swing.border.TitledBorder; - -/** - * A simple border with a title attached to it. - * - * @author ben - * - */ -public class SimpleTitledBorder extends TitledBorder { - // Version ID for serialization - private static final long serialVersionUID = -5655969079949148487L; - - /** - * Create a new border with the specified title. - * - * @param title - * The title for the border. - */ - public SimpleTitledBorder(final String title) { - super(new EtchedBorder(), title); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/gui/TextAreaOutputStream.java b/BJC-Utils2/src/main/java/bjc/utils/gui/TextAreaOutputStream.java deleted file mode 100644 index fbc58ed..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/gui/TextAreaOutputStream.java +++ /dev/null @@ -1,35 +0,0 @@ -package bjc.utils.gui; - -import java.io.IOException; -import java.io.OutputStream; - -import javax.swing.JTextArea; - -/** - * An output stream that prints to a JTextArea - * - * @author epr - * @author Levente S\u00e1ntha (lsantha@users.sourceforge.net) - */ -public class TextAreaOutputStream extends OutputStream { - private final JTextArea textArea; - - /** - * Create a new output stream attached to a textarea - * - * @param console - * The textarea to write to - */ - public TextAreaOutputStream(final JTextArea console) { - this.textArea = console; - } - - @Override - public void write(final int b) throws IOException { - textArea.append("" + (char) b); - - if (b == '\n') { - textArea.repaint(); - } - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/gui/awt/ExtensionFileFilter.java b/BJC-Utils2/src/main/java/bjc/utils/gui/awt/ExtensionFileFilter.java deleted file mode 100644 index eb60ae2..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/gui/awt/ExtensionFileFilter.java +++ /dev/null @@ -1,50 +0,0 @@ -package bjc.utils.gui.awt; - -import java.io.File; -import java.io.FilenameFilter; -import java.util.List; - -import bjc.utils.funcdata.FunctionalList; -import bjc.utils.funcdata.IList; - -/** - * Filter a set of filenames by extension. - * - * Built for AWT - * - * @author ben - * - */ -public class ExtensionFileFilter implements FilenameFilter { - /** - * The list of extensions to filter - */ - private final IList<String> extensions; - - /** - * Create a new filter only showing files with the specified extensions. - * - * @param exts - * The extensions to show in this filter. - */ - public ExtensionFileFilter(final List<String> exts) { - if (exts == null) throw new NullPointerException("Extensions must not be null"); - - extensions = new FunctionalList<>(exts); - } - - /** - * Create a new filter only showing files with the specified extensions. - * - * @param exts - * The extensions to show in this filter. - */ - public ExtensionFileFilter(final String... exts) { - extensions = new FunctionalList<>(exts); - } - - @Override - public boolean accept(final File directory, final String name) { - return extensions.anyMatch(name::endsWith); - } -}
\ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/gui/awt/SimpleFileDialog.java b/BJC-Utils2/src/main/java/bjc/utils/gui/awt/SimpleFileDialog.java deleted file mode 100644 index 77a4a59..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/gui/awt/SimpleFileDialog.java +++ /dev/null @@ -1,144 +0,0 @@ -package bjc.utils.gui.awt; - -import java.awt.FileDialog; -import java.awt.Frame; -import java.io.File; -import java.io.FilenameFilter; - -import bjc.utils.gui.SimpleDialogs; - -/** - * A simple way to get the user to pick a file - * - * Built for AWT. - * - * @author ben - * - */ -public class SimpleFileDialog { - /** - * Prompt the user to pick a file to open - * - * @param parent - * The parent of the file picker - * @param title - * The title of the file picker - * @return The file the user picked - */ - public static File getOpenFile(final Frame parent, final String title) { - return getOpenFile(parent, title, (String[]) null); - } - - /** - * Prompt the user to pick a file to open - * - * @param parent - * The parent of the file picker - * @param title - * The title of the file picker - * @param extensions - * The extensions to accept as valid - * @return The file the user picked - */ - public static File getOpenFile(final Frame parent, final String title, final String... extensions) { - if (parent == null) - throw new NullPointerException("Parent must not be null"); - else if (title == null) throw new NullPointerException("Title must not be null"); - - final FileDialog chooser = new FileDialog(parent, title, FileDialog.LOAD); - - if (extensions != null) { - final FilenameFilter filter = new ExtensionFileFilter(extensions); - chooser.setFilenameFilter(filter); - } - - chooser.setVisible(true); - - while (chooser.getFile() == null) { - SimpleDialogs.showError(parent, "File I/O Error", "Please choose a file to open."); - chooser.setVisible(true); - } - - return chooser.getFiles()[0]; - } - - /** - * Prompt the user to pick a file to open - * - * @param parent - * The parent of the file picker - * @param title - * The title of the file picker - * @param extensions - * The extensions to accept as valid - * @return The file the user picked - */ - public static File[] getOpenFiles(final Frame parent, final String title, final String... extensions) { - if (parent == null) - throw new NullPointerException("Parent must not be null"); - else if (title == null) throw new NullPointerException("Title must not be null"); - - final FileDialog chooser = new FileDialog(parent, title, FileDialog.LOAD); - - if (extensions != null) { - final FilenameFilter filter = new ExtensionFileFilter(extensions); - chooser.setFilenameFilter(filter); - } - - chooser.setMultipleMode(true); - chooser.setVisible(true); - - while (chooser.getFile() == null) { - SimpleDialogs.showError(parent, "File I/O Error", "Please choose a file to open."); - chooser.setVisible(true); - } - - return chooser.getFiles(); - } - - /** - * Prompt the user to pick a file to save - * - * @param parent - * The parent of the file picker - * @param title - * The title of the file picker - * @return The file the user picked - */ - public static File getSaveFile(final Frame parent, final String title) { - return getSaveFile(parent, title, (String[]) null); - } - - /** - * Prompt the user to pick a file to save - * - * @param parent - * The parent of the file picker - * @param title - * The title of the file picker - * @param extensions - * The extensions to accept as valid - * @return The file the user picked - */ - public static File getSaveFile(final Frame parent, final String title, final String... extensions) { - if (parent == null) - throw new NullPointerException("Parent must not be null"); - else if (title == null) throw new NullPointerException("Title must not be null"); - - final FileDialog chooser = new FileDialog(parent, title, FileDialog.SAVE); - - if (extensions != null) { - final FilenameFilter filter = new ExtensionFileFilter(extensions); - chooser.setFilenameFilter(filter); - } - - chooser.setVisible(true); - - while (chooser.getFile() == null) { - SimpleDialogs.showError(parent, "File I/O Error", "Please choose a file to save to."); - chooser.setVisible(true); - } - - return chooser.getFiles()[0]; - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/gui/layout/AutosizeLayout.java b/BJC-Utils2/src/main/java/bjc/utils/gui/layout/AutosizeLayout.java deleted file mode 100644 index 6f384f2..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/gui/layout/AutosizeLayout.java +++ /dev/null @@ -1,22 +0,0 @@ -package bjc.utils.gui.layout; - -import java.awt.GridLayout; - -/** - * A layout that simply holds one component that it auto-resizes whenever it is - * resized. - * - * @author ben - * - */ -public class AutosizeLayout extends GridLayout { - // Version id for serialization - private static final long serialVersionUID = -2495693595953396924L; - - /** - * Create a new auto-size layout. - */ - public AutosizeLayout() { - super(1, 1); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/gui/layout/HLayout.java b/BJC-Utils2/src/main/java/bjc/utils/gui/layout/HLayout.java deleted file mode 100644 index 4ed1661..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/gui/layout/HLayout.java +++ /dev/null @@ -1,25 +0,0 @@ -package bjc.utils.gui.layout; - -import java.awt.GridLayout; - -/** - * A layout manager that lays out its components horizontally, evenly sizing - * them. - * - * @author ben - * - */ -public class HLayout extends GridLayout { - // Version ID for serialization - private static final long serialVersionUID = 1244964456966270026L; - - /** - * Create a new horizontal layout with the specified number of columns. - * - * @param columns - * The number of columns in this layout. - */ - public HLayout(final int columns) { - super(1, columns); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/gui/layout/VLayout.java b/BJC-Utils2/src/main/java/bjc/utils/gui/layout/VLayout.java deleted file mode 100644 index 6993365..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/gui/layout/VLayout.java +++ /dev/null @@ -1,25 +0,0 @@ -package bjc.utils.gui.layout; - -import java.awt.GridLayout; - -/** - * A layout that lays out its components vertically, evenly sharing space among - * them. - * - * @author ben - * - */ -public class VLayout extends GridLayout { - // Version ID for serializations - private static final long serialVersionUID = -6417962941602322663L; - - /** - * Create a new vertical layout with the specified number of rows. - * - * @param rows - * The number of rows. - */ - public VLayout(final int rows) { - super(rows, 1); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/gui/panels/DropdownListPanel.java b/BJC-Utils2/src/main/java/bjc/utils/gui/panels/DropdownListPanel.java deleted file mode 100644 index 4f71d38..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/gui/panels/DropdownListPanel.java +++ /dev/null @@ -1,73 +0,0 @@ -package bjc.utils.gui.panels; - -import java.awt.BorderLayout; - -import javax.swing.DefaultListModel; -import javax.swing.JButton; -import javax.swing.JComboBox; -import javax.swing.JList; -import javax.swing.JPanel; -import javax.swing.ListSelectionModel; - -import bjc.utils.funcdata.IList; -import bjc.utils.gui.layout.AutosizeLayout; -import bjc.utils.gui.layout.HLayout; - -/** - * A panel that allows you to select choices from a dropdown list - * - * @author ben - * - */ -public class DropdownListPanel extends JPanel { - private static final long serialVersionUID = 2719963952350133541L; - - /** - * Create a new dropdown list panel - * - * @param <T> - * The type of items in the dropdown list - * @param type - * The label of the type of items in the list - * @param model - * The model to put items into - * @param choices - * The items to choose from - */ - public <T> DropdownListPanel(final String type, final DefaultListModel<T> model, final IList<T> choices) { - setLayout(new AutosizeLayout()); - - final JPanel itemInputPanel = new JPanel(); - itemInputPanel.setLayout(new BorderLayout()); - - final JPanel addItemPanel = new JPanel(); - addItemPanel.setLayout(new HLayout(2)); - - final JComboBox<T> addItemBox = new JComboBox<>(); - choices.forEach(addItemBox::addItem); - - final JButton addItemButton = new JButton("Add " + type); - - addItemPanel.add(addItemBox); - addItemPanel.add(addItemButton); - - final JList<T> itemList = new JList<>(model); - itemList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - - final JButton removeItemButton = new JButton("Remove " + type); - - addItemButton.addActionListener((ev) -> { - model.addElement(addItemBox.getItemAt(addItemBox.getSelectedIndex())); - }); - - removeItemButton.addActionListener((ev) -> { - model.remove(itemList.getSelectedIndex()); - }); - - itemInputPanel.add(addItemPanel, BorderLayout.PAGE_START); - itemInputPanel.add(itemList, BorderLayout.CENTER); - itemInputPanel.add(removeItemButton, BorderLayout.PAGE_END); - - add(itemInputPanel); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/gui/panels/FormattedInputPanel.java b/BJC-Utils2/src/main/java/bjc/utils/gui/panels/FormattedInputPanel.java deleted file mode 100644 index 2cecf0c..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/gui/panels/FormattedInputPanel.java +++ /dev/null @@ -1,66 +0,0 @@ -package bjc.utils.gui.panels; - -import java.util.function.Consumer; - -import javax.swing.JFormattedTextField; -import javax.swing.JFormattedTextField.AbstractFormatter; -import javax.swing.JLabel; -import javax.swing.JPanel; - -import bjc.utils.gui.layout.HLayout; - -/** - * A simple panel allowing for input of a single formatted value - * - * @author ben - * - * @param <InputVal> - * The type of value being formatted - */ -public class FormattedInputPanel<InputVal> extends JPanel { - private static final long serialVersionUID = 5232016563558588031L; - - private final JFormattedTextField field; - - /** - * Create a new formatted input panel - * - * @param label - * The label for this panel - * @param length - * The length of this panel - * @param formatter - * The formatter to use for input - * @param reciever - * The action to call whenever the value changes - */ - @SuppressWarnings("unchecked") - public FormattedInputPanel(final String label, final int length, final AbstractFormatter formatter, - final Consumer<InputVal> reciever) { - setLayout(new HLayout(2)); - - final JLabel lab = new JLabel(label); - field = new JFormattedTextField(formatter); - - field.setColumns(length); - field.setFocusLostBehavior(JFormattedTextField.COMMIT_OR_REVERT); - field.addPropertyChangeListener("value", (event) -> { - // This is safe, because InputVal should be the type of - // whatever object the formatter is returning - reciever.accept((InputVal) field.getValue()); - }); - - add(lab); - add(field); - } - - /** - * Reset the value in this panel to a specified value - * - * @param value - * The value to set the panel to - */ - public void resetValues(final InputVal value) { - field.setValue(value); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/gui/panels/HolderOutputPanel.java b/BJC-Utils2/src/main/java/bjc/utils/gui/panels/HolderOutputPanel.java deleted file mode 100644 index 653dace..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/gui/panels/HolderOutputPanel.java +++ /dev/null @@ -1,79 +0,0 @@ -package bjc.utils.gui.panels; - -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.Timer; - -import bjc.utils.data.IHolder; -import bjc.utils.gui.layout.HLayout; - -/** - * A panel that outputs a value bound to a {@link IHolder} - * - * @author ben - * - */ -public class HolderOutputPanel extends JPanel { - private static final long serialVersionUID = 166573313903782080L; - - private Timer updater; - private final JLabel value; - private final int nDelay; - private final IHolder<String> val; - - /** - * Create a new display panel, backed by a holder - * - * @param lab - * The label to attach to this field - * @param valueHolder - * The holder to get the value from - * @param nDelay - * The delay in ms between value updates - */ - public HolderOutputPanel(final String lab, final IHolder<String> valueHolder, final int nDelay) { - this.val = valueHolder; - this.nDelay = nDelay; - - setLayout(new HLayout(2)); - - final JLabel label = new JLabel(lab); - value = new JLabel("(stopped)"); - - updater = new Timer(nDelay, (event) -> { - value.setText(valueHolder.getValue()); - }); - - add(label); - add(value); - } - - /** - * Set this panel back to its initial state - */ - public void reset() { - stopUpdating(); - - value.setText("(stopped)"); - - updater = new Timer(nDelay, (event) -> { - value.setText(val.getValue()); - }); - } - - /** - * Start updating the contents of the field from the holder - */ - public void startUpdating() { - updater.start(); - } - - /** - * Stop updating the contents of the field from the holder - */ - public void stopUpdating() { - updater.stop(); - - value.setText(value.getText() + " (stopped)"); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/gui/panels/ListParameterPanel.java b/BJC-Utils2/src/main/java/bjc/utils/gui/panels/ListParameterPanel.java deleted file mode 100644 index cca73d5..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/gui/panels/ListParameterPanel.java +++ /dev/null @@ -1,133 +0,0 @@ -package bjc.utils.gui.panels; - -import java.util.function.Consumer; -import java.util.function.Supplier; - -import javax.swing.DefaultListModel; -import javax.swing.JButton; -import javax.swing.JList; -import javax.swing.JPanel; -import javax.swing.ListSelectionModel; - -import bjc.utils.funcdata.IList; -import bjc.utils.gui.SimpleJList; -import bjc.utils.gui.layout.HLayout; -import bjc.utils.gui.layout.VLayout; - -/** - * A panel that has a list of objects and ways of manipulating that list - * - * @author ben - * - * @param <E> - * The type of data stored in the list - */ -public class ListParameterPanel<E> extends JPanel { - // Version id for serialization - private static final long serialVersionUID = 3442971104975491571L; - - /** - * Create a new panel using the specified actions for doing things - * - * @param add - * The action that provides items - * @param edit - * The action that edits items - * @param remove - * The action that removes items - */ - public ListParameterPanel(final Supplier<E> add, final Consumer<E> edit, final Consumer<E> remove) { - this(add, edit, remove, null); - } - - /** - * Create a new panel using the specified actions for doing things - * - * @param add - * The action that provides items - * @param edit - * The action that edits items - * @param remove - * The action that removes items - * @param defaults - * The default values to put in the list - */ - public ListParameterPanel(final Supplier<E> add, final Consumer<E> edit, final Consumer<E> remove, - final IList<E> defaults) { - setLayout(new VLayout(2)); - - JList<E> list; - - if (defaults != null) { - list = SimpleJList.buildFromList(defaults.toIterable()); - } else { - list = new JList<>(new DefaultListModel<>()); - } - - list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - - final JPanel buttonPanel = new JPanel(); - - int numButtons = 0; - - if (add != null) { - numButtons++; - } - - if (edit != null) { - numButtons++; - } - - if (remove != null) { - numButtons++; - } - - buttonPanel.setLayout(new HLayout(numButtons)); - - JButton addParam = null; - - if (add != null) { - addParam = new JButton("Add..."); - addParam.addActionListener((event) -> { - final DefaultListModel<E> model = (DefaultListModel<E>) list.getModel(); - - model.addElement(add.get()); - }); - } - - JButton editParam = null; - - if (edit != null) { - editParam = new JButton("Edit..."); - editParam.addActionListener((event) -> { - edit.accept(list.getSelectedValue()); - }); - } - - JButton removeParam = null; - - if (remove != null) { - removeParam = new JButton("Remove..."); - removeParam.addActionListener((event) -> { - final DefaultListModel<E> model = (DefaultListModel<E>) list.getModel(); - - remove.accept(model.remove(list.getSelectedIndex())); - }); - } - - if (add != null) { - buttonPanel.add(addParam); - } - - if (edit != null) { - buttonPanel.add(editParam); - } - - if (remove != null) { - buttonPanel.add(removeParam); - } - - add(list); - add(buttonPanel); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/gui/panels/SimpleInputPanel.java b/BJC-Utils2/src/main/java/bjc/utils/gui/panels/SimpleInputPanel.java deleted file mode 100644 index 65c533d..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/gui/panels/SimpleInputPanel.java +++ /dev/null @@ -1,45 +0,0 @@ -package bjc.utils.gui.panels; - -import java.awt.BorderLayout; - -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JTextField; - -/** - * A simple component for text input - * - * @author ben - * - */ -public class SimpleInputPanel extends JPanel { - private static final long serialVersionUID = -4734279623645236868L; - - /** - * The text field containing the input value - */ - public final JTextField inputValue; - - /** - * Create a new input panel - * - * @param label - * The label for the field - * @param columns - * The number of columns of text input to take - */ - public SimpleInputPanel(final String label, final int columns) { - setLayout(new BorderLayout()); - - final JLabel inputLabel = new JLabel(label); - - if (columns < 1) { - inputValue = new JTextField(); - } else { - inputValue = new JTextField(columns); - } - - add(inputLabel, BorderLayout.LINE_START); - add(inputValue, BorderLayout.CENTER); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/gui/panels/SimpleListPanel.java b/BJC-Utils2/src/main/java/bjc/utils/gui/panels/SimpleListPanel.java deleted file mode 100644 index edc1797..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/gui/panels/SimpleListPanel.java +++ /dev/null @@ -1,93 +0,0 @@ -package bjc.utils.gui.panels; - -import java.awt.BorderLayout; -import java.util.function.Consumer; -import java.util.function.Predicate; - -import javax.swing.DefaultListModel; -import javax.swing.JButton; -import javax.swing.JList; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JTextField; -import javax.swing.ListSelectionModel; - -import bjc.utils.gui.layout.AutosizeLayout; -import bjc.utils.gui.layout.HLayout; - -/** - * A simple list of strings - * - * @author ben - * - */ -public class SimpleListPanel extends JPanel { - private static final long serialVersionUID = 2719963952350133541L; - - private static void addItem(final DefaultListModel<String> model, final Predicate<String> verifier, - final Consumer<String> onFailure, final JTextField addItemField) { - final String potentialItem = addItemField.getText(); - - if (verifier == null || verifier.test(potentialItem)) { - model.addElement(potentialItem); - } else { - onFailure.accept(potentialItem); - } - - addItemField.setText(""); - } - - /** - * Create a new list panel - * - * @param type - * The type of things in the list - * @param model - * The model to put items into - * @param verifier - * The predicate to use to verify items - * @param onFailure - * The function to call when an item doesn't verify - */ - public SimpleListPanel(final String type, final DefaultListModel<String> model, - final Predicate<String> verifier, final Consumer<String> onFailure) { - setLayout(new AutosizeLayout()); - - final JPanel itemInputPanel = new JPanel(); - itemInputPanel.setLayout(new BorderLayout()); - - final JPanel addItemPanel = new JPanel(); - addItemPanel.setLayout(new HLayout(2)); - - final JTextField addItemField = new JTextField(255); - final JButton addItemButton = new JButton("Add " + type); - - addItemPanel.add(addItemField); - addItemPanel.add(addItemButton); - - final JList<String> itemList = new JList<>(model); - itemList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - - final JScrollPane listScroller = new JScrollPane(itemList); - - final JButton removeItemButton = new JButton("Remove " + type); - - addItemButton.addActionListener((ev) -> { - addItem(model, verifier, onFailure, addItemField); - }); - - addItemField.addActionListener((ev) -> { - addItem(model, verifier, onFailure, addItemField); - }); - - removeItemButton.addActionListener((ev) -> { - model.remove(itemList.getSelectedIndex()); - }); - - itemInputPanel.add(addItemPanel, BorderLayout.PAGE_START); - itemInputPanel.add(listScroller, BorderLayout.CENTER); - itemInputPanel.add(removeItemButton, BorderLayout.PAGE_END); - - add(itemInputPanel); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/gui/panels/SimpleSpinnerPanel.java b/BJC-Utils2/src/main/java/bjc/utils/gui/panels/SimpleSpinnerPanel.java deleted file mode 100644 index 6106182..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/gui/panels/SimpleSpinnerPanel.java +++ /dev/null @@ -1,42 +0,0 @@ -package bjc.utils.gui.panels; - -import java.awt.BorderLayout; - -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JSpinner; -import javax.swing.SpinnerModel; - -/** - * A simple spinner control - * - * @author ben - * - */ -public class SimpleSpinnerPanel extends JPanel { - private static final long serialVersionUID = -4734279623645236868L; - - /** - * The spinner being used - */ - public final JSpinner inputValue; - - /** - * Create a new spinner panel - * - * @param label - * The label for the spinner - * @param model - * The model to attach to the spinner - */ - public SimpleSpinnerPanel(final String label, final SpinnerModel model) { - setLayout(new BorderLayout()); - - final JLabel inputLabel = new JLabel(label); - - inputValue = new JSpinner(model); - - add(inputLabel, BorderLayout.LINE_START); - add(inputValue, BorderLayout.CENTER); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/gui/panels/SliderInputPanel.java b/BJC-Utils2/src/main/java/bjc/utils/gui/panels/SliderInputPanel.java deleted file mode 100644 index e6a6da4..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/gui/panels/SliderInputPanel.java +++ /dev/null @@ -1,187 +0,0 @@ -package bjc.utils.gui.panels; - -import java.text.ParseException; -import java.util.function.Consumer; - -import javax.swing.JFormattedTextField; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JSlider; - -import bjc.utils.gui.layout.HLayout; - -/** - * A simple input panel for a slider-controlled value and a manual-input field - * for setting the slider - * - * @author ben - * - */ -public class SliderInputPanel extends JPanel { - private final class NumberFormatter extends JFormattedTextField.AbstractFormatter { - private static final long serialVersionUID = -4448291795913908270L; - - private final int minValue; - private final int maxValue; - - private final int initValue; - - public NumberFormatter(final SliderSettings settings) { - minValue = settings.minValue; - maxValue = settings.maxValue; - - initValue = settings.initValue; - } - - @Override - public Object stringToValue(final String text) throws ParseException { - try { - final int val = Integer.parseInt(text); - - if (val < minValue) - throw new ParseException("Value must be greater than " + minValue, 0); - else if (val > maxValue) - throw new ParseException("Value must be smaller than " + maxValue, 0); - else return val; - } catch (final NumberFormatException nfex) { - final ParseException pex = new ParseException("Value must be a valid integer", 0); - - pex.initCause(nfex); - - throw pex; - } - } - - @Override - public String valueToString(final Object value) throws ParseException { - if (value == null) return Integer.toString(initValue); - - return Integer.toString((Integer) value); - } - } - - /** - * Represents the settings for a slider - * - * @author ben - * - */ - public static class SliderSettings { - /** - * The minimum value of the slider - */ - public final int minValue; - /** - * The maximum value of the slider - */ - public final int maxValue; - - /** - * The initial value of the slider - */ - public final int initValue; - - /** - * Create a new slider settings, with the initial value in the - * middle - * - * @param min - * The minimum value of the slider - * @param max - * The maximum value of the slider - */ - public SliderSettings(final int min, final int max) { - this(min, max, (min + max) / 2); - } - - /** - * Create a new set of slider sttings - * - * @param min - * The minimum slider value - * @param max - * The maximum slider value - * @param init - * Th initial slider value - */ - public SliderSettings(final int min, final int max, final int init) { - minValue = min; - maxValue = max; - - initValue = init; - } - } - - private static final long serialVersionUID = 2956394160569961404L; - private final JSlider slider; - private final JFormattedTextField field; - - /** - * Create a new slider input panel - * - * @param lab - * The label for the field - * @param settings - * The settings for slider values - * @param majorTick - * The setting for where to place big ticks - * @param minorTick - * The setting for where to place small ticks - * @param action - * The action to execute for a given value - */ - public SliderInputPanel(final String lab, final SliderSettings settings, final int majorTick, - final int minorTick, final Consumer<Integer> action) { - setLayout(new HLayout(3)); - - final JLabel label = new JLabel(lab); - - slider = new JSlider(settings.minValue, settings.maxValue, settings.initValue); - field = new JFormattedTextField(new NumberFormatter(settings)); - - slider.setMajorTickSpacing(majorTick); - slider.setMinorTickSpacing(minorTick); - slider.setPaintTicks(true); - slider.setPaintLabels(true); - - slider.addChangeListener((event) -> { - if (slider.getValueIsAdjusting()) { - // Do nothing - } else { - final int val = slider.getValue(); - - field.setValue(val); - - action.accept(val); - } - }); - - field.setFocusLostBehavior(JFormattedTextField.COMMIT_OR_REVERT); - field.setColumns(15); - field.addPropertyChangeListener("value", (event) -> { - final Object value = field.getValue(); - - if (value == null) { - // Do nothing - } else { - slider.setValue((Integer) value); - } - }); - - add(label); - add(slider); - add(field); - } - - /** - * Reset the values in this panel to a specified value - * - * @param value - * The value to reset the fields to - */ - public void resetValues(final int value) { - slider.setValue(value); - - field.setValue(value); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/gui/panels/package-info.java b/BJC-Utils2/src/main/java/bjc/utils/gui/panels/package-info.java deleted file mode 100644 index 4361885..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/gui/panels/package-info.java +++ /dev/null @@ -1,5 +0,0 @@ -/** - * @author ben - * - */ -package bjc.utils.gui.panels;
\ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/ioutils/CLFormatter.java b/BJC-Utils2/src/main/java/bjc/utils/ioutils/CLFormatter.java deleted file mode 100644 index eefd532..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/ioutils/CLFormatter.java +++ /dev/null @@ -1,531 +0,0 @@ -package bjc.utils.ioutils;
-
-import java.util.HashMap;
-import java.util.IllegalFormatConversionException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.UnknownFormatConversionException;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import bjc.utils.PropertyDB;
-import bjc.utils.esodata.Tape;
-import bjc.utils.esodata.SingleTape;
-
-import static bjc.utils.PropertyDB.applyFormat;
-import static bjc.utils.PropertyDB.getCompiledRegex;
-import static bjc.utils.PropertyDB.getRegex;
-
-public class CLFormatter {
- public static class CLModifiers {
- public final boolean atMod;
- public final boolean colonMod;
-
- public CLModifiers(boolean at, boolean colon) {
- atMod = at;
- colonMod = colon;
- }
-
- public static CLModifiers fromString(String modString) {
- boolean atMod = false;
- boolean colonMod = false;
- if(modString != null) {
- atMod = modString.contains("@");
- colonMod = modString.contains(":");
- }
-
- return new CLModifiers(atMod, colonMod);
- }
- }
-
- public static class EscapeException extends RuntimeException {
- public final boolean endIteration;
-
- public EscapeException() {
- endIteration = false;
- }
-
- public EscapeException(boolean end) {
- endIteration = end;
- }
- }
-
- @FunctionalInterface
- public interface Directive {
- /*
- * @TODO fill in parameters
- */
- public void format();
- }
-
- private static final String prefixParam = getRegex("clFormatPrefix");
- private static final Pattern pPrefixParam = Pattern.compile(prefixParam);
-
- private static final String formatMod = getRegex("clFormatModifier");
-
- private static final String prefixList = applyFormat("delimSeparatedList", prefixParam, ",");
-
- private static final String directiveName = getRegex("clFormatName");
-
- private static final String formatDirective = applyFormat("clFormatDirective", prefixList, formatMod, directiveName);
- private static final Pattern pFormatDirective = Pattern.compile(formatDirective);
-
- private Map<String, Directive> extraDirectives;
-
- public CLFormatter() {
- extraDirectives = new HashMap<>();
- }
-
- private void checkItem(Object itm, char directive) {
- if(itm == null)
- throw new IllegalArgumentException(String.format("No argument provided for %c directive", directive));
- }
-
- public String formatString(String format, Object... params) {
- StringBuffer sb = new StringBuffer();
- /* Put the parameters where we can easily handle them. */
- Tape<Object> tParams = new SingleTape(params);
-
- doFormatString(format, sb, tParams);
-
- return sb.toString();
- }
-
- private void doFormatString(String format, StringBuffer sb, Tape<Object> tParams) {
- Matcher dirMatcher = pFormatDirective.matcher(format);
-
- while(dirMatcher.find()) {
- dirMatcher.appendReplacement(sb, "");
-
- String dirName = dirMatcher.group("name");
- String dirFunc = dirMatcher.group("funcname");
- String dirMods = dirMatcher.group("modifiers");
- String dirParams = dirMatcher.group("params");
-
- CLParameters arrParams = CLParameters.fromDirective(dirParams.split("(?<!'),"), tParams);
- CLModifiers mods = CLModifiers.fromString(dirMods);
-
- Object item = tParams.item();
- if(dirName == null && dirFunc != null) {
- /*
- * @TODO implement user-called functions.
- */
- continue;
- }
-
- switch(dirName) {
- case "A":
- checkItem(item, 'A');
- handleAestheticDirective(sb, item, mods, arrParams);
- tParams.right();
- break;
- case "B":
- checkItem(item, 'B');
- if(!(item instanceof Number)) {
- throw new IllegalFormatConversionException('B', item.getClass());
- }
- handleNumberDirective(sb, mods, arrParams, -1, ((Number)item).longValue(), 2);
- tParams.right();
- break;
- case "C":
- checkItem(item, 'C');
- handleCDirective(sb, item, mods);
- tParams.right();
- break;
- case "D":
- checkItem(item, 'D');
- if(!(item instanceof Number)) {
- throw new IllegalFormatConversionException('D', item.getClass());
- }
- handleNumberDirective(sb, mods, arrParams, -1, ((Number)item).longValue(), 10);
- tParams.right();
- break;
- case "O":
- checkItem(item, 'O');
- if(!(item instanceof Number)) {
- throw new IllegalFormatConversionException('O', item.getClass());
- }
- handleNumberDirective(sb, mods, arrParams, -1, ((Number)item).longValue(), 8);
- tParams.right();
- break;
- case "R":
- checkItem(item, 'R');
- handleRadixDirective(sb, mods, arrParams, item);
- tParams.right();
- break;
- case "X":
- checkItem(item, 'X');
- if(!(item instanceof Number)) {
- throw new IllegalFormatConversionException('X', item.getClass());
- }
- handleNumberDirective(sb, mods, arrParams, -1, ((Number)item).longValue(), 16);
- tParams.right();
- break;
- case "&":
- handleFreshlineDirective(sb, arrParams);
- break;
- case "%":
- handleLiteralDirective(sb, arrParams, "\n", '%');
- break;
- case "|":
- handleLiteralDirective(sb, arrParams, "\f", '|');
- break;
- case "~":
- handleLiteralDirective(sb, arrParams, "~", '~');
- break;
- case "*":
- handleGotoDirective(mods, arrParams, tParams);
- break;
- case "^":
- handleEscapeDirective(mods, arrParams, tParams);
- break;
- case "[":
- handleConditionalDirective(sb, mods, arrParams, tParams, dirMatcher);
- break;
- case "]":
- throw new IllegalArgumentException("Found conditional-end outside of conditional.");
- case ";":
- throw new IllegalArgumentException("Found conditional-seperator outside of conditional.");
- case "T":
- case "<":
- case ">":
- /* @TODO
- * Figure out how to implement
- * tabulation/justification in a
- * reasonable manner.
- */
- throw new IllegalArgumentException("Layout-control directives aren't implemented yet.");
- case "F":
- case "E":
- case "G":
- case "$":
- /* @TODO implement floating point directives. */
- throw new IllegalArgumentException("Floating-point directives aren't implemented yet.");
- case "S":
- case "W":
- /* @TODO
- * figure out if we want to implement
- * someting for these directives instead
- * of punting.
- * */
- throw new IllegalArgumentException("S and W aren't implemented. Use A instead");
- default:
- String msg = String.format("Unknown format directive '%s'", dirName);
- throw new UnknownFormatConversionException(msg);
- }
- }
-
- dirMatcher.appendTail(sb);
- }
-
- private void handleCDirective(StringBuffer buff, Object parm, CLModifiers mods) {
- if(!(parm instanceof Character)) {
- throw new IllegalFormatConversionException('C', parm.getClass());
- }
-
- char ch = (Character) parm;
- int codepoint = (int) ch;
-
- if(mods.colonMod) {
- /*
- * Colon mod means print Unicode character name.
- */
- buff.append(Character.getName(codepoint));
- } else {
- buff.append(ch);
- }
- }
-
- private void handleFreshlineDirective(StringBuffer buff, CLParameters params) {
- int nTimes = 1;
-
- if(params.length() > 1) {
- nTimes = params.getInt(0, "occurance count", '&');
- }
-
- if(buff.charAt(buff.length() - 1) == '\n') nTimes -= 1;
-
- for(int i = 0; i < nTimes; i++) {
- buff.append("\n");
- }
- }
-
- private void handleLiteralDirective(StringBuffer buff, CLParameters params, String lit, char directive) {
- int nTimes = 1;
-
- if(params.length() > 1) {
- nTimes = params.getInt(0, "occurance count", directive);
- }
-
- for(int i = 0; i < nTimes; i++) {
- buff.append(lit);
- }
- }
-
- private void handleNumberDirective(StringBuffer buff, CLModifiers mods, CLParameters params, int argidx, long val, int radix) {
- /*
- * Initialize the two padding related parameters, and
- * then fill them in from the directive parameters if
- * they are present.
- */
- int mincol = 0;
- char padchar = ' ';
- if(params.length() > (argidx + 2)) {
- mincol = params.getIntDefault(argidx + 1, "minimum column count", 'R', 0);
- }
- if(params.length() > (argidx + 3)) {
- padchar = params.getCharDefault(argidx + 2, "padding character", 'R', ' ');
- }
-
- if(mods.colonMod) {
- /*
- * We're doing commas, so check if the two
- * comma-related parameters were supplied.
- */
- int commaInterval = 0;
- char commaChar = ',';
- if(params.length() > (argidx + 3)) {
- commaChar = params.getCharDefault((argidx + 3), "comma character", 'R', ' ');
- }
- if(params.length() > (argidx + 4)) {
- commaInterval = params.getIntDefault((argidx + 4), "comma interval", 'R', 0);
- }
-
- NumberUtils.toCommaString(val, mincol, padchar, commaInterval, commaChar, mods.atMod, radix);
- } else {
- NumberUtils.toNormalString(val, mincol, padchar, mods.atMod, radix);
- }
- }
-
- private void handleRadixDirective(StringBuffer buff, CLModifiers mods, CLParameters params, Object arg) {
- if(!(arg instanceof Number)) {
- throw new IllegalFormatConversionException('R', arg.getClass());
- }
-
- /*
- * @TODO see if this is the way we want to do this.
- */
- long val = ((Number)arg).longValue();
-
- if(params.length() == 0) {
- if(mods.atMod) {
- buff.append(NumberUtils.toRoman((Long)val, mods.colonMod));
- } else if(mods.colonMod) {
- buff.append(NumberUtils.toOrdinal(val));
- } else {
- buff.append(NumberUtils.toCardinal(val));
- }
- } else {
- if(params.length() < 1)
- throw new IllegalArgumentException("R directive requires at least one parameter, the radix");
-
- int radix = params.getInt(0, "radix", 'R');
-
- handleNumberDirective(buff, mods, params, 0, val, radix);
- }
- }
-
- private void handleAestheticDirective(StringBuffer buff, Object item, CLModifiers mods, CLParameters params) {
- int mincol = 0, colinc = 1, minpad = 0;
- char padchar = ' ';
-
- if(params.length() > 1) {
- mincol = params.getIntDefault(0, "minimum column count", 'A', 0);
- }
-
- if(params.length() < 4) {
- throw new IllegalArgumentException("Must provide either zero, one or four arguments to A directive");
- }
-
- colinc = params.getIntDefault(1, "padding increment", 'A', 1);
- minpad = params.getIntDefault(2, "minimum amount of padding", 'A', 0);
- padchar = params.getCharDefault(3, "padding character", 'A', ' ');
-
- StringBuilder work = new StringBuilder();
-
- if(mods.atMod) {
- for(int i = 0; i < minpad; i++) {
- work.append(padchar);
- }
-
- for(int i = work.length(); i < mincol; i++) {
- for(int k = 0; k < colinc; k++) {
- work.append(padchar);
- }
- }
- }
-
- work.append(item.toString());
-
- if(!mods.atMod) {
- for(int i = 0; i < minpad; i++) {
- work.append(padchar);
- }
-
- for(int i = work.length(); i < mincol; i++) {
- for(int k = 0; k < colinc; k++) {
- work.append(padchar);
- }
- }
- }
- }
-
- private void handleGotoDirective(CLModifiers mods, CLParameters params, Tape<Object> formatParams) {
- if(mods.colonMod) {
- int num = 1;
- if(params.length() > 1) {
- num = params.getIntDefault(0, "number of arguments backward", '*', 1);
- }
-
- formatParams.left(num);
- } else if(mods.atMod) {
- int num = 0;
- if(params.length() > 1) {
- num = params.getIntDefault(0, "argument index", '*', 0);
- }
-
- formatParams.first();
- formatParams.right(num);
- } else {
- int num = 1;
- if(params.length() > 1) {
- num = params.getIntDefault(0, "number of arguments forward", '*', 1);
- }
-
- formatParams.right(num);
- }
- }
-
- private void handleConditionalDirective(StringBuffer sb, CLModifiers mods, CLParameters arrParams, Tape<Object> formatParams, Matcher dirMatcher) {
- StringBuffer condBody = new StringBuffer();
-
- List<String> clauses = new ArrayList<>();
- String defClause = null;
- boolean isDefault = false;
-
- while(dirMatcher.find()) {
- /* Process a list of clauses. */
- String dirName = dirMatcher.group("name");
- String dirMods = dirMatcher.group("modifiers");
-
- if(dirName != null) {
- /* Append everything up to this directive. */
- dirMatcher.appendReplacement(condBody, "");
-
- if(dirName.equals("]")) {
- /* End the conditional. */
- String clause = condBody.toString();
- if(isDefault) {
- defClause = clause;
- } else {
- clauses.add(clause);
- }
-
- break;
- } else if(dirName.equals(";")) {
- /* End the clause. */
- String clause = condBody.toString();
- if(isDefault) {
- defClause = clause;
- } else {
- clauses.add(clause);
- }
-
- /* Mark the next clause as the default. */
- if(dirMods.contains(":")) {
- isDefault = true;
- }
- } else {
- /* Not a special directive. */
- condBody.append(dirMatcher.group());
- }
- }
- }
-
- Object par = formatParams.item();
- if(mods.colonMod) {
- formatParams.right();
-
- if(par == null) {
- throw new IllegalArgumentException("No parameter provided for [ directive.");
- } else if(!(par instanceof Boolean)) {
- throw new IllegalFormatConversionException('[', par.getClass());
- }
- boolean res = (Boolean)par;
-
- String fmt;
- if(res) fmt = clauses.get(1);
- else fmt = clauses.get(0);
-
- doFormatString(fmt, sb, formatParams);
- } else if(mods.atMod) {
- if(par == null) {
- throw new IllegalArgumentException("No parameter provided for [ directive.");
- } else if(!(par instanceof Boolean)) {
- throw new IllegalFormatConversionException('[', par.getClass());
- }
- boolean res = (Boolean)par;
-
- if(res) {
- doFormatString(clauses.get(0), sb, formatParams);
- } else {
- formatParams.right();
- }
- } else {
- int res;
- if(arrParams.length() > 1) {
- res = arrParams.getInt(0, "conditional choice", '[');
- } else {
- if(par == null) {
- throw new IllegalArgumentException("No parameter provided for [ directive.");
- } else if(!(par instanceof Number)) {
- throw new IllegalFormatConversionException('[', par.getClass());
- }
- res = ((Number)par).intValue();
-
- formatParams.right();
- }
-
- if(res < 0 || res > clauses.size()) {
- if(defClause != null) doFormatString(defClause, sb, formatParams);
- } else {
- doFormatString(clauses.get(res), sb, formatParams);
- }
- }
- return;
- }
-
- private void handleEscapeDirective(CLModifiers mods, CLParameters params, Tape<Object> formatParams) {
- boolean shouldExit;
-
- switch(params.length()) {
- case 0:
- shouldExit = formatParams.size() == 0;
- break;
- case 1:
- int num = params.getInt(0, "condition count", '^');
- shouldExit = num == 0;
- break;
- case 2:
- int left = params.getInt(0, "left-hand condition", '^');
- int right = params.getInt(1, "right-hand condition", '^');
- shouldExit = left == right;
- break;
- case 3:
- default:
- int low = params.getInt(0, "lower-bound condition", '^');
- int mid = params.getInt(1, "interval condition", '^');
- int high = params.getInt(2, "upper-bound condition", '^');
- shouldExit = (low <= mid) && (mid <= high);
- break;
- }
-
- /* At negates it. */
- if(mods.atMod) shouldExit = !shouldExit;
-
- if(shouldExit) throw new EscapeException(mods.colonMod);
- }
-
-
-}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/ioutils/CLParameters.java b/BJC-Utils2/src/main/java/bjc/utils/ioutils/CLParameters.java deleted file mode 100644 index e4bb6fb..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/ioutils/CLParameters.java +++ /dev/null @@ -1,109 +0,0 @@ -package bjc.utils.ioutils; - -import java.util.ArrayList; -import java.util.List; - -import bjc.utils.esodata.Tape; - -/** - * Represents a set of parameters to a CL format directive. - * - * @author Benjamin Culkin - */ -public class CLParameters { - private String[] params; - - public CLParameters(String[] params) { - this.params = params; - } - - public int length() { - return params.length; - } - - /** - * Creates a set of parameters from an array of parameters. - * - * Mostly, this just fills in V and # parameters. - * - * @param params - * The parameters of the directive. - * @param dirParams - * The parameters of the format string. - * - * @return A set of CL parameters. - */ - public static CLParameters fromDirective(String[] params, Tape<Object> dirParams) { - List<String> parameters = new ArrayList<>(); - - for(String param : params) { - if(param.equalsIgnoreCase("V")) { - Object par = dirParams.item(); - boolean succ = dirParams.right(); - - if(par == null) { - throw new IllegalArgumentException("Expected a format parameter for V inline parameter"); - } - - if(par instanceof Number) { - int val = ((Number)par).intValue(); - - parameters.add(Integer.toString(val)); - } else if(par instanceof Character) { - char ch = ((Character)par); - - parameters.add(Character.toString(ch)); - } else { - throw new IllegalArgumentException("Incorrect type of parameter for V inline parameter"); - } - } else if(param.equals("#")) { - parameters.add(Integer.toString(dirParams.position())); - } else { - parameters.add(param); - } - } - - return new CLParameters(parameters.toArray(new String[0])); - } - - public char getCharDefault(int idx, String paramName, char directive, char def) { - if(!params[idx].equals("")) { - return getChar(idx, paramName, directive); - } - - return def; - } - - public char getChar(int idx, String paramName, char directive) { - String param = params[idx]; - - if(!param.startsWith("'")) { - throw new IllegalArgumentException(String.format("Invalid %s %s to %c directive", paramName, param, directive)); - } - - return param.charAt(1); - } - - public int getIntDefault(int idx, String paramName, char directive, int def) { - if(!params[idx].equals("")) { - - } - - return def; - } - - public int getInt(int idx, String paramName, char directive) { - String param = params[idx]; - - try { - return Integer.parseInt(param); - } catch (NumberFormatException nfex) { - String msg = String.format("Invalid %s %s to %c directive", paramName, param, directive); - - IllegalArgumentException iaex = new IllegalArgumentException(msg); - iaex.initCause(nfex); - - throw iaex; - } - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/ioutils/NumberUtils.java b/BJC-Utils2/src/main/java/bjc/utils/ioutils/NumberUtils.java deleted file mode 100644 index 1b754e2..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/ioutils/NumberUtils.java +++ /dev/null @@ -1,405 +0,0 @@ -package bjc.utils.ioutils; - -import java.util.Map; -import java.util.function.BiFunction; -import java.util.function.LongPredicate; - -import static java.util.Map.Entry; - -public class NumberUtils { - /* - * @TODO Use U+305 for large roman numerals, as well as excels 'concise' - * numerals (as implemented by roman()). - */ - public static String toRoman(long number, boolean classic) { - StringBuilder work = new StringBuilder(); - - long currNumber = number; - - if(currNumber == 0) { - return "N"; - } - - if(currNumber < 0) { - currNumber *= -1; - - work.append("-"); - } - - if(currNumber >= 1000) { - int numM = (int)(currNumber / 1000); - currNumber = currNumber % 1000; - - for(int i = 0; i < numM; i++) { - work.append("M"); - } - } - - if(currNumber >= 900 && !classic) { - currNumber = currNumber % 900; - - work.append("CM"); - } - - if(currNumber >= 500) { - currNumber = currNumber % 500; - - work.append("D"); - } - - if(currNumber >= 400 && !classic) { - currNumber = currNumber % 400; - - work.append("CD"); - } - - if(currNumber >= 100) { - int numC = (int)(currNumber / 100); - currNumber = currNumber % 100; - - for(int i = 0; i < numC; i++) { - work.append("C"); - } - } - - if(currNumber >= 90 && !classic) { - currNumber = currNumber % 90; - - work.append("XC"); - } - - if(currNumber >= 50) { - currNumber = currNumber % 50; - - work.append("L"); - } - - if(currNumber >= 40 && !classic) { - currNumber = currNumber % 40; - - work.append("XL"); - } - - if(currNumber >= 10) { - int numX = (int)(currNumber / 10); - currNumber = currNumber % 10; - - for(int i = 0; i < numX; i++) { - work.append("X"); - } - } - - if(currNumber >= 9 && !classic) { - currNumber = currNumber % 9; - - work.append("IX"); - } - - if(currNumber >= 5) { - currNumber = currNumber % 5; - - work.append("V"); - } - - if(currNumber >= 4 && !classic) { - currNumber = currNumber % 4; - - work.append("IV"); - } - - if(currNumber >= 1) { - int numI = (int)(currNumber / 1); - currNumber = currNumber % 1; - - for(int i = 0; i < numI; i++) { - work.append("I"); - } - } - - return work.toString(); - } - - public static String toCardinal(long number) { - return toCardinal(number, null); - } - - private static String[] cardinals = new String[] { - "zero", "one", "two", "three", "four", "five", "six", "seven", - "eight", "nine", "ten", "eleven", "twelve", "thirteen", - "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", - "nineteen", "twenty", - }; - - public static class CardinalState { - public final Map<Long, String> customNumbers; - public final Map<LongPredicate, BiFunction<Long, CardinalState, String>> customScales; - - public CardinalState(Map<Long, String> customNumbers, Map<LongPredicate, BiFunction<Long, CardinalState, String>> customScales) { - this.customNumbers = customNumbers; - this.customScales = customScales; - } - - public String handleCustom(long number) { - if(customNumbers.containsKey(number)) { - return customNumbers.get(number); - } - - for(Entry<LongPredicate, BiFunction<Long, CardinalState, String>> ent : customScales.entrySet()) { - if(ent.getKey().test(number)) { - return ent.getValue().apply(number, this); - } - } - - return null; - } - } - - public static String toCardinal(long number, CardinalState custom) { - if(custom != null) { - String res = custom.handleCustom(number); - - if(res != null) return res; - } - - if(number < 0) return "negative " + toCardinal(number * -1, custom); - - if(number <= 20) return cardinals[(int)number]; - - if(number < 100) { - if(number % 10 == 0) { - switch((int)number) { - case 30: - return "thirty"; - case 40: - return "forty"; - case 50: - return "fifty"; - case 60: - return "sixty"; - case 70: - return "seventy"; - case 80: - return "eighty"; - case 90: - return "ninety"; - default: - /* - * Shouldn't happen. - */ - assert(false); - } - } - - long numTens = (long)(number / 10); - long numOnes = number % 10; - - return toCardinal(numTens, custom) + "-" + toCardinal(numOnes, custom); - } - - if(number < 1000) { - long numHundreds = (long)(number / 100); - long rest = number % 100; - - return toCardinal(numHundreds, custom) + " hundred and " + toCardinal(rest, custom); - } - - long MILLION = (long)(Math.pow(10, 6)); - if(number < MILLION) { - long numThousands = (long)(number / 1000); - long rest = number % 1000; - - return toCardinal(numThousands, custom) + " thousand, " + toCardinal(rest, custom); - } - - long BILLION = (long)(Math.pow(10, 9)); - if(number < BILLION) { - long numMillions = (long)(number / MILLION); - long rest = number % MILLION; - - return toCardinal(numMillions, custom) + " million, " + toCardinal(rest, custom); - } - - long TRILLION = (long)(Math.pow(10, 12)); - if(number < TRILLION) { - long numBillions = (long)(number / BILLION); - long rest = number % BILLION; - - return toCardinal(numBillions, custom) + " billion, " + toCardinal(rest, custom); - } - - throw new IllegalArgumentException("Numbers greater than or equal to 1 trillion are not supported yet."); - } - - public static String toOrdinal(long number) { - if(number < 0) { - return "minus " + toOrdinal(number); - } - - if(number < 20) { - switch((int)number) { - case 0: - return "zeroth"; - case 1: - return "first"; - case 2: - return "second"; - case 3: - return "third"; - case 4: - return "fourth"; - case 5: - return "fifth"; - case 6: - return "sixth"; - case 7: - return "seventh"; - case 8: - return "eighth"; - case 9: - return "ninth"; - case 10: - return "tenth"; - case 11: - return "eleventh"; - case 12: - return "twelfth"; - case 13: - return "thirteenth"; - case 14: - return "fourteenth"; - case 15: - return "fifteenth"; - case 16: - return "sixteenth"; - case 17: - return "seventeenth"; - case 18: - return "eighteenth"; - case 19: - return "nineteenth"; - default: - /* - * Shouldn't happen. - */ - assert(false); - } - } - - if(number < 100) { - if(number % 10 == 0) { - switch((int)number) { - case 20: - return "twentieth"; - case 30: - return "thirtieth"; - case 40: - return "fortieth"; - case 50: - return "fiftieth"; - case 60: - return "sixtieth"; - case 70: - return "seventieth"; - case 80: - return "eightieth"; - case 90: - return "ninetieth"; - } - } - - long numPostfix = number % 10; - return toCardinal(number - numPostfix) + "-" + toOrdinal(numPostfix); - } - - long procNum = number % 100; - long tens = (long)(procNum / 10); - long ones = procNum % 10; - - if(tens == 1) { - return Long.toString(number) + "th"; - } - - switch((int)ones) { - case 1: - return Long.toString(number) + "st"; - case 2: - return Long.toString(number) + "nd"; - case 3: - return Long.toString(number) + "rd"; - default: - return Long.toString(number) + "th"; - } - } - - private static char[] radixChars = new char[62]; - static { - int idx = 0; - - for(char i = 0; i < 10; i++) { - radixChars[idx] = (char)('0' + i); - - idx += 1; - } - - for(char i = 0; i < 26; i++) { - radixChars[idx] = (char)('A' + i); - - idx += 1; - } - - for(char i = 0; i < 26; i++) { - radixChars[idx] = (char)('a' + i); - - idx += 1; - } - } - - public static String toCommaString(long val, int mincols, char padchar, int commaInterval, char commaChar, boolean signed, int radix) { - if(radix > radixChars.length) { - throw new IllegalArgumentException(String.format("Radix %d is larger than largest supported radix %d", radix, radixChars.length)); - } - - StringBuilder work = new StringBuilder(); - - boolean isNeg = false; - long currVal = val; - if(currVal < 0) { - isNeg = true; - currVal *= -1; - } - - if(currVal == 0) { - work.append(radixChars[0]); - } else { - int valCounter = 0; - - while(currVal != 0) { - valCounter += 1; - - int radDigit = (int)(currVal % radix); - work.append(radixChars[radDigit]); - currVal = (long)(currVal / radix); - - if(commaInterval != 0 && valCounter % commaInterval == 0) work.append(commaChar); - } - } - - if(isNeg) work.append("-"); - else if(signed) work.append("+"); - - work.reverse(); - - /* @TODO Should we have some way to specify how to pad? */ - if(work.length() < mincols) { - for(int i = work.length(); i < mincols; i++) { - work.append(padchar); - } - } - - return work.toString(); - } - - public static String toNormalString(long val, int mincols, char padchar, boolean signed, int radix) { - return toCommaString(val, mincols, padchar, 0, ',', signed, radix); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/ioutils/Prompter.java b/BJC-Utils2/src/main/java/bjc/utils/ioutils/Prompter.java deleted file mode 100644 index a6ec4c0..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/ioutils/Prompter.java +++ /dev/null @@ -1,47 +0,0 @@ -package bjc.utils.ioutils; - -import java.io.PrintStream; - -import bjc.utils.ioutils.blocks.TriggeredBlockReader; - -/** - * A runnable for use with {@link TriggeredBlockReader} to prompt the user for - * input. - * - * @author bjculkin - * - */ -public final class Prompter implements Runnable { - private String promt; - private final PrintStream printer; - - /** - * Create a new prompter using the specified prompt. - * - * @param prompt - * The prompt to present. - * - * @param output - * The stream to print the prompt on. - */ - public Prompter(final String prompt, final PrintStream output) { - promt = prompt; - - printer = output; - } - - /** - * Set the prompt this prompter uses. - * - * @param prompt - * The prompt this prompter uses. - */ - public void setPrompt(final String prompt) { - promt = prompt; - } - - @Override - public void run() { - printer.print(promt); - } -}
\ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/ioutils/RegexStringEditor.java b/BJC-Utils2/src/main/java/bjc/utils/ioutils/RegexStringEditor.java deleted file mode 100644 index 71f6782..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/ioutils/RegexStringEditor.java +++ /dev/null @@ -1,230 +0,0 @@ -package bjc.utils.ioutils; - -import java.util.function.BiFunction; -import java.util.function.UnaryOperator; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import bjc.utils.data.Toggle; -import bjc.utils.data.ValueToggle; -import bjc.utils.funcdata.FunctionalList; -import bjc.utils.funcdata.IList; -import bjc.utils.functypes.ID; - -/** - * Editor methods for strings based off the command language for the Sam editor. - * - * @author EVE - * - */ -public class RegexStringEditor { - private static final UnaryOperator<String> SID = ID.id(); - - /** - * Replace every occurrence of the pattern with the result of applying - * the action to the string matched by the pattern. - * - * @param input - * The input string to process. - * - * @param patt - * The pattern to match the string against. - * - * @param action - * The action to transform matches with. - * - * @return The string, with matches replaced with the action. - */ - public static String onOccurances(final String input, final Pattern patt, final UnaryOperator<String> action) { - return reduceOccurances(input, patt, SID, action); - } - - /** - * Replace every occurrence between the patterns with the result of - * applying the action to the strings between the patterns. - * - * @param input - * The input string to process. - * - * @param patt - * The pattern to match the string against. - * - * @param action - * The action to transform matches with. - * - * @return The string, with strings between the matches replaced with - * the action. - */ - public static String betweenOccurances(final String input, final Pattern patt, - final UnaryOperator<String> action) { - return reduceOccurances(input, patt, action, SID); - } - - /** - * Execute actions between and on matches of a regular expression. - * - * @param input - * The input string. - * - * @param rPatt - * The pattern to match against the string. - * - * @param betweenAction - * The function to execute between matches of the string. - * - * @param onAction - * The function to execute on matches of the string. - * - * @return The string, with both actions applied. - */ - public static String reduceOccurances(final String input, final Pattern rPatt, - final UnaryOperator<String> betweenAction, final UnaryOperator<String> onAction) { - /* - * Get all of the occurances. - */ - final IList<String> occurances = listOccurances(input, rPatt); - - /* - * Execute the correct action on every occurance. - */ - final Toggle<UnaryOperator<String>> actions = new ValueToggle<>(onAction, betweenAction); - final BiFunction<String, StringBuilder, StringBuilder> reducer = (strang, state) -> { - return state.append(actions.get().apply(strang)); - }; - - /* - * Convert the list back to a string. - */ - return occurances.reduceAux(new StringBuilder(), reducer, StringBuilder::toString); - } - - /** - * Execute actions between and on matches of a regular expression. - * - * @param input - * The input string. - * - * @param rPatt - * The pattern to match against the string. - * - * @param betweenAction - * The function to execute between matches of the string. - * - * @param onAction - * The function to execute on matches of the string. - * - * @return The string, with both actions applied. - */ - public static IList<String> mapOccurances(final String input, final Pattern rPatt, - final UnaryOperator<String> betweenAction, final UnaryOperator<String> onAction) { - /* - * Get all of the occurances. - */ - final IList<String> occurances = listOccurances(input, rPatt); - - /* - * Execute the correct action on every occurance. - */ - final Toggle<UnaryOperator<String>> actions = new ValueToggle<>(onAction, betweenAction); - return occurances.map(strang -> actions.get().apply(strang)); - } - - /** - * Separate a string into match/non-match segments. - * - * @param input - * The string to separate. - * - * @param rPatt - * The pattern to use for separation. - * - * @return The string, as a list of match/non-match segments, - * starting/ending with a non-match segment. - */ - public static IList<String> listOccurances(final String input, final Pattern rPatt) { - final IList<String> res = new FunctionalList<>(); - - /* - * Create the matcher and work buffer. - */ - final Matcher matcher = rPatt.matcher(input); - StringBuffer work = new StringBuffer(); - - /* - * For every match. - */ - while (matcher.find()) { - final String match = matcher.group(); - - /* - * Append the text until the match to the buffer. - */ - matcher.appendReplacement(work, ""); - - res.add(work.toString()); - res.add(match); - - /* - * Clear the buffer. - */ - work = new StringBuffer(); - } - - /* - * Add the text after the last match to the buffer. - */ - matcher.appendTail(work); - res.add(work.toString()); - - return res; - } - - /** - * Apply an operation to a string if it matches a regular expression. - * - * @param input - * The input string. - * - * @param patt - * The pattern to match against it. - * - * @param action - * The action to execute if it matches. - * - * @return The string, modified by the action if the pattern matched. - */ - public static String ifMatches(final String input, final Pattern patt, final UnaryOperator<String> action) { - final Matcher matcher = patt.matcher(input); - - if (matcher.matches()) { - return action.apply(input); - } else { - return input; - } - } - - /** - * Apply an operation to a string if it matches a regular expression. - * - * @param input - * The input string. - * - * @param patt - * The pattern to match against it. - * - * @param action - * The action to execute if it doesn't match. - * - * @return The string, modified by the action if the pattern didn't - * match. - */ - public static String ifNotMatches(final String input, final Pattern patt, final UnaryOperator<String> action) { - final Matcher matcher = patt.matcher(input); - - if (matcher.matches()) { - return input; - } else { - return action.apply(input); - } - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/ioutils/RuleBasedConfigReader.java b/BJC-Utils2/src/main/java/bjc/utils/ioutils/RuleBasedConfigReader.java deleted file mode 100644 index 7c5205b..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/ioutils/RuleBasedConfigReader.java +++ /dev/null @@ -1,265 +0,0 @@ -package bjc.utils.ioutils; - -import java.io.InputStream; -import java.util.InputMismatchException; -import java.util.Scanner; -import java.util.function.BiConsumer; -import java.util.function.Consumer; - -import bjc.utils.data.IHolder; -import bjc.utils.data.IPair; -import bjc.utils.data.Identity; -import bjc.utils.data.Pair; -import bjc.utils.exceptions.UnknownPragmaException; -import bjc.utils.funcdata.FunctionalMap; -import bjc.utils.funcdata.FunctionalStringTokenizer; -import bjc.utils.funcdata.IMap; - -/** - * This class parses a rules based config file, and uses it to drive a provided - * set of actions - * - * @author ben - * - * @param <E> - * The type of the state object to use - * - */ -public class RuleBasedConfigReader<E> { - /* Function to execute when starting a rule. - * Takes the tokenizer, and a pair of the read token and application state - */ - private BiConsumer<FunctionalStringTokenizer, IPair<String, E>> start; - - /* - * Function to use when continuing a rule - * Takes a tokenizer and application state - */ - private BiConsumer<FunctionalStringTokenizer, E> continueRule; - - /* - * Function to use when ending a rule - * Takes an application state - */ - private Consumer<E> end; - - /* - * Map of pragma names to pragma actions - * Pragma actions are functions taking a tokenizer and application state - */ - private final IMap<String, BiConsumer<FunctionalStringTokenizer, E>> pragmas; - - /** - * Create a new rule-based config reader - * - * @param start - * The action to fire when starting a rule - * @param continueRule - * The action to fire when continuing a rule - * @param end - * The action to fire when ending a rule - */ - public RuleBasedConfigReader(final BiConsumer<FunctionalStringTokenizer, IPair<String, E>> start, - final BiConsumer<FunctionalStringTokenizer, E> continueRule, final Consumer<E> end) { - this.start = start; - this.continueRule = continueRule; - this.end = end; - - this.pragmas = new FunctionalMap<>(); - } - - /** - * Add a pragma to this reader - * - * @param name - * The name of the pragma to add - * @param action - * The function to execute when this pragma is read - */ - public void addPragma(final String name, final BiConsumer<FunctionalStringTokenizer, E> action) { - if (name == null) throw new NullPointerException("Pragma name must not be null"); - else if (action == null) throw new NullPointerException("Pragma action must not be null"); - - pragmas.put(name, action); - } - - private void continueRule(final E state, final boolean isRuleOpen, final String line) { - // Make sure our input is correct - if (isRuleOpen == false) - throw new InputMismatchException("Cannot continue rule with no rule open"); - else if (continueRule == null) - throw new InputMismatchException("Rule continuation not supported for current grammar"); - - /* - * Accept the rule - */ - continueRule.accept(new FunctionalStringTokenizer(line.substring(1), " "), state); - } - - private boolean endRule(final E state, final boolean isRuleOpen) { - /* - * Ignore blank line without an open rule - */ - if (isRuleOpen == false) - /* - * Do nothing - */ - return false; - else { - /* - * Nothing happens on rule end - */ - if (end != null) { - /* - * Process the rule ending - */ - end.accept(state); - } - - /* - * Return a closed rule - */ - return false; - } - } - - /** - * Run a stream through this reader - * - * @param input - * The stream to get input - * @param initialState - * The initial state of the reader - * @return The final state of the reader - */ - public E fromStream(final InputStream input, final E initialState) { - if (input == null) throw new NullPointerException("Input stream must not be null"); - - /* - * Application state: We're giving this back later - */ - final E state = initialState; - - /* - * Prepare our input source - */ - try (Scanner source = new Scanner(input)) { - source.useDelimiter("\n"); - /* - * This is true when a rule's open - */ - final IHolder<Boolean> isRuleOpen = new Identity<>(false); - - /* - * Do something for every line of the file - */ - source.forEachRemaining((line) -> { - /* - * Skip comment lines - */ - if (line.startsWith("#") || line.startsWith("//")) - /* - * It's a comment - */ - return; - else if (line.equals("")) { - /* - * End the rule - */ - isRuleOpen.replace(endRule(state, isRuleOpen.getValue())); - } else if (line.startsWith("\t")) { - /* - * Continue the rule - */ - continueRule(state, isRuleOpen.getValue(), line); - } else { - /* - * Open a rule - */ - isRuleOpen.replace(startRule(state, isRuleOpen.getValue(), line)); - } - }); - } - - /* - * Return the state that the user has created - */ - return state; - } - - /** - * Set the action to execute when continuing a rule - * - * @param continueRule - * The action to execute on continuation of a rule - */ - public void setContinueRule(final BiConsumer<FunctionalStringTokenizer, E> continueRule) { - this.continueRule = continueRule; - } - - /** - * Set the action to execute when ending a rule - * - * @param end - * The action to execute on ending of a rule - */ - public void setEndRule(final Consumer<E> end) { - this.end = end; - } - - /** - * Set the action to execute when starting a rule - * - * @param start - * The action to execute on starting of a rule - */ - public void setStartRule(final BiConsumer<FunctionalStringTokenizer, IPair<String, E>> start) { - if (start == null) throw new NullPointerException("Action on rule start must be non-null"); - - this.start = start; - } - - private boolean startRule(final E state, boolean isRuleOpen, final String line) { - /* - * Create the line tokenizer - */ - final FunctionalStringTokenizer tokenizer = new FunctionalStringTokenizer(line, " "); - - /* - * Get the initial token - */ - final String nextToken = tokenizer.nextToken(); - - /* - * Handle pragmas - */ - if (nextToken.equals("pragma")) { - /* - * Get the pragma name - */ - final String token = tokenizer.nextToken(); - - /* - * Handle pragmas - */ - pragmas.getOrDefault(token, (tokenzer, stat) -> { - throw new UnknownPragmaException("Unknown pragma " + token); - }).accept(tokenizer, state); - } else { - /* - * Make sure input is correct - */ - if (isRuleOpen == true) - throw new InputMismatchException("Nested rules are currently not supported"); - - /* - * Start a rule - */ - start.accept(tokenizer, new Pair<>(nextToken, state)); - - isRuleOpen = true; - } - - return isRuleOpen; - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/ioutils/RuleBasedReaderPragmas.java b/BJC-Utils2/src/main/java/bjc/utils/ioutils/RuleBasedReaderPragmas.java deleted file mode 100644 index e26a7ee..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/ioutils/RuleBasedReaderPragmas.java +++ /dev/null @@ -1,100 +0,0 @@ -package bjc.utils.ioutils; - -import java.util.function.BiConsumer; - -import bjc.utils.exceptions.PragmaFormatException; -import bjc.utils.funcdata.FunctionalStringTokenizer; -import bjc.utils.funcutils.ListUtils; - -/** - * Contains factory methods for common pragma types - * - * @author ben - * - */ -public class RuleBasedReaderPragmas { - - /** - * Creates a pragma that takes a single integer argument - * - * @param <StateType> - * The type of state that goes along with this pragma - * @param name - * The name of this pragma, for error message purpose - * @param consumer - * The function to invoke with the parsed integer - * @return A pragma that functions as described above. - */ - public static <StateType> BiConsumer<FunctionalStringTokenizer, StateType> buildInteger(final String name, - final BiConsumer<Integer, StateType> consumer) { - return (tokenizer, state) -> { - /* - * Check our input is correct - */ - if (!tokenizer.hasMoreTokens()) { - String fmt = "Pragma %s requires one integer argument"; - - throw new PragmaFormatException(String.format(fmt, name)); - } - - /* - * Read the argument - */ - final String token = tokenizer.nextToken(); - - try { - /* - * Run the pragma - */ - consumer.accept(Integer.parseInt(token), state); - } catch (final NumberFormatException nfex) { - /* - * Tell the user their argument isn't correct - */ - String fmt = "Argument %s to %s pragma isn't a valid integer, and this pragma requires an integer argument."; - - final PragmaFormatException pfex = new PragmaFormatException(String.format(fmt, token, name)); - - pfex.initCause(nfex); - - throw pfex; - } - }; - } - - /** - * Creates a pragma that takes any number of arguments and collapses - * them all into a single string - * - * @param <StateType> - * The type of state that goes along with this pragma - * @param name - * The name of this pragma, for error message purpose - * @param consumer - * The function to invoke with the parsed string - * @return A pragma that functions as described above. - */ - public static <StateType> BiConsumer<FunctionalStringTokenizer, StateType> buildStringCollapser( - final String name, final BiConsumer<String, StateType> consumer) { - return (tokenizer, state) -> { - /* - * Check our input - */ - if (!tokenizer.hasMoreTokens()) { - String fmt = "Pragma %s requires one or more string arguments."; - - throw new PragmaFormatException(String.format(fmt, name)); - } - - /* - * Build our argument - */ - final String collapsed = ListUtils.collapseTokens(tokenizer.toList()); - - /* - * Run the pragma - */ - consumer.accept(collapsed, state); - }; - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/ioutils/SimpleProperties.java b/BJC-Utils2/src/main/java/bjc/utils/ioutils/SimpleProperties.java deleted file mode 100644 index e6279c4..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/ioutils/SimpleProperties.java +++ /dev/null @@ -1,170 +0,0 @@ -package bjc.utils.ioutils; - -import java.io.InputStream; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; -import java.util.NoSuchElementException; -import java.util.Scanner; -import java.util.Set; - -/** - * Simple file based properties. - * - * @author EVE - * - */ -public class SimpleProperties implements Map<String, String> { - private final Map<String, String> props; - - /** - * Create a new set of simple properties. - */ - public SimpleProperties() { - props = new HashMap<>(); - } - - /** - * Load properties from the provided input stream. - * - * The format is the name, a space, then the body. - * - * All leading/trailing spaces from the name & body are removed. - * - * @param is - * The stream to read from. - * - * @param allowDuplicates - * Whether or not duplicate keys should be allowed. - */ - public void loadFrom(final InputStream is, final boolean allowDuplicates) { - try (Scanner scn = new Scanner(is)) { - while (scn.hasNextLine()) { - final String ln = scn.nextLine().trim(); - - /* - * Skip blank lines/comments - */ - if (ln.equals("")) { - continue; - } - if (ln.startsWith("#")) { - continue; - } - - final int sepIdx = ln.indexOf(' '); - - /* - * Complain about improperly formatted lines. - */ - if (sepIdx == -1) { - final String fmt = "Properties must be a name, a space, then the body.\n\tOffending line is '%s'"; - final String msg = String.format(fmt, ln); - - throw new NoSuchElementException(msg); - } - - final String name = ln.substring(0, sepIdx).trim(); - final String body = ln.substring(sepIdx).trim(); - - /* - * Complain about duplicates, if that is wanted. - */ - if (!allowDuplicates && containsKey(name)) { - final String msg = String.format("Duplicate key '%s'", name); - - throw new IllegalStateException(msg); - } - - put(name, body); - } - } - } - - /** - * Output the set of read properties. - */ - public void outputProperties() { - System.out.println("Read properties:"); - - for (final Entry<String, String> entry : entrySet()) { - System.out.printf("\t'%s'\t'%s'\n", entry.getKey(), entry.getValue()); - } - - System.out.println(); - } - - @Override - public int size() { - return props.size(); - } - - @Override - public boolean isEmpty() { - return props.isEmpty(); - } - - @SuppressWarnings("unlikely-arg-type") - @Override - public boolean containsKey(final Object key) { - return props.containsKey(key); - } - - @SuppressWarnings("unlikely-arg-type") - @Override - public boolean containsValue(final Object value) { - return props.containsValue(value); - } - - @SuppressWarnings("unlikely-arg-type") - @Override - public String get(final Object key) { - return props.get(key); - } - - @Override - public String put(final String key, final String value) { - return props.put(key, value); - } - - @SuppressWarnings("unlikely-arg-type") - @Override - public String remove(final Object key) { - return props.remove(key); - } - - @Override - public void putAll(final Map<? extends String, ? extends String> m) { - props.putAll(m); - } - - @Override - public void clear() { - props.clear(); - } - - @Override - public Set<String> keySet() { - return props.keySet(); - } - - @Override - public Collection<String> values() { - return props.values(); - } - - @Override - public Set<java.util.Map.Entry<String, String>> entrySet() { - return props.entrySet(); - } - - @Override - public boolean equals(final Object o) { - return props.equals(o); - } - - @Override - public int hashCode() { - return props.hashCode(); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/Block.java b/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/Block.java deleted file mode 100644 index 15f3510..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/Block.java +++ /dev/null @@ -1,88 +0,0 @@ -package bjc.utils.ioutils.blocks; - -/** - * Represents a block of text read in from a source. - * - * @author EVE - * - */ -public class Block { - /** - * The contents of this block. - */ - public final String contents; - - /** - * The line of the source this block started on. - */ - public final int startLine; - - /** - * The line of the source this block ended on. - */ - public final int endLine; - - /** - * The number of this block. - */ - public final int blockNo; - - /** - * Create a new block. - * - * @param blockNo - * The number of this block. - * @param contents - * The contents of this block. - * @param startLine - * The line this block started on. - * @param endLine - * The line this block ended. - */ - public Block(final int blockNo, final String contents, final int startLine, final int endLine) { - this.contents = contents; - this.startLine = startLine; - this.endLine = endLine; - this.blockNo = blockNo; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - - result = prime * result + blockNo; - result = prime * result + (contents == null ? 0 : contents.hashCode()); - result = prime * result + endLine; - result = prime * result + startLine; - - return result; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) return true; - if (obj == null) return false; - if (!(obj instanceof Block)) return false; - - final Block other = (Block) obj; - - if (blockNo != other.blockNo) return false; - - if (contents == null) { - if (other.contents != null) return false; - } else if (!contents.equals(other.contents)) return false; - - if (endLine != other.endLine) return false; - if (startLine != other.startLine) return false; - - return true; - } - - @Override - public String toString() { - String fmt = "Block #%d (from lines %d to %d), length: %d characters"; - - return String.format(fmt, blockNo, startLine, endLine, contents.length()); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/BlockReader.java b/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/BlockReader.java deleted file mode 100644 index 3c695c6..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/BlockReader.java +++ /dev/null @@ -1,73 +0,0 @@ -package bjc.utils.ioutils.blocks; - -import java.io.IOException; -import java.util.Iterator; -import java.util.function.Consumer; - -/** - * A source of blocks of characters, marked with line numbers as to block - * start/block end. - * - * @author bjculkin - * - */ -public interface BlockReader extends AutoCloseable, Iterator<Block> { - /** - * Check if this reader has an available block. - * - * @return Whether or not another block is available. - */ - boolean hasNextBlock(); - - /** - * Get the current block. - * - * @return The current block, or null if there is no current block. - */ - Block getBlock(); - - /** - * Move to the next block. - * - * @return Whether or not the next block was successfully read. - */ - boolean nextBlock(); - - /** - * Retrieve the number of blocks that have been read so far. - * - * @return The number of blocks read so far. - */ - int getBlockCount(); - - @Override - void close() throws IOException; - - /* - * Methods with default impls. - */ - - /** - * Execute an action for each remaining block. - * - * @param action - * The action to execute for each block - */ - default void forEachBlock(final Consumer<Block> action) { - while (hasNext()) { - action.accept(next()); - } - } - - @Override - default boolean hasNext() { - return hasNextBlock(); - } - - @Override - default Block next() { - nextBlock(); - - return getBlock(); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/BlockReaders.java b/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/BlockReaders.java deleted file mode 100644 index 8bbb89c..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/BlockReaders.java +++ /dev/null @@ -1,81 +0,0 @@ -package bjc.utils.ioutils.blocks; - -import java.io.Reader; - -/** - * Utility methods for constructing instances of {@link BlockReader} - * - * @author bjculkin - * - */ -public class BlockReaders { - /** - * Create a new simple block reader that works off a regex. - * - * @param blockDelim - * The regex that separates blocks. - * - * @param source - * The reader to get blocks from. - * - * @return A configured simple reader. - */ - public static SimpleBlockReader simple(final String blockDelim, final Reader source) { - return new SimpleBlockReader(blockDelim, source); - } - - /** - * Create a new pushback block reader. - * - * @param src - * The block reader to read blocks from. - * - * @return A configured pushback reader. - */ - public static PushbackBlockReader pushback(final BlockReader src) { - return new PushbackBlockReader(src); - } - - /** - * Create a new triggered block reader. - * - * @param source - * The block reader to read blocks from. - * - * @param action - * The action to execute before reading a block. - * - * @return A configured triggered block reader. - */ - public static BlockReader trigger(final BlockReader source, final Runnable action) { - return new TriggeredBlockReader(source, action); - } - - /** - * Create a new layered block reader. - * - * @param primary - * The first source to read blocks from. - * - * @param secondary - * The second source to read blocks from. - * - * @return A configured layered block reader. - */ - public static BlockReader layered(final BlockReader primary, final BlockReader secondary) { - return new LayeredBlockReader(primary, secondary); - } - - /** - * Create a new serial block reader. - * - * @param readers - * The readers to pull from, in the order to pull from - * them. - * - * @return A configured serial block reader. - */ - public static BlockReader serial(final BlockReader... readers) { - return new SerialBlockReader(readers); - } -}
\ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/BoundBlockReader.java b/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/BoundBlockReader.java deleted file mode 100644 index b1e82d7..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/BoundBlockReader.java +++ /dev/null @@ -1,61 +0,0 @@ -package bjc.utils.ioutils.blocks; - -import java.io.IOException; - -import java.util.function.BooleanSupplier; -import java.util.function.Supplier; - -public class BoundBlockReader implements BlockReader { - @FunctionalInterface - public interface Closer { - public void close() throws IOException; - } - - private BooleanSupplier checker; - private Supplier<Block> getter; - private Closer closer; - - private Block current; - - private int blockNo; - - public BoundBlockReader(BooleanSupplier blockChecker, Supplier<Block> blockGetter, Closer blockCloser) { - checker = blockChecker; - getter = blockGetter; - closer = blockCloser; - - blockNo = 0; - } - - @Override - public boolean hasNextBlock() { - return checker.getAsBoolean(); - } - - @Override - public Block getBlock() { - return current; - } - - @Override - public boolean nextBlock() { - if(checker.getAsBoolean()) { - current = getter.get(); - blockNo += 1; - - return true; - } - - return false; - } - - @Override - public int getBlockCount() { - return blockNo; - } - - @Override - public void close() throws IOException { - closer.close(); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/FilteredBlockReader.java b/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/FilteredBlockReader.java deleted file mode 100644 index 0b43f7a..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/FilteredBlockReader.java +++ /dev/null @@ -1,97 +0,0 @@ -package bjc.utils.ioutils.blocks; - -import java.io.IOException; - -import java.util.function.Consumer; -import java.util.function.Predicate; - -public class FilteredBlockReader implements BlockReader { - /* - * The source of blocks. - */ - private BlockReader source; - - /* - * The current and next block. - * - * Both have already been checked for the predicate. - */ - private Block current; - private Block pending; - - /* - * Number of blocks that passed the predicate. - */ - private int blockNo; - - /* - * The predicate blocks must pass. - */ - private Predicate<Block> pred; - - /* - * The action to call on failure, if there is one. - */ - private Consumer<Block> failAction; - - public FilteredBlockReader(BlockReader src, Predicate<Block> predic) { - this(src, predic, null); - } - - public FilteredBlockReader(BlockReader src, Predicate<Block> predic, Consumer<Block> failAct) { - source = src; - pred = predic; - failAction = failAct; - - blockNo = 0; - } - - @Override - public boolean hasNextBlock() { - if(pending != null) return true; - - while(source.hasNextBlock()) { - /* - * Only say we have a next block if the next block would - * pass the predicate. - */ - pending = source.next(); - - if(pred.test(pending)) { - blockNo += 1; - return true; - } else { - failAction.accept(pending); - } - } - - return false; - } - - @Override - public Block getBlock() { - return current; - } - - @Override - public boolean nextBlock() { - if(pending != null || hasNextBlock()) { - current = pending; - pending = null; - - return true; - } - - return false; - } - - @Override - public int getBlockCount() { - return blockNo; - } - - @Override - public void close() throws IOException { - source.close(); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/FlatMappedBlockReader.java b/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/FlatMappedBlockReader.java deleted file mode 100644 index f4d8439..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/FlatMappedBlockReader.java +++ /dev/null @@ -1,86 +0,0 @@ -package bjc.utils.ioutils.blocks; - -import java.io.IOException; - -import java.util.Iterator; -import java.util.List; -import java.util.function.Function; -import java.util.function.UnaryOperator; - -/** - * A block reader that supports applying a flatmap operation to blocks. - * - * The use-case in mind for this was tokenizing blocks. - * - * @author Benjamin Culkin - */ -public class FlatMappedBlockReader implements BlockReader { - /* - * The source reader. - */ - private BlockReader reader; - - /* - * The current block, and any blocks pending from the last source block. - */ - private Iterator<Block> pending; - private Block current; - - /* - * The operator to open blocks with. - */ - private Function<Block, List<Block>> transform; - - /* - * The current block number. - */ - private int blockNo; - - public FlatMappedBlockReader(BlockReader source, Function<Block, List<Block>> trans) { - reader = source; - transform = trans; - - blockNo = 0; - } - - @Override - public boolean hasNextBlock() { - return pending.hasNext() || reader.hasNextBlock(); - } - - @Override - public Block getBlock() { - return current; - } - - @Override - public boolean nextBlock() { - /* - * Attempt to get a new pending list if the one we have isn't - * valid. - */ - while(pending == null || !pending.hasNext()) { - if(!reader.hasNext()) return false; - - pending = transform.apply(reader.next()).iterator(); - } - - /* - * Advance the iterator. - */ - current = pending.next(); - blockNo += 1; - - return true; - } - - @Override - public int getBlockCount() { - return blockNo; - } - - @Override - public void close() throws IOException { - reader.close(); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/LayeredBlockReader.java b/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/LayeredBlockReader.java deleted file mode 100644 index 967a1f2..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/LayeredBlockReader.java +++ /dev/null @@ -1,81 +0,0 @@ -package bjc.utils.ioutils.blocks; - -import java.io.IOException; - -/** - * A block reader that supports draining all the blocks from one reading before - * swapping to another. - * - * This is more a 'prioritize blocks from one over the other', than a 'read all - * the blocks from one, then all the blocks from the other'. If you need that, - * look at {@link SerialBlockReader}. - * - * @author bjculkin - * - */ -public class LayeredBlockReader implements BlockReader { - /* - * The readers to drain from. - */ - private final BlockReader first; - private final BlockReader second; - - /* - * The current block number. - */ - private int blockNo; - - /** - * Create a new layered block reader. - * - * @param primary - * The first source to read blocks from. - * - * @param secondary - * The second source to read blocks from. - */ - public LayeredBlockReader(final BlockReader primary, final BlockReader secondary) { - first = primary; - second = secondary; - } - - @Override - public boolean hasNextBlock() { - return first.hasNextBlock() || second.hasNextBlock(); - } - - @Override - public Block getBlock() { - final Block firstBlock = first.getBlock(); - - /* - * Only drain a block from the second reader if none are - * available in the first reader. - */ - return firstBlock == null ? second.getBlock() : firstBlock; - } - - @Override - public boolean nextBlock() { - final boolean gotFirst = first.nextBlock(); - final boolean succ = gotFirst ? gotFirst : second.nextBlock(); - - if (succ) { - blockNo += 1; - } - - return succ; - } - - @Override - public int getBlockCount() { - return blockNo; - } - - @Override - public void close() throws IOException { - second.close(); - - first.close(); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/MappedBlockReader.java b/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/MappedBlockReader.java deleted file mode 100644 index 12fa848..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/MappedBlockReader.java +++ /dev/null @@ -1,54 +0,0 @@ -package bjc.utils.ioutils.blocks; - -import java.io.IOException; - -import java.util.function.UnaryOperator; - -public class MappedBlockReader implements BlockReader { - private BlockReader reader; - - private Block current; - - private UnaryOperator<Block> transform; - - private int blockNo; - - public MappedBlockReader(BlockReader source, UnaryOperator<Block> trans) { - reader = source; - transform = trans; - - blockNo = 0; - } - - @Override - public boolean hasNextBlock() { - return reader.hasNextBlock(); - } - - @Override - public Block getBlock() { - return current; - } - - @Override - public boolean nextBlock() { - if(hasNextBlock()) { - current = transform.apply(reader.next()); - blockNo += 1; - - return true; - } - - return false; - } - - @Override - public int getBlockCount() { - return blockNo; - } - - @Override - public void close() throws IOException { - reader.close(); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/PushbackBlockReader.java b/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/PushbackBlockReader.java deleted file mode 100644 index 0cc9dea..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/PushbackBlockReader.java +++ /dev/null @@ -1,106 +0,0 @@ -package bjc.utils.ioutils.blocks; - -import java.io.IOException; -import java.util.Deque; -import java.util.LinkedList; - -/** - * A block reader that supports pushing blocks onto the input queue so that they - * are provided before blocks read from an input source. - * - * @author bjculkin - * - */ -public class PushbackBlockReader implements BlockReader { - private final BlockReader source; - - /* - * The queue of pushed-back blocks. - */ - private final Deque<Block> waiting; - - private Block curBlock; - - private int blockNo; - - /** - * Create a new pushback block reader. - * - * @param src - * The block reader to use when no blocks are queued. - */ - public PushbackBlockReader(final BlockReader src) { - source = src; - - waiting = new LinkedList<>(); - } - - @Override - public boolean hasNextBlock() { - return !waiting.isEmpty() || source.hasNextBlock(); - } - - @Override - public Block getBlock() { - return curBlock; - } - - @Override - public boolean nextBlock() { - /* - * Drain pushed-back blocks first. - */ - if (!waiting.isEmpty()) { - curBlock = waiting.pop(); - - blockNo += 1; - - return true; - } else { - final boolean succ = source.nextBlock(); - curBlock = source.getBlock(); - - if (succ) { - blockNo += 1; - } - - return succ; - } - } - - @Override - public int getBlockCount() { - return blockNo; - } - - @Override - public void close() throws IOException { - source.close(); - } - - /** - * Insert a block at the back of the queue of pending blocks. - * - * @param blk - * The block to put at the back. - */ - public void addBlock(final Block blk) { - waiting.add(blk); - } - - /** - * Insert a block at the front of the queue of pending blocks. - * - * @param blk - * The block to put at the front. - */ - public void pushBlock(final Block blk) { - waiting.push(blk); - } - - @Override - public String toString() { - return String.format("PushbackBlockReader [waiting=%s, curBlock=%s, blockNo=%s]", waiting, curBlock, - blockNo); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/SerialBlockReader.java b/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/SerialBlockReader.java deleted file mode 100644 index c229da1..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/SerialBlockReader.java +++ /dev/null @@ -1,102 +0,0 @@ -package bjc.utils.ioutils.blocks; - -import java.io.IOException; -import java.util.Deque; - -/** - * Provides a means of concatenating two block readers. - * - * @author bjculkin - * - */ -public class SerialBlockReader implements BlockReader { - private Deque<BlockReader> readerQueue; - - private int blockNo; - - /** - * Create a new serial block reader. - * - * @param readers - * The readers to pull from, in the order to pull from - * them. - */ - public SerialBlockReader(final BlockReader... readers) { - for (final BlockReader reader : readers) { - readerQueue.add(reader); - } - } - - @Override - public boolean hasNextBlock() { - if (readerQueue.isEmpty()) return false; - - /* - * Attempt to get a block from the first reader. - */ - boolean hasBlock = readerQueue.peek().hasNextBlock(); - boolean cont = hasBlock || readerQueue.isEmpty(); - - /* - * Close/dispose of readers until we get an open one. - */ - while (!cont) { - try { - readerQueue.pop().close(); - } catch (final IOException ioex) { - throw new IllegalStateException("Exception thrown by discarded reader", ioex); - } - - hasBlock = readerQueue.peek().hasNextBlock(); - cont = hasBlock || readerQueue.isEmpty(); - } - - return hasBlock; - } - - @Override - public Block getBlock() { - if (readerQueue.isEmpty()) - return null; - else return readerQueue.peek().getBlock(); - } - - @Override - public boolean nextBlock() { - if (readerQueue.isEmpty()) return false; - - boolean gotBlock = readerQueue.peek().nextBlock(); - boolean cont = gotBlock || readerQueue.isEmpty(); - - while (!cont) { - try { - readerQueue.pop().close(); - } catch (final IOException ioex) { - throw new IllegalStateException("Exception thrown by discarded reader", ioex); - } - - gotBlock = readerQueue.peek().nextBlock(); - cont = gotBlock || readerQueue.isEmpty(); - } - - if (cont) { - blockNo += 1; - } - - return cont; - } - - @Override - public int getBlockCount() { - return blockNo; - } - - @Override - public void close() throws IOException { - while (!readerQueue.isEmpty()) { - final BlockReader reader = readerQueue.pop(); - - reader.close(); - } - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/SimpleBlockReader.java b/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/SimpleBlockReader.java deleted file mode 100644 index 734bde8..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/SimpleBlockReader.java +++ /dev/null @@ -1,115 +0,0 @@ -package bjc.utils.ioutils.blocks; - -import java.io.IOException; -import java.io.LineNumberReader; -import java.io.Reader; -import java.util.NoSuchElementException; -import java.util.Scanner; -import java.util.regex.Pattern; - -import bjc.utils.funcutils.StringUtils; -/** - * Simple implementation of {@link BlockReader} - * - * NOTE: The EOF marker is always treated as a delimiter. You are expected to - * handle blocks that may be shorter than you expect. - * - * @author EVE - * - */ -public class SimpleBlockReader implements BlockReader { - /* - * I/O source for blocks. - */ - private final Scanner blockReader; - - /* - * The current block. - */ - private Block currBlock; - - /* - * Info about the current block. - */ - private int blockNo; - private int lineNo; - - /** - * Create a new block reader. - * - * @param blockDelim - * The pattern that separates blocks. Note that the end - * of file is always considered to end a block. - * - * @param source - * The source to read blocks from. - */ - public SimpleBlockReader(final String blockDelim, final Reader source) { - blockReader = new Scanner(source); - - final String pattern = String.format("(?:%s)|\\Z", blockDelim); - final Pattern pt = Pattern.compile(pattern, Pattern.MULTILINE); - - blockReader.useDelimiter(pt); - - lineNo = 1; - } - - @Override - public boolean hasNextBlock() { - return blockReader.hasNext(); - } - - @Override - public Block getBlock() { - return currBlock; - } - - @Override - public boolean nextBlock() { - try { - /* - * Read in a new block, and keep the line numbers sane. - */ - final int blockStartLine = lineNo; - final String blockContents = blockReader.next(); - final int blockEndLine = lineNo + StringUtils.countMatches(blockContents, "\\R"); - - lineNo = blockEndLine; - blockNo += 1; - - currBlock = new Block(blockNo, blockContents, blockStartLine, blockEndLine); - - return true; - } catch (final NoSuchElementException nseex) { - currBlock = null; - - return false; - } - } - - @Override - public int getBlockCount() { - return blockNo; - } - - @Override - public void close() throws IOException { - blockReader.close(); - } - - /** - * Set the delimiter used to separate blocks. - * - * @param delim - * The delimiter used to separate blocks. - */ - public void setDelimiter(final String delim) { - blockReader.useDelimiter(delim); - } - - @Override - public String toString() { - return String.format("SimpleBlockReader [currBlock=%s, blockNo=%s]", currBlock, blockNo); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/ToggledBlockReader.java b/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/ToggledBlockReader.java deleted file mode 100644 index 8f39b8f..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/ToggledBlockReader.java +++ /dev/null @@ -1,63 +0,0 @@ -package bjc.utils.ioutils.blocks; - -import java.io.IOException; - -import bjc.utils.data.BooleanToggle; - -public class ToggledBlockReader implements BlockReader { - private BlockReader leftSource; - private BlockReader rightSource; - - /* - * We choose the left source when this is true. - */ - private BooleanToggle leftToggle; - - private int blockNo; - - public ToggledBlockReader(BlockReader left, BlockReader right) { - leftSource = left; - rightSource = right; - - blockNo = 0; - - leftToggle = new BooleanToggle(); - } - - @Override - public boolean hasNextBlock() { - if(leftToggle.peek()) return leftSource.hasNextBlock(); - else return rightSource.hasNextBlock(); - } - - @Override - public Block getBlock() { - if(leftToggle.peek()) return leftSource.getBlock(); - else return rightSource.getBlock(); - } - - @Override - public boolean nextBlock() { - boolean succ; - - if(leftToggle.get()) { - succ = leftSource.nextBlock(); - } else { - succ = rightSource.nextBlock(); - } - - if(succ) blockNo += 1; - return succ; - } - - @Override - public int getBlockCount() { - return blockNo; - } - - @Override - public void close() throws IOException { - leftSource.close(); - rightSource.close(); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/TriggeredBlockReader.java b/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/TriggeredBlockReader.java deleted file mode 100644 index 3a1e393..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/ioutils/blocks/TriggeredBlockReader.java +++ /dev/null @@ -1,70 +0,0 @@ -package bjc.utils.ioutils.blocks; - -import java.io.IOException; - -/** - * A block reader that fires an action before a block is actually read. - * - * @author bjculkin - * - */ -public class TriggeredBlockReader implements BlockReader { - private final BlockReader source; - - private int blockNo; - - /* - * The action to fire. - */ - private final Runnable action; - - /** - * Create a new triggered reader with the specified source/action. - * - * @param source - * The block reader to read blocks from. - * - * @param action - * The action to execute before reading a block. - */ - public TriggeredBlockReader(final BlockReader source, final Runnable action) { - this.source = source; - this.action = action; - - blockNo = 0; - } - - @Override - public boolean hasNextBlock() { - action.run(); - - return source.hasNextBlock(); - } - - @Override - public Block getBlock() { - return source.getBlock(); - } - - @Override - public boolean nextBlock() { - blockNo += 1; - - return source.nextBlock(); - } - - @Override - public int getBlockCount() { - return blockNo; - } - - @Override - public void close() throws IOException { - source.close(); - } - - @Override - public String toString() { - return String.format("TriggeredBlockReader [source=%s]", source); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/DoubleMatcher.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/DoubleMatcher.java deleted file mode 100644 index a885808..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/DoubleMatcher.java +++ /dev/null @@ -1,46 +0,0 @@ -package bjc.utils.parserutils; - -import static bjc.utils.PropertyDB.applyFormat; -import static bjc.utils.PropertyDB.getRegex; - -import java.util.regex.Pattern; - -/* - * Checks if a string would pass Double.parseDouble. - * - * Uses a regex from the javadoc for Double.valueOf() - */ -class DoubleMatcher { - /* - * Unit pieces. - */ - private static final String rDecDigits = getRegex("fpDigits"); - private static final String rHexDigits = getRegex("fpHexDigits"); - private static final String rExponent = applyFormat("fpExponent", getRegex("fpExponent"), rDecDigits); - - /* - * Decimal floating point numbers. - */ - private static final String rSimpleDec = applyFormat("fpDecimalDecimal", rDecDigits, rExponent); - private static final String rSimpleIntDec = applyFormat("fpDecimalInteger", rDecDigits, rExponent); - - /* - * Hex floating point numbers. - */ - private static final String rHexInt = applyFormat("fpHexInteger", rHexDigits); - private static final String rHexDec = applyFormat("fpHexDecimal", rHexDigits); - private static final String rHexLead = applyFormat("fpHexLeader", rHexInt, rHexDec); - private static final String rHexString = applyFormat("fpHexString", rHexLead, rDecDigits); - - /* - * Floating point components. - */ - private static final String rFPLeader = getRegex("fpLeader"); - private static final String rFPNum = applyFormat("fpNumber", rSimpleIntDec, rSimpleDec, rHexString); - - /* - * Full double. - */ - private static final String rDouble = applyFormat("fpDouble", rFPLeader, rFPNum); - public static final Pattern doubleLiteral = Pattern.compile("\\A" + rDouble + "\\Z"); -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/IPrecedent.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/IPrecedent.java deleted file mode 100644 index aa366cf..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/IPrecedent.java +++ /dev/null @@ -1,28 +0,0 @@ -package bjc.utils.parserutils; - -/** - * Represents something that has a set precedence - * - * @author ben - * - */ -@FunctionalInterface -public interface IPrecedent { - /** - * Create a new object with set precedence - * - * @param precedence - * The precedence of the object to handle - * @return A new object with set precedence - */ - public static IPrecedent newSimplePrecedent(final int precedence) { - return () -> precedence; - } - - /** - * Get the precedence of the attached object - * - * @return The precedence of the attached object - */ - public int getPrecedence(); -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/ParserException.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/ParserException.java deleted file mode 100644 index ae33aba..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/ParserException.java +++ /dev/null @@ -1,36 +0,0 @@ -package bjc.utils.parserutils; - -/** - * General superclass for exceptions thrown during parsing. - * - * @author EVE - * - */ -public class ParserException extends Exception { - /** - * - */ - private static final long serialVersionUID = 631298568113373233L; - - /** - * Create a new exception with the provided message. - * - * @param msg - * The message for the exception. - */ - public ParserException(final String msg) { - super(msg); - } - - /** - * Create a new exception with the provided message and cause. - * - * @param msg - * The message for the exception. - * @param cause - * The cause of the exception. - */ - public ParserException(final String msg, final Exception cause) { - super(msg, cause); - } -}
\ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/ShuntingYard.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/ShuntingYard.java deleted file mode 100644 index a1b5feb..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/ShuntingYard.java +++ /dev/null @@ -1,274 +0,0 @@ -package bjc.utils.parserutils; - -import java.util.Deque; -import java.util.LinkedList; -import java.util.function.Consumer; -import java.util.function.Function; - -import bjc.utils.funcdata.FunctionalList; -import bjc.utils.funcdata.FunctionalMap; -import bjc.utils.funcdata.IList; -import bjc.utils.funcdata.IMap; -import bjc.utils.funcutils.StringUtils; - -/** - * Utility to run the shunting yard algorithm on a bunch of tokens. - * - * @author ben - * - * @param <TokenType> - * The type of tokens being shunted. - */ -public class ShuntingYard<TokenType> { - /** - * A enum representing the fundamental operator types. - * - * @author ben - * - */ - public static enum Operator implements IPrecedent { - /** - * Represents addition. - */ - ADD(1), - /** - * Represents subtraction. - */ - SUBTRACT(2), - - /** - * Represents multiplication. - */ - MULTIPLY(3), - /** - * Represents division. - */ - DIVIDE(4); - - private final int precedence; - - private Operator(final int prec) { - precedence = prec; - } - - @Override - public int getPrecedence() { - return precedence; - } - } - - /* - * Function that shunts tokens. - */ - private final class TokenShunter implements Consumer<String> { - private final IList<TokenType> output; - private final Deque<String> stack; - private final Function<String, TokenType> transformer; - - public TokenShunter(final IList<TokenType> outpt, final Deque<String> stack, - final Function<String, TokenType> transformer) { - this.output = outpt; - this.stack = stack; - this.transformer = transformer; - } - - @Override - public void accept(final String token) { - /* - * Handle operators - */ - if (operators.containsKey(token)) { - /* - * Pop operators while there isn't a higher precedence one - */ - while (!stack.isEmpty() && isHigherPrec(token, stack.peek())) { - output.add(transformer.apply(stack.pop())); - } - - /* - * Put this operator onto the stack - */ - stack.push(token); - } else if (StringUtils.containsOnly(token, "\\(")) { - /* - * Handle groups of parenthesis for multiple nesting levels - */ - stack.push(token); - } else if (StringUtils.containsOnly(token, "\\)")) { - /* - * Handle groups of parenthesis for multiple nesting levels - */ - final String swappedToken = token.replace(')', '('); - - /* - * Remove tokens up to a matching parenthesis - */ - while (!stack.peek().equals(swappedToken)) { - output.add(transformer.apply(stack.pop())); - } - - /* - * Remove the parenthesis - */ - stack.pop(); - } else { - /* - * Just add the transformed token - */ - output.add(transformer.apply(token)); - } - } - } - - /* - * Holds all the shuntable operations. - */ - private IMap<String, IPrecedent> operators; - - /** - * Create a new shunting yard with a default set of operators. - * - * @param configureBasics - * Whether or not basic math operators should be - * provided. - */ - public ShuntingYard(final boolean configureBasics) { - operators = new FunctionalMap<>(); - - /* - * Add basic operators if we're configured to do so - */ - if (configureBasics) { - operators.put("+", Operator.ADD); - operators.put("-", Operator.SUBTRACT); - operators.put("*", Operator.MULTIPLY); - operators.put("/", Operator.DIVIDE); - } - } - - /** - * Add an operator to the list of shuntable operators. - * - * @param operator - * The token representing the operator. - * - * @param precedence - * The precedence of the operator to add. - */ - public void addOp(final String operator, final int precedence) { - /* - * Create the precedence marker - */ - final IPrecedent prec = IPrecedent.newSimplePrecedent(precedence); - - this.addOp(operator, prec); - } - - /** - * Add an operator to the list of shuntable operators. - * - * @param operator - * The token representing the operator. - * - * @param precedence - * The precedence of the operator. - */ - public void addOp(final String operator, final IPrecedent precedence) { - /* - * Complain about trying to add an incorrect operator - */ - if (operator == null) - throw new NullPointerException("Operator must not be null"); - else if (precedence == null) throw new NullPointerException("Precedence must not be null"); - - /* - * Add the operator to the ones we handle - */ - operators.put(operator, precedence); - } - - private boolean isHigherPrec(final String left, final String right) { - /* - * Check if the right operator exists - */ - final boolean exists = operators.containsKey(right); - - /* - * If it doesn't, the left is higher precedence. - */ - if (!exists) return false; - - /* - * Get the precedence of operators - */ - final int rightPrecedence = operators.get(right).getPrecedence(); - final int leftPrecedence = operators.get(left).getPrecedence(); - - /* - * Evaluate what we were asked - */ - return rightPrecedence >= leftPrecedence; - } - - /** - * Transform a string of tokens from infix notation to postfix. - * - * @param input - * The string to transform. - * - * @param transformer - * The function to use to transform strings to tokens. - * - * @return A list of tokens in postfix notation. - */ - public IList<TokenType> postfix(final IList<String> input, final Function<String, TokenType> transformer) { - /* - * Check our input - */ - if (input == null) - throw new NullPointerException("Input must not be null"); - else if (transformer == null) throw new NullPointerException("Transformer must not be null"); - - /* - * Here's what we're handing back - */ - final IList<TokenType> output = new FunctionalList<>(); - - /* - * The stack to put operators on - */ - final Deque<String> stack = new LinkedList<>(); - - /* - * Shunt the tokens - */ - input.forEach(new TokenShunter(output, stack, transformer)); - - /* - * Transform any resulting tokens - */ - stack.forEach(token -> { - output.add(transformer.apply(token)); - }); - - return output; - } - - /** - * Remove an operator from the list of shuntable operators. - * - * @param operator - * The token representing the operator. If null, remove - * all operators. - */ - public void removeOp(final String operator) { - /* - * Check if we want to remove all operators - */ - if (operator == null) { - operators = new FunctionalMap<>(); - } else { - operators.remove(operator); - } - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/StringDescaper.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/StringDescaper.java deleted file mode 100644 index 096656a..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/StringDescaper.java +++ /dev/null @@ -1,242 +0,0 @@ -package bjc.utils.parserutils; - -import java.util.HashMap; -import java.util.Map; -import java.util.function.UnaryOperator; -import java.util.logging.Logger; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.regex.PatternSyntaxException; - -import static java.util.Map.Entry; - -import static bjc.utils.PropertyDB.applyFormat; -import static bjc.utils.PropertyDB.getCompiledRegex; -import static bjc.utils.PropertyDB.getRegex; - -public class StringDescaper { - private Logger LOGGER = Logger.getLogger(StringDescaper.class.getName()); - - /* - * Patterns and pattern parts. - */ - private static String rPossibleEscapeString = getRegex("possibleStringEscape"); - private static Pattern possibleEscapePatt = Pattern.compile(rPossibleEscapeString); - - private static String rShortEscape = getRegex("shortFormStringEscape"); - private static String rOctalEscape = getRegex("octalStringEscape"); - private static String rUnicodeEscape = getRegex("unicodeStringEscape"); - - private String rEscapeString; - private Pattern escapePatt; - - private static String rDoubleQuoteString = applyFormat("doubleQuotes", getRegex("nonStringEscape"), rPossibleEscapeString); - private static Pattern doubleQuotePatt = Pattern.compile(rDoubleQuoteString); - - private static Pattern quotePatt = getCompiledRegex("unescapedQuote"); - - private Map<String, String> literalEscapes; - private Map<Pattern, UnaryOperator<String>> specialEscapes; - - public StringDescaper() { - literalEscapes = new HashMap<>(); - specialEscapes = new HashMap<>(); - - rEscapeString = String.format("\\\\(%1$s|%2$s|%3$s)"); - escapePatt = Pattern.compile(rEscapeString); - } - - public void addLiteralEscape(String escape, String val) { - if(literalEscapes.containsKey(escape)) { - LOGGER.warning(String.format("Shadowing literal escape '%s'\n", escape)); - } - - literalEscapes.put(escape, val); - } - - public void addSpecialEscape(String escape, UnaryOperator<String> val) { - if(specialEscapes.containsKey(escape)) { - LOGGER.warning(String.format("Shadowing special escape '%s'\n", escape)); - } - - /* - * Make sure this special escape is a valid regex. - */ - - Pattern patt = null; - try { - patt = Pattern.compile(escape); - } catch (PatternSyntaxException psex) { - String msg = String.format("Invalid special escape '%s'", escape); - - IllegalArgumentException iaex = new IllegalArgumentException(msg); - iaex.initCause(psex); - - throw psex; - } - - specialEscapes.put(patt, val); - } - - public void compileEscapes() { - StringBuilder work = new StringBuilder(); - - for(String litEscape : literalEscapes.keySet()) { - work.append("|(?:"); - work.append(Pattern.quote(litEscape)); - work.append(")"); - } - - for(Pattern specEscape : specialEscapes.keySet()) { - work.append("|(?:"); - work.append(specEscape.toString()); - work.append(")"); - } - - /* - * Convert user-defined escapes to a regex for matching. - * We don't need a bar before %4 because the string has it. - */ - rEscapeString = String.format("\\(%1$s|%2$s|%3$s%4$s)", rShortEscape, rOctalEscape, rUnicodeEscape, work.toString()); - escapePatt = Pattern.compile(rEscapeString); - } - - /** - * Replace escape characters with their actual equivalents. - * - * @param inp - * The string to replace escape sequences in. - * - * @return The string with escape sequences replaced by their equivalent - * characters. - */ - public String descapeString(final String inp) { - if (inp == null) { - throw new NullPointerException("Input to descapeString must not be null"); - } - - /* - * Prepare the buffer and escape finder. - */ - final StringBuffer work = new StringBuffer(); - final Matcher possibleEscapeFinder = possibleEscapePatt.matcher(inp); - final Matcher escapeFinder = escapePatt.matcher(inp); - - while (possibleEscapeFinder.find()) { - if (!escapeFinder.find()) { - /* - * Found a possible escape that isn't actually an - * escape. - */ - final String msg = String.format("Illegal escape sequence '%s' at position %d of string '%s'", - possibleEscapeFinder.group(), possibleEscapeFinder.start(), inp); - throw new IllegalArgumentException(msg); - } - - final String escapeSeq = escapeFinder.group(); - - /* - * Convert the escape to a string. - */ - String escapeRep = ""; - switch (escapeSeq) { - case "\\b": - escapeRep = "\b"; - break; - case "\\t": - escapeRep = "\t"; - break; - case "\\n": - escapeRep = "\n"; - break; - case "\\f": - escapeRep = "\f"; - break; - case "\\r": - escapeRep = "\r"; - break; - case "\\\"": - escapeRep = "\""; - break; - case "\\'": - escapeRep = "'"; - break; - case "\\\\": - /* - * Skip past the second slash. - */ - possibleEscapeFinder.find(); - escapeRep = "\\"; - break; - default: - if (escapeSeq.startsWith("u")) { - escapeRep = handleUnicodeEscape(escapeSeq.substring(1)); - } else if(escapeSeq.startsWith("O")) { - escapeRep = handleOctalEscape(escapeSeq.substring(1)); - } else if(literalEscapes.containsKey(escapeSeq)) { - escapeRep = literalEscapes.get(escapeSeq); - } else { - for(Entry<Pattern, UnaryOperator<String>> ent : specialEscapes.entrySet()) { - Pattern pat = ent.getKey(); - - Matcher mat = pat.matcher(escapeSeq); - if(mat.matches()) { - escapeRep = ent.getValue().apply(escapeSeq); - break; - } - } - } - } - - escapeFinder.appendReplacement(work, escapeRep); - } - - escapeFinder.appendTail(work); - - return work.toString(); - } - - /* - * Handle a unicode codepoint. - */ - private static String handleUnicodeEscape(final String seq) { - try { - final int codepoint = Integer.parseInt(seq, 16); - - return new String(Character.toChars(codepoint)); - } catch (final IllegalArgumentException iaex) { - final String msg = String.format("'%s' is not a valid Unicode escape sequence'", seq); - - final IllegalArgumentException reiaex = new IllegalArgumentException(msg); - - reiaex.initCause(iaex); - - throw reiaex; - } - } - - /* - * Handle a octal codepoint. - */ - private static String handleOctalEscape(final String seq) { - try { - final int codepoint = Integer.parseInt(seq, 8); - - if (codepoint > 255) { - final String msg = String.format("'%d' is outside the range of octal escapes', codepoint"); - - throw new IllegalArgumentException(msg); - } - - return new String(Character.toChars(codepoint)); - } catch (final IllegalArgumentException iaex) { - final String msg = String.format("'%s' is not a valid octal escape sequence'", seq); - - final IllegalArgumentException reiaex = new IllegalArgumentException(msg); - - reiaex.initCause(iaex); - - throw reiaex; - } - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/TokenTransformer.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/TokenTransformer.java deleted file mode 100644 index 30ccc5a..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/TokenTransformer.java +++ /dev/null @@ -1,131 +0,0 @@ -package bjc.utils.parserutils; - -import java.util.Deque; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Predicate; -import java.util.function.UnaryOperator; - -import bjc.utils.data.IHolder; -import bjc.utils.data.ITree; -import bjc.utils.data.Pair; -import bjc.utils.data.Tree; -import bjc.utils.parserutils.TreeConstructor.ConstructorState; -import bjc.utils.parserutils.TreeConstructor.QueueFlattener; - -/* - * Handle creating ASTs from tokens. - */ -final class TokenTransformer<TokenType> implements Consumer<TokenType> { - /* - * Handle operators - */ - private final class OperatorHandler implements UnaryOperator<ConstructorState<TokenType>> { - private final TokenType element; - - public OperatorHandler(final TokenType element) { - this.element = element; - } - - @Override - public ConstructorState<TokenType> apply(final ConstructorState<TokenType> pair) { - /* - * Replace the current AST with the result of handling an operator - */ - return new ConstructorState<>(pair.bindLeft(queuedASTs -> { - return handleOperator(queuedASTs); - })); - } - - private ConstructorState<TokenType> handleOperator(final Deque<ITree<TokenType>> queuedASTs) { - /* - * The AST we're going to hand back - */ - ITree<TokenType> newAST; - - /* - * Handle special operators - */ - if (isSpecialOperator.test(element)) { - newAST = handleSpecialOperator.apply(element).apply(queuedASTs); - } else { - /* - * Error if we don't have enough for a binary operator - */ - if (queuedASTs.size() < 2) { - final String msg = String.format( - "Attempted to parse binary operator without enough operands\n\tProblem operator is: %s\n\tPossible operand is: %s", - element.toString(), queuedASTs.peek().toString()); - - throw new IllegalStateException(msg); - } - - /* - * Grab the two operands - */ - final ITree<TokenType> right = queuedASTs.pop(); - final ITree<TokenType> left = queuedASTs.pop(); - - /* - * Create a new AST - */ - newAST = new Tree<>(element, left, right); - } - - /* - * Stick it onto the stack - */ - queuedASTs.push(newAST); - - /* - * Hand back the state - */ - return new ConstructorState<>(queuedASTs, newAST); - } - } - - private final IHolder<ConstructorState<TokenType>> initialState; - - private final Predicate<TokenType> operatorPredicate; - - private final Predicate<TokenType> isSpecialOperator; - private final Function<TokenType, QueueFlattener<TokenType>> handleSpecialOperator; - - /* - * Create a new transformer - */ - public TokenTransformer(final IHolder<ConstructorState<TokenType>> initialState, - final Predicate<TokenType> operatorPredicate, final Predicate<TokenType> isSpecialOperator, - final Function<TokenType, QueueFlattener<TokenType>> handleSpecialOperator) { - this.initialState = initialState; - this.operatorPredicate = operatorPredicate; - this.isSpecialOperator = isSpecialOperator; - this.handleSpecialOperator = handleSpecialOperator; - } - - @Override - public void accept(final TokenType element) { - /* - * Handle operators - */ - if (operatorPredicate.test(element)) { - initialState.transform(new OperatorHandler(element)); - } else { - final ITree<TokenType> newAST = new Tree<>(element); - - /* - * Insert the new tree into the AST - */ - initialState.transform(pair -> { - /* - * Transform the pair, ignoring the current AST in favor of the one consisting of the current element - */ - return new ConstructorState<>(pair.bindLeft(queue -> { - queue.push(newAST); - - return new Pair<>(queue, newAST); - })); - }); - } - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/TokenUtils.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/TokenUtils.java deleted file mode 100644 index 67c1e5a..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/TokenUtils.java +++ /dev/null @@ -1,303 +0,0 @@ -package bjc.utils.parserutils; - -import static bjc.utils.PropertyDB.applyFormat; -import static bjc.utils.PropertyDB.getCompiledRegex; -import static bjc.utils.PropertyDB.getRegex; - -import java.util.LinkedList; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import bjc.utils.funcdata.FunctionalList; -import bjc.utils.funcdata.IList; -import bjc.utils.parserutils.splitter.TokenSplitter; - -/** - * Utilities useful for operating on PL tokens. - * - * @author EVE - * - */ -public class TokenUtils { - /** - * Simple implementation of TokenSplitter for removing double-quoted - * strings. - * - * @author EVE - * - */ - public static class StringTokenSplitter implements TokenSplitter { - @Override - public IList<String> split(final String input) { - return new FunctionalList<>(TokenUtils.removeDQuotedStrings(input)); - } - } - - /* - * Patterns and pattern parts. - */ - private static String rPossibleEscapeString = getRegex("possibleStringEscape"); - - private static Pattern possibleEscapePatt = Pattern.compile(rPossibleEscapeString); - - private static String rShortEscape = getRegex("shortFormStringEscape"); - private static String rOctalEscape = getRegex("octalStringEscape"); - private static String rUnicodeEscape = getRegex("unicodeStringEscape"); - - private static String rEscapeString = applyFormat("stringEscape", rShortEscape, rOctalEscape, rUnicodeEscape); - - private static Pattern escapePatt = Pattern.compile(rEscapeString); - - private static String rDoubleQuoteString = applyFormat("doubleQuotes", getRegex("nonStringEscape"), - rPossibleEscapeString); - - private static Pattern doubleQuotePatt = Pattern.compile(rDoubleQuoteString); - - private static Pattern quotePatt = getCompiledRegex("unescapedQuote"); - - private static Pattern intLitPattern = getCompiledRegex("intLiteral"); - - /** - * Remove double quoted strings from a string. - * - * Splits a string around instances of java-style double-quoted strings. - * - * @param inp - * The string to split. - * - * @return An list containing alternating bits of the string and the - * embedded double-quoted strings that separated them. - */ - public static List<String> removeDQuotedStrings(final String inp) { - if (inp == null) throw new NullPointerException("inp must not be null"); - - /* - * What we need for piece-by-piece string building - */ - StringBuffer work = new StringBuffer(); - final List<String> res = new LinkedList<>(); - - /* - * Matcher for proper strings and single quotes. - */ - final Matcher mt = doubleQuotePatt.matcher(inp); - final Matcher corr = quotePatt.matcher(inp); - - if (corr.find() && !corr.find()) { - /* - * There's a unmatched opening quote with no strings. - */ - final String msg = String.format( - "Unclosed string literal '%s'. Opening quote was at position %d", inp, - inp.indexOf("\"")); - - throw new IllegalArgumentException(msg); - } - - while (mt.find()) { - /* - * Remove the string until the quoted string. - */ - mt.appendReplacement(work, ""); - - /* - * Add the string preceding the double-quoted string and - * the double-quoted string to the list. - */ - res.add(work.toString()); - res.add(mt.group(1)); - - /* - * Renew the buffer. - */ - work = new StringBuffer(); - } - - /* - * Grab the remainder of the string. - */ - mt.appendTail(work); - final String tail = work.toString(); - - if (tail.contains("\"")) { - /* - * There's a unmatched opening quote with at least one - * string. - */ - final String msg = String.format( - "Unclosed string literal '%s'. Opening quote was at position %d", inp, - inp.lastIndexOf("\"")); - - throw new IllegalArgumentException(msg); - } - - /* - * Only add an empty tail if the string was empty. - */ - if (!tail.equals("") || res.isEmpty()) { - res.add(tail); - } - - return res; - } - - /** - * Replace escape characters with their actual equivalents. - * - * @param inp - * The string to replace escape sequences in. - * - * @return The string with escape sequences replaced by their equivalent - * characters. - */ - public static String descapeString(final String inp) { - if (inp == null) throw new NullPointerException("inp must not be null"); - - /* - * Prepare the buffer and escape finder. - */ - final StringBuffer work = new StringBuffer(); - final Matcher possibleEscapeFinder = possibleEscapePatt.matcher(inp); - final Matcher escapeFinder = escapePatt.matcher(inp); - - while (possibleEscapeFinder.find()) { - if (!escapeFinder.find()) { - /* - * Found a possible escape that isn't actually an - * escape. - */ - final String msg = String.format("Illegal escape sequence '%s' at position %d", - possibleEscapeFinder.group(), possibleEscapeFinder.start()); - - throw new IllegalArgumentException(msg); - } - - final String escapeSeq = escapeFinder.group(); - - /* - * Convert the escape to a string. - */ - String escapeRep = ""; - switch (escapeSeq) { - case "\\b": - escapeRep = "\b"; - break; - case "\\t": - escapeRep = "\t"; - break; - case "\\n": - escapeRep = "\n"; - break; - case "\\f": - escapeRep = "\f"; - break; - case "\\r": - escapeRep = "\r"; - break; - case "\\\"": - escapeRep = "\""; - break; - case "\\'": - escapeRep = "'"; - break; - case "\\\\": - /* - * Skip past the second slash. - */ - possibleEscapeFinder.find(); - escapeRep = "\\"; - break; - default: - if (escapeSeq.startsWith("u")) { - escapeRep = handleUnicodeEscape(escapeSeq.substring(1)); - } else { - escapeRep = handleOctalEscape(escapeSeq); - } - } - - escapeFinder.appendReplacement(work, escapeRep); - } - - escapeFinder.appendTail(work); - - return work.toString(); - } - - /* - * Handle a unicode codepoint. - */ - private static String handleUnicodeEscape(final String seq) { - try { - final int codepoint = Integer.parseInt(seq, 16); - - return new String(Character.toChars(codepoint)); - } catch (final IllegalArgumentException iaex) { - final String msg = String.format("'%s' is not a valid Unicode escape sequence'", seq); - - final IllegalArgumentException reiaex = new IllegalArgumentException(msg); - - reiaex.initCause(iaex); - - throw reiaex; - } - } - - /* - * Handle a octal codepoint. - */ - private static String handleOctalEscape(final String seq) { - try { - final int codepoint = Integer.parseInt(seq, 8); - - if (codepoint > 255) { - final String msg = String - .format("'%d' is outside the range of octal escapes', codepoint"); - - throw new IllegalArgumentException(msg); - } - - return new String(Character.toChars(codepoint)); - } catch (final IllegalArgumentException iaex) { - final String msg = String.format("'%s' is not a valid octal escape sequence'", seq); - - final IllegalArgumentException reiaex = new IllegalArgumentException(msg); - - reiaex.initCause(iaex); - - throw reiaex; - } - } - - /** - * Check if a given string would be successfully converted to a double - * by {@link Double#parseDouble(String)}. - * - * @param inp - * The string to check. - * @return Whether the string is a valid double or not. - */ - public static boolean isDouble(final String inp) { - return DoubleMatcher.doubleLiteral.matcher(inp).matches(); - } - - /** - * Check if a given string would be successfully converted to a integer - * by {@link Integer#parseInt(String)}. - * - * NOTE: This only checks syntax. Using values out of the range of - * integers will still cause errors. - * - * @param inp - * The input to check. - * @return Whether the string is a valid integer or not. - */ - public static boolean isInt(final String inp) { - try { - Integer.parseInt(inp); - return true; - } catch (NumberFormatException nfex) { - return false; - } - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/TreeConstructor.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/TreeConstructor.java deleted file mode 100644 index 90141ef..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/TreeConstructor.java +++ /dev/null @@ -1,125 +0,0 @@ -package bjc.utils.parserutils; - -import java.util.Deque; -import java.util.LinkedList; -import java.util.function.Function; -import java.util.function.Predicate; - -import bjc.utils.data.IHolder; -import bjc.utils.data.IPair; -import bjc.utils.data.ITree; -import bjc.utils.data.Identity; -import bjc.utils.data.Pair; -import bjc.utils.funcdata.IList; - -/** - * Creates a parse tree from a postfix expression - * - * @author ben - * - */ -public class TreeConstructor { - /** - * Alias interface for special operator types. - * - * @param <TokenType> - * The token type of the tree. - */ - public interface QueueFlattener<TokenType> extends Function<Deque<ITree<TokenType>>, ITree<TokenType>> { - - } - - /* - * Alias for constructor state. - */ - static final class ConstructorState<TokenType> extends Pair<Deque<ITree<TokenType>>, ITree<TokenType>> { - public ConstructorState(final Deque<ITree<TokenType>> left, final ITree<TokenType> right) { - super(left, right); - } - - public ConstructorState(final IPair<Deque<ITree<TokenType>>, ITree<TokenType>> par) { - super(par.getLeft(), par.getRight()); - } - } - - /** - * Construct a tree from a list of tokens in postfix notation - * - * Only binary operators are accepted. - * - * @param <TokenType> - * The elements of the parse tree - * @param tokens - * The list of tokens to build a tree from - * @param isOperator - * The predicate to use to determine if something is a - * operator - * @return A AST from the expression - */ - public static <TokenType> ITree<TokenType> constructTree(final IList<TokenType> tokens, - final Predicate<TokenType> isOperator) { - /* - * Construct a tree with no special operators - */ - return constructTree(tokens, isOperator, op -> false, null); - } - - /** - * Construct a tree from a list of tokens in postfix notation. - * - * Only binary operators are accepted by default. Use the last two - * parameters to handle non-binary operators. - * - * @param <TokenType> - * The elements of the parse tree. - * - * @param tokens - * The list of tokens to build a tree from. - * - * @param isOperator - * The predicate to use to determine if something is a - * operator. - * - * @param isSpecialOperator - * The predicate to use to determine if an operator needs - * special handling. - * - * @param handleSpecialOperator - * The function to use to handle special case operators. - * - * @return A AST from the expression - * - */ - public static <TokenType> ITree<TokenType> constructTree(final IList<TokenType> tokens, - final Predicate<TokenType> isOperator, final Predicate<TokenType> isSpecialOperator, - final Function<TokenType, QueueFlattener<TokenType>> handleSpecialOperator) { - /* - * Make sure our parameters are valid - */ - if (tokens == null) - throw new NullPointerException("Tokens must not be null"); - else if (isOperator == null) - throw new NullPointerException("Operator predicate must not be null"); - else if (isSpecialOperator == null) - throw new NullPointerException("Special operator determiner must not be null"); - - /* - * Here is the state for the tree construction - */ - final IHolder<ConstructorState<TokenType>> initialState = new Identity<>( - new ConstructorState<>(new LinkedList<>(), null)); - - /* - * Transform each of the tokens - */ - tokens.forEach(new TokenTransformer<>(initialState, isOperator, isSpecialOperator, - handleSpecialOperator)); - - /* - * Grab the tree from the state - */ - return initialState.unwrap(pair -> { - return pair.getRight(); - }); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/defines/IteratedDefine.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/defines/IteratedDefine.java deleted file mode 100644 index 552b471..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/defines/IteratedDefine.java +++ /dev/null @@ -1,48 +0,0 @@ -package bjc.utils.parserutils.defines; - -import java.util.Arrays; -import java.util.Iterator; -import java.util.function.UnaryOperator; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import bjc.utils.data.CircularIterator; - -public class IteratedDefine implements UnaryOperator<String> { - private Pattern patt; - - private Iterator<String> repls; - - /** - * Create a new iterated define. - * - * @param pattern - * The pattern to use for matching. - * @param circular - * Whether or not to loop through the list of replacers, or just - * repeat the last one. - * @param replacers - * The set of replacers to use. - */ - public IteratedDefine(Pattern pattern, boolean circular, String... replacers) { - patt = pattern; - - repls = new CircularIterator<>(Arrays.asList(replacers), circular); - } - - @Override - public String apply(String ln) { - Matcher mat = patt.matcher(ln); - StringBuffer sb = new StringBuffer(); - - while(mat.find()) { - String repl = repls.next(); - - mat.appendReplacement(sb, repl); - } - - mat.appendTail(sb); - - return sb.toString(); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/defines/SimpleDefine.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/defines/SimpleDefine.java deleted file mode 100644 index 42866c2..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/defines/SimpleDefine.java +++ /dev/null @@ -1,23 +0,0 @@ -package bjc.utils.parserutils.defines; - -import java.util.function.UnaryOperator; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class SimpleDefine implements UnaryOperator<String> { - private Pattern patt; - private String repl; - - public SimpleDefine(Pattern pattern, String replace) { - patt = pattern; - - repl = replace; - } - - @Override - public String apply(String line) { - Matcher mat = patt.matcher(line); - - return mat.replaceAll(repl); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/delims/DelimiterException.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/delims/DelimiterException.java deleted file mode 100644 index 071afb4..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/delims/DelimiterException.java +++ /dev/null @@ -1,21 +0,0 @@ -package bjc.utils.parserutils.delims; - -/** - * The superclass for exceptions thrown during sequence delimitation. - */ -public class DelimiterException extends RuntimeException { - /** - * - */ - private static final long serialVersionUID = 2079514406049040888L; - - /** - * Create a new generic delimiter exception. - * - * @param res - * The reason for this exception. - */ - public DelimiterException(final String res) { - super(res); - } -}
\ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/delims/DelimiterGroup.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/delims/DelimiterGroup.java deleted file mode 100644 index b1d8597..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/delims/DelimiterGroup.java +++ /dev/null @@ -1,593 +0,0 @@ -package bjc.utils.parserutils.delims; - -import java.util.Arrays; -import java.util.Deque; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.function.BiPredicate; -import java.util.function.Function; - -import bjc.utils.data.IPair; -import bjc.utils.data.ITree; -import bjc.utils.data.Pair; -import bjc.utils.data.Tree; -import bjc.utils.funcdata.FunctionalList; -import bjc.utils.funcdata.IList; - -/** - * Represents a possible delimiter group to match. - * - * @author EVE - * - * @param <T> - * The type of items in the sequence. - */ -public class DelimiterGroup<T> { - /** - * Represents an instance of a delimiter group. - * - * @author EVE - * - */ - public class OpenGroup { - /* - * The contents of this group. - */ - private final Deque<ITree<T>> contents; - - /* - * The contents of the current subgroup. - */ - private IList<ITree<T>> currentGroup; - - /* - * The token that opened the group, and any opening parameters. - */ - private final T opener; - private final T[] params; - - /** - * Create a new instance of a delimiter group. - * - * @param open - * The item that opened this group. - * - * @param parms - * Any parameters from the opener. - */ - public OpenGroup(final T open, final T[] parms) { - opener = open; - params = parms; - - contents = new LinkedList<>(); - - currentGroup = new FunctionalList<>(); - } - - /** - * Add an item to this group instance. - * - * @param itm - * The item to add to this group instance. - */ - public void addItem(final ITree<T> itm) { - currentGroup.add(itm); - } - - /** - * Mark a subgroup. - * - * @param marker - * The item that indicated this subgroup. - * - * @param chars - * The characteristics for building the tree. - */ - public void markSubgroup(final T marker, final SequenceCharacteristics<T> chars) { - /* - * Add all of the contents to the subgroup. - */ - final ITree<T> subgroupContents = new Tree<>(chars.contents); - for (final ITree<T> itm : currentGroup) { - subgroupContents.addChild(itm); - } - - /* - * Handle subordinate sub-groups. - */ - while (!contents.isEmpty()) { - final ITree<T> possibleSubordinate = contents.peek(); - - /* - * Subordinate lower priority subgroups. - */ - if (possibleSubordinate.getHead().equals(chars.subgroup)) { - final T otherMarker = possibleSubordinate.getChild(1).getHead(); - - if (subgroups.get(marker) > subgroups.get(otherMarker)) { - subgroupContents.prependChild(contents.pop()); - } else { - break; - } - } else { - subgroupContents.prependChild(contents.pop()); - } - } - - final Tree<T> subgroup = new Tree<>(chars.subgroup, subgroupContents, new Tree<>(marker)); - - contents.push(subgroup); - - currentGroup = new FunctionalList<>(); - } - - /** - * Convert this group into a tree. - * - * @param closer - * The item that closed this group. - * - * @param chars - * The characteristics for building the tree. - * - * @return This group as a tree. - */ - public ITree<T> toTree(final T closer, final SequenceCharacteristics<T> chars) { - /* - * Mark any implied subgroups. - */ - if (impliedSubgroups.containsKey(closer)) { - markSubgroup(impliedSubgroups.get(closer), chars); - } - - final ITree<T> res = new Tree<>(chars.contents); - - /* - * Add either the contents of the current group, - * or subgroups if they're their. - */ - if (contents.isEmpty()) { - currentGroup.forEach(res::addChild); - } else { - while (!contents.isEmpty()) { - res.prependChild(contents.poll()); - } - - currentGroup.forEach(res::addChild); - } - - return new Tree<>(groupName, new Tree<>(opener), res, new Tree<>(closer)); - } - - @Override - public String toString() { - final StringBuilder builder = new StringBuilder(); - - builder.append("OpenGroup [contents="); - builder.append(contents); - builder.append(", currentGroup="); - builder.append(currentGroup); - builder.append(", opener="); - builder.append(opener); - builder.append("]"); - - return builder.toString(); - } - - /** - * Check if a group is excluded at the top level of this group. - * - * @param groupName - * The group to check. - * - * @return Whether or not the provided group is excluded. - */ - public boolean excludes(final T groupName) { - return topLevelExclusions.contains(groupName); - } - - /** - * Check if the provided delimiter would close this group. - * - * @param del - * The string to check as a closing delimiter. - * - * @return Whether or not the provided delimiter closes this - * group. - */ - public boolean isClosing(final T del) { - if (closingDelimiters.contains(del)) return true; - - for (final BiPredicate<T, T[]> pred : predClosers) { - if (pred.test(del, params)) return true; - } - - return closingDelimiters.contains(del); - } - - /** - * Get the name of the group this is an instance of. - * - * @return The name of the group this is an instance of. - */ - public T getName() { - return groupName; - } - - /** - * Get the groups that aren't allowed at all in this group. - * - * @return The groups that aren't allowed at all in this group. - */ - public Set<T> getNestingExclusions() { - return groupExclusions; - } - - /** - * Get the groups that are allowed to open anywhere inside this - * group. - * - * @return The groups allowed to open anywhere inside this - * group. - */ - public Map<T, T> getNestingOpeners() { - return nestedOpenDelimiters; - } - - /** - * Checks if a given token marks a subgroup. - * - * @param tok - * The token to check. - * - * @return Whether or not the token marks a subgroup. - */ - public boolean marksSubgroup(final T tok) { - return subgroups.containsKey(tok); - } - - /** - * Checks if a given token opens a group. - * - * @param marker - * The token to check. - * - * @return The name of the group T opens, or null if it doesn't - * open one. - */ - public IPair<T, T[]> doesOpen(final T marker) { - if (openDelimiters.containsKey(marker)) return new Pair<>(openDelimiters.get(marker), null); - - for (final Function<T, IPair<T, T[]>> pred : predOpeners) { - final IPair<T, T[]> par = pred.apply(marker); - - if (par.getLeft() != null) return par; - } - - return new Pair<>(null, null); - } - - /** - * Check if this group starts a new nesting scope. - * - * @return Whether this group starts a new nesting scope. - */ - public boolean isForgetful() { - return forgetful; - } - } - - /** - * The name of this delimiter group. - */ - public final T groupName; - - /* - * The delimiters that open groups at the top level of this group. - */ - private final Map<T, T> openDelimiters; - - /* - * The delimiters that open groups inside of this group. - */ - private final Map<T, T> nestedOpenDelimiters; - - /* - * The delimiters that close this group. - */ - private final Set<T> closingDelimiters; - - /* - * The groups that can't occur in the top level of this group. - */ - private final Set<T> topLevelExclusions; - - /* - * The groups that can't occur anywhere inside this group. - */ - private final Set<T> groupExclusions; - - /* - * Mapping from sub-group delimiters, to any sub-groups enclosed in - * them. - */ - private final Map<T, Integer> subgroups; - - /* - * Subgroups implied by a particular closing delimiter - */ - private final Map<T, T> impliedSubgroups; - - /* - * Allows more complex openings - */ - private final List<Function<T, IPair<T, T[]>>> predOpeners; - - /* - * Allow more complex closings - */ - private final List<BiPredicate<T, T[]>> predClosers; - - /* - * Whether or not this group starts a new nesting set. - */ - private boolean forgetful; - - /** - * Create a new empty delimiter group. - * - * @param name - * The name of the delimiter group - */ - public DelimiterGroup(final T name) { - if (name == null) throw new NullPointerException("Group name must not be null"); - - groupName = name; - - openDelimiters = new HashMap<>(); - nestedOpenDelimiters = new HashMap<>(); - - closingDelimiters = new HashSet<>(); - - topLevelExclusions = new HashSet<>(); - groupExclusions = new HashSet<>(); - - subgroups = new HashMap<>(); - impliedSubgroups = new HashMap<>(); - - predOpeners = new LinkedList<>(); - predClosers = new LinkedList<>(); - } - - /** - * Adds one or more delimiters that close this group. - * - * @param closers - * Delimiters that close this group. - */ - @SafeVarargs - public final void addClosing(final T... closers) { - final List<T> closerList = Arrays.asList(closers); - - for (final T closer : closerList) { - if (closer == null) - throw new NullPointerException("Closing delimiter must not be null"); - else if (closer.equals("")) - /* - * We can do this because equals works on - * arbitrary objects, not just those of the same - * type. - */ - throw new IllegalArgumentException("Empty string is not a valid exclusion"); - else { - closingDelimiters.add(closer); - } - } - } - - /** - * Adds one or more groups that cannot occur in the top level of this - * group. - * - * @param exclusions - * The groups forbidden in the top level of this group. - */ - @SafeVarargs - public final void addTopLevelForbid(final T... exclusions) { - for (final T exclusion : exclusions) { - if (exclusion == null) - throw new NullPointerException("Exclusion must not be null"); - else if (exclusion.equals("")) - /* - * We can do this because equals works on - * arbitrary objects, not just those of the same - * type. - */ - throw new IllegalArgumentException("Empty string is not a valid exclusion"); - else { - topLevelExclusions.add(exclusion); - } - } - } - - /** - * Adds one or more groups that cannot occur at all in this group. - * - * @param exclusions - * The groups forbidden inside this group. - */ - @SafeVarargs - public final void addGroupForbid(final T... exclusions) { - for (final T exclusion : exclusions) { - if (exclusion == null) - throw new NullPointerException("Exclusion must not be null"); - else if (exclusion.equals("")) - /* - * We can do this because equals works on - * arbitrary objects, not just those of the same - * type. - */ - throw new IllegalArgumentException("Empty string is not a valid exclusion"); - else { - groupExclusions.add(exclusion); - } - } - } - - /** - * Adds sub-group markers to this group. - * - * @param subgroup - * The token to mark a sub-group. - * - * @param priority - * The priority of this sub-group. - */ - public void addSubgroup(final T subgroup, final int priority) { - if (subgroup == null) throw new NullPointerException("Subgroup marker must not be null"); - - subgroups.put(subgroup, priority); - } - - /** - * Adds a marker that opens a group at the top level of this group. - * - * @param opener - * The marker that opens the group. - * - * @param group - * The group opened by the marker. - */ - public void addOpener(final T opener, final T group) { - if (opener == null) throw new NullPointerException("Opener must not be null"); - else if (group == null) throw new NullPointerException("Group to open must not be null"); - - openDelimiters.put(opener, group); - } - - /** - * Adds a marker that opens a group inside of this group. - * - * @param opener - * The marker that opens the group. - * - * @param group - * The group opened by the marker. - */ - public void addNestedOpener(final T opener, final T group) { - if (opener == null) throw new NullPointerException("Opener must not be null"); - else if (group == null) throw new NullPointerException("Group to open must not be null"); - - nestedOpenDelimiters.put(opener, group); - } - - /** - * Mark a closing delimiter as implying a subgroup. - * - * @param closer - * The closing delimiter. - * - * @param subgroup - * The subgroup to imply. - */ - public void implySubgroup(final T closer, final T subgroup) { - if (closer == null) throw new NullPointerException("Closer must not be null"); - else if (subgroup == null) throw new NullPointerException("Subgroup must not be null"); - else if (!closingDelimiters.contains(closer)) throw new IllegalArgumentException(String.format("No closing delimiter '%s' defined", closer)); - else if (!subgroups.containsKey(subgroup)) throw new IllegalArgumentException(String.format("No subgroup '%s' defined", subgroup)); - - impliedSubgroups.put(closer, subgroup); - } - - @Override - public String toString() { - final StringBuilder builder = new StringBuilder(); - - builder.append("("); - - builder.append("groupName=["); - builder.append(groupName); - builder.append("], "); - - builder.append("closingDelimiters=["); - for (final T closer : closingDelimiters) { - builder.append(closer + ","); - } - builder.deleteCharAt(builder.length() - 1); - builder.append("]"); - - if (topLevelExclusions != null && !topLevelExclusions.isEmpty()) { - builder.append(", "); - builder.append("topLevelExclusions=["); - for (final T exclusion : topLevelExclusions) { - builder.append(exclusion + ","); - } - builder.deleteCharAt(builder.length() - 1); - builder.append("]"); - } - - if (groupExclusions != null && !groupExclusions.isEmpty()) { - builder.append(", "); - builder.append("groupExclusions=["); - for (final T exclusion : groupExclusions) { - builder.append(exclusion + ","); - } - builder.deleteCharAt(builder.length() - 1); - builder.append("]"); - } - - builder.append(" )"); - - return builder.toString(); - } - - /** - * Open an instance of this group. - * - * @param opener - * The item that opened this group. - * - * @param parms - * The parameters that opened this group - * - * @return An opened instance of this group. - */ - public OpenGroup open(final T opener, final T[] parms) { - return new OpenGroup(opener, parms); - } - - /** - * Adds a predicated opener to the top level of this group. - * - * @param pred - * The predicate that defines the opener and its - * parameters. - */ - public void addPredOpener(final Function<T, IPair<T, T[]>> pred) { - predOpeners.add(pred); - } - - /** - * Adds a predicated closer to the top level of this group. - * - * @param pred - * The predicate that defines the closer. - */ - public void addPredCloser(final BiPredicate<T, T[]> pred) { - predClosers.add(pred); - } - - /** - * Set whether or not this group starts a new nesting set. - * - * @param forgetful - * Whether this group starts a new nesting set. - */ - public void setForgetful(final boolean forgetful) { - this.forgetful = forgetful; - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/delims/RegexCloser.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/delims/RegexCloser.java deleted file mode 100644 index 4b29949..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/delims/RegexCloser.java +++ /dev/null @@ -1,33 +0,0 @@ -package bjc.utils.parserutils.delims; - -import java.util.function.BiPredicate; - -/** - * A predicated closer for use with {@link RegexOpener}. - * - * @author bjculkin - * - */ -public class RegexCloser implements BiPredicate<String, String[]> { - private final String rep; - - /** - * Create a new regex closer. - * - * @param closer - * The format string to use for closing. - */ - public RegexCloser(final String closer) { - rep = closer; - } - - @Override - public boolean test(final String closer, final String[] params) { - /* - * Confirm passing an array instead of a single var-arg. - */ - final String work = String.format(rep, (Object[]) params); - - return work.equals(closer); - } -}
\ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/delims/RegexOpener.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/delims/RegexOpener.java deleted file mode 100644 index ee93b73..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/delims/RegexOpener.java +++ /dev/null @@ -1,54 +0,0 @@ -package bjc.utils.parserutils.delims; - -import java.util.function.Function; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import bjc.utils.data.IPair; -import bjc.utils.data.Pair; - -/** - * A predicated opener for use with {@link RegexCloser} - * - * @author bjculkin - * - */ -public class RegexOpener implements Function<String, IPair<String, String[]>> { - private final String name; - - private final Pattern patt; - - /** - * Create a new regex opener. - * - * @param groupName - * The name of the opened group. - * - * @param groupRegex - * The regex that matches the opener. - */ - public RegexOpener(final String groupName, final String groupRegex) { - name = groupName; - - patt = Pattern.compile(groupRegex); - } - - @Override - public IPair<String, String[]> apply(final String str) { - final Matcher m = patt.matcher(str); - - if (m.matches()) { - final int numGroups = m.groupCount(); - - final String[] parms = new String[numGroups + 1]; - - for (int i = 0; i <= numGroups; i++) { - parms[i] = m.group(i); - } - - return new Pair<>(name, parms); - } - - return new Pair<>(null, null); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/delims/SequenceCharacteristics.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/delims/SequenceCharacteristics.java deleted file mode 100644 index 882b4c5..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/delims/SequenceCharacteristics.java +++ /dev/null @@ -1,93 +0,0 @@ -package bjc.utils.parserutils.delims; - -/** - * Marks the parameters for building a sequence tree. - * - * @author EVE - * - * @param <T> - * The type of item in the tree. - */ -public class SequenceCharacteristics<T> { - /** - * The item to mark the root of the tree. - */ - public final T root; - - /** - * The item to mark the contents of a group/subgroup. - */ - - public final T contents; - - /** - * The item to mark a subgroup. - */ - public final T subgroup; - - /** - * Create a new set of parameters for building a tree. - * - * @param root - * The root marker. - * @param contents - * The group/subgroup contents marker. - * @param subgroup - * The subgroup marker. - */ - public SequenceCharacteristics(final T root, final T contents, final T subgroup) { - this.root = root; - this.contents = contents; - this.subgroup = subgroup; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - - result = prime * result + (contents == null ? 0 : contents.hashCode()); - result = prime * result + (root == null ? 0 : root.hashCode()); - result = prime * result + (subgroup == null ? 0 : subgroup.hashCode()); - - return result; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) return true; - if (obj == null) return false; - if (!(obj instanceof SequenceCharacteristics)) return false; - - final SequenceCharacteristics<?> other = (SequenceCharacteristics<?>) obj; - - if (contents == null) { - if (other.contents != null) return false; - } else if (!contents.equals(other.contents)) return false; - - if (root == null) { - if (other.root != null) return false; - } else if (!root.equals(other.root)) return false; - - if (subgroup == null) { - if (other.subgroup != null) return false; - } else if (!subgroup.equals(other.subgroup)) return false; - - return true; - } - - @Override - public String toString() { - final StringBuilder builder = new StringBuilder(); - - builder.append("SequenceCharacteristics [root="); - builder.append(root == null ? "(null)" : root); - builder.append(", contents="); - builder.append(contents == null ? "(null)" : contents); - builder.append(", subgroup="); - builder.append(subgroup == null ? "(null)" : subgroup); - builder.append("]"); - - return builder.toString(); - } -}
\ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/delims/SequenceDelimiter.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/delims/SequenceDelimiter.java deleted file mode 100644 index ccfaffb..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/delims/SequenceDelimiter.java +++ /dev/null @@ -1,371 +0,0 @@ -package bjc.utils.parserutils.delims; - -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; - -import com.google.common.collect.HashMultimap; -import com.google.common.collect.HashMultiset; -import com.google.common.collect.Multimap; -import com.google.common.collect.Multiset; - -import bjc.utils.data.IPair; -import bjc.utils.data.ITree; -import bjc.utils.data.Tree; -import bjc.utils.esodata.PushdownMap; -import bjc.utils.esodata.SimpleStack; -import bjc.utils.esodata.Stack; -import bjc.utils.funcdata.IMap; -import bjc.utils.funcutils.StringUtils; - -/** - * Convert linear sequences into trees that represent group structure. - * - * @author EVE - * - * @param <T> - * The type of items in the sequence. - */ -public class SequenceDelimiter<T> { - /* - * Mapping from group names to actual groups. - */ - private final Map<T, DelimiterGroup<T>> groups; - - /* - * The initial group to start with. - */ - private DelimiterGroup<T> initialGroup; - - /** - * Create a new sequence delimiter. - */ - public SequenceDelimiter() { - groups = new HashMap<>(); - } - - /** - * Convert a linear sequence into a tree that matches the delimiter - * structure. - * - * Essentially, creates a parse tree of the expression against the - * following grammar while obeying the defined grouping rules. - * - * <pre> - * <tree> → (<data> | <subgroup> | <group>)* - * <subgroup> → <tree> <marker> - * <group> → <open> <tree> <close> - * - * <data> → STRING - * <open> → STRING - * <close> → STRING - * <marker> → STRING - * </pre> - * - * @param chars - * The parameters on how to mark certain portions of the - * tree. - * @param seq - * The sequence to delimit. - * - * @return The sequence as a tree that matches its group structure. Each - * node in the tree is either a data node, a subgroup node, or a - * group node. - * - * A data node is a leaf node whose data is the string it - * represents. - * - * A subgroup node is a node with two children, and the name of - * the sub-group as its label. The first child is the contents - * of the sub-group, and the second is the marker that started - * the subgroup. The marker is a leaf node labeled with its - * contents, and the contents contains a recursive tree. - * - * A group node is a node with three children, and the name of - * the group as its label. The first child is the opening - * delimiter, the second is the group contents, and the third is - * the closing delimiter. The delimiters are leaf nodes labeled - * with their contents, while the group node contains a - * recursive tree. - * - * @throws DelimiterException - * Thrown if something went wrong during sequence - * delimitation. - * - */ - public ITree<T> delimitSequence(final SequenceCharacteristics<T> chars, - @SuppressWarnings("unchecked") final T... seq) throws DelimiterException { - if (initialGroup == null) throw new NullPointerException("Initial group must be specified."); - else if (chars == null) throw new NullPointerException("Sequence characteristics must not be null"); - - /* - * The stack of opened and not yet closed groups. - */ - final Stack<DelimiterGroup<T>.OpenGroup> groupStack = new SimpleStack<>(); - - /* - * Open initial group. - */ - groupStack.push(initialGroup.open(chars.root, null)); - - /* - * Groups that aren't allowed to be opened at the moment. - */ - final Stack<Multiset<T>> forbiddenDelimiters = new SimpleStack<>(); - forbiddenDelimiters.push(HashMultiset.create()); - - /* - * Groups that are allowed to be opened at the moment. - */ - final Stack<Multimap<T, T>> allowedDelimiters = new SimpleStack<>(); - allowedDelimiters.push(HashMultimap.create()); - - /* - * Map of who forbid what for debugging purposes. - */ - final IMap<T, T> whoForbid = new PushdownMap<>(); - - /* - * Process each member of the sequence. - */ - for (int i = 0; i < seq.length; i++) { - final T tok = seq[i]; - - /* - * Check if this token could open a group. - */ - final IPair<T, T[]> possibleOpenPar = groupStack.top().doesOpen(tok); - T possibleOpen = possibleOpenPar.getLeft(); - - if (possibleOpen == null) { - /* - * Handle nested openers. - * - * Local openers take priority over nested ones - * if they overlap. - */ - if (allowedDelimiters.top().containsKey(tok)) { - possibleOpen = allowedDelimiters.top().get(tok).iterator().next(); - } - } - - /* - * If we have an opening delimiter, handle it. - */ - if (possibleOpen != null) { - final DelimiterGroup<T> group = groups.get(possibleOpen); - - /* - * Error on groups that can't open in this - * context. - * - * This means groups that can't occur at the - * top-level of this group, as well as nested - * exclusions from all enclosing groups. - */ - if (isForbidden(groupStack, forbiddenDelimiters, possibleOpen)) { - T forbiddenBy; - - if (whoForbid.containsKey(tok)) { - forbiddenBy = whoForbid.get(tok); - } else { - forbiddenBy = groupStack.top().getName(); - } - - final String ctxList = StringUtils.toEnglishList(groupStack.toArray(), "then"); - - final String fmt = "Group '%s' can't be opened in this context. (forbidden by '%s')\nContext Stack: %s"; - - throw new DelimiterException(String.format(fmt, group, forbiddenBy, ctxList)); - } - - /* - * Add an open group. - */ - final DelimiterGroup<T>.OpenGroup open = group.open(tok, possibleOpenPar.getRight()); - groupStack.push(open); - - /* - * Handle 'forgetful' groups that reset nesting - */ - if (open.isForgetful()) { - allowedDelimiters.push(HashMultimap.create()); - forbiddenDelimiters.push(HashMultiset.create()); - } - - /* - * Add the nested opens from this group. - */ - final Multimap<T, T> currentAllowed = allowedDelimiters.top(); - for (final Entry<T, T> opener : open.getNestingOpeners().entrySet()) { - currentAllowed.put(opener.getKey(), opener.getValue()); - } - - /* - * Add the nested exclusions from this group - */ - final Multiset<T> currentForbidden = forbiddenDelimiters.top(); - for (final T exclusion : open.getNestingExclusions()) { - currentForbidden.add(exclusion); - - whoForbid.put(exclusion, possibleOpen); - } - } else if (!groupStack.empty() && groupStack.top().isClosing(tok)) { - /* - * Close the group. - */ - final DelimiterGroup<T>.OpenGroup closed = groupStack.pop(); - - groupStack.top().addItem(closed.toTree(tok, chars)); - - /* - * Remove nested exclusions from this group. - */ - final Multiset<T> currentForbidden = forbiddenDelimiters.top(); - for (final T excludedGroup : closed.getNestingExclusions()) { - currentForbidden.remove(excludedGroup); - - whoForbid.remove(excludedGroup); - } - - /* - * Remove the nested opens from this group. - */ - final Multimap<T, T> currentAllowed = allowedDelimiters.top(); - for (final Entry<T, T> closer : closed.getNestingOpeners().entrySet()) { - currentAllowed.remove(closer.getKey(), closer.getValue()); - } - - /* - * Handle 'forgetful' groups that reset nesting. - */ - if (closed.isForgetful()) { - allowedDelimiters.drop(); - forbiddenDelimiters.drop(); - } - } else if (!groupStack.empty() && groupStack.top().marksSubgroup(tok)) { - /* - * Mark a subgroup. - */ - groupStack.top().markSubgroup(tok, chars); - } else { - /* - * Add an item to the group. - */ - groupStack.top().addItem(new Tree<>(tok)); - } - } - - /* - * Error if not all groups were closed. - */ - if (groupStack.size() > 1) { - final DelimiterGroup<T>.OpenGroup group = groupStack.top(); - - final StringBuilder msgBuilder = new StringBuilder(); - - final String closingDelims = StringUtils.toEnglishList(group.getNestingExclusions().toArray(), - false); - - final String ctxList = StringUtils.toEnglishList(groupStack.toArray(), "then"); - - msgBuilder.append("Unclosed group '"); - msgBuilder.append(group.getName()); - msgBuilder.append("'. Expected one of "); - msgBuilder.append(closingDelims); - msgBuilder.append(" to close it\nOpen groups: "); - msgBuilder.append(ctxList); - - final String fmt = "Unclosed group '%s'. Expected one of %s to close it.\nOpen groups: %n"; - - throw new DelimiterException(String.format(fmt, group.getName(), closingDelims, ctxList)); - } - - return groupStack.pop().toTree(chars.root, chars); - } - - /* - * Check if a group is forbidden to open in a context. - */ - private boolean isForbidden(final Stack<DelimiterGroup<T>.OpenGroup> groupStack, - final Stack<Multiset<T>> forbiddenDelimiters, final T groupName) { - boolean localForbid; - - /* - * Check if a delimiter is locally forbidden. - */ - if (groupStack.empty()) { - localForbid = false; - } else { - localForbid = groupStack.top().excludes(groupName); - } - - return localForbid || forbiddenDelimiters.top().contains(groupName); - } - - /** - * Add a delimiter group. - * - * @param group - * The delimiter group. - */ - public void addGroup(final DelimiterGroup<T> group) { - if (group == null) throw new NullPointerException("Group must not be null"); - - groups.put(group.groupName, group); - } - - /** - * Creates and adds a delimiter group using the provided settings. - * - * @param openers - * The tokens that open this group - * @param groupName - * The name of the group - * @param closers - * The tokens that close this group - */ - public void addGroup(final T[] openers, final T groupName, @SuppressWarnings("unchecked") final T... closers) { - final DelimiterGroup<T> group = new DelimiterGroup<>(groupName); - - group.addClosing(closers); - - addGroup(group); - - for (final T open : openers) { - group.addOpener(open, groupName); - } - } - - @Override - public String toString() { - final StringBuilder builder = new StringBuilder(); - - builder.append("SequenceDelimiter ["); - - if (groups != null) { - builder.append("groups="); - builder.append(groups); - builder.append(","); - } - - if (initialGroup != null) { - builder.append("initialGroup="); - builder.append(initialGroup); - } - - builder.append("]"); - - return builder.toString(); - } - - /** - * Set the initial group of this delimiter. - * - * @param initialGroup - * The initial group of this delimiter. - */ - public void setInitialGroup(final DelimiterGroup<T> initialGroup) { - this.initialGroup = initialGroup; - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/delims/StringDelimiter.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/delims/StringDelimiter.java deleted file mode 100644 index e3eeea5..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/delims/StringDelimiter.java +++ /dev/null @@ -1,31 +0,0 @@ -package bjc.utils.parserutils.delims; - -import bjc.utils.data.ITree; - -/** - * A sequence delimiter specialized for strings. - * - * @author EVE - * - */ -public class StringDelimiter extends SequenceDelimiter<String> { - - /** - * Override of - * {@link SequenceDelimiter#delimitSequence(SequenceCharacteristics, Object...)} - * for ease of use for strings. - * - * @param seq - * The sequence to delimit. - * - * @return The sequence as a tree. - * - * @throws DelimiterException - * if something went wrong with delimiting the sequence. - * - * @see SequenceDelimiter - */ - public ITree<String> delimitSequence(final String... seq) throws DelimiterException { - return super.delimitSequence(new SequenceCharacteristics<>("root", "contents", "subgroup"), seq); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/splitter/ChainTokenSplitter.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/splitter/ChainTokenSplitter.java deleted file mode 100644 index 4736310..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/splitter/ChainTokenSplitter.java +++ /dev/null @@ -1,50 +0,0 @@ -package bjc.utils.parserutils.splitter; - -import bjc.utils.funcdata.FunctionalList; -import bjc.utils.funcdata.IList; - -/** - * A token splitter that chains several other splitters together. - * - * @author EVE - * - */ -public class ChainTokenSplitter implements TokenSplitter { - private final IList<TokenSplitter> spliters; - - /** - * Create a new chain token splitter. - */ - public ChainTokenSplitter() { - spliters = new FunctionalList<>(); - } - - /** - * Append a series of splitters to the chain. - * - * @param splitters - * The splitters to append to the chain. - */ - public void appendSplitters(final TokenSplitter... splitters) { - spliters.addAll(splitters); - } - - /** - * Prepend a series of splitters to the chain. - * - * @param splitters - * The splitters to append to the chain. - */ - public void prependSplitters(final TokenSplitter... splitters) { - spliters.prependAll(splitters); - } - - @Override - public IList<String> split(final String input) { - final IList<String> initList = new FunctionalList<>(input); - - return spliters.reduceAux(initList, (splitter, strangs) -> { - return strangs.flatMap(splitter::split); - }); - } -}
\ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/splitter/ConfigurableTokenSplitter.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/splitter/ConfigurableTokenSplitter.java deleted file mode 100644 index 48ddcb4..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/splitter/ConfigurableTokenSplitter.java +++ /dev/null @@ -1,122 +0,0 @@ -package bjc.utils.parserutils.splitter; - -import static bjc.utils.PropertyDB.applyFormat; - -import java.util.LinkedHashSet; -import java.util.Set; -import java.util.regex.Pattern; - -import bjc.utils.funcdata.IList; - -/** - * Split a string into pieces around a regular expression, and offer an easy way - * to configure the regular expression. - * - * @author EVE - * - */ -public class ConfigurableTokenSplitter extends SimpleTokenSplitter { - private final Set<String> simpleDelimiters; - private final Set<String> multipleDelimiters; - private final Set<String> rRawDelimiters; - - /** - * Create a new token splitter with blank configuration. - * - * @param keepDelims - * Whether or not to keep delimiters. - */ - public ConfigurableTokenSplitter(final boolean keepDelims) { - super(null, keepDelims); - - /* - * Use linked hash-sets to keep items in insertion order. - */ - simpleDelimiters = new LinkedHashSet<>(); - multipleDelimiters = new LinkedHashSet<>(); - rRawDelimiters = new LinkedHashSet<>(); - } - - /** - * Add a set of simple delimiters to this splitter. - * - * Simple delimiters match one occurrence of themselves as literals. - * - * @param simpleDelims - * The simple delimiters to add. - */ - public void addSimpleDelimiters(final String... simpleDelims) { - for (final String simpleDelim : simpleDelims) { - simpleDelimiters.add(simpleDelim); - } - } - - /** - * Add a set of multiple delimiters to this splitter. - * - * Multiple delimiters match one or more occurrences of themselves as - * literals. - * - * @param multiDelims - * The multiple delimiters to add. - */ - public void addMultiDelimiters(final String... multiDelims) { - for (final String multiDelim : multiDelims) { - multipleDelimiters.add(multiDelim); - } - } - - /** - * Add a set of raw delimiters to this splitter. - * - * Raw delimiters match one occurrence of themselves as regular - * expressions. - * - * @param rRawDelims - * The raw delimiters to add. - */ - public void addRawDelimiters(final String... rRawDelims) { - for (final String rRawDelim : rRawDelims) { - rRawDelimiters.add(rRawDelim); - } - } - - /** - * Take the configuration and compile it into a regular expression to - * use when splitting. - */ - public void compile() { - final StringBuilder rPattern = new StringBuilder(); - - for (final String rRawDelimiter : rRawDelimiters) { - rPattern.append(applyFormat("rawDelim", rRawDelimiter)); - } - - for (final String multipleDelimiter : multipleDelimiters) { - rPattern.append(applyFormat("multipleDelim", multipleDelimiter)); - } - - for (final String simpleDelimiter : simpleDelimiters) { - rPattern.append(applyFormat("simpleDelim", simpleDelimiter)); - } - - rPattern.deleteCharAt(rPattern.length() - 1); - - spliter = Pattern.compile(rPattern.toString()); - } - - @Override - public IList<String> split(final String input) { - if (spliter == null) throw new IllegalStateException("Must compile splitter before use"); - - return super.split(input); - } - - @Override - public String toString() { - final String fmt = "ConfigurableTokenSplitter [simpleDelimiters=%s, multipleDelimiters=%s," - + " rRawDelimiters=%s, spliter=%s]"; - - return String.format(fmt, simpleDelimiters, multipleDelimiters, rRawDelimiters, spliter); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/splitter/ExcludingTokenSplitter.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/splitter/ExcludingTokenSplitter.java deleted file mode 100644 index 369e7ae..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/splitter/ExcludingTokenSplitter.java +++ /dev/null @@ -1,71 +0,0 @@ -package bjc.utils.parserutils.splitter; - -import java.util.HashSet; -import java.util.Set; -import java.util.function.Predicate; - -import bjc.utils.funcdata.FunctionalList; -import bjc.utils.funcdata.IList; - -/** - * A token splitter that will not split certain tokens. - * - * @author EVE - * - */ -public class ExcludingTokenSplitter implements TokenSplitter { - private final Set<String> literalExclusions; - - private final IList<Predicate<String>> predExclusions; - - private final TokenSplitter spliter; - - /** - * Create a new excluding token splitter. - * - * @param splitter - * The splitter to apply to non-excluded strings. - */ - public ExcludingTokenSplitter(final TokenSplitter splitter) { - spliter = splitter; - - literalExclusions = new HashSet<>(); - - predExclusions = new FunctionalList<>(); - } - - /** - * Exclude literal strings from splitting. - * - * @param exclusions - * The strings to exclude from splitting. - */ - public final void addLiteralExclusions(final String... exclusions) { - for (final String exclusion : exclusions) { - literalExclusions.add(exclusion); - } - } - - /** - * Exclude all of the strings matching any of the predicates from - * splitting. - * - * @param exclusions - * The predicates to use for exclusions. - */ - @SafeVarargs - public final void addPredicateExclusion(final Predicate<String>... exclusions) { - for (final Predicate<String> exclusion : exclusions) { - predExclusions.add(exclusion); - } - } - - @Override - public IList<String> split(final String input) { - if (literalExclusions.contains(input)) - return new FunctionalList<>(input); - else if (predExclusions.anyMatch(pred -> pred.test(input))) - return new FunctionalList<>(input); - else return spliter.split(input); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/splitter/FilteredTokenSplitter.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/splitter/FilteredTokenSplitter.java deleted file mode 100644 index 5d954e0..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/splitter/FilteredTokenSplitter.java +++ /dev/null @@ -1,37 +0,0 @@ -package bjc.utils.parserutils.splitter; - -import java.util.function.Predicate; - -import bjc.utils.funcdata.IList; - -/** - * A token splitter that removes tokens that match a predicate from the stream - * of tokens. - * - * @author bjculkin - * - */ -public class FilteredTokenSplitter implements TokenSplitter { - private TokenSplitter source; - - private Predicate<String> filter; - - /** - * Create a new filtered token splitter. - * - * @param source - * The splitter to get tokens from. - * - * @param filter - * The filter to pass tokens through. - */ - public FilteredTokenSplitter(TokenSplitter source, Predicate<String> filter) { - this.source = source; - this.filter = filter; - } - - @Override - public IList<String> split(String input) { - return source.split(input).getMatching(filter); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/splitter/SimpleTokenSplitter.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/splitter/SimpleTokenSplitter.java deleted file mode 100644 index c357886..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/splitter/SimpleTokenSplitter.java +++ /dev/null @@ -1,46 +0,0 @@ -package bjc.utils.parserutils.splitter; - -import java.util.regex.Pattern; - -import bjc.utils.funcdata.IList; -import bjc.utils.functypes.ID; -import bjc.utils.ioutils.RegexStringEditor; - -/** - * Splits a string into pieces around a regular expression. - * - * @author EVE - * - */ -public class SimpleTokenSplitter implements TokenSplitter { - protected Pattern spliter; - - private final boolean keepDelim; - - /** - * Create a new simple token splitter. - * - * @param splitter - * The pattern to split around. - * - * @param keepDelims - * Whether or not delimiters should be kept. - */ - public SimpleTokenSplitter(final Pattern splitter, final boolean keepDelims) { - spliter = splitter; - - keepDelim = keepDelims; - } - - @Override - public IList<String> split(final String input) { - if (keepDelim) - return RegexStringEditor.mapOccurances(input, spliter, ID.id(), ID.id()); - else return RegexStringEditor.mapOccurances(input, spliter, ID.id(), strang -> ""); - } - - @Override - public String toString() { - return String.format("SimpleTokenSplitter [spliter=%s, keepDelim=%s]", spliter, keepDelim); - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/splitter/TokenSplitter.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/splitter/TokenSplitter.java deleted file mode 100644 index ddb28a7..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/splitter/TokenSplitter.java +++ /dev/null @@ -1,21 +0,0 @@ -package bjc.utils.parserutils.splitter; - -import bjc.utils.funcdata.IList; - -/** - * Split a string into a list of pieces. - * - * @author EVE - * - */ -public interface TokenSplitter { - /** - * Split a string into a list of pieces. - * - * @param input - * The string to split. - * - * @return The pieces of the string. - */ - public IList<String> split(String input); -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/splitter/TransformTokenSplitter.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/splitter/TransformTokenSplitter.java deleted file mode 100644 index 80490f5..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/splitter/TransformTokenSplitter.java +++ /dev/null @@ -1,38 +0,0 @@ -package bjc.utils.parserutils.splitter; - -import java.util.function.UnaryOperator; - -import bjc.utils.funcdata.IList; - -/** - * A token splitter that performs a transform on the tokens from another - * splitter. - * - * @author bjculkin - * - */ -public class TransformTokenSplitter implements TokenSplitter { - private TokenSplitter source; - - private UnaryOperator<String> transform; - - /** - * Create a new transforming splitter. - * - * @param source - * The splitter to use as a source. - * - * @param transform - * The transform to apply to tokens. - */ - public TransformTokenSplitter(TokenSplitter source, UnaryOperator<String> transform) { - this.source = source; - this.transform = transform; - } - - @Override - public IList<String> split(String input) { - return source.split(input).map(transform); - } - -} diff --git a/BJC-Utils2/src/test/java/bjc/utils/test/parserutils/TokenUtilsTest.java b/BJC-Utils2/src/test/java/bjc/utils/test/parserutils/TokenUtilsTest.java deleted file mode 100644 index 6fba1b2..0000000 --- a/BJC-Utils2/src/test/java/bjc/utils/test/parserutils/TokenUtilsTest.java +++ /dev/null @@ -1,152 +0,0 @@ -package bjc.utils.test.parserutils; - -import static bjc.utils.parserutils.TokenUtils.descapeString; -import static bjc.utils.parserutils.TokenUtils.removeDQuotedStrings; -import static org.hamcrest.CoreMatchers.containsString; -import static org.hamcrest.CoreMatchers.hasItems; -import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; - -import java.util.List; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -/* - * Tests for TokenUtils - */ -public class TokenUtilsTest { - @Rule - public ExpectedException exp = ExpectedException.none(); - - /* - * Test removeDQuoted - */ - - /* - * Check handling of mismatched strings with no matching strings. - */ - @Test - public void testRemoveDQuoted_MismatchedStringNoMatch() throws IllegalArgumentException { - exp.expect(IllegalArgumentException.class); - exp.expectMessage(containsString("Opening quote was at position 0")); - - removeDQuotedStrings("\"hello"); - } - - /* - * Check handling of mismatched strings with a matching string. - */ - @Test - public void testRemoveDQuoted_MismatchedStringMatch() throws IllegalArgumentException { - exp.expect(IllegalArgumentException.class); - exp.expectMessage(containsString("Opening quote was at position 7")); - - removeDQuotedStrings("\"hello\"\""); - } - - /* - * Check handling of strings with a single embedded string. - */ - @Test - public void testRemoveDQuoted_SingleString() { - final List<String> onSingleMatchString = removeDQuotedStrings("hello\"there\""); - - assertThat(onSingleMatchString, hasItems("hello", "\"there\"")); - } - - /* - * Check handling of strings with multiple quoted strings in a row. - */ - @Test - public void testRemoveDQuoted_MultipleSerialString() { - final List<String> onMultipleSerialMatchString = removeDQuotedStrings("\"hello\"\"there\""); - - assertThat(onMultipleSerialMatchString, hasItems("\"hello\"", "\"there\"")); - } - - /* - * Check handling of strings with multiple interleaved strings. - */ - @Test - public void testRemoveDQuoted_MultipleInterleavedString() { - final List<String> onMultipleInterleaveMatchString = removeDQuotedStrings("one\"two\"three\"four\""); - - assertThat(onMultipleInterleaveMatchString, hasItems("one", "\"two\"", "three", "\"four\"")); - } - - /* - * Check handling of strings without embedded strings. - */ - @Test - public void testRemoveDQuote_NoString() { - final List<String> onNonmatchingString = removeDQuotedStrings("hello"); - - assertThat(onNonmatchingString, hasItems("hello")); - } - - /* - * Check handling of empty strings. - */ - @Test - public void testRemoveDQuote_EmptyString() { - final List<String> onEmptyString = removeDQuotedStrings(""); - - assertThat(onEmptyString, hasItems("")); - } - - /* - * Test descapeString - */ - /* - * Check handling of empty strings. - */ - @Test - public void testDescapeString_EmptyString() { - final String onEmptyString = descapeString(""); - - assertThat(onEmptyString, is("")); - } - - /* - * Check handling of strings without escapes - */ - @Test - public void testDescapeString_NonescapeString() { - final String onNonescapeString = descapeString("hello there"); - - assertThat(onNonescapeString, is("hello there")); - } - - /* - * Check handling of strings with single escapes. - */ - @Test - public void testDescapeString_SingleEscapeString() { - final String onSingleEscapeString = descapeString("hello\\tthere"); - - assertThat(onSingleEscapeString, is("hello\tthere")); - } - - /* - * Check handling of strings with multiple escapes. - */ - @Test - public void testDescapeString_MultipleEscapeString() { - final String onMultipleEscapeString = descapeString("hello\\tthere\\tworld"); - - assertThat(onMultipleEscapeString, is("hello\tthere\tworld")); - } - - /* - * Check handling of strings with invalid single escapes. - */ - @Test - public void testDescapeString_InvalidSingleEscapeString() throws IllegalArgumentException { - exp.expect(IllegalArgumentException.class); - exp.expectMessage(containsString("at position 0")); - - descapeString("\\x"); - } -}
\ No newline at end of file |
