Package jodd.bean

Source Code of jodd.bean.BeanUtilUtil

// Copyright (c) 2003-2014, Jodd Team (jodd.org). All Rights Reserved.

package jodd.bean;

import jodd.introspector.Getter;
import jodd.introspector.Introspector;
import jodd.introspector.Setter;
import jodd.typeconverter.TypeConverterManager;
import jodd.typeconverter.TypeConverterManagerBean;
import jodd.util.ReflectUtil;

import java.lang.reflect.Array;
import java.util.Collection;
import java.util.List;

/**
* Various bean property utilities that makes writings of {@link BeanUtil} classes easy.
*/
class BeanUtilUtil {

  protected Introspector introspector = JoddBean.introspector;
  protected TypeConverterManagerBean typeConverterManager = TypeConverterManager.getDefaultTypeConverterManager();

  /**
   * Sets {@link Introspector introspector} implementation.
   */
  public void setIntrospector(Introspector introspector) {
    this.introspector = introspector;
  }

  /**
   * Returns {@link Introspector introspector} implementation.
   */
  public Introspector getIntrospector() {
    return introspector;
  }

  /**
   * Sets {@link TypeConverterManagerBean type converter manager} implementation.
   */
  public void setTypeConverterManager(TypeConverterManagerBean typeConverterManager) {
    this.typeConverterManager = typeConverterManager;
  }

  /**
   * Returns {@link TypeConverterManagerBean type converter manager} implementation.
   */
  public TypeConverterManagerBean getTypeConverterManager() {
    return typeConverterManager;
  }

  /**
   * Converts object to destination type. Invoked before the
   * value is set into destination. Throws <code>TypeConversionException</code>
   * if conversion fails.
   */
  @SuppressWarnings("unchecked")
  protected Object convertType(Object value, Class type) {
    return typeConverterManager.convertType(value, type);
  }

  /**
   * Convert to collection.
   */
  protected Object convertToCollection(Object value, Class destinationType, Class componentType) {
    return typeConverterManager.convertToCollection(value, destinationType, componentType);
  }

 
  // ---------------------------------------------------------------- accessors

  /**
   * Invokes setter, but first converts type to match the setter type.
   */
  protected Object invokeSetter(Setter setter, BeanProperty bp, Object value) {
    try {
      Class type = setter.getSetterRawType();

      if (ReflectUtil.isTypeOf(type, Collection.class)) {
        Class componentType = setter.getSetterRawComponentType();

        value = convertToCollection(value, type, componentType);
      } else {
        // no collections
        value = convertType(value, type);
      }

      setter.invokeSetter(bp.bean, value);
    } catch (Exception ex) {
      if (bp.silent) {
        return null;
      }
      throw new BeanException("Setter failed: " + setter, ex);
    }
    return value;
  }

  // ---------------------------------------------------------------- forced

  /**
   * Returns the element of an array forced. If value is <code>null</code>, it will be instantiated.
   * If not the last part of indexed bean property, array will be expanded to the index if necessary.
   */
  protected Object arrayForcedGet(BeanProperty bp, Object array, int index) {
    Class componentType = array.getClass().getComponentType();
    if (bp.last == false) {
      array = ensureArraySize(bp, array, componentType, index);
    }
    Object value = Array.get(array, index);
    if (value == null) {
      try {
        value = ReflectUtil.newInstance(componentType);
      } catch (Exception ex) {
        if (bp.silent) {
          return null;
        }
        throw new BeanException("Invalid array element: " + bp.name + '[' + index + ']', bp, ex);
      }
      Array.set(array, index, value);
    }
    return value;
  }

  /**
   * Sets the array element forced. If index is greater then arrays length, array will be expanded to the index.
   * If speed is critical, it is better to allocate an array with proper size before using this method.
   */
  protected void arrayForcedSet(BeanProperty bp, Object array, int index, Object value) {
    Class componentType = array.getClass().getComponentType();
    array = ensureArraySize(bp, array, componentType, index);
    value = convertType(value, componentType);
    Array.set(array, index, value);
  }


  @SuppressWarnings({"SuspiciousSystemArraycopy"})
  protected Object ensureArraySize(BeanProperty bp, Object array, Class componentType, int index) {
    int len = Array.getLength(array);
    if (index >= len) {
      Object newArray = Array.newInstance(componentType, index + 1);
      System.arraycopy(array, 0, newArray, 0, len);

      Setter setter = bp.getSetter(true);
      if (setter == null) {
        // no point to check for bp.silent, throws NPE later
        throw new BeanException("Setter or field not found: " + bp.name, bp);
      }

      newArray = invokeSetter(setter, bp, newArray);

      array = newArray;
    }
    return array;
  }

  @SuppressWarnings({"unchecked"})
  protected void ensureListSize(List list, int size) {
    int len = list.size();
    while (size >= len) {
      list.add(null);
      len++;
    }
  }

  // ---------------------------------------------------------------- index

  /**
   * Finds the very first next dot. Ignores dots between index brackets.
   * Returns <code>-1</code> when dot is not found.
   */
  protected int indexOfDot(String name) {
    int ndx = 0;
    int len = name.length();

    boolean insideBracket = false;

    while (ndx < len) {
      char c = name.charAt(ndx);

      if (insideBracket) {
        if (c == ']') {
          insideBracket = false;
        }
      } else {
        if (c == '.') {
          return ndx;
        }
        if (c == '[') {
          insideBracket = true;
        }
      }
      ndx++;
    }
    return -1;
  }


  /**
   * Extract index string from non-nested property name.
   * If index is found, it is stripped from bean property name.
   * If no index is found, it returns <code>null</code>.
   */
  protected String extractIndex(BeanProperty bp) {
    bp.index = null;
    String name = bp.name;
    int lastNdx = name.length() - 1;
    if (lastNdx < 0) {
      return null;
    }
    if (name.charAt(lastNdx) == ']') {
      int leftBracketNdx = name.lastIndexOf('[');
      if (leftBracketNdx != -1) {
        bp.setName(name.substring(0, leftBracketNdx));
        bp.index = name.substring(leftBracketNdx + 1, lastNdx);
        return bp.index;
      }
    }
    return null;
  }

  protected int parseInt(String indexString, BeanProperty bp) {
    try {
      return Integer.parseInt(indexString);
    } catch (NumberFormatException nfex) {
      // no point to use bp.silent, as will throw exception
      throw new BeanException("Invalid index: " + indexString, bp, nfex);
    }
  }

  // ---------------------------------------------------------------- create property

  /**
   * Creates new instance for current property name through its setter.
   * It uses default constructor!
   */
  protected Object createBeanProperty(BeanProperty bp) {
    Setter setter = bp.getSetter(true);
    if (setter == null) {
      return null;
    }

    Class type = setter.getSetterRawType();

    Object newInstance;
    try {
      newInstance = ReflectUtil.newInstance(type);
    } catch (Exception ex) {
      if (bp.silent) {
        return null;
      }
      throw new BeanException("Invalid property: " + bp.name, bp, ex);
    }

    newInstance = invokeSetter(setter, bp, newInstance);

    return newInstance;
  }

  // ---------------------------------------------------------------- generic and type

  /**
   * Extracts generic component type of a property. Returns <code>Object.class</code>
   * when property does not have component.
   */
  protected Class extractGenericComponentType(Getter getter) {
    Class componentType = null;

    if (getter != null) {
      componentType = getter.getGetterRawComponentType();
    }

    if (componentType == null) {
      componentType = Object.class;
    }
    return componentType;
  }

  /**
   * Converts <b>Map</b> index to key type. If conversion fails, original value will be returned.
   */
  protected Object convertIndexToMapKey(Getter getter, Object index) {
    Class indexType = null;

    if (getter != null) {
      indexType = getter.getGetterRawKeyComponentType();
    }

    // check if set
    if (indexType == null) {
      indexType = Object.class// marker for no generic type
    }

    if (indexType == Object.class) {
      return index;
    }

    try {
      return convertType(index, indexType);
    } catch (Exception ignore) {
      return index;
    }
  }

  /**
   * Extracts type of current property.
   */
  protected Class extractType(BeanProperty bp) {
    Getter getter = bp.getGetter(bp.declared);
    if (getter != null) {
      if (bp.index != null) {
        Class type = getter.getGetterRawComponentType();
        return type == null ? Object.class : type;
      }
      return getter.getGetterRawType();
    }

    return null// this should not happens
  }

}
TOP

Related Classes of jodd.bean.BeanUtilUtil

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.