MultiFunctionUtils.java

  1. package com.github.dakusui.pcond.experimentals.currying.multi;

  2. import com.github.dakusui.pcond.core.printable.PrintableFunctionFactory;
  3. import com.github.dakusui.pcond.internals.InternalUtils;

  4. import java.lang.reflect.Method;
  5. import java.util.Arrays;
  6. import java.util.HashMap;
  7. import java.util.List;
  8. import java.util.Map;

  9. import static java.util.Arrays.asList;
  10. import static java.util.stream.Collectors.toList;

  11. /**
  12.  * A utility class that collects helper methods for the multi-parameters function.
  13.  */
  14. public enum MultiFunctionUtils {
  15.   ;
  16.   private static final ThreadLocal<Map<List<Object>, MultiFunction<?>>> METHOD_BASED_FUNCTION_POOL = new ThreadLocal<>();

  17.   @SuppressWarnings("unchecked")
  18.   public static <R> MultiFunction<R> multifunction(int[] order, Class<?> aClass, String methodName, Class<?>... parameterTypes) {
  19.     Map<List<Object>, MultiFunction<?>> methodBasedMultiParameterFunctionPool = methodBasedMultiParameterFunctionPool();
  20.     List<Object> multiParamFuncDef = composeFuncDef(order, aClass, methodName, parameterTypes);
  21.     methodBasedMultiParameterFunctionPool.computeIfAbsent(
  22.         multiParamFuncDef,
  23.         MultiFunctionUtils::createMultiParameterFunctionForStaticMethod);
  24.     return (MultiFunction<R>) methodBasedMultiParameterFunctionPool.get(multiParamFuncDef);
  25.   }

  26.   private static List<Object> composeFuncDef(int[] order, Class<?> aClass, String methodName, Class<?>[] parameterTypes) {
  27.     return asList(InternalUtils.getMethod(aClass, methodName, parameterTypes), Arrays.stream(order).boxed().collect(toList()));
  28.   }

  29.   private static <R> MultiFunction<R> createMultiParameterFunctionForStaticMethod(List<Object> multiParamFuncDef) {
  30.     final Method method = (Method) multiParamFuncDef.get(0);
  31.     @SuppressWarnings("unchecked") final List<Integer> paramOrder = (List<Integer>) multiParamFuncDef.get(1);
  32.     return PrintableFunctionFactory.multifunction(method, paramOrder);
  33.   }

  34.   private static Map<List<Object>, MultiFunction<?>> methodBasedMultiParameterFunctionPool() {
  35.     if (METHOD_BASED_FUNCTION_POOL.get() == null)
  36.       METHOD_BASED_FUNCTION_POOL.set(new HashMap<>());
  37.     return METHOD_BASED_FUNCTION_POOL.get();
  38.   }
  39. }