From 87ae1dfc8d8cb7b51d7bda4750ce841bbe691cfc Mon Sep 17 00:00:00 2001 From: bculkin2442 Date: Sat, 7 May 2016 12:51:23 -0400 Subject: General changes --- .../java/bjc/utils/cli/GenericCommandMode.java | 8 +- .../utils/components/FileComponentRepository.java | 4 +- .../java/bjc/utils/configuration/ConfigFile.java | 162 --------------------- .../bjc/utils/configuration/Configuration.java | 26 ---- .../java/bjc/utils/configuration/Configurator.java | 44 ------ .../java/bjc/utils/configuration/FieldMarker.java | 25 ---- .../java/bjc/utils/configuration/FieldType.java | 147 ------------------- .../src/main/java/bjc/utils/data/BoundLazy.java | 8 + .../main/java/bjc/utils/data/BoundLazyPair.java | 60 +++++++- .../main/java/bjc/utils/data/BoundListHolder.java | 61 ++++++++ .../java/bjc/utils/data/HalfBoundLazyPair.java | 52 ++++++- .../src/main/java/bjc/utils/data/IHolder.java | 82 +++++++++-- BJC-Utils2/src/main/java/bjc/utils/data/IPair.java | 72 ++++++++- .../src/main/java/bjc/utils/data/Identity.java | 8 + BJC-Utils2/src/main/java/bjc/utils/data/Lazy.java | 9 ++ .../src/main/java/bjc/utils/data/LazyPair.java | 48 +++++- .../src/main/java/bjc/utils/data/ListHolder.java | 79 ++++++++++ .../src/main/java/bjc/utils/data/Option.java | 74 ++++++++++ BJC-Utils2/src/main/java/bjc/utils/data/Pair.java | 16 +- .../src/main/java/bjc/utils/data/WrappedLazy.java | 69 +++++++++ .../main/java/bjc/utils/data/WrappedOption.java | 89 +++++++++++ .../java/bjc/utils/funcdata/IFunctionalList.java | 10 ++ .../main/java/bjc/utils/funcdata/PushdownMap.java | 91 ++++++++++++ .../java/bjc/utils/funcdata/theory/Bifunctor.java | 66 +++++++++ .../java/bjc/utils/funcdata/theory/Functor.java | 39 +++++ .../bjc/utils/funcdata/theory/package-info.java | 7 + .../main/java/bjc/utils/funcutils/StringUtils.java | 10 +- .../main/java/bjc/utils/gui/HolderOutputPanel.java | 27 +++- .../utils/parserutils/StackBasedConfigReader.java | 37 +++++ 29 files changed, 989 insertions(+), 441 deletions(-) delete mode 100644 BJC-Utils2/src/main/java/bjc/utils/configuration/ConfigFile.java delete mode 100644 BJC-Utils2/src/main/java/bjc/utils/configuration/Configuration.java delete mode 100644 BJC-Utils2/src/main/java/bjc/utils/configuration/Configurator.java delete mode 100644 BJC-Utils2/src/main/java/bjc/utils/configuration/FieldMarker.java delete mode 100644 BJC-Utils2/src/main/java/bjc/utils/configuration/FieldType.java create mode 100644 BJC-Utils2/src/main/java/bjc/utils/data/BoundListHolder.java create mode 100644 BJC-Utils2/src/main/java/bjc/utils/data/ListHolder.java create mode 100644 BJC-Utils2/src/main/java/bjc/utils/data/Option.java create mode 100644 BJC-Utils2/src/main/java/bjc/utils/data/WrappedLazy.java create mode 100644 BJC-Utils2/src/main/java/bjc/utils/data/WrappedOption.java create mode 100644 BJC-Utils2/src/main/java/bjc/utils/funcdata/PushdownMap.java create mode 100644 BJC-Utils2/src/main/java/bjc/utils/funcdata/theory/Bifunctor.java create mode 100644 BJC-Utils2/src/main/java/bjc/utils/funcdata/theory/Functor.java create mode 100644 BJC-Utils2/src/main/java/bjc/utils/funcdata/theory/package-info.java create mode 100644 BJC-Utils2/src/main/java/bjc/utils/parserutils/StackBasedConfigReader.java diff --git a/BJC-Utils2/src/main/java/bjc/utils/cli/GenericCommandMode.java b/BJC-Utils2/src/main/java/bjc/utils/cli/GenericCommandMode.java index a9c9054..0007616 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/cli/GenericCommandMode.java +++ b/BJC-Utils2/src/main/java/bjc/utils/cli/GenericCommandMode.java @@ -82,11 +82,11 @@ public class GenericCommandMode implements ICommandMode { } else { ICommand aliasedCommand; if (defaultHandlers.containsKey(commandName)) { - aliasedCommand = - defaultHandlers.get(commandName).createAlias(); + aliasedCommand = defaultHandlers.get(commandName) + .createAlias(); } else { - aliasedCommand = - commandHandlers.get(commandName).createAlias(); + aliasedCommand = commandHandlers.get(commandName) + .createAlias(); } commandHandlers.put(aliasName, aliasedCommand); diff --git a/BJC-Utils2/src/main/java/bjc/utils/components/FileComponentRepository.java b/BJC-Utils2/src/main/java/bjc/utils/components/FileComponentRepository.java index bc1b990..e05afc0 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/components/FileComponentRepository.java +++ b/BJC-Utils2/src/main/java/bjc/utils/components/FileComponentRepository.java @@ -57,7 +57,7 @@ public class FileComponentRepository * The function to use to convert files to components */ public FileComponentRepository(File directory, - Function componentReader) { + Function componentReader) { if (!directory.isDirectory()) { throw new IllegalArgumentException("File " + directory + " is not a directory.\n" @@ -123,7 +123,7 @@ public class FileComponentRepository return "Components read from directory " + sourceDirectory + "."; } - private void loadComponent(Function componentReader, + private void loadComponent(Function componentReader, Path pth) { try { E component = componentReader.apply(pth.toFile()); diff --git a/BJC-Utils2/src/main/java/bjc/utils/configuration/ConfigFile.java b/BJC-Utils2/src/main/java/bjc/utils/configuration/ConfigFile.java deleted file mode 100644 index aa436ee..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/configuration/ConfigFile.java +++ /dev/null @@ -1,162 +0,0 @@ -package bjc.utils.configuration; - -import java.io.InputStream; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; -import java.util.Scanner; - -import javax.lang.model.SourceVersion; - -/** - * A config file with support for categories, comments and other thins - * - * @author ben - * - */ -public class ConfigFile { - /** - * A category in a configuration file - * - * @author ben - * - */ - public static class ConfigCategory { - private Map children; - - /** - * Create a new config category - */ - public ConfigCategory() { - children = new HashMap<>(); - } - - /** - * Add a child category to this category - * - * @param childName - * The name of the child - * @param child - * The child category - */ - public void addChild(String childName, ConfigCategory child) { - children.put(childName, child); - } - } - - private static Map topLevelCategories; - - private static boolean isCommentMarker(String token) { - switch (token) { - case "#": - case "//": - return true; - default: - return false; - } - } - - /** - * Parse the values in a config file from a stream - * - * @param source - * The stream to parse values from - * @return A config file with values parsed from the stream - */ - public static ConfigFile parse(InputStream source) { - Scanner scn = new Scanner(source); - - ConfigFile returnedFile = new ConfigFile(); - - while (scn.hasNextLine()) { - String currentLine = scn.nextLine(); - - // Ignore blank lines - if (currentLine.equals("")) { - continue; - } - - String[] currentTokens = currentLine.split(" "); - - // Ignore lines that start with a comment marker - if (isCommentMarker(currentTokens[0])) { - continue; - } else if (SourceVersion.isName(currentTokens[0]) - && currentTokens[1].equals("{")) { - topLevelCategories.put(currentTokens[0], - parseCategory(currentTokens[0], scn)); - } - } - - scn.close(); - - return returnedFile; - } - - private static ConfigCategory parseCategory( - @SuppressWarnings("unused") String categoryName, - Scanner inputSource) { - ConfigCategory category = new ConfigCategory(); - - String currentLine = inputSource.nextLine(); - - String[] tokens = currentLine.split("\\s+ "); - - // Parse contents of category - while (!tokens[0].equals("}")) { - // Ignore lines starting with comment marker - if (isCommentMarker(tokens[0])) { - continue; - } - - int initialCommandToken = 0; - - // Skip over blank tokens from lots of spacing - for (int i = 0; i < tokens.length; i++) { - String token = tokens[i]; - - if (token.equals("")) { - continue; - } else { - initialCommandToken = i; - break; - } - } - - String[] relevantTokens = Arrays.copyOfRange(tokens, - initialCommandToken, tokens.length); - - // Parse child subcategories - if (SourceVersion.isName(relevantTokens[0]) - && relevantTokens[1].equals("{")) { - parseCategory(relevantTokens[0], inputSource); - } else { - // Parse config fields - parseEntry(category, relevantTokens); - } - currentLine = inputSource.nextLine(); - - tokens = currentLine.split("\\s+ "); - } - - return category; - } - - private static void parseEntry( - @SuppressWarnings("unused") ConfigCategory category, - String[] entryParts) { - String entry = String.join("", entryParts); - - String[] expParts = entry.split("="); - - String[] expSpecifiers = expParts[0].split(":"); - - String expType = expSpecifiers[0]; - @SuppressWarnings("unused") - String expName = expSpecifiers[1]; - - switch (expType) { - - } - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/configuration/Configuration.java b/BJC-Utils2/src/main/java/bjc/utils/configuration/Configuration.java deleted file mode 100644 index 7944c44..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/configuration/Configuration.java +++ /dev/null @@ -1,26 +0,0 @@ -package bjc.utils.configuration; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Annotation that marks a class as having a config file bound to it - * - * For this annotation to be valid to apply to the class, the class must - * meet two qualities - * - * 1. Have a public no-args constructor - * - * 2. Have one or more fields annoted with a {@link FieldMarker} annotation - * - * @author ben - * - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.TYPE) -@Documented -public @interface Configuration { -} \ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/configuration/Configurator.java b/BJC-Utils2/src/main/java/bjc/utils/configuration/Configurator.java deleted file mode 100644 index e116dea..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/configuration/Configurator.java +++ /dev/null @@ -1,44 +0,0 @@ -package bjc.utils.configuration; - -import java.io.InputStream; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; - -/** - * Bind the values in a prepared class to a config file - * - * @author ben - * - */ -public class Configurator { - /** - * Bind the values in a config file to the values in a class, - * substituting default values if none are appropriate - * - * @param - * The type of the object to bind - * @param clasz - * The class of the object to bind - * @param inputSource - * The source to get input from - * @return A instance of the provided class, with values filled in from - * a config file - */ - public static E readConfig(Class clasz, - InputStream inputSource) { - try { - Constructor noArgConstructor = clasz.getConstructor(); - - E backingStore = noArgConstructor.newInstance(); - - return backingStore; - } catch (NoSuchMethodException | SecurityException - | InstantiationException | IllegalAccessException - | IllegalArgumentException | InvocationTargetException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - - return null; - } - } -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/configuration/FieldMarker.java b/BJC-Utils2/src/main/java/bjc/utils/configuration/FieldMarker.java deleted file mode 100644 index 1d59fa3..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/configuration/FieldMarker.java +++ /dev/null @@ -1,25 +0,0 @@ -package bjc.utils.configuration; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Annotation to bind a field to a field in a config file - * - * @author ben - * - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.FIELD) -@Documented -public @interface FieldMarker { - /** - * The type of config field being represented - * - * @return The type of config field being represented - */ - public FieldType value(); -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/configuration/FieldType.java b/BJC-Utils2/src/main/java/bjc/utils/configuration/FieldType.java deleted file mode 100644 index a1545e5..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/configuration/FieldType.java +++ /dev/null @@ -1,147 +0,0 @@ -package bjc.utils.configuration; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Container interface for field type markers - * - * There can't be a String field type, so for fields of a single string, - * use FieldType itself - * - * @author ben - * - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.FIELD) -@Documented -public @interface FieldType { - /** - * Marker to indicate a field as a single boolean flag - * - * @author Benjamin - * - */ - @Retention(RetentionPolicy.RUNTIME) - @Target(ElementType.FIELD) - public @interface Flag { - /** - * The default value of the flag - * - * @return The default value of the flag - */ - boolean value() default false; - } - - /** - * Marker to indicate a fields as an array of boolean flags - * - * @author Benjamin - * - */ - @Retention(RetentionPolicy.RUNTIME) - @Target(ElementType.FIELD) - public @interface Flags { - /** - * The default value of the flags - * - * @return The default value of the flags - */ - boolean[] value() default { false }; - } - - /** - * Marker to indicate a field as a single floating point value - * - * @author Benjamin - * - */ - @Retention(RetentionPolicy.RUNTIME) - @Target(ElementType.FIELD) - public @interface Float { - /** - * The default value of the number - * - * @return The default value of the number - */ - double value() default 0.0; - } - - /** - * Marker to indicate a fields as an array of floating point values - * - * @author Benjamin - * - */ - @Retention(RetentionPolicy.RUNTIME) - @Target(ElementType.FIELD) - public @interface Floats { - /** - * The default value of the numbers - * - * @return The default value of the numbers - */ - double[] value() default { 0.0 }; - } - - /** - * Marker to indicate a field as a single integral value - * - * @author Benjamin - * - */ - @Retention(RetentionPolicy.RUNTIME) - @Target(ElementType.FIELD) - public @interface Integer { - /** - * The default value of the integer - * - * @return The default value of the integer - */ - int value() default 0; - } - - /** - * Marker to indicate a fields as an array of integral values - * - * @author Benjamin - * - */ - @Retention(RetentionPolicy.RUNTIME) - @Target(ElementType.FIELD) - public @interface Integers { - /** - * The default value of the integers - * - * @return The default value of the integers - */ - int[] value() default { 0 }; - } - - /** - * Marker to indicate a fields as an array of strings - * - * @author Benjamin - * - */ - @Retention(RetentionPolicy.RUNTIME) - @Target(ElementType.FIELD) - public @interface Strings { - /** - * The default value of each of the strings - * - * @return The default value of each of the strings - */ - String[] value() default { "" }; - } - - /** - * The default value of the string - * - * @return The default value of the strings - */ - public String value() default ""; -} diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/BoundLazy.java b/BJC-Utils2/src/main/java/bjc/utils/data/BoundLazy.java index ce47eb9..9ab3c05 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/data/BoundLazy.java +++ b/BJC-Utils2/src/main/java/bjc/utils/data/BoundLazy.java @@ -96,4 +96,12 @@ class BoundLazy return boundHolder.unwrap(unwrapper); } + + @Override + public Function> lift( + Function func) { + return (val) -> { + return new Lazy<>(func.apply(val)); + }; + } } \ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/BoundLazyPair.java b/BJC-Utils2/src/main/java/bjc/utils/data/BoundLazyPair.java index a49bb9a..1635e06 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/data/BoundLazyPair.java +++ b/BJC-Utils2/src/main/java/bjc/utils/data/BoundLazyPair.java @@ -90,8 +90,8 @@ class BoundLazyPair } @Override - public MergedType merge( - BiFunction merger) { + public MergedType + merge(BiFunction merger) { if (!pairBound) { boundPair = binder.apply(leftSupplier.get(), rightSupplier.get()); @@ -110,4 +110,60 @@ class BoundLazyPair return "(un-materialized)"; } + + @Override + public IPair + mapLeft(Function mapper) { + Supplier leftSupp = () -> { + if (!pairBound) { + NewLeft leftVal = binder + .apply(leftSupplier.get(), rightSupplier.get()) + .getLeft(); + + return mapper.apply(leftVal); + } + + return mapper.apply(boundPair.getLeft()); + }; + + Supplier rightSupp = () -> { + if (!pairBound) { + return binder + .apply(leftSupplier.get(), rightSupplier.get()) + .getRight(); + } + + return boundPair.getRight(); + }; + + return new LazyPair<>(leftSupp, rightSupp); + } + + @Override + public IPair + mapRight(Function mapper) { + Supplier leftSupp = () -> { + if (!pairBound) { + return binder + .apply(leftSupplier.get(), rightSupplier.get()) + .getLeft(); + } + + return boundPair.getLeft(); + }; + + Supplier rightSupp = () -> { + if (!pairBound) { + NewRight rightVal = binder + .apply(leftSupplier.get(), rightSupplier.get()) + .getRight(); + + return mapper.apply(rightVal); + } + + return mapper.apply(boundPair.getRight()); + }; + + return new LazyPair<>(leftSupp, rightSupp); + } } \ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/BoundListHolder.java b/BJC-Utils2/src/main/java/bjc/utils/data/BoundListHolder.java new file mode 100644 index 0000000..fcb62f6 --- /dev/null +++ b/BJC-Utils2/src/main/java/bjc/utils/data/BoundListHolder.java @@ -0,0 +1,61 @@ +package bjc.utils.data; + +import java.util.function.Function; +import java.util.function.UnaryOperator; + +import bjc.utils.funcdata.IFunctionalList; + +class BoundListHolder implements IHolder { + private IFunctionalList> heldHolders; + + public BoundListHolder( + IFunctionalList> toHold) { + heldHolders = toHold; + } + + @Override + public IHolder bind( + Function> binder) { + IFunctionalList> boundHolders = heldHolders + .map((containedHolder) -> { + return containedHolder.bind(binder); + }); + + return new BoundListHolder<>(boundHolders); + } + + @Override + public IHolder map( + Function mapper) { + IFunctionalList> mappedHolders = heldHolders + .map((containedHolder) -> { + return containedHolder.map(mapper); + }); + + return new BoundListHolder<>(mappedHolders); + } + + @Override + public IHolder transform( + UnaryOperator transformer) { + heldHolders.forEach((containedHolder) -> { + containedHolder.transform(transformer); + }); + + return this; + } + + @Override + public UnwrappedType unwrap( + Function unwrapper) { + return heldHolders.randItem().unwrap(unwrapper); + } + + @Override + public Function> lift( + Function func) { + return (val) -> { + return new ListHolder<>(func.apply(val)); + }; + } +} diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/HalfBoundLazyPair.java b/BJC-Utils2/src/main/java/bjc/utils/data/HalfBoundLazyPair.java index 037dddf..9e26924 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/data/HalfBoundLazyPair.java +++ b/BJC-Utils2/src/main/java/bjc/utils/data/HalfBoundLazyPair.java @@ -80,8 +80,8 @@ class HalfBoundLazyPair } @Override - public MergedType merge( - BiFunction merger) { + public MergedType + merge(BiFunction merger) { if (!pairBound) { boundPair = binder.apply(oldSupplier.get()); @@ -90,4 +90,52 @@ class HalfBoundLazyPair return boundPair.merge(merger); } + + @Override + public IPair + mapLeft(Function mapper) { + Supplier leftSupp = () -> { + if (pairBound) { + return mapper.apply(boundPair.getLeft()); + } + + NewLeft leftVal = binder.apply(oldSupplier.get()).getLeft(); + + return mapper.apply(leftVal); + }; + + Supplier rightSupp = () -> { + if (pairBound) { + return boundPair.getRight(); + } + + return binder.apply(oldSupplier.get()).getRight(); + }; + + return new LazyPair<>(leftSupp, rightSupp); + } + + @Override + public IPair + mapRight(Function mapper) { + Supplier leftSupp = () -> { + if (pairBound) { + return boundPair.getLeft(); + } + + return binder.apply(oldSupplier.get()).getLeft(); + }; + + Supplier rightSupp = () -> { + if (pairBound) { + return mapper.apply(boundPair.getRight()); + } + + NewRight rightVal = binder.apply(oldSupplier.get()).getRight(); + + return mapper.apply(rightVal); + }; + + return new LazyPair<>(leftSupp, rightSupp); + } } \ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/IHolder.java b/BJC-Utils2/src/main/java/bjc/utils/data/IHolder.java index ecf3f14..58ae5db 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/data/IHolder.java +++ b/BJC-Utils2/src/main/java/bjc/utils/data/IHolder.java @@ -4,6 +4,9 @@ import java.util.function.Consumer; import java.util.function.Function; import java.util.function.UnaryOperator; +import bjc.utils.funcdata.FunctionalList; +import bjc.utils.funcdata.theory.Functor; + /** * A holder of a single value. * @@ -12,7 +15,7 @@ import java.util.function.UnaryOperator; * @param * The type of value held */ -public interface IHolder { +public interface IHolder extends Functor { /** * Bind a function across the value in this container * @@ -22,8 +25,8 @@ public interface IHolder { * The function to bind to the value * @return A holder from binding the value */ - public IHolder bind( - Function> binder); + public IHolder + bind(Function> binder); /** * Apply an action to the value @@ -31,7 +34,7 @@ public interface IHolder { * @param action * The action to apply to the value */ - public default void doWith(Consumer action) { + public default void doWith(Consumer action) { transform((value) -> { action.accept(value); @@ -39,13 +42,64 @@ public interface IHolder { }); } + @Override + default + Function, Functor> + fmap(Function func) { + return (argumentFunctor) -> { + if (!(argumentFunctor instanceof IHolder)) { + throw new IllegalArgumentException( + "This functor only supports mapping over instances of IHolder"); + } + + IHolder holder = (IHolder) argumentFunctor; + + return holder.map(func); + }; + } + + @Override + public default ContainedType getValue() { + return unwrap((value) -> value); + } + /** - * Get the value contained in this holder without changing it. + * Lifts a function to bind over this holder * - * @return The value held in this holder + * @param + * The type of the functions return + * @param func + * The function to lift over the holder + * @return The function lifted over the holder */ - public default ContainedType getValue() { - return unwrap((value) -> value); + public Function> + lift(Function func); + + /** + * Make this holder lazy + * + * @return A lazy version of this holder + */ + public default IHolder makeLazy() { + return new WrappedLazy<>(this); + } + + /** + * Make this holder a list + * + * @return A list version of this holder + */ + public default IHolder makeList() { + return new BoundListHolder<>(new FunctionalList<>(this)); + } + + /** + * Make this holder optional + * + * @return An optional version of this holder + */ + public default IHolder makeOptional() { + return new WrappedOption<>(this); } /** @@ -60,8 +114,8 @@ public interface IHolder { * The function to do mapping with * @return A holder with the mapped value */ - public IHolder map( - Function mapper); + public IHolder + map(Function mapper); /** * Replace the held value with a new one @@ -83,8 +137,8 @@ public interface IHolder { * The function to transform the value with * @return The holder itself, for easy chaining */ - public IHolder transform( - UnaryOperator transformer); + public IHolder + transform(UnaryOperator transformer); /** * Unwrap the value contained in this holder so that it is no longer @@ -96,6 +150,6 @@ public interface IHolder { * The function to use to unwrap the value * @return The unwrapped held value */ - public UnwrappedType unwrap( - Function unwrapper); + public UnwrappedType + unwrap(Function 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 index 316074e..707724b 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/data/IPair.java +++ b/BJC-Utils2/src/main/java/bjc/utils/data/IPair.java @@ -4,6 +4,8 @@ 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 * @@ -14,7 +16,8 @@ import java.util.function.Function; * The type of the right side of the pair * */ -public interface IPair { +public interface IPair + extends Bifunctor { /** * Bind a function across the values in this pair * @@ -68,11 +71,45 @@ public interface IPair { }); } + @Override + default + Function, Bifunctor> + fmapLeft(Function func) { + return (argumentPair) -> { + if (!(argumentPair instanceof IPair)) { + throw new IllegalArgumentException( + "This function can only be applied to instances of IPair"); + } + + IPair argPair = (IPair) argumentPair; + + return argPair.mapLeft(func); + }; + } + + @Override + default + Function, Bifunctor> + + fmapRight(Function func) { + return (argumentPair) -> { + if (!(argumentPair instanceof IPair)) { + throw new IllegalArgumentException( + "This function can only be applied to instances of IPair"); + } + + IPair argPair = (IPair) 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); } @@ -82,10 +119,39 @@ public interface IPair { * * @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 + * 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 IPair + mapLeft(Function mapper); + + /** + * Transform the value on the right side of the pair. Doesn't modify + * the pair + * + * @param + * 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 IPair + mapRight(Function mapper); + /** * Merge the two values in this pair into a single value * @@ -95,6 +161,6 @@ public interface IPair { * The function to use for merging * @return The pair, merged into a single value */ - public MergedType merge( - BiFunction merger); + public MergedType + merge(BiFunction merger); } diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/Identity.java b/BJC-Utils2/src/main/java/bjc/utils/data/Identity.java index dcc7bef..f42ceb7 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/data/Identity.java +++ b/BJC-Utils2/src/main/java/bjc/utils/data/Identity.java @@ -112,4 +112,12 @@ public class Identity implements IHolder { Function unwrapper) { return unwrapper.apply(heldValue); } + + @Override + public Function> lift( + Function func) { + return (val) -> { + return new Identity<>(func.apply(val)); + }; + } } \ 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 index 061486e..62b0bb0 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/data/Lazy.java +++ b/BJC-Utils2/src/main/java/bjc/utils/data/Lazy.java @@ -133,4 +133,13 @@ public class Lazy implements IHolder { return unwrapper.apply(heldValue); } + + @Override + public Function> lift( + Function func) { + // TODO Auto-generated method stub + return (val) -> { + return new Lazy<>(func.apply(val)); + }; + } } diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/LazyPair.java b/BJC-Utils2/src/main/java/bjc/utils/data/LazyPair.java index b02d9cb..6f1be10 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/data/LazyPair.java +++ b/BJC-Utils2/src/main/java/bjc/utils/data/LazyPair.java @@ -115,8 +115,8 @@ public class LazyPair } @Override - public MergedType merge( - BiFunction merger) { + public MergedType + merge(BiFunction merger) { if (!leftMaterialized) { leftValue = leftSupplier.get(); @@ -154,4 +154,48 @@ public class LazyPair return sb.toString(); } + + @Override + public IPair + mapLeft(Function mapper) { + Supplier leftSupp = () -> { + if (leftMaterialized) { + return mapper.apply(leftValue); + } + + return mapper.apply(leftSupplier.get()); + }; + + Supplier rightSupp = () -> { + if (rightMaterialized) { + return rightValue; + } + + return rightSupplier.get(); + }; + + return new LazyPair<>(leftSupp, rightSupp); + } + + @Override + public IPair + mapRight(Function mapper) { + Supplier leftSupp = () -> { + if (leftMaterialized) { + return leftValue; + } + + return leftSupplier.get(); + }; + + Supplier rightSupp = () -> { + if (rightMaterialized) { + return mapper.apply(rightValue); + } + + return mapper.apply(rightSupplier.get()); + }; + + return new LazyPair<>(leftSupp, rightSupp); + } } diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/ListHolder.java b/BJC-Utils2/src/main/java/bjc/utils/data/ListHolder.java new file mode 100644 index 0000000..8dc33d3 --- /dev/null +++ b/BJC-Utils2/src/main/java/bjc/utils/data/ListHolder.java @@ -0,0 +1,79 @@ +package bjc.utils.data; + +import java.util.function.Function; +import java.util.function.UnaryOperator; + +import bjc.utils.funcdata.FunctionalList; +import bjc.utils.funcdata.IFunctionalList; + +/** + * A holder that represents a set of non-deterministic computations + * + * @author ben + * + * @param + * The type of contained value + */ +public class ListHolder implements IHolder { + private IFunctionalList heldValues; + + private ListHolder(IFunctionalList toHold) { + heldValues = toHold; + } + + /** + * Create a new list holder + * + * @param values + * The possible values for the computation + */ + @SafeVarargs + public ListHolder(ContainedType... values) { + heldValues = new FunctionalList<>(); + + if (values != null) { + for (ContainedType containedValue : values) { + heldValues.add(containedValue); + } + } + } + + @Override + public IHolder bind( + Function> binder) { + IFunctionalList> boundValues = heldValues + .map(binder); + + return new BoundListHolder<>(boundValues); + } + + @Override + public IHolder map( + Function mapper) { + IFunctionalList mappedValues = heldValues.map(mapper); + + return new ListHolder<>(mappedValues); + } + + @Override + public IHolder transform( + UnaryOperator transformer) { + heldValues = heldValues.map(transformer); + + return this; + } + + @Override + public UnwrappedType unwrap( + Function unwrapper) { + return unwrapper.apply(heldValues.randItem()); + } + + @Override + public Function> lift( + Function func) { + return (val) -> { + return new ListHolder<>(new FunctionalList<>(func.apply(val))); + }; + } +} diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/Option.java b/BJC-Utils2/src/main/java/bjc/utils/data/Option.java new file mode 100644 index 0000000..9f6d448 --- /dev/null +++ b/BJC-Utils2/src/main/java/bjc/utils/data/Option.java @@ -0,0 +1,74 @@ +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 + * The type of the value that may or may not be held + */ +public class Option implements IHolder { + private ContainedType held; + + /** + * Create a new optional, using the given initial value + * + * @param seedValue + * The initial value for the optional + */ + public Option(ContainedType seedValue) { + held = seedValue; + } + + @Override + public IHolder bind( + Function> binder) { + if (held == null) { + return new Option<>(null); + } + + return binder.apply(held); + } + + @Override + public IHolder map( + Function mapper) { + if (held == null) { + return new Option<>(null); + } + + return new Option<>(mapper.apply(held)); + } + + @Override + public IHolder transform( + UnaryOperator transformer) { + if (held != null) { + held = transformer.apply(held); + } + + return this; + } + + @Override + public UnwrappedType unwrap( + Function unwrapper) { + if (held == null) { + return null; + } + + return unwrapper.apply(held); + } + + @Override + public Function> lift( + Function func) { + return (val) -> { + return new Option<>(func.apply(val)); + }; + } +} diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/Pair.java b/BJC-Utils2/src/main/java/bjc/utils/data/Pair.java index 05955b6..0d2c1b0 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/data/Pair.java +++ b/BJC-Utils2/src/main/java/bjc/utils/data/Pair.java @@ -56,8 +56,8 @@ public class Pair } @Override - public MergedType merge( - BiFunction merger) { + public MergedType + merge(BiFunction merger) { return merger.apply(leftValue, rightValue); } @@ -66,4 +66,16 @@ public class Pair return "pair[l=" + leftValue.toString() + ", r=" + rightValue.toString() + "]"; } + + @Override + public IPair + mapLeft(Function mapper) { + return new Pair<>(mapper.apply(leftValue), rightValue); + } + + @Override + public IPair + mapRight(Function mapper) { + return new Pair<>(leftValue, mapper.apply(rightValue)); + } } \ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/WrappedLazy.java b/BJC-Utils2/src/main/java/bjc/utils/data/WrappedLazy.java new file mode 100644 index 0000000..737482c --- /dev/null +++ b/BJC-Utils2/src/main/java/bjc/utils/data/WrappedLazy.java @@ -0,0 +1,69 @@ +package bjc.utils.data; + +import java.util.function.Function; +import java.util.function.UnaryOperator; + +class WrappedLazy implements IHolder { + private IHolder> held; + + // This has an extra parameter, because otherwise it erases to the same + // as the public one + private WrappedLazy(IHolder> wrappedHolder, + @SuppressWarnings("unused") boolean dummy) { + held = wrappedHolder; + } + + public WrappedLazy(IHolder wrappedHolder) { + held = new Lazy<>(wrappedHolder); + } + + @Override + public IHolder bind( + Function> binder) { + IHolder> newHolder = held + .map((containedHolder) -> { + return containedHolder.bind(binder); + }); + + return new WrappedLazy<>(newHolder, false); + } + + @Override + public IHolder map( + Function mapper) { + IHolder> newHolder = held + .map((containedHolder) -> { + return containedHolder.map(mapper); + }); + + return new WrappedLazy<>(newHolder, false); + } + + @Override + public IHolder transform( + UnaryOperator transformer) { + // FIXME this smells bad to me, but I can't figure out how else to + // do it + held.transform((containedHolder) -> { + return containedHolder.transform(transformer); + }); + + return this; + } + + @Override + public UnwrappedType unwrap( + Function unwrapper) { + return held.unwrap((containedHolder) -> { + return containedHolder.unwrap(unwrapper); + }); + } + + @Override + public Function> lift( + Function func) { + return (val) -> { + return new Lazy<>(func.apply(val)); + }; + } +} diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/WrappedOption.java b/BJC-Utils2/src/main/java/bjc/utils/data/WrappedOption.java new file mode 100644 index 0000000..c36cafa --- /dev/null +++ b/BJC-Utils2/src/main/java/bjc/utils/data/WrappedOption.java @@ -0,0 +1,89 @@ +package bjc.utils.data; + +import java.util.function.Function; +import java.util.function.UnaryOperator; + +class WrappedOption implements IHolder { + private IHolder> held; + + private WrappedOption(IHolder> toHold, + @SuppressWarnings("unused") boolean dummy) { + held = toHold; + } + + public WrappedOption(IHolder seedValue) { + held = new Option<>(seedValue); + } + + @Override + public IHolder bind( + Function> binder) { + IHolder> 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 IHolder map( + Function mapper) { + IHolder> 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 transform( + UnaryOperator transformer) { + held.transform((containedHolder) -> { + return containedHolder.transform((containedValue) -> { + if (containedValue == null) { + return null; + } + + return transformer.apply(containedValue); + }); + }); + + return this; + } + + @Override + public UnwrappedType unwrap( + Function unwrapper) { + return held.unwrap((containedHolder) -> { + return containedHolder.unwrap((containedValue) -> { + if (containedValue == null) { + return null; + } + + return unwrapper.apply(containedValue); + }); + }); + } + + @Override + public Function> lift( + Function func) { + return (val) -> { + return new Option<>(func.apply(val)); + }; + } +} diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcdata/IFunctionalList.java b/BJC-Utils2/src/main/java/bjc/utils/funcdata/IFunctionalList.java index 91b2ba3..5327dbe 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/funcdata/IFunctionalList.java +++ b/BJC-Utils2/src/main/java/bjc/utils/funcdata/IFunctionalList.java @@ -245,6 +245,16 @@ public interface IFunctionalList { */ ContainedType randItem(Function rnd); + /** + * 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)); + } + /** * Reduce this list to a single value, using a accumulative approach. * diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcdata/PushdownMap.java b/BJC-Utils2/src/main/java/bjc/utils/funcdata/PushdownMap.java new file mode 100644 index 0000000..cc31923 --- /dev/null +++ b/BJC-Utils2/src/main/java/bjc/utils/funcdata/PushdownMap.java @@ -0,0 +1,91 @@ +package bjc.utils.funcdata; + +import java.util.function.BiConsumer; +import java.util.function.Consumer; +import java.util.function.Function; + +/** + * A map where + * + * @author ben + * + * @param + * @param + */ +public class PushdownMap + implements IFunctionalMap { + + @Override + public boolean containsKey(KeyType key) { + // TODO Auto-generated method stub + return false; + } + + @Override + public IFunctionalMap extend() { + // TODO Auto-generated method stub + return null; + } + + @Override + public void forEach(BiConsumer action) { + // TODO Auto-generated method stub + + } + + @Override + public void forEachKey(Consumer action) { + // TODO Auto-generated method stub + + } + + @Override + public void forEachValue(Consumer action) { + // TODO Auto-generated method stub + + } + + @Override + public ValueType get(KeyType key) { + // TODO Auto-generated method stub + return null; + } + + @Override + public int getSize() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public IFunctionalList keyList() { + // TODO Auto-generated method stub + return null; + } + + @Override + public IFunctionalMap mapValues( + Function transformer) { + // TODO Auto-generated method stub + return null; + } + + @Override + public ValueType put(KeyType key, ValueType val) { + // TODO Auto-generated method stub + return null; + } + + @Override + public ValueType remove(KeyType key) { + // TODO Auto-generated method stub + return null; + } + + @Override + public IFunctionalList valueList() { + // TODO Auto-generated method stub + return null; + } + +} 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 new file mode 100644 index 0000000..3bea135 --- /dev/null +++ b/BJC-Utils2/src/main/java/bjc/utils/funcdata/theory/Bifunctor.java @@ -0,0 +1,66 @@ +package bjc.utils.funcdata.theory; + +import java.util.function.Function; + +/** + * A functor over a pair of heterogenous types + * + * @author ben + * @param + * The type stored on the 'left' of the pair + * @param + * The type stored on the 'right' of the pair + * + */ +public interface Bifunctor { + /** + * Lift a function to operate over the left part of this pair + * + * @param + * The old left type of the pair + * @param + * The old right type of the pair + * @param + * 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 + Function, Bifunctor> + fmapLeft(Function func); + + /** + * Lift a function to operate over the right part of this pair + * + * @param + * The old left type of the pair + * @param + * The old right type of the pair + * @param + * 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 + Function, Bifunctor> + fmapRight(Function 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 new file mode 100644 index 0000000..76f48e2 --- /dev/null +++ b/BJC-Utils2/src/main/java/bjc/utils/funcdata/theory/Functor.java @@ -0,0 +1,39 @@ +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 + * The value inside the functor + */ +public interface Functor { + /** + * 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 + * The argument of the function + * @param + * 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 Function, Functor> fmap( + Function 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/funcdata/theory/package-info.java b/BJC-Utils2/src/main/java/bjc/utils/funcdata/theory/package-info.java new file mode 100644 index 0000000..33c80d6 --- /dev/null +++ b/BJC-Utils2/src/main/java/bjc/utils/funcdata/theory/package-info.java @@ -0,0 +1,7 @@ +/** + * Random functional type things that don't belong elsewhere + * + * @author ben + * + */ +package bjc.utils.funcdata.theory; \ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcutils/StringUtils.java b/BJC-Utils2/src/main/java/bjc/utils/funcutils/StringUtils.java index 2f8aa09..9401b7e 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/funcutils/StringUtils.java +++ b/BJC-Utils2/src/main/java/bjc/utils/funcutils/StringUtils.java @@ -74,8 +74,14 @@ public class StringUtils { } } + /** + * Print out a deque with a special case for easily showing a deque is empty + * @param 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 String printDeque( - Deque queuedTrees) { - return queuedTrees.isEmpty() ? "(none)" : queuedTrees.toString(); + Deque queue) { + return queue.isEmpty() ? "(none)" : queue.toString(); } } diff --git a/BJC-Utils2/src/main/java/bjc/utils/gui/HolderOutputPanel.java b/BJC-Utils2/src/main/java/bjc/utils/gui/HolderOutputPanel.java index 4cbfb61..49c7283 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/gui/HolderOutputPanel.java +++ b/BJC-Utils2/src/main/java/bjc/utils/gui/HolderOutputPanel.java @@ -17,25 +17,31 @@ public class HolderOutputPanel extends JPanel { private static final long serialVersionUID = 166573313903782080L; private Timer updateTimer; private JLabel value; + private int nDelay; + private IHolder val; /** * Create a new display panel, backed by a holder * * @param lab * The label to attach to this field - * @param val + * @param valueHolder * The holder to get the value from * @param nDelay * The delay in ms between value updates */ - public HolderOutputPanel(String lab, IHolder val, int nDelay) { + public HolderOutputPanel(String lab, IHolder valueHolder, + int nDelay) { + this.val = valueHolder; + this.nDelay = nDelay; + setLayout(new HLayout(2)); JLabel label = new JLabel(lab); - value = new JLabel(val.getValue() + " (stopped)"); + value = new JLabel("(stopped)"); updateTimer = new Timer(nDelay, (event) -> { - value.setText(val.getValue()); + value.setText(valueHolder.getValue()); }); add(label); @@ -57,4 +63,17 @@ public class HolderOutputPanel extends JPanel { value.setText(value.getText() + " (stopped)"); } + + /** + * Set this panel back to its initial state + */ + public void reset() { + stopUpdating(); + + value.setText("(stopped)"); + + updateTimer = new Timer(nDelay, (event) -> { + value.setText(val.getValue()); + }); + } } diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/StackBasedConfigReader.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/StackBasedConfigReader.java new file mode 100644 index 0000000..2d15711 --- /dev/null +++ b/BJC-Utils2/src/main/java/bjc/utils/parserutils/StackBasedConfigReader.java @@ -0,0 +1,37 @@ +package bjc.utils.parserutils; + +/** + * This class parses a config file written in RPN and uses it to construct + * data items + * + * @author ben + * + * TODO implement me + */ +public class StackBasedConfigReader { + public static interface IItem { + public ItemType getType(); + } + + /** + * Represents the types of item that can be found on stacks + * + * @author ben + * + */ + public static enum ItemType { + /** + * Represents an integral number + */ + INTEGER, + /** + * Represents a string of characters + */ + STRING, + /** + * Represents an arbitrary object + */ + OBJECT + } + +} -- cgit v1.2.3