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

com.datatorrent.lib.util.PojoUtils Maven / Gradle / Ivy

/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package com.datatorrent.lib.util;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.codehaus.commons.compiler.CompileException;
import org.codehaus.commons.compiler.CompilerFactoryFactory;
import org.codehaus.commons.compiler.IScriptEvaluator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.apache.commons.lang3.ClassUtils;
import org.apache.commons.lang3.StringUtils;

import com.google.common.base.Preconditions;
import com.google.common.collect.Maps;

import com.datatorrent.lib.expression.Expression;
import com.datatorrent.lib.expression.JavaExpressionParser;

/**
 * @since 2.1.0
 */
public class PojoUtils
{
  private static final Logger logger = LoggerFactory.getLogger(PojoUtils.class);

  public static final String DEFAULT_EXP_OBJECT_PLACEHOLDER = "{$}";
  public static final String DEFAULT_EXP_VAL_PLACEHOLDER = "{#}";
  public static final String DEFAULT_EXPRESSION_OBJ_PLACEHOLDER = "$";

  private static final String OBJECT = "object";
  private static final String VAL = "val";

  private static final String GET = "get";
  private static final String IS = "is";
  private static final String SET = "set";

  private static final Map, Class> primitiveClassToGetterInterface = Maps.newHashMap();
  private static final Map, Class> primitiveClassToSetterInterface = Maps.newHashMap();

  static {
    primitiveClassToGetterInterface.put(boolean.class, GetterBoolean.class);
    primitiveClassToGetterInterface.put(byte.class, GetterByte.class);
    primitiveClassToGetterInterface.put(char.class, GetterChar.class);
    primitiveClassToGetterInterface.put(short.class, GetterShort.class);
    primitiveClassToGetterInterface.put(int.class, GetterInt.class);
    primitiveClassToGetterInterface.put(long.class, GetterLong.class);
    primitiveClassToGetterInterface.put(float.class, GetterFloat.class);
    primitiveClassToGetterInterface.put(double.class, GetterDouble.class);

    primitiveClassToSetterInterface.put(boolean.class, SetterBoolean.class);
    primitiveClassToSetterInterface.put(byte.class, SetterByte.class);
    primitiveClassToSetterInterface.put(char.class, SetterChar.class);
    primitiveClassToSetterInterface.put(short.class, SetterShort.class);
    primitiveClassToSetterInterface.put(int.class, SetterInt.class);
    primitiveClassToSetterInterface.put(long.class, SetterLong.class);
    primitiveClassToSetterInterface.put(float.class, SetterFloat.class);
    primitiveClassToSetterInterface.put(double.class, SetterDouble.class);
  }

  private PojoUtils()
  {
  }

  public interface GetterBoolean
  {
    boolean get(T obj);
  }

  public interface GetterByte
  {
    byte get(T obj);
  }

  public interface GetterChar
  {
    char get(T obj);
  }

  public interface GetterShort
  {
    short get(T obj);
  }

  public interface GetterInt
  {
    int get(T obj);
  }

  public interface GetterLong
  {
    long get(T obj);
  }

  public interface GetterFloat
  {
    float get(T obj);
  }

  public interface GetterDouble
  {
    double get(T obj);
  }

  public interface Getter
  {
    V get(T obj);
  }

  public static  GetterBoolean createGetterBoolean(Class pojoClass, String getterExpr)
  {
    return createGetterBoolean(pojoClass, getterExpr, DEFAULT_EXP_OBJECT_PLACEHOLDER);
  }

  @SuppressWarnings("unchecked")
  public static  GetterBoolean createGetterBoolean(Class pojoClass, String getterExpr, String exprObjectPlaceholder)
  {
    return (GetterBoolean)createGetter(pojoClass, getterExpr, exprObjectPlaceholder, boolean.class,
        GetterBoolean.class);
  }

  public static  GetterByte createGetterByte(Class pojoClass, String getterExpr)
  {
    return createGetterByte(pojoClass, getterExpr, DEFAULT_EXP_OBJECT_PLACEHOLDER);
  }

  @SuppressWarnings("unchecked")
  public static  GetterByte createGetterByte(Class pojoClass, String getterExpr, String exprObjectPlaceholder)
  {
    return (GetterByte)createGetter(pojoClass, getterExpr, exprObjectPlaceholder, byte.class, GetterByte.class);
  }

  public static  GetterChar createGetterChar(Class pojoClass, String getterExpr)
  {
    return createGetterChar(pojoClass, getterExpr, DEFAULT_EXP_OBJECT_PLACEHOLDER);
  }

  @SuppressWarnings({ "unchecked"})
  public static  GetterChar createGetterChar(Class pojoClass, String getterExpr, String exprObjectPlaceholder)
  {
    return (GetterChar)createGetter(pojoClass, getterExpr, exprObjectPlaceholder, char.class, GetterChar.class);
  }

  public static  GetterShort createGetterShort(Class pojoClass, String getterExpr)
  {
    return createGetterShort(pojoClass, getterExpr, DEFAULT_EXP_OBJECT_PLACEHOLDER);
  }

  @SuppressWarnings("unchecked")
  public static  GetterShort createGetterShort(Class pojoClass, String getterExpr, String exprObjectPlaceholder)
  {
    return (GetterShort)createGetter(pojoClass, getterExpr, exprObjectPlaceholder, short.class, GetterShort.class);
  }

  public static  GetterInt createGetterInt(Class pojoClass, String getterExpr)
  {
    return createGetterInt(pojoClass, getterExpr, DEFAULT_EXP_OBJECT_PLACEHOLDER);
  }

  @SuppressWarnings("unchecked")
  public static  GetterInt createGetterInt(Class pojoClass, String getterExpr, String exprObjectPlaceholder)
  {
    return (GetterInt)createGetter(pojoClass, getterExpr, exprObjectPlaceholder, int.class, GetterInt.class);
  }

  public static  GetterLong createGetterLong(Class pojoClass, String getterExpr)
  {
    return createGetterLong(pojoClass, getterExpr, DEFAULT_EXP_OBJECT_PLACEHOLDER);
  }

  @SuppressWarnings("unchecked")
  public static  GetterLong createGetterLong(Class pojoClass, String getterExpr, String exprObjectPlaceholder)
  {
    return (GetterLong)createGetter(pojoClass, getterExpr, exprObjectPlaceholder, long.class, GetterLong.class);
  }

  public static  GetterFloat createGetterFloat(Class pojoClass, String getterExpr)
  {
    return createGetterFloat(pojoClass, getterExpr, DEFAULT_EXP_OBJECT_PLACEHOLDER);
  }

  @SuppressWarnings("unchecked")
  public static  GetterFloat createGetterFloat(Class pojoClass, String getterExpr, String exprObjectPlaceholder)
  {
    return (GetterFloat)createGetter(pojoClass, getterExpr, exprObjectPlaceholder, float.class, GetterFloat.class);
  }

  public static  GetterDouble createGetterDouble(Class pojoClass, String getterExpr)
  {
    return createGetterDouble(pojoClass, getterExpr, DEFAULT_EXP_OBJECT_PLACEHOLDER);
  }

  @SuppressWarnings("unchecked")
  public static  GetterDouble createGetterDouble(Class pojoClass, String getterExpr, String exprObjectPlaceholder)
  {
    return (GetterDouble)createGetter(pojoClass, getterExpr, exprObjectPlaceholder, double.class,
        GetterDouble.class);
  }

  public static  Getter createGetter(Class pojoClass, String getterExpr, Class exprClass)
  {
    return createGetter(pojoClass, getterExpr, DEFAULT_EXP_OBJECT_PLACEHOLDER, exprClass);
  }

  @SuppressWarnings("unchecked")
  public static  Getter createGetter(Class pojoClass, String getterExpr, String exprObjectPlaceholder, Class exprClass)
  {
    if (primitiveClassToGetterInterface.get(exprClass) != null) {
      throw new IllegalArgumentException("createGetter does not allow primitive class \"" + exprClass.getName() +
              "\" for exprClass argument. Use createGetter" + upperCaseWord(exprClass.getName()) + " or constructGetter().");
    }
    return (Getter)createGetter(pojoClass, getterExpr, exprObjectPlaceholder, exprClass, Getter.class);
  }

  public static Object constructGetter(Class pojoClass, String getterExpr, Class exprClass)
  {
    return constructGetter(pojoClass, getterExpr, DEFAULT_EXP_OBJECT_PLACEHOLDER, exprClass);
  }

  public static Object constructGetter(Class pojoClass, String getterExpr, String exprObjectPlaceholder, Class exprClass)
  {
    Class interfaceToImplement = primitiveClassToGetterInterface.get(exprClass);
    if (interfaceToImplement == null) {
      interfaceToImplement = Getter.class;
    }
    return createGetter(pojoClass, getterExpr, exprObjectPlaceholder, exprClass, interfaceToImplement);
  }

  /**
   * Setter interface for boolean primitives
   * @param  class of objects that the setter applies to
   */
  public interface SetterBoolean
  {
    void set(T obj, boolean booleanVal);
  }

  /**
   * Setter interface for byte primitives
   * @param  class of objects that the setter applies to
   */
  public interface SetterByte
  {
    void set(T obj, byte byteVal);
  }

  /**
   * Setter interface for char primitives
   * @param  class of objects that the setter applies to
   */
  public interface SetterChar
  {
    void set(T obj, char charVal);
  }

  /**
   * Setter interface for short primitives
   * @param  class of objects that the setter applies to
   */
  public interface SetterShort
  {
    void set(T obj, short shortVal);
  }

  /**
   * Setter interface for int primitives
   * @param  class of objects that the setter applies to
   */
  public interface SetterInt
  {
    void set(T obj, int intVal);
  }

  /**
   * Setter interface for long primitives
   * @param  class of objects that the setter applies to
   */
  public interface SetterLong
  {
    void set(T obj, long longVal);
  }

  /**
   * Setter interface for float primitives
   * @param  class of objects that the setter applies to
   */
  public interface SetterFloat
  {
    void set(T obj, float floatVal);
  }

  /**
   * Setter interface for double primitives
   * @param  class of objects that the setter applies to
   */
  public interface SetterDouble
  {
    void set(T obj, double doubleVal);
  }

  /**
   * Setter interface for arbitrary object
   * @param  class of objects that the setter applies to
   * @param  class of the rhs expression
   */
  public interface Setter
  {
    void set(T obj, V value);
  }

  public static  SetterBoolean createSetterBoolean(Class pojoClass, String setterExpr)
  {
    return createSetterBoolean(pojoClass, setterExpr, DEFAULT_EXP_OBJECT_PLACEHOLDER, DEFAULT_EXP_VAL_PLACEHOLDER);
  }

  @SuppressWarnings("unchecked")
  public static  SetterBoolean createSetterBoolean(Class pojoClass, String setterExpr, String exprObjectPlaceholder, String exprValuePlaceholder)
  {
    return (SetterBoolean)createSetter(pojoClass, setterExpr, exprObjectPlaceholder, exprValuePlaceholder,
        boolean.class, SetterBoolean.class);
  }

  public static  SetterByte createSetterByte(Class pojoClass, String setterExpr)
  {
    return createSetterByte(pojoClass, setterExpr, DEFAULT_EXP_OBJECT_PLACEHOLDER, DEFAULT_EXP_VAL_PLACEHOLDER);
  }

  @SuppressWarnings("unchecked")
  public static  SetterByte createSetterByte(Class pojoClass, String setterExpr, String exprObjectPlaceholder, String exprValuePlaceholder)
  {
    return (SetterByte)createSetter(pojoClass, setterExpr, exprObjectPlaceholder, exprValuePlaceholder, byte.class,
        SetterByte.class);
  }

  public static  SetterChar createSetterChar(Class pojoClass, String setterExpr)
  {
    return createSetterChar(pojoClass, setterExpr, DEFAULT_EXP_OBJECT_PLACEHOLDER, DEFAULT_EXP_VAL_PLACEHOLDER);
  }

  @SuppressWarnings("unchecked")
  public static  SetterChar createSetterChar(Class pojoClass, String setterExpr, String exprObjectPlaceholder, String exprValuePlaceholder)
  {
    return (SetterChar)createSetter(pojoClass, setterExpr, exprObjectPlaceholder, exprValuePlaceholder, char.class,
        SetterChar.class);
  }

  public static  SetterShort createSetterShort(Class pojoClass, String setterExpr)
  {
    return createSetterShort(pojoClass, setterExpr, DEFAULT_EXP_OBJECT_PLACEHOLDER, DEFAULT_EXP_VAL_PLACEHOLDER);
  }

  @SuppressWarnings("unchecked")
  public static  SetterShort createSetterShort(Class pojoClass, String setterExpr, String exprObjectPlaceholder, String exprValuePlaceholder)
  {
    return (SetterShort)createSetter(pojoClass, setterExpr, exprObjectPlaceholder, exprValuePlaceholder, short.class,
        SetterShort.class);
  }

  public static  SetterInt createSetterInt(Class pojoClass, String setterExpr)
  {
    return createSetterInt(pojoClass, setterExpr, DEFAULT_EXP_OBJECT_PLACEHOLDER, DEFAULT_EXP_VAL_PLACEHOLDER);
  }

  @SuppressWarnings("unchecked")
  public static  SetterInt createSetterInt(Class pojoClass, String setterExpr, String exprObjectPlaceholder, String exprValuePlaceholder)
  {
    return (SetterInt)createSetter(pojoClass, setterExpr, exprObjectPlaceholder, exprValuePlaceholder, int.class,
        SetterInt.class);
  }

  public static  SetterLong createSetterLong(Class pojoClass, String setterExpr)
  {
    return createSetterLong(pojoClass, setterExpr, DEFAULT_EXP_OBJECT_PLACEHOLDER, DEFAULT_EXP_VAL_PLACEHOLDER);
  }

  @SuppressWarnings("unchecked")
  public static  SetterLong createSetterLong(Class pojoClass, String setterExpr, String exprObjectPlaceholder, String exprValuePlaceholder)
  {
    return (SetterLong)createSetter(pojoClass, setterExpr, exprObjectPlaceholder, exprValuePlaceholder, long.class,
        SetterLong.class);
  }

  public static  SetterFloat createSetterFloat(Class pojoClass, String setterExpr)
  {
    return createSetterFloat(pojoClass, setterExpr, DEFAULT_EXP_OBJECT_PLACEHOLDER, DEFAULT_EXP_VAL_PLACEHOLDER);
  }

  @SuppressWarnings("unchecked")
  public static  SetterFloat createSetterFloat(Class pojoClass, String setterExpr, String exprObjectPlaceholder, String exprValuePlaceholder)
  {
    return (SetterFloat)createSetter(pojoClass, setterExpr, exprObjectPlaceholder, exprValuePlaceholder, float.class,
        SetterFloat.class);
  }

  public static  SetterDouble createSetterDouble(Class pojoClass, String setterExpr)
  {
    return createSetterDouble(pojoClass, setterExpr, DEFAULT_EXP_OBJECT_PLACEHOLDER, DEFAULT_EXP_VAL_PLACEHOLDER);
  }

  @SuppressWarnings("unchecked")
  public static  SetterDouble createSetterDouble(Class pojoClass, String setterExpr, String exprObjectPlaceholder, String exprValuePlaceholder)
  {
    return (SetterDouble)createSetter(pojoClass, setterExpr, exprObjectPlaceholder, exprValuePlaceholder,
        double.class, SetterDouble.class);
  }

  public static  Setter createSetter(Class pojoClass, String setterExpr, Class exprClass)
  {
    return createSetter(pojoClass, setterExpr, DEFAULT_EXP_OBJECT_PLACEHOLDER, DEFAULT_EXP_VAL_PLACEHOLDER, exprClass);
  }

  @SuppressWarnings("unchecked")
  public static  Setter createSetter(Class pojoClass, String setterExpr, String exprObjectPlaceholder, String exprValuePlaceholder, Class exprClass)
  {
    if (primitiveClassToSetterInterface.get(exprClass) != null) {
      throw new IllegalArgumentException("createSetter does not allow primitive class \"" + exprClass.getName() +
              "\" for exprClass argument. Use createSetter" + upperCaseWord(exprClass.getName()) + " or constructSetter().");
    }
    return (Setter)createSetter(pojoClass, setterExpr, exprObjectPlaceholder, exprValuePlaceholder, exprClass,
        Setter.class);
  }

  public static Object constructSetter(Class pojoClass, String setterExpr, Class exprClass)
  {
    return constructSetter(pojoClass, setterExpr, DEFAULT_EXP_OBJECT_PLACEHOLDER, DEFAULT_EXP_VAL_PLACEHOLDER, exprClass);
  }

  /**
   *
   * @param pojoClass Class object that the setter applies to
   * @param setterExpr expression to use for setter
   * @param exprClass Class that setter will accept as parameter
   * @return instance of a class that implements requested Setter interface
   */
  public static Object constructSetter(Class pojoClass, String setterExpr, String exprObjectPlaceholder, String exprValPlaceholder, Class exprClass)
  {
    Class interfaceToImplement = primitiveClassToSetterInterface.get(exprClass);
    if (interfaceToImplement == null) {
      interfaceToImplement = Setter.class;
    }
    return createSetter(pojoClass, setterExpr, exprObjectPlaceholder, exprValPlaceholder, exprClass, interfaceToImplement);
  }

  private static class JavaStatement
  {
    private final StringBuilder javaStatement;
    private final int capacity;

    private JavaStatement()
    {
      javaStatement = new StringBuilder();
      capacity = javaStatement.capacity();
    }

    private JavaStatement(int length)
    {
      javaStatement = new StringBuilder(length);
      capacity = javaStatement.capacity();
    }

    @Override
    public String toString()
    {
      return javaStatement.toString();
    }

    protected JavaStatement append(String string)
    {
      javaStatement.append(string);
      return this;
    }

    private JavaStatement appendCastToTypeExpr(Class type, String expr)
    {
      return append("((").append(type.getName()).append(")(").append(expr).append("))");
    }

    protected String getStatement()
    {
      if (capacity < javaStatement.length() + 1) {
        logger.debug("Java statement capacity {} was not sufficient for the statement length {}. Actual statement {}", capacity, javaStatement.length(), javaStatement);
      }
      return javaStatement.append(";").toString();
    }
  }

  private static class JavaReturnStatement extends JavaStatement
  {
    private JavaReturnStatement(Class returnType)
    {
      super();
      append("return (").append(returnType.getName()).append(")");
    }

    private JavaReturnStatement(int length, Class returnType)
    {
      super(length);
      append("return ((").append(returnType.getName()).append(")");
    }

    @Override
    protected String getStatement()
    {
      append(")");
      return super.getStatement();
    }
  }

  private static String upperCaseWord(String field)
  {
    Preconditions.checkArgument(!field.isEmpty(), field);
    return field.substring(0, 1).toUpperCase() + field.substring(1);
  }

  /**
   * Return the getter expression for the given field.
   * 

* If the field is a public member, the field name is used else the getter function. If no matching field or getter * method is found, the expression is returned unmodified. * * @param pojoClass class to check for the field * @param fieldExpression field name expression * @param exprClass expected field type * @return java code fragment */ private static String getSingleFieldGetterExpression(final Class pojoClass, final String fieldExpression, final Class exprClass) { JavaStatement code = new JavaReturnStatement(pojoClass.getName().length() + fieldExpression.length() + exprClass.getName().length() + 32, exprClass); code.appendCastToTypeExpr(pojoClass, OBJECT).append("."); try { final Field field = pojoClass.getField(fieldExpression); if (ClassUtils.isAssignable(field.getType(), exprClass)) { return code.append(field.getName()).getStatement(); } logger.debug("Field {} can not be assigned to {}. Proceeding to locate a getter method.", field, exprClass); } catch (NoSuchFieldException ex) { logger.debug("{} does not have field {}. Proceeding to locate a getter method.", pojoClass, fieldExpression); } catch (SecurityException ex) { logger.debug("{} does not have field {}. Proceeding to locate a getter method.", pojoClass, fieldExpression); } String methodName = GET + upperCaseWord(fieldExpression); try { Method method = pojoClass.getMethod(methodName); if (ClassUtils.isAssignable(method.getReturnType(), exprClass)) { return code.append(methodName).append("()").getStatement(); } logger.debug("method {} of the {} returns {} that can not be assigned to {}. Proceeding to locate another getter method.", pojoClass, methodName, method.getReturnType(), exprClass); } catch (NoSuchMethodException | SecurityException ex) { logger.debug("{} does not have method {}. Proceeding to locate another getter method.", pojoClass, methodName); } methodName = IS + upperCaseWord(fieldExpression); try { Method method = pojoClass.getMethod(methodName); if (ClassUtils.isAssignable(method.getReturnType(), exprClass)) { return code.append(methodName).append("()").getStatement(); } logger.debug("method {} of the {} returns {} that can not be assigned to {}. Proceeding with the original expression {}.", pojoClass, methodName, method.getReturnType(), exprClass, fieldExpression); } catch (NoSuchMethodException | SecurityException ex) { logger.debug("{} does not have method {}. Proceeding with the original expression {}.", pojoClass, methodName, fieldExpression); } return code.append(fieldExpression).getStatement(); } @SuppressWarnings("StringEquality") private static Object createGetter(Class pojoClass, String getterExpr, String exprObjectPlaceholder, Class exprClass, Class getterClass) { logger.debug("{} {} {} {}", pojoClass, getterExpr, exprClass, getterClass); JavaExpressionParser javaExpressionParser = new JavaExpressionParser(); javaExpressionParser.setInputObjectPlaceholder(PojoUtils.DEFAULT_EXPRESSION_OBJ_PLACEHOLDER, PojoUtils.OBJECT); String code = javaExpressionParser.convertToCompilableExpression(getterExpr, pojoClass, exprClass); return compileExpression(code, getterClass, new String[] {PojoUtils.OBJECT}); } private static String getSingleFieldSetterExpression(final Class pojoClass, final String fieldExpression, final Class exprClass) { JavaStatement code = new JavaStatement(pojoClass.getName().length() + fieldExpression.length() + exprClass.getName().length() + 32); /* Construct (()pojo). */ code.appendCastToTypeExpr(pojoClass, OBJECT).append("."); try { final Field field = pojoClass.getField(fieldExpression); if (ClassUtils.isAssignable(exprClass, field.getType())) { /* there is public field on the class, use direct assignment. */ /* append = ()val; */ return code.append(field.getName()).append(" = ").appendCastToTypeExpr(exprClass, VAL).getStatement(); } logger.debug("{} can not be assigned to {}. Proceeding to locate a setter method.", exprClass, field); } catch (NoSuchFieldException ex) { logger.debug("{} does not have field {}. Proceeding to locate a setter method.", pojoClass, fieldExpression); } catch (SecurityException ex) { logger.debug("{} does not have field {}. Proceeding to locate a setter method.", pojoClass, fieldExpression); } final String setMethodName = SET + upperCaseWord(fieldExpression); Method bestMatchMethod = null; List candidates = new ArrayList(); for (Method method : pojoClass.getMethods()) { if (setMethodName.equals(method.getName())) { Class[] parameterTypes = method.getParameterTypes(); if (parameterTypes.length == 1) { if (exprClass == parameterTypes[0]) { bestMatchMethod = method; break; } else if (ClassUtils.isAssignable(exprClass, parameterTypes[0])) { candidates.add(method); } } } } if (bestMatchMethod == null) { // We did not find the exact match, use candidates to find the match if (candidates.size() == 0) { logger.debug("{} does not have suitable setter method {}. Returning original expression {}.", pojoClass, setMethodName, fieldExpression); /* We did not find any match at all, use original expression */ /* append = ()val;*/ return code.append(fieldExpression).append(" = ").appendCastToTypeExpr(exprClass, VAL).getStatement(); } else { // TODO: see if we can find a better match bestMatchMethod = candidates.get(0); } } /* We found a method that we may use for setter */ /* append (( pojoClass, String setterExpr, String exprObjectPlaceholder, String exprValPlaceholder, Class exprClass, Class setterClass) { if (setterExpr.startsWith(".")) { setterExpr = setterExpr.substring(1); } if (setterExpr.isEmpty()) { throw new IllegalArgumentException("The setter expression: \"" + setterExpr + "\" is invalid."); } logger.debug("{} {} {} {}", pojoClass, setterExpr, exprClass, setterClass); String code = StringUtils.replaceEach(setterExpr, new String[]{exprObjectPlaceholder, exprValPlaceholder}, new String[]{new JavaStatement().appendCastToTypeExpr(pojoClass, OBJECT).toString(), new JavaStatement().appendCastToTypeExpr(exprClass, VAL).toString()}); if (code != setterExpr) { code = new JavaStatement(code.length() + 1).append(code).getStatement(); logger.debug("Original expression {} is a complex expression. Replacing it with {}.", setterExpr, code); } else { code = getSingleFieldSetterExpression(pojoClass, setterExpr, exprClass); } return compileExpression(code, setterClass, new String[] {PojoUtils.OBJECT, PojoUtils.VAL}); } /** * This method takes in expression, compiles the expression to provide a executable form of expression. * This method uses {@link com.datatorrent.lib.expression.JavaExpressionParser} as expression parser. * * @param inputType Type of input object * @param expr expression to be compiled. * @param returnType Return type of the expression. * @return Object of type {@link Expression} which can be directly executed. */ public static Expression createExpression(Class inputType, String expr, Class returnType) { return createExpression(inputType, expr, returnType, null); } /** * This method takes in expression, compiles the expression to provide a executable form of expression. * This methods also takes in list of classes and method which can be imported statically in expression. *

* This method uses {@link JavaExpressionParser} as expression parser. * * @param inputType Type of input object * @param expr expression to be compiled. * @param returnType Return type of the expression. * @param defaultImports List of classes/method which will be statically imported to expression compilation. * @return Object of type {@link Expression} which can be directly executed. */ public static Expression createExpression(Class inputType, String expr, Class returnType, String[] defaultImports) { JavaExpressionParser javaExpressionParser = new JavaExpressionParser(); javaExpressionParser.setInputObjectPlaceholder("$", PojoUtils.OBJECT); return createExpression(inputType, expr, returnType, defaultImports, javaExpressionParser); } /** * This method takes in expression, compiles the expression to provide a executable form of expression. * This methods also takes in list of classes and method which can be imported statically in expression. *

* Using this method one can override expression parser implementation. * * @param inputType Type of input object * @param expr expression to be compiled. * @param returnType Return type of the expression. * @param defaultImports List of classes/method which will be statically imported to expression compilation. * @param parser Expression parser that should be used to parse expression. * @return Object of type {@link Expression} which can be directly executed. * @see {@link JavaExpressionParser} as a example. */ public static Expression createExpression(Class inputType, String expr, Class returnType, String[] defaultImports, Expression.ExpressionParser parser) { String code = parser.convertToCompilableExpression(expr, inputType, returnType); return (Expression)compileExpression(code, Expression.class, new String[] {PojoUtils.OBJECT}, defaultImports); } private static Object compileExpression(String code, Class implClass, String[] params) { return compileExpression(code, implClass, params, null); } private static Object compileExpression(String code, Class implClass, String[] params, String[] defaultImports) { List imports = new LinkedList<>(); if (defaultImports != null && defaultImports.length != 0) { for (String defaultImport : defaultImports) { if (defaultImport != null) { if (!defaultImport.startsWith("static")) { imports.add("static " + defaultImport); } else { imports.add(defaultImport); } } } } IScriptEvaluator se; try { se = CompilerFactoryFactory.getDefaultCompilerFactory().newScriptEvaluator(); se.setDefaultImports(imports.toArray(new String[imports.size()])); } catch (Exception ex) { throw new RuntimeException(ex); } try { logger.debug("code: {}", code); return se.createFastEvaluator(code, implClass, params); } catch (CompileException ex) { throw new RuntimeException(ex); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy