All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.spun.util.MethodExecutionPath Maven / Gradle / Ivy

There is a newer version: 24.9.0
Show newest version
package com.spun.util;

import com.spun.util.filters.Filter;
import org.lambda.query.Query;

import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;

public class MethodExecutionPath implements Serializable
{
  private static final long       serialVersionUID         = 1L;
  public static final Object      NULL_ENCOUNTERED_ON_PATH = new Object();
  private Class classType, returnType;
  private String[]                methodNames;
  private Parameters[]            parameters;
  private Method[]                methods;
  public MethodExecutionPath(Class clazz, String methodName)
  {
    this(clazz, new String[]{methodName}, null);
  }
  public MethodExecutionPath(Class clazz, String... methodNames)
  {
    this(clazz, methodNames, null);
  }
  public MethodExecutionPath(Class clazz, String methodName, Parameters parameters)
  {
    this(clazz, new String[]{methodName}, new Parameters[]{parameters});
  }
  public MethodExecutionPath(Class clazz, String[] methodNames, Parameters[] parameters)
  {
    this.classType = clazz;
    this.methodNames = methodNames;
    this.parameters = parameters;
    this.methods = getRecursiveMethods(clazz, methodNames, parameters);
    this.returnType = (this.methods != null) ? methods[methods.length - 1].getReturnType() : null;
  }
  public static MethodExecutionPath method(Class class1, String method, Object... paramaters)
  {
    return new MethodExecutionPath(class1, new String[]{method}, new Parameters[]{new Parameters(paramaters)});
  }
  public static Method[] getRecursiveMethods(Class clazz, String[] methodNames, Parameters[] parameters)
  {
    if (clazz == null)
    { return null; }
    Method[] methods = new Method[methodNames.length];
    String currentMethodName = null;
    Parameters parameter = null;
    try
    {
      for (int i = 0; i < methods.length; i++)
      {
        currentMethodName = methodNames[i];
        parameter = Parameters.getParametersFor(parameters, i);
        methods[i] = parameter.getBestFitMethod(clazz, currentMethodName);
        clazz = methods[i].getReturnType();
      }
      return methods;
    }
    catch (Exception e)
    {
      throw new Error(
          "Unable to get method for " + clazz.getName() + "." + currentMethodName + "(" + parameter + ")", e);
    }
  }
  public Object extractValue(Object object)
  {
    if (object == null)
    { return NULL_ENCOUNTERED_ON_PATH; }
    Method[] methods = this.methods == null
        ? getRecursiveMethods(object.getClass(), this.methodNames, this.parameters)
        : this.methods;
    for (int i = 0; i < methods.length; i++)
    {
      if (object == null)
      { return NULL_ENCOUNTERED_ON_PATH; }
      object = extractValue(object, methods[i], Parameters.getParametersFor(parameters, i).values);
    }
    return object;
  }
  private static Object extractValue(Object object, Method method, Object[] values)
  {
    try
    {
      return method.invoke(object, values);
    }
    catch (Exception e)
    {
      throw new Error("Problems extracting values from " + object.getClass().getName() + "." + method.getName(),
          e);
    }
  }
  public Class getClassType()
  {
    return classType;
  }
  public Class getReturnType()
  {
    return returnType;
  }
  public static class Parameters
  {
    public static final Parameters EMPTY = new Parameters(null, null);
    public Class[]              definitions;
    public Object[]                values;
    public Parameters(Object... values)
    {
      if (!ArrayUtils.isEmpty(values))
      {
        this.values = values;
        this.definitions = Query.select(values, m -> m.getClass()).toArray(new Class[0]);
      }
    }
    public Parameters(Class[] definitions, Object[] values)
    {
      this.definitions = definitions;
      this.values = values;
    }
    public Method getBestFitMethod(Class clazz, String currentMethodName)
    {
      return getBestFitMethod(clazz, currentMethodName, definitions);
    }
    public static Method getBestFitMethod(Class clazz, String currentMethodName, Class[] definitions)
    {
      try
      {
        return clazz.getMethod(currentMethodName, definitions);
      }
      catch (NoSuchMethodException e)
      {
        List methods = Query.where(clazz.getMethods(),
            m -> new MethodParameterFilter(currentMethodName, definitions).isExtracted(m));
        if (methods.isEmpty())
        { throw ObjectUtils.throwAsError(e); }
        if (methods.size() == 1)
        {
          return methods.get(0);
        }
        else
        {
          throw new Error("Don't know how to handle multiple available methods yet.");
        }
      }
    }
    public static Parameters getParametersFor(Parameters[] parameters, int i)
    {
      if (parameters == null || (i >= parameters.length) || parameters[i] == null)
      { return EMPTY; }
      return parameters[i];
    }
    public String toString()
    {
      return definitions == null ? "" : Arrays.asList(definitions).toString();
    }
  }
  public static class MethodParameterFilter implements Filter
  {
    private String     methodName;
    private Class[] classParameters;
    public MethodParameterFilter(String methodName, Class[] classParameters)
    {
      super();
      this.methodName = methodName;
      this.classParameters = classParameters;
    }
    public boolean isExtracted(Object object) throws IllegalArgumentException
    {
      ObjectUtils.assertInstance(Method.class, object);
      Method m = (Method) object;
      if (m.getName().equals(methodName) && m.getParameterTypes().length == classParameters.length)
      {
        Class[] params = m.getParameterTypes();
        for (int i = 0; i < params.length; i++)
        {
          if (!ObjectUtils.isThisInstanceOfThat(classParameters[i], params[i]))
          { return false; }
        }
        return true;
      }
      else
      {
        return false;
      }
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy