diff --git a/Core/src/main/java/org/gusdb/fgputil/IoUtil.java b/Core/src/main/java/org/gusdb/fgputil/IoUtil.java index 3f83d146..e9ef75e1 100644 --- a/Core/src/main/java/org/gusdb/fgputil/IoUtil.java +++ b/Core/src/main/java/org/gusdb/fgputil/IoUtil.java @@ -31,6 +31,7 @@ import java.util.function.Supplier; import org.apache.log4j.Logger; +import org.gusdb.fgputil.collection.AutoCloseableList; public class IoUtil { diff --git a/Core/src/main/java/org/gusdb/fgputil/AutoCloseableList.java b/Core/src/main/java/org/gusdb/fgputil/collection/AutoCloseableList.java similarity index 96% rename from Core/src/main/java/org/gusdb/fgputil/AutoCloseableList.java rename to Core/src/main/java/org/gusdb/fgputil/collection/AutoCloseableList.java index 8b826fe7..8cfda08a 100644 --- a/Core/src/main/java/org/gusdb/fgputil/AutoCloseableList.java +++ b/Core/src/main/java/org/gusdb/fgputil/collection/AutoCloseableList.java @@ -1,4 +1,4 @@ -package org.gusdb.fgputil; +package org.gusdb.fgputil.collection; import java.util.ArrayList; import java.util.Collection; diff --git a/Core/src/main/java/org/gusdb/fgputil/collection/ReadOnlyHashMap.java b/Core/src/main/java/org/gusdb/fgputil/collection/ReadOnlyHashMap.java index 54ece1ea..91c494b6 100644 --- a/Core/src/main/java/org/gusdb/fgputil/collection/ReadOnlyHashMap.java +++ b/Core/src/main/java/org/gusdb/fgputil/collection/ReadOnlyHashMap.java @@ -5,9 +5,10 @@ import java.util.LinkedHashMap; import java.util.Map; import java.util.Map.Entry; -import java.util.Set; -import org.gusdb.fgputil.MapBuilder; +import org.gusdb.fgputil.collection.builder.MapBuilder; + +import java.util.Set; public class ReadOnlyHashMap implements ReadOnlyMap { diff --git a/Core/src/main/java/org/gusdb/fgputil/ListBuilder.java b/Core/src/main/java/org/gusdb/fgputil/collection/builder/ListBuilder.java similarity index 97% rename from Core/src/main/java/org/gusdb/fgputil/ListBuilder.java rename to Core/src/main/java/org/gusdb/fgputil/collection/builder/ListBuilder.java index bf17f083..e6b36439 100644 --- a/Core/src/main/java/org/gusdb/fgputil/ListBuilder.java +++ b/Core/src/main/java/org/gusdb/fgputil/collection/builder/ListBuilder.java @@ -1,4 +1,4 @@ -package org.gusdb.fgputil; +package org.gusdb.fgputil.collection.builder; import java.util.ArrayList; import java.util.Arrays; diff --git a/Core/src/main/java/org/gusdb/fgputil/MapBuilder.java b/Core/src/main/java/org/gusdb/fgputil/collection/builder/MapBuilder.java similarity index 98% rename from Core/src/main/java/org/gusdb/fgputil/MapBuilder.java rename to Core/src/main/java/org/gusdb/fgputil/collection/builder/MapBuilder.java index 6dcd95c4..3e6520ec 100644 --- a/Core/src/main/java/org/gusdb/fgputil/MapBuilder.java +++ b/Core/src/main/java/org/gusdb/fgputil/collection/builder/MapBuilder.java @@ -1,4 +1,4 @@ -package org.gusdb.fgputil; +package org.gusdb.fgputil.collection.builder; import java.util.Collection; import java.util.HashMap; diff --git a/Core/src/main/java/org/gusdb/fgputil/SetBuilder.java b/Core/src/main/java/org/gusdb/fgputil/collection/builder/SetBuilder.java similarity index 96% rename from Core/src/main/java/org/gusdb/fgputil/SetBuilder.java rename to Core/src/main/java/org/gusdb/fgputil/collection/builder/SetBuilder.java index a3d5feb5..7996660f 100644 --- a/Core/src/main/java/org/gusdb/fgputil/SetBuilder.java +++ b/Core/src/main/java/org/gusdb/fgputil/collection/builder/SetBuilder.java @@ -1,4 +1,4 @@ -package org.gusdb.fgputil; +package org.gusdb.fgputil.collection.builder; import java.util.Collection; import java.util.HashSet; diff --git a/Core/src/main/java/org/gusdb/fgputil/functional/ExceptionUtil.java b/Core/src/main/java/org/gusdb/fgputil/functional/ExceptionUtil.java new file mode 100644 index 00000000..7bf6822e --- /dev/null +++ b/Core/src/main/java/org/gusdb/fgputil/functional/ExceptionUtil.java @@ -0,0 +1,317 @@ +package org.gusdb.fgputil.functional; + +import java.util.Optional; +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.function.Supplier; + +import org.gusdb.fgputil.functional.FunctionalInterfaces.BiConsumerWithException; +import org.gusdb.fgputil.functional.FunctionalInterfaces.BiFunctionWithException; +import org.gusdb.fgputil.functional.FunctionalInterfaces.ConsumerWithException; +import org.gusdb.fgputil.functional.FunctionalInterfaces.FunctionWithException; +import org.gusdb.fgputil.functional.FunctionalInterfaces.PredicateWithException; +import org.gusdb.fgputil.functional.FunctionalInterfaces.Procedure; +import org.gusdb.fgputil.functional.FunctionalInterfaces.ProcedureWithException; +import org.gusdb.fgputil.functional.FunctionalInterfaces.Reducer; +import org.gusdb.fgputil.functional.FunctionalInterfaces.ReducerWithException; +import org.gusdb.fgputil.functional.FunctionalInterfaces.SupplierWithException; + +/** + * Provides a set of static exception management functions for wrapping, handling, and + * easing use of exceptions, esp while using functional interfaces that do and do not + * throw exceptions in their APIs. + * + * @author rdoherty + */ +public class ExceptionUtil { + + // static class + private ExceptionUtil(){} + + /** + * Throws an exception supplied by the passed supplier. This allows the following pattern: + *
+   *   return condition ? someValue : doThrow(()-> new SomeException());
+   * 
+ * @param type of return value + * @param type of exception thrown + * @param exceptionSupplier supplier of the exception + * @return nothing + * @throws E exception supplied + */ + public static T doThrow(Supplier exceptionSupplier) throws E { + throw exceptionSupplier.get(); + } + + /** + * Returns the passed argument if it is already a RuntimeException, else + * wraps the argument in a RuntimeException and returns the wrapper. + * + * @param e unknown exception + * @return a runtime exception + */ + public static RuntimeException ensureRuntimeException(Exception e) { + return e instanceof RuntimeException ? (RuntimeException)e : new RuntimeException(e); + } + + /** + * Takes a function that may or may not have checked exceptions and returns a new function that performs + * the same operation but "swallows" any checked exception by wrapping it in a RuntimeException and + * throwing that instead. If calling code wishes to inspect the underlying exception it must catch the + * RuntimeException and use getCause(). + * + * @param f function to wrap + * @return a new function that swallows checked exceptions + */ + public static Function fSwallow(FunctionWithException f) { + return x -> { + try { + return f.apply(x); + } + catch (Exception e) { + throw ensureRuntimeException(e); + } + }; + } + + /** + * Takes a consumer that may or may not have checked exceptions and returns a + * new consumer that performs the same operation but "swallows" any checked + * exception by wrapping it in a RuntimeException and throwing that instead. + * If calling code wishes to inspect the underlying exception it must catch + * the RuntimeException and use getCause(). + * + * @param c + * consumer to wrap + * + * @return a new consumer that swallows checked exceptions + */ + public static Consumer cSwallow(ConsumerWithException c) { + return x -> { + try { + c.accept(x); + } + catch (Exception e) { + throw ensureRuntimeException(e); + } + }; + } + + /** + * Takes a bi-consumer that may or may not have checked exceptions and returns + * a new bi-consumer that performs the same operation but "swallows" any checked + * exception by wrapping it in a RuntimeException and throwing that instead. + * If calling code wishes to inspect the underlying exception it must catch + * the RuntimeException and use getCause(). + * + * @param c + * bi-consumer to wrap + * + * @return a new bi-consumer that swallows checked exceptions + */ + public static BiConsumer c2Swallow(BiConsumerWithException c) { + return (x, y) -> { + try { + c.accept(x, y); + } + catch (Exception e) { + throw ensureRuntimeException(e); + } + }; + } + + /** + * Takes a predicate that may or may not have checked exceptions and returns a + * new predicate that performs the same operation but "swallows" any checked + * exception by wrapping it in a RuntimeException and throwing that instead. + * If calling code wishes to inspect the underlying exception it must catch + * the RuntimeException and use getCause(). + * + * @param f + * predicate to wrap + * + * @return a new predicate that swallows checked exceptions + */ + public static Predicate pSwallow(PredicateWithException f) { + return x -> { + try { + return f.test(x); + } + catch (Exception e) { + throw ensureRuntimeException(e); + } + }; + } + + /** + * Takes a reducer that may or may not have checked exceptions and returns a new reducer that performs + * the same operation but "swallows" any checked exception by wrapping it in a RuntimeException and + * throwing that instead. If calling code wishes to inspect the underlying exception it must catch the + * RuntimeException and use getCause(). + * + * @param r reducer to wrap + * @return a new reducer that swallows checked exceptions + */ + public static Reducer rSwallow(ReducerWithException r) { + return (accumulator, next) -> { + try { + return r.reduce(accumulator, next); + } + catch (Exception e) { + throw ensureRuntimeException(e); + } + }; + } + + /** + * Takes a no-arg function that may or may not have checked exceptions and returns a new no-arg function + * that performs the same operation but "swallows" any checked exception by wrapping it in a + * RuntimeException and throwing that instead. If calling code wishes to inspect the underlying exception + * it must catch the RuntimeException and use getCause(). + * + * @param f function to wrap + * @return a new function that swallows checked exceptions + */ + public static Supplier sSwallow(SupplierWithException f) { + return () -> { + try { + return f.get(); + } + catch (Exception e) { + throw ensureRuntimeException(e); + } + }; + } + + /** + * Takes a 2-arg function that may or may not have checked exceptions and returns a new 2-arg function + * that performs the same operation but "swallows" any checked exception by wrapping it in a + * RuntimeException and throwing that instead. If calling code wishes to inspect the underlying exception + * it must catch the RuntimeException and use getCause(). + * + * @param f function to wrap + * @return a new function that swallows checked exceptions + */ + public static BiFunction f2Swallow(BiFunctionWithException f) { + return (obj1, obj2) -> { + try { + return f.apply(obj1, obj2); + } + catch (Exception e) { + throw ensureRuntimeException(e); + } + }; + } + + /** + * Takes a procedure (no args, no return value) that may or may not have checked exceptions + * and returns a procedure that performs the same operation but "swallows" any checked exception + * by wrapping it in a RuntimeException and throwing that instead. If calling code wishes to + * inspect the underlying exception it must catch the RuntimeException and use getCause(). + * + * @param p procedure to wrap + * @return a new procedure that swallows checked exceptions + */ + public static Procedure pSwallow(ProcedureWithException p) { + return () -> { + try { + p.perform(); + } + catch (Exception e) { + throw ensureRuntimeException(e); + } + }; + } + + /** + * Attempts to retrieve a value from the passed supplier. If an exception occurs, a default value + * is returned and the exception is buried. + * + * @param f supplier function to execute + * @param defaultValue value to return if supplier fails + */ + public static T defaultOnException(SupplierWithException f, T defaultValue) { + try { + return f.get(); + } + catch (Exception e) { + return defaultValue; + } + } + + /** + * Tries to get the next value from the passed supplier. If successful, + * returns an optional containing the supplied value; if not and an exception + * is thrown, returns an empty optional. + * + * @param supplier supplier with exception + * @return optional of supplied value, or empty optional if exception thrown + */ + public static Optional optionalOnException(SupplierWithException supplier) { + try { + return Optional.of(supplier.get()); + } + catch (Exception e) { + return Optional.empty(); + } + } + + /** + * Takes a supplier that may throw an exception, and a mapper from that exception to a desired exception; + * calls the supplier, throwing a mapped exception if something goes wrong. + * + * @param s supplier + * @param exceptionMapper exception mapper + * @return value supplied by supplier if successful + * @throws S mapped exception if supplier is not successful + */ + public static T mapException(SupplierWithException s, Function exceptionMapper) throws S { + try { + return s.get(); + } + catch (Exception e) { + throw exceptionMapper.apply(e); + } + } + + /** + * Takes a procedure that may throw an exception, and a mapper from that exception to a desired exception; + * calls the procedure, throwing a mapped exception if something goes wrong. + * + * @param p procedure + * @param exceptionMapper exception mapper + * @throws S mapped exception if supplier is not successful + */ + public static void mapException(ProcedureWithException f, Function exceptionMapper) throws S { + try { + f.perform(); + } + catch (Exception e) { + throw exceptionMapper.apply(e); + } + } + + /** + * Calls the passed function with the passed value and returns true if no exception is thrown, else false. + * + * @param function function to be called + * @param inputValue value to pass to the function + * @return false if exception thrown, else true + */ + public static boolean executesWithoutException(Function function, T inputValue) { + try { function.apply(inputValue); return true; } catch(Exception e) { return false; } + } + + /** + * Calls the passed supplier and returns true if no exception is thrown, else false. + * + * @param f supplier to be called + * @return false if exception thrown, else true + */ + public static boolean executesWithoutException(SupplierWithException f) { + try { f.get(); return true; } catch(Exception e) { return false; } + } +} diff --git a/Core/src/main/java/org/gusdb/fgputil/functional/FunctionalInterfaces.java b/Core/src/main/java/org/gusdb/fgputil/functional/FunctionalInterfaces.java index a08c1a05..ac56dcc5 100644 --- a/Core/src/main/java/org/gusdb/fgputil/functional/FunctionalInterfaces.java +++ b/Core/src/main/java/org/gusdb/fgputil/functional/FunctionalInterfaces.java @@ -1,7 +1,5 @@ package org.gusdb.fgputil.functional; -import java.util.function.Predicate; - /** * Static class provides basic functional interfaces and true and false predicates * @@ -70,6 +68,27 @@ public interface TriFunction { U apply(R obj1, S obj2, T obj3); } + /** + * Defines a three-argument function that may throw and exception + * + * @param type of first function input + * @param type of second function input + * @param type of third function input + * @param type of function output + */ + @FunctionalInterface + public interface TriFunctionWithException { + /** + * Applies the function to the given input and returns output + * + * @param obj1 input to function + * @param obj2 input to function + * @param obj3 input to function + * @return result of function + */ + U apply(R obj1, S obj2, T obj3) throws Exception; + } + /** * Defines a no-argument function that may throw an exception * @@ -91,6 +110,7 @@ public interface SupplierWithException { * * @param type of object being consumed */ + @FunctionalInterface public interface ConsumerWithException { /** * Consumes an object of type T @@ -107,6 +127,7 @@ public interface ConsumerWithException { * @param type of first object being consumed * @param type of second object being consumed */ + @FunctionalInterface public interface BiConsumerWithException { /** * Consumes objects of type T, S @@ -182,34 +203,11 @@ public interface Procedure { } /** - * Typed predicate that always returns true. - * - * @param type of object being evaluated - */ - public static class TruePredicate implements Predicate { - @Override public boolean test(T obj) { return true; } - } - - /** - * Returns a predicate that tests whether an object is equal to - * the passed object using the object's equal() method. - * - * @param obj object - * @return predicate to test equality to passed object + * Performs a procedure that has no output and does not need parameters that may throw an exception */ - public static Predicate equalTo(final T obj) { - return obj::equals; + @FunctionalInterface + public interface ProcedureWithException { + void perform() throws Exception; } - /** - * Returns a predicate that negates the result of the passed predicate - * for each input (i.e. if the passed predicate's test method returns - * true, the returned predicate returns false, and vice versa). - * - * @param predicate any predicate - * @return predicate that negates results of the passed predicate - */ - public static Predicate negate(final Predicate predicate) { - return candidate -> !predicate.test(candidate); - } } diff --git a/Core/src/main/java/org/gusdb/fgputil/functional/Functions.java b/Core/src/main/java/org/gusdb/fgputil/functional/Functions.java index e81995f8..4ba44524 100644 --- a/Core/src/main/java/org/gusdb/fgputil/functional/Functions.java +++ b/Core/src/main/java/org/gusdb/fgputil/functional/Functions.java @@ -10,33 +10,32 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; -import java.util.Optional; -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.function.Supplier; import java.util.stream.Collector; import java.util.stream.Collectors; -import org.gusdb.fgputil.ListBuilder; -import org.gusdb.fgputil.MapBuilder; import org.gusdb.fgputil.Tuples.TwoTuple; -import org.gusdb.fgputil.functional.FunctionalInterfaces.BiConsumerWithException; -import org.gusdb.fgputil.functional.FunctionalInterfaces.BiFunctionWithException; -import org.gusdb.fgputil.functional.FunctionalInterfaces.ConsumerWithException; -import org.gusdb.fgputil.functional.FunctionalInterfaces.FunctionWithException; -import org.gusdb.fgputil.functional.FunctionalInterfaces.PredicateWithException; +import org.gusdb.fgputil.collection.builder.ListBuilder; +import org.gusdb.fgputil.collection.builder.MapBuilder; import org.gusdb.fgputil.functional.FunctionalInterfaces.Reducer; -import org.gusdb.fgputil.functional.FunctionalInterfaces.ReducerWithException; -import org.gusdb.fgputil.functional.FunctionalInterfaces.SupplierWithException; import org.gusdb.fgputil.functional.FunctionalInterfaces.TriFunction; public class Functions { + // static class private Functions() {} + /** + * Typed predicate that always returns true. + * + * @param type of object being evaluated + */ + public static Predicate alwaysTrue() { + return x -> true; + } + /** * Returns a copy (a new HashMap) of the input map with entries trimmed out whose keys do not pass the * passed predicate @@ -254,170 +253,6 @@ public static Map transformValues(Map map, Function trans return newMap; } - /** - * Takes a function that may or may not have checked exceptions and returns a new function that performs - * the same operation but "swallows" any checked exception by wrapping it in a RuntimeException and - * throwing that instead. If calling code wishes to inspect the underlying exception it must catch the - * RuntimeException and use getCause(). - * - * @param f function to wrap - * @return a new function that swallows checked exceptions - */ - public static Function fSwallow(FunctionWithException f) { - return x -> { - try { - return f.apply(x); - } - catch (Exception e) { - throw (e instanceof RuntimeException ? (RuntimeException)e : new RuntimeException(e)); - } - }; - } - - /** - * Takes a consumer that may or may not have checked exceptions and returns a - * new consumer that performs the same operation but "swallows" any checked - * exception by wrapping it in a RuntimeException and throwing that instead. - * If calling code wishes to inspect the underlying exception it must catch - * the RuntimeException and use getCause(). - * - * @param c - * consumer to wrap - * - * @return a new consumer that swallows checked exceptions - */ - public static Consumer cSwallow(ConsumerWithException c) { - return x -> { - try { - c.accept(x); - } - catch (Exception e) { - throw (e instanceof RuntimeException ? (RuntimeException)e : new RuntimeException(e)); - } - }; - } - - /** - * Takes a bi-consumer that may or may not have checked exceptions and returns - * a new bi-consumer that performs the same operation but "swallows" any checked - * exception by wrapping it in a RuntimeException and throwing that instead. - * If calling code wishes to inspect the underlying exception it must catch - * the RuntimeException and use getCause(). - * - * @param c - * bi-consumer to wrap - * - * @return a new bi-consumer that swallows checked exceptions - */ - public static BiConsumer c2Swallow(BiConsumerWithException c) { - return (x, y) -> { - try { - c.accept(x, y); - } - catch (Exception e) { - throw (e instanceof RuntimeException ? (RuntimeException)e : new RuntimeException(e)); - } - }; - } - - /** - * Takes a predicate that may or may not have checked exceptions and returns a - * new predicate that performs the same operation but "swallows" any checked - * exception by wrapping it in a RuntimeException and throwing that instead. - * If calling code wishes to inspect the underlying exception it must catch - * the RuntimeException and use getCause(). - * - * @param f - * predicate to wrap - * - * @return a new predicate that swallows checked exceptions - */ - public static Predicate pSwallow(PredicateWithException f) { - return x -> { - try { - return f.test(x); - } - catch (Exception e) { - throw (e instanceof RuntimeException ? (RuntimeException)e : new RuntimeException(e)); - } - }; - } - - /** - * Takes a reducer that may or may not have checked exceptions and returns a new reducer that performs - * the same operation but "swallows" any checked exception by wrapping it in a RuntimeException and - * throwing that instead. If calling code wishes to inspect the underlying exception it must catch the - * RuntimeException and use getCause(). - * - * @param r reducer to wrap - * @return a new reducer that swallows checked exceptions - */ - public static Reducer rSwallow(ReducerWithException r) { - return (accumulator, next) -> { - try { - return r.reduce(accumulator, next); - } - catch (Exception e) { - throw (e instanceof RuntimeException ? (RuntimeException)e : new RuntimeException(e)); - } - }; - } - - /** - * Takes a no-arg function that may or may not have checked exceptions and returns a new no-arg function - * that performs the same operation but "swallows" any checked exception by wrapping it in a - * RuntimeException and throwing that instead. If calling code wishes to inspect the underlying exception - * it must catch the RuntimeException and use getCause(). - * - * @param f function to wrap - * @return a new function that swallows checked exceptions - */ - public static Supplier f0Swallow(SupplierWithException f) { - return () -> { - try { - return f.get(); - } - catch (Exception e) { - throw (e instanceof RuntimeException ? (RuntimeException)e : new RuntimeException(e)); - } - }; - } - - /** - * Takes a 2-arg function that may or may not have checked exceptions and returns a new 2-arg function - * that performs the same operation but "swallows" any checked exception by wrapping it in a - * RuntimeException and throwing that instead. If calling code wishes to inspect the underlying exception - * it must catch the RuntimeException and use getCause(). - * - * @param f function to wrap - * @return a new function that swallows checked exceptions - */ - public static BiFunction f2Swallow(BiFunctionWithException f) { - return (obj1, obj2) -> { - try { - return f.apply(obj1, obj2); - } - catch (Exception e) { - throw (e instanceof RuntimeException ? (RuntimeException)e : new RuntimeException(e)); - } - }; - } - - /** - * Takes a no-arg function that may throw an exception, calls it, and returns the result - * - * @param producer a function that produces a value from no arguments - * @return the value the function produces - */ - public static T swallowAndGet(SupplierWithException producer) { - try { - return producer.get(); - } - catch (Exception e) { - throw new RuntimeException(e); - } - } - /** * Zips two Iterables of objects into a single List of "combined" objects. Combined objects are generated * by the passed zipper function. If the two input Iterables contain unequal numbers of objects, the @@ -483,51 +318,6 @@ public static boolean contains(Iterable items, Predicate return findFirstIndex(items, predicate) != -1; } - /** - * Attempts to retrieve a value from the passed supplier. If an exception occurs, a default value - * is returned and the exception is buried. - * - * @param f supplier function to execute - * @param defaultValue value to return if supplier fails - */ - public static T defaultOnException(SupplierWithException f, T defaultValue) { - try { - return f.get(); - } - catch (Exception e) { - return defaultValue; - } - } - - /** - * Takes a supplier that may throw an exception, and a mapper from that exception to a desired exception; - * calls the supplier, throwing a mapped exception is something goes wrong. - * - * @param f supplier - * @param exceptionMapper exception mapper - * @return value supplied by supplier if successful - * @throws S mapped exception if supplier is not successful - */ - public static T mapException(SupplierWithException f, Function exceptionMapper) throws S { - try { - return f.get(); - } - catch (Exception e) { - throw exceptionMapper.apply(e); - } - } - - /** - * Calls the passed supplier and wraps any throw exception with a RuntimeException - * - * @param f supplier - * @return value supplied by the supplier if successful - * @throws RuntimeException if not successful - */ - public static T wrapException(SupplierWithException f) { - return mapException(f, RuntimeException::new); - } - /** * Checks the passed list's size to ensure n is a valid index; if so, returns the * value at that index, else returns null. @@ -540,47 +330,6 @@ public static T getNthOrNull(List list, int n) { return n >= 0 && list.size() > n ? list.get(n) : null; } - /** - * Negate a given predicate - * - * @return Negated predicate - */ - public static Predicate not(final Predicate pred) { - return pred.negate(); - } - - /** - * Tries to get the next value from the passed supplier. If successful, - * returns an optional containing the supplied value; if not and an exception - * is thrown, returns an empty optional. - * - * @param supplier supplier with exception - * @return optional of supplied value, or empty optional if exception thrown - */ - public static Optional optionalOnException(SupplierWithException supplier) { - try { - return Optional.of(supplier.get()); - } - catch (Exception e) { - return Optional.empty(); - } - } - - /** - * Calls the passed function with the passed value and returns true if no exception is thrown, else false. - * - * @param function function to be called - * @param inputValue value to pass to the function - * @return false if exception thrown, else true - */ - public static boolean executesWithoutException(Function function, T inputValue) { - try { function.apply(inputValue); return true; } catch(Exception e) { return false; } - } - - public static T doThrow(Supplier exceptionSupplier) throws E { - throw exceptionSupplier.get(); - } - /** * Given a collection of items, bins the items by a characteristic value * pulled from each item using a function. Skips items that fail the passed diff --git a/Core/src/main/java/org/gusdb/fgputil/functional/TreeHelpers.java b/Core/src/main/java/org/gusdb/fgputil/functional/TreeHelpers.java new file mode 100644 index 00000000..19cc8c0f --- /dev/null +++ b/Core/src/main/java/org/gusdb/fgputil/functional/TreeHelpers.java @@ -0,0 +1,269 @@ +package org.gusdb.fgputil.functional; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.Optional; +import java.util.Queue; +import java.util.function.BiFunction; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +import org.gusdb.fgputil.Tuples.TwoTuple; + +/** + * Contains static functions that interrogate or operate on the TreeNode implementation of trees. + * + * @author rdoherty + */ +public class TreeHelpers { + + // static class + private TreeHelpers() {} + + /** + * Returns a predicate that takes a TreeNode that returns true iff + * its contents pass the the passed predicate. + * + * @param predicate predicate to operate on node contents + * @return predicate to operate on node + */ + public static Predicate> toNodePredicate(final Predicate predicate) { + return node -> predicate.test(node.getContents()); + } + + /** + * An interface to model the mapping of this tree structure to some other + * arbitrary tree structure. + * + * @param The type of object stored in this tree + * @param The type of a single 'node' each node in this tree will be mapped to + */ + @FunctionalInterface + public interface StructureMapper extends BiFunction, S> { + /** + * Maps the contents of a node, and its already-mapped children, to the + * node type of the new structure. + * + * @param obj the contents of an individual node + * @param mappedChildren the already-mapped children of this node + * @return a mapped object incorporating this node's contents and its children + */ + @Override + S apply(T obj, List mappedChildren); + } + + /** + * Enables a mapping of a TreeNode tree structure to an arbitrary tree + * structure of a different type. + * + * @param mapper maps an individual node and its children to the new type + * @return a mapped object + */ + public static S mapStructure(TreeNode root, StructureMapper mapper) { + // first create list of mapped child objects + List mappedChildren = new ArrayList<>(); + for (TreeNode child : root.getChildNodes()) { + mappedChildren.add(mapStructure(child, mapper)); + } + // pass this object plus converted children to mapper + return mapper.apply(root.getContents(), mappedChildren); + } + + /** + * Finds first node in this tree that matches the passed node predicate and + * whose contents match the generic predicate, and returns it. Uses a + * depth-first search. Null can be passed as either predicate and evaluates + * to 'true'. + * + * @param nodePred predicate to test nodes against + * @param pred predicate to test node contents against + * @return found node or null if not found + */ + public static Optional> findFirst(TreeNode root, Predicate> predicate) { + if (predicate.test(root)) { + return Optional.of(root); + } + for (TreeNode child : root.getChildNodes()) { + Optional> found = findFirst(child, predicate); + if (found.isPresent()) { + return found; + } + } + return Optional.empty(); + } + + /** + * Finds all nodes in this tree that match the passed predicate and returns + * them. Uses a depth-first search (determining list order). + * + * @param predicate predicate to test nodes against + * @return list of found nodes + */ + public static List> findAll(TreeNode root, Predicate> predicate) { + List> matches = new ArrayList<>(); + if (predicate.test(root)) { + matches.add(root); + } + for (TreeNode child : root.getChildNodes()) { + matches.addAll(findAll(child, predicate)); + } + return matches; + } + + /** + * Removes any subtrees that pass the passed predicate. This is a top-down + * operation, so e.g. an TreeNode::isLeaf predicate will not result in an + * empty tree. The root node is NOT tested since that API would be ambiguous. + * + * @param pred predicate to test node against + * @return number of subtrees removed + */ + public static int removeSubtrees(TreeNode root, Predicate> pred) { + int numRemoved = 0; + List> children = root.getChildNodes(); // not a copy + for (int i = 0; i < children.size(); i++) { + if (pred.test(children.get(i))) { + children.remove(i); + numRemoved++; + i--; // reuse the current index, now pointing to the next node + } + else { + // keep this node but search children for nodes to remove + numRemoved += removeSubtrees(children.get(i), pred); + } + } + return numRemoved; + } + + /** + * Replaces each node's contents with the result of the passed function + * + * @param root root of the tree + * @param function function to apply to each node + */ + public void apply(TreeNode root, Function function) { + apply(root, function, Functions.alwaysTrue()); + } + + /** + * Replaces each node's contents with the result of the passed function, but + * only if that node passes the passed predicate. + * + * @param root root of the tree + * @param function function to apply + * @param predicate predicate to filter nodes to which the function should be applied + */ + public static void apply(TreeNode root, Function function, Predicate> predicate) { + if (predicate.test(root)) { + root.setContents(function.apply(root.getContents())); + } + for (TreeNode child : root.getChildNodes()) { + apply(child, function, predicate); + } + } + + /** + * Finds any circular paths in this "tree" i.e. assesses the validity of the tree + * structure. If any circular paths are found, the recursive helper methods (and + * any independently written ones) run against this tree will never end and result + * in stack exhaustion. Thus, if a tree is generated from unknown input, it may + * be a good idea to validate the tree using this method before operating on it. + * A non-empty list indicates an invalid tree. The paths are included so callers + * can display the circular paths in an error message. + * + * @param type of the tree + * @param root root node + * @return list of circular paths + */ + public static List>> findCircularPaths(TreeNode root) { + // TODO: implement this + throw new UnsupportedOperationException(); + } + + /** + * Flatten the tree into a Collection of its contents in breadth-first order. + * + * @param type of the tree + * @param root root of the tree + * @return list of the contents of this tree node in order of depth. + */ + public static List flatten(TreeNode root) { + + final List out = new ArrayList<>(root.size()); + final Queue> next = new LinkedList<>(); + + next.offer(root); + + while(!next.isEmpty()) { + final TreeNode cur = next.poll(); + out.add(cur._nodeContents); + cur._childNodes.forEach(next::offer); + } + + return out; + } + + /** + * Given a tree, returns a copy, trimmed to only nodes of interest (active + * nodes) and their shared ancestors. Inactive nodes and parents of only + * one active node are removed. + * + * Sample usage that may support a trimmed tree for SQL joins: + * + * private static class Entity { public String getName() { return null; }} + * TreeNode<Entity> entityTree; + * String targetEntityName; + * List<String> filteredEntityNames; + * + * TreeNode<Entity> trimmedRoot = trimToActiveAndPivotNodes(entityTree, + * e -> targetEntityName.equals(e.getName()) || filteredEntityNames.contains(e.getName())); + */ + public static TreeNode trimToActiveAndPivotNodes(TreeNode root, Predicate isActive) { + return mapStructure(root, (nodeContents, mappedChildren) -> { + List> activeChildren = mappedChildren.stream() + .filter(child -> child != null) // filter dead branches + .collect(Collectors.toList()); + return isActive.test(nodeContents) || activeChildren.size() > 1 ? + // this node is active itself or a pivot node; return with any active children + new TreeNode(nodeContents).addAllChildNodes(activeChildren) : + // inactive, non-pivot node; return single active child or null + activeChildren.isEmpty() ? null : activeChildren.get(0); + }); + } + + /** + * Returns a list of tuples, each representing an edge by containing the + * content of the nodes joined by the edge. + * + * @param type of node contents + * @param root root node of the tree + * @return list of edges i.e. node tuples + */ + @SuppressWarnings("unchecked") // lambdas are not smart enough (for now) to type this properly + public static List> getEdges(TreeNode root) { + List> edges = new ArrayList<>(); + mapStructure(root, (current, mappedChildren) -> { + mappedChildren.forEach(child -> edges.add(new TwoTuple(current, (T)child))); + return current; + }); + return edges; + } + + /** + * Retrieves the edges of the tree and applies the passed binary function to + * each, returning a list of objects produced by the edges. + * + * @param type of node contents + * @param type of edge object + * @param root root node of the tree + * @param relationCreator binary function converting an edge to an object + * @return list of objects created from edges + */ + public static List getEdgeObjects(TreeNode root, BiFunction relationCreator) { + return getEdges(root).stream() + .map(tup -> relationCreator.apply(tup.getFirst(), tup.getSecond())) + .collect(Collectors.toList()); + } +} diff --git a/Core/src/main/java/org/gusdb/fgputil/functional/TreeNode.java b/Core/src/main/java/org/gusdb/fgputil/functional/TreeNode.java index 995cb8b2..a160a8df 100644 --- a/Core/src/main/java/org/gusdb/fgputil/functional/TreeNode.java +++ b/Core/src/main/java/org/gusdb/fgputil/functional/TreeNode.java @@ -1,20 +1,13 @@ package org.gusdb.fgputil.functional; - -import static java.util.function.Predicate.not; import static org.gusdb.fgputil.FormatUtil.NL; +import static org.gusdb.fgputil.functional.Functions.alwaysTrue; import java.util.ArrayList; -import java.util.Collection; -import java.util.LinkedList; import java.util.List; -import java.util.Queue; -import java.util.function.BiFunction; -import java.util.function.Function; import java.util.function.Predicate; import org.gusdb.fgputil.FormatUtil.MultiLineToString; -import org.gusdb.fgputil.functional.FunctionalInterfaces.Reducer; /** * This class provides a common implementation of tree structure and the ability @@ -25,48 +18,13 @@ public class TreeNode implements MultiLineToString { /** - * A typed predicate that returns true for leaf nodes + * Contents object of this node */ - public final Predicate> LEAF_PREDICATE = TreeNode::isLeaf; - - /** - * A typed predicate that returns true for non-leaf nodes - */ - public final Predicate> NONLEAF_PREDICATE = not(TreeNode::isLeaf); - - /** - * Returns a predicate that takes a TreeNode that returns true its contents - * pass the the passed predicate, else false. - * - * @param predicate predicate to operate on node contents - * @return predicate to operate on node - */ - public Predicate> createNodePredicate(final Predicate predicate) { - return obj -> predicate.test(obj.getContents()); - } + protected T _nodeContents; /** - * An interface to model the mapping of this tree structure to some other - * arbitrary tree structure. - * - * @param The type of object stored in this tree - * @param The type of a single 'node' each node in this tree will be mapped to + * Children of this node */ - @FunctionalInterface - public interface StructureMapper extends BiFunction, S> { - /** - * Maps the contents of a node, and its already-mapped children, to the - * node type of the new structure. - * - * @param obj the contents of an individual node - * @param mappedChildren the already-mapped children of this node - * @return a mapped object incorporating this node's contents and its children - */ - @Override - S apply(T obj, List mappedChildren); - } - - protected T _nodeContents; protected List> _childNodes = new ArrayList<>(); // private since determined by type of _nodeContents @@ -94,6 +52,17 @@ public boolean isLeaf() { return _childNodes.isEmpty(); } + public boolean hasChildren() { + return !_childNodes.isEmpty(); + } + + /** + * @return The total count of nodes in this tree + */ + public int size() { + return 1 + _childNodes.stream().mapToInt(TreeNode::size).sum(); + } + /** * Creates a new node containing the passed contents and appends it to * this node's list of children @@ -102,8 +71,7 @@ public boolean isLeaf() { * @return this node */ public TreeNode addChild(T childContents) { - _childNodes.add(new TreeNode<>(childContents)); - return this; + return addChildNode(new TreeNode<>(childContents)); } /** @@ -124,7 +92,7 @@ public TreeNode addChildNode(TreeNode child) { * @return this node */ public TreeNode addAllChildNodes(List> children) { - return addChildNodes(children, new FunctionalInterfaces.TruePredicate<>()); + return addChildNodes(children, alwaysTrue()); } /** @@ -146,153 +114,6 @@ public List> getChildNodes() { return _childNodes; } - public List> getLeafNodes() { - return findAll(LEAF_PREDICATE, null); - } - - public List> getNonLeafNodes() { - return findAll(NONLEAF_PREDICATE, null); - } - - /** - * Finds first node in this tree whose contents match the passed predicate and - * returns it. Uses a depth-first search. - * - * @param pred predicate to test node contents against - * @return found node or null if not found - */ - public TreeNode findFirst(Predicate pred) { - return findFirst(null, pred); - } - - /** - * Finds first node in this tree that matches the passed node predicate and - * whose contents match the generic predicate, and returns it. Uses a - * depth-first search. Null can be passed as either predicate and evaluates - * to 'true'. - * - * @param nodePred predicate to test nodes against - * @param pred predicate to test node contents against - * @return found node or null if not found - */ - public TreeNode findFirst(Predicate> nodePred, Predicate pred) { - if ((nodePred == null || nodePred.test(this)) && - (pred == null || pred.test(_nodeContents))) { - return this; - } - for (TreeNode node : _childNodes) { - TreeNode found = node.findFirst(nodePred, pred); - if (found != null) return found; - } - return null; - } - - /** - * Finds all nodes in this tree whose contents match the passed predicate and - * returns them. Uses a depth-first search. - * - * @param pred predicate to test node contents against - * @return list of found nodes - */ - public List> findAll(Predicate pred) { - return findAll(null, pred); - } - - /** - * Finds all nodes in this tree that match the passed node predicate and - * whose contents match the generic predicate, and returns them. Uses a - * depth-first search. Null can be passed as either predicate and evaluates - * to 'true'. - * - * @param nodePred predicate to test nodes against - * @param pred predicate to test node contents against - * @return list of found nodes - */ - public List> findAll(Predicate> nodePred, Predicate pred) { - List> matches = new ArrayList<>(); - if ((nodePred == null || nodePred.test(this)) && - (pred == null || pred.test(_nodeContents))) { - matches.add(this); - } - for (TreeNode node : _childNodes) { - matches.addAll(node.findAll(nodePred, pred)); - } - return matches; - } - - /** - * Finds all nodes in this tree that match the passed node predicate and - * whose contents match the generic predicate, and returns a list of outputs - * generated by passing those nodes' contents to the passed mapper. Uses a - * depth-first search. Null can be passed as either predicate and evaluates - * to 'true'. Passing null for the mapper will result in a - * NullPointerException. - * - * @param nodePred predicate to test nodes against - * @param pred predicate to test node contents against - * @param mapper transform to use to map the found nodes' contents into other - * data - * @return list of function results - */ - public List findAndMap(Predicate> nodePred, Predicate pred, Function mapper) { - List matches = new ArrayList<>(); - if ((nodePred == null || nodePred.test(this)) && - (pred == null || pred.test(_nodeContents))) { - matches.add(mapper.apply(this._nodeContents)); - } - for (TreeNode node : _childNodes) { - matches.addAll(node.findAndMap(nodePred, pred, mapper)); - } - return matches; - } - - /** - * Aggregates information in this tree into a single value, with behavior - * defined by the passed Reducer. - * - * @param reducer reducer to use to aggregate information - * @return result - */ - public S reduce(Reducer reducer) { - return reduce(null, reducer, null); - } - - /** - * Aggregates information in the nodes that pass the predicate into a single - * value, with behavior defined by the passed Reducer. - * - * @param nodePred predicate to filter nodes that will contribute to the reduction - * @param reducer reducer to use to aggregate information - * @param initialValue initial value passed to the first call to the reducer's reduce method - * @return result, or initialValue if no nodes match the predicate - */ - public S reduce(Predicate> nodePred, Reducer reducer, S initialValue) { - if (nodePred == null || nodePred.test(this)) { - initialValue = reducer.reduce(initialValue, _nodeContents); - } - for (TreeNode node : _childNodes) { - initialValue = node.reduce(nodePred, reducer, initialValue); - } - return initialValue; - } - - /** - * Enables a mapping of a TreeNode tree structure to an arbitrary tree - * structure of a different type. - * - * @param mapper maps an individual node and its children to the new type - * @return a mapped object - */ - public S mapStructure(StructureMapper mapper) { - // first create list of mapped child objects - List mappedChildren = new ArrayList<>(); - for (TreeNode child : _childNodes) { - mappedChildren.add(child.mapStructure(mapper)); - } - // pass this object plus converted children to mapper - return mapper.apply(_nodeContents, mappedChildren); - } - /** * Returns a clone of this tree. This is a "deep" clone in the sense that all * child nodes are also replicated; however the contents of the nodes are not @@ -304,141 +125,13 @@ public S mapStructure(StructureMapper mapper) { */ @Override public TreeNode clone() { - return mapStructure((obj, mappedChildren) -> { + return TreeHelpers.mapStructure(this, (obj, mappedChildren) -> { TreeNode copy = new TreeNode(obj); copy._childNodes = mappedChildren; return copy; }); } - /** - * Removes any subtrees that pass the passed predicate - * - * @param pred predicate to test node contents against - * @return number of subtrees removed - */ - public int removeAll(Predicate pred) { - int numRemoved = 0; - for (int i = 0; i < _childNodes.size(); i++) { - if (pred.test(_childNodes.get(i)._nodeContents)) { - _childNodes.remove(i); - numRemoved++; - i--; // reuse the current index, now pointing to the next node - } - else { - numRemoved += _childNodes.get(i).removeAll(pred); - } - } - return numRemoved; - } - - /** - * Removes any subtrees that pass the passed predicate - * - * @param pred predicate to test node contents against - * @return number of subtrees removed - */ - public int removeAllNodes(Predicate> pred) { - int numRemoved = 0; - for (int i = 0; i < _childNodes.size(); i++) { - if (pred.test(_childNodes.get(i))) { - _childNodes.remove(i); - numRemoved++; - i--; // reuse the current index, now pointing to the next node - } - else { - numRemoved += _childNodes.get(i).removeAllNodes(pred); - } - } - return numRemoved; - } - - /** - * Replaces each node's contents with the result of the passed function - * - * @param function function to apply to each node - */ - public void apply(Function function) { - apply(null, null, function); - } - - /** - * Replaces each node's contents with the result of the passed function, but - * only if that node's contents pass the passed predicate. - * - * @param pred predicate to filter nodes to which the function should be - * applied - * @param function function to apply - */ - public void apply(Predicate pred, Function function) { - apply(null, pred, function); - } - - /** - * Replaces each node's contents with the result of the passed function, but - * only if that node passes the passed predicate. - * - * @param function function to apply - * @param pred predicate to filter nodes to which the function should be - * applied - */ - public void apply(Function function, Predicate> pred) { - apply(pred, null, function); - } - - /** - * Replaces each node's contents with the result of the passed function, but - * only if that node passes both the passed predicates. - * - * @param nodePred predicate to filter nodes to which the function should be - * applied (tests node) - * @param pred predicate to filter nodes to which the function should be - * applied (tests node contents) - * @param function function to apply - */ - public void apply(Predicate> nodePred, Predicate pred, Function function) { - if ((nodePred == null || nodePred.test(this)) && - (pred == null || pred.test(_nodeContents))) { - _nodeContents = function.apply(_nodeContents); - } - for (TreeNode node : _childNodes) { - node.apply(nodePred, pred, function); - } - } - - public List>> findCircularPaths() { - // TODO: implement this - throw new UnsupportedOperationException(); - } - - /** - * @return The total count of nodes in this tree. - */ - public int size() { - return 1 + _childNodes.stream().mapToInt(TreeNode::size).sum(); - } - - /** - * Flatten the tree into a Collection of it's contents. - * - * @return Collection of the contents of this tree node in order of depth. - */ - public Collection flatten() { - final int len = size(); - final List out = new ArrayList<>(len); - final Queue> next = new LinkedList<>(); - - next.offer(this); - - while(!next.isEmpty()) { - final TreeNode cur = next.poll(); - out.add(cur._nodeContents); - cur._childNodes.forEach(next::offer); - } - - return out; - } - /** * Returns a string representation of this node and its subtree. */ diff --git a/Core/src/main/java/org/gusdb/fgputil/functional/TreeUtil.java b/Core/src/main/java/org/gusdb/fgputil/functional/TreeUtil.java deleted file mode 100644 index 53633068..00000000 --- a/Core/src/main/java/org/gusdb/fgputil/functional/TreeUtil.java +++ /dev/null @@ -1,84 +0,0 @@ -package org.gusdb.fgputil.functional; - -import java.util.ArrayList; -import java.util.List; -import java.util.function.BiFunction; -import java.util.function.Predicate; -import java.util.stream.Collectors; - -import org.gusdb.fgputil.Tuples.TwoTuple; - -/** - * Contains static functions (should be "pure") that operate on the TreeNode - * implementation of trees. - * - * @author rdoherty - */ -// TODO: move utility methods from TreeNode to here and convert to pure functions -public class TreeUtil { - - // class should not be instantiated - private TreeUtil(){} - - /** - * Given a tree, returns a copy, trimmed to only nodes of interest (active - * nodes) and their shared ancestors. Inactive nodes and parents of only - * one active node are removed. - * - * Sample usage that may support a trimmed tree for SQL joins: - * - * private static class Entity { public String getName() { return null; }} - * TreeNode<Entity> entityTree; - * String targetEntityName; - * List<String> filteredEntityNames; - * - * TreeNode<Entity> trimmedRoot = trimToActiveAndPivotNodes(entityTree, - * e -> targetEntityName.equals(e.getName()) || filteredEntityNames.contains(e.getName())); - */ - public static TreeNode trimToActiveAndPivotNodes(TreeNode root, Predicate isActive) { - return root.mapStructure((nodeContents, mappedChildren) -> { - List> activeChildren = mappedChildren.stream() - .filter(child -> child != null) // filter dead branches - .collect(Collectors.toList()); - return isActive.test(nodeContents) || activeChildren.size() > 1 ? - // this node is active itself or a pivot node; return with any active children - new TreeNode(nodeContents).addAllChildNodes(activeChildren) : - // inactive, non-pivot node; return single active child or null - activeChildren.isEmpty() ? null : activeChildren.get(0); - }); - } - - /** - * Returns a list of tuples, each representing an edge by containing the - * content of the nodes joined by the edge. - * - * @param type of node contents - * @param root root node of the tree - * @return list of edges i.e. node tuples - */ - @SuppressWarnings("unchecked") // lambdas are not smart enough (for now) to type this properly - public static List> getEdges(TreeNode root) { - List> edges = new ArrayList<>(); - root.mapStructure((current, mappedChildren) -> { - mappedChildren.forEach(child -> edges.add(new TwoTuple(current, (T)child))); - return current; - }); - return edges; - } - - /** - * Retrieves the edges of the tree and applies the passed binary function to - * each, returning a list of objects produced by the edges. - * - * @param type of node contents - * @param type of edge object - * @param root root node of the tree - * @param relationCreator binary function converting an edge to an object - * @return list of objects created from edges - */ - public static List getEdgeObjects(TreeNode root, BiFunction relationCreator) { - return getEdges(root).stream() - .map(tup -> relationCreator.apply(tup.getFirst(), tup.getSecond())) - .collect(Collectors.toList()); - } -} diff --git a/Core/src/main/java/org/gusdb/fgputil/script/JavaScript.java b/Core/src/main/java/org/gusdb/fgputil/script/JavaScript.java index a064afa5..139e38ed 100644 --- a/Core/src/main/java/org/gusdb/fgputil/script/JavaScript.java +++ b/Core/src/main/java/org/gusdb/fgputil/script/JavaScript.java @@ -6,7 +6,7 @@ import javax.script.ScriptEngine; import javax.script.ScriptException; -import org.gusdb.fgputil.ListBuilder; +import org.gusdb.fgputil.collection.builder.ListBuilder; import org.gusdb.fgputil.script.Scripting.Language; /** diff --git a/Core/src/main/java/org/gusdb/fgputil/validation/ValidationBundle.java b/Core/src/main/java/org/gusdb/fgputil/validation/ValidationBundle.java index 935a3ab4..203eeba3 100644 --- a/Core/src/main/java/org/gusdb/fgputil/validation/ValidationBundle.java +++ b/Core/src/main/java/org/gusdb/fgputil/validation/ValidationBundle.java @@ -10,7 +10,7 @@ import java.util.Map; import java.util.stream.Collectors; -import org.gusdb.fgputil.ListBuilder; +import org.gusdb.fgputil.collection.builder.ListBuilder; import org.json.JSONObject; /** diff --git a/Core/src/test/java/org/gusdb/fgputil/ArrayTest.java b/Core/src/test/java/org/gusdb/fgputil/ArrayTest.java index 40a75637..ddd88b05 100644 --- a/Core/src/test/java/org/gusdb/fgputil/ArrayTest.java +++ b/Core/src/test/java/org/gusdb/fgputil/ArrayTest.java @@ -5,6 +5,7 @@ import java.util.Arrays; +import org.gusdb.fgputil.collection.builder.ListBuilder; import org.junit.Test; /** diff --git a/Core/src/test/java/org/gusdb/fgputil/AutoCloseableListTest.java b/Core/src/test/java/org/gusdb/fgputil/AutoCloseableListTest.java index 88617012..b029667e 100644 --- a/Core/src/test/java/org/gusdb/fgputil/AutoCloseableListTest.java +++ b/Core/src/test/java/org/gusdb/fgputil/AutoCloseableListTest.java @@ -4,6 +4,7 @@ import java.util.List; import org.apache.log4j.Logger; +import org.gusdb.fgputil.collection.AutoCloseableList; import org.junit.Test; public class AutoCloseableListTest { diff --git a/Core/src/test/java/org/gusdb/fgputil/FormatTest.java b/Core/src/test/java/org/gusdb/fgputil/FormatTest.java index 514da36a..35e67af3 100644 --- a/Core/src/test/java/org/gusdb/fgputil/FormatTest.java +++ b/Core/src/test/java/org/gusdb/fgputil/FormatTest.java @@ -10,6 +10,7 @@ import java.util.Map; import org.gusdb.fgputil.FormatUtil.Style; +import org.gusdb.fgputil.collection.builder.MapBuilder; import org.junit.Assert; import org.junit.Test; diff --git a/Core/src/test/java/org/gusdb/fgputil/functional/TreeNodeTest.java b/Core/src/test/java/org/gusdb/fgputil/functional/TreeNodeTest.java index 81fb8987..0e4c13f1 100644 --- a/Core/src/test/java/org/gusdb/fgputil/functional/TreeNodeTest.java +++ b/Core/src/test/java/org/gusdb/fgputil/functional/TreeNodeTest.java @@ -4,7 +4,7 @@ import java.util.List; -import org.gusdb.fgputil.functional.TreeNode.StructureMapper; +import org.gusdb.fgputil.functional.TreeHelpers.StructureMapper; import org.json.JSONArray; import org.json.JSONObject; import org.junit.Test; @@ -16,7 +16,7 @@ public class TreeNodeTest { @Test public void testStructureMap() { TreeNode root = buildTestTree(); - JSONObject result = root.mapStructure(new StructureMapper(){ + JSONObject result = TreeHelpers.mapStructure(root, new StructureMapper(){ @Override public JSONObject apply(Integer obj, List mappedChildren) { JSONObject json = new JSONObject(); diff --git a/Core/src/test/java/org/gusdb/fgputil/iterator/IterablesTest.java b/Core/src/test/java/org/gusdb/fgputil/iterator/IterablesTest.java index 6c777d96..7599bd0e 100644 --- a/Core/src/test/java/org/gusdb/fgputil/iterator/IterablesTest.java +++ b/Core/src/test/java/org/gusdb/fgputil/iterator/IterablesTest.java @@ -14,8 +14,8 @@ import java.util.List; import org.gusdb.fgputil.AlphabetUtils.AlphabetDataProvider; +import org.gusdb.fgputil.collection.builder.ListBuilder; import org.gusdb.fgputil.IoUtil; -import org.gusdb.fgputil.ListBuilder; import org.junit.Test; public class IterablesTest { diff --git a/Db/src/main/java/org/gusdb/fgputil/db/cache/SqlCountCache.java b/Db/src/main/java/org/gusdb/fgputil/db/cache/SqlCountCache.java index 8de2bce9..2a811942 100644 --- a/Db/src/main/java/org/gusdb/fgputil/db/cache/SqlCountCache.java +++ b/Db/src/main/java/org/gusdb/fgputil/db/cache/SqlCountCache.java @@ -1,6 +1,6 @@ package org.gusdb.fgputil.db.cache; -import static org.gusdb.fgputil.functional.Functions.fSwallow; +import static org.gusdb.fgputil.functional.ExceptionUtil.fSwallow; import javax.sql.DataSource; diff --git a/Db/src/main/java/org/gusdb/fgputil/db/stream/ResultSetInputStream.java b/Db/src/main/java/org/gusdb/fgputil/db/stream/ResultSetInputStream.java index 2f60ac6b..a949864b 100644 --- a/Db/src/main/java/org/gusdb/fgputil/db/stream/ResultSetInputStream.java +++ b/Db/src/main/java/org/gusdb/fgputil/db/stream/ResultSetInputStream.java @@ -1,5 +1,7 @@ package org.gusdb.fgputil.db.stream; +import static org.gusdb.fgputil.functional.ExceptionUtil.fSwallow; + import java.io.IOException; import java.sql.Connection; import java.sql.PreparedStatement; @@ -14,7 +16,6 @@ import org.gusdb.fgputil.db.ResultSetColumnInfo; import org.gusdb.fgputil.db.SqlUtils; import org.gusdb.fgputil.db.slowquery.QueryLogger; -import org.gusdb.fgputil.functional.Functions; import org.gusdb.fgputil.iterator.IteratingInputStream; import org.gusdb.fgputil.iterator.IteratorUtil; @@ -98,9 +99,7 @@ private static DataProvider buildDataProvider(ResultSet resultSet, @Override public Iterator getRecordIterator() { return IteratorUtil.toIterator(SqlUtils.toCursor( - resultSet, rs -> Functions.mapException( - () -> resultConverter.getRow(rs, columnInfo), - e -> new RuntimeException(e)))); + resultSet, fSwallow(rs -> resultConverter.getRow(rs, columnInfo)))); } }; } diff --git a/Db/src/test/java/org/gusdb/fgputil/db/stream/ResultSetStreamingTest.java b/Db/src/test/java/org/gusdb/fgputil/db/stream/ResultSetStreamingTest.java index d5ccbac5..9b35dba0 100644 --- a/Db/src/test/java/org/gusdb/fgputil/db/stream/ResultSetStreamingTest.java +++ b/Db/src/test/java/org/gusdb/fgputil/db/stream/ResultSetStreamingTest.java @@ -1,8 +1,8 @@ package org.gusdb.fgputil.db.stream; import static org.gusdb.fgputil.FormatUtil.NL; -import static org.gusdb.fgputil.functional.Functions.cSwallow; -import static org.gusdb.fgputil.functional.Functions.wrapException; +import static org.gusdb.fgputil.functional.ExceptionUtil.cSwallow; +import static org.gusdb.fgputil.functional.ExceptionUtil.mapException; import java.io.BufferedWriter; import java.io.ByteArrayOutputStream; @@ -83,7 +83,7 @@ public void iteratorTestWithWrite() throws Exception { // iterate through groups and format into strings to be written to stream for (List group : IteratorUtil.toIterable(groups)) { - wrapException(() -> { writer.write(FORMATTER.apply(group) + NL); return null; }); + mapException(() -> writer.write(FORMATTER.apply(group) + NL), RuntimeException::new); } }); } diff --git a/Json/src/main/java/org/gusdb/fgputil/json/JsonUtil.java b/Json/src/main/java/org/gusdb/fgputil/json/JsonUtil.java index 49027a7a..d8dfe108 100644 --- a/Json/src/main/java/org/gusdb/fgputil/json/JsonUtil.java +++ b/Json/src/main/java/org/gusdb/fgputil/json/JsonUtil.java @@ -1,6 +1,6 @@ package org.gusdb.fgputil.json; -import static org.gusdb.fgputil.functional.Functions.swallowAndGet; +import static org.gusdb.fgputil.functional.ExceptionUtil.sSwallow; import java.util.ArrayList; import java.util.Arrays; @@ -350,7 +350,7 @@ public static Result toJsonString(Object any) { * @throws RuntimeException if unable to serialize object */ public static String serializeObject(Object object) { - return swallowAndGet(() -> Jackson.writeValueAsString(object)); + return sSwallow(() -> Jackson.writeValueAsString(object)).get(); } /**