Fast Property accessor for a single class. : Field « Reflection « Java

Home
Java
1.2D Graphics GUI
2.3D
3.Advanced Graphics
4.Ant
5.Apache Common
6.Chart
7.Class
8.Collections Data Structure
9.Data Type
10.Database SQL JDBC
11.Design Pattern
12.Development Class
13.EJB3
14.Email
15.Event
16.File Input Output
17.Game
18.Generics
19.GWT
20.Hibernate
21.I18N
22.J2EE
23.J2ME
24.JDK 6
25.JNDI LDAP
26.JPA
27.JSP
28.JSTL
29.Language Basics
30.Network Protocol
31.PDF RTF
32.Reflection
33.Regular Expressions
34.Scripting
35.Security
36.Servlets
37.Spring
38.Swing Components
39.Swing JFC
40.SWT JFace Eclipse
41.Threads
42.Tiny Application
43.Velocity
44.Web Services SOA
45.XML
Java » Reflection » FieldScreenshots 
Fast Property accessor for a single class.
        
/**
 * Copyright (C) 2010 altuure <altuure [AT] gmail [DOT] com> http://www.altuure.com/projects/yagdao
 *
 * Licensed 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.altuure.yagdao.common;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * Fast Property accessor for a single class.
 
 @author altuure
 */

@SuppressWarnings("rawtypes")
public class FastPropertyUtil {
  public static final Log log = LogFactory.getLog(FastPropertyUtil.class);
  /**
   * init setter and getter lazy.
   */
  public static final boolean LAZY = true;

  /**
   * Get method prefix.
   */
  private static final String GET = "get";
  /**
   * is method prefix.
   */
  private static final String IS = "is";
  /**
   * set method prefix.
   */
  private static final String SET = "set";

  /**
   * set method cache.
   */
  private Map<String, NestedHandler> setters = new HashMap<String, NestedHandler>();

  /**
   * getter method cache.
   */
  private Map<String, NestedHandler> getters = new HashMap<String, NestedHandler>();

  /**
   * wrapped class .
   */
  private Class adaptedClass;

  /**
   * create new instance for given class.
   
   @see #LAZY
   @param adaptedClass
   *            wrapped class
   */
  public FastPropertyUtil(Class adaptedClass) {
    this(adaptedClass, LAZY);

  }

  /**
   * create new instance for given class .
   
   @param adaptedClass
   *            wrapped class
   @param initLazy
   *            true if init lazy or false init now
   */
  public FastPropertyUtil(Class adaptedClass, boolean initLazy) {
    super();
    this.adaptedClass = adaptedClass;
    init(initLazy);
  }

  /**
   * set object property value.
   
   @param obj
   *            object
   @param property
   *            property
   @param value
   *            value
   @throws IllegalArgumentException
   *             underlying exception
   @see {@link Method#invoke(Object, Object...)}
   @throws IllegalAccessException
   *             underlying exception
   @see {@link Method#invoke(Object, Object...)}
   @throws InvocationTargetException
   *             underlying exception
   @throws InstantiationException
   *             new instance error
   @see {@link Method#invoke(Object, Object...)}
   */
  public void set(Object obj, String property, Object value)
      throws IllegalArgumentException, IllegalAccessException,
      InvocationTargetException, InstantiationException {
    if (setters.containsKey(property)) {
      NestedHandler member = setters.get(property);
      member.set(obj, value);
    else {
      NestedHandler nestedHandler = new NestedHandler(property, true);
      setters.put(property, nestedHandler);
      nestedHandler.set(obj, value);
    }

  }

  /**
   * get object property value.
   
   @param obj
   *            object
   @param property
   *            property
   @return value
   @throws IllegalArgumentException
   *             underlying exception
   @see {@link Method#invoke(Object, Object...)}
   @throws IllegalAccessException
   *             underlying exception
   @see {@link Method#invoke(Object, Object...)}
   @throws InvocationTargetException
   *             underlying exception
   @see {@link Method#invoke(Object, Object...)}
   */
  public Object get(Object obj, String property)
      throws IllegalArgumentException, IllegalAccessException,
      InvocationTargetException {
    if (getters.containsKey(property)) {
      NestedHandler member = getters.get(property);
      return member.get(obj);
    else {
      NestedHandler nestedHandler = new NestedHandler(property, false);
      getters.put(property, nestedHandler);
      return nestedHandler.get(obj);
    }

  }

  /**
   * goes through fields and initialize caches setters and getters.
   
   @param initLazy
   *            is lazy
   */
  private void init(boolean initLazy) {
    if (initLazy)
      return;
    Field[] fields = adaptedClass.getFields();

    for (Field field : fields) {
      field.setAccessible(true);
      setters.put(field.getName()new NestedHandler(field));
      getters.put(field.getName()new NestedHandler(field));
    }
    Method[] methods = adaptedClass.getMethods();
    for (Method method : methods) {

      if (isPropertyAccessor(method))
        continue;// not a property accessor;
      String propertyName = getPropertyAccessor(method);
      if (propertyName != null)
        getters.put(propertyName, new NestedHandler(method));
      propertyName = setPropertyAccessor(method);
      if (propertyName != null)
        setters.put(propertyName, new NestedHandler(method));
    }

  }

  /**
   * return a property name for setter methods .
   
   @param method
   *            method
   @return null if not starts with set
   */
  private String setPropertyAccessor(Method method) {
    return propertyAccessor(method, SET);
  }

  /**
   * return a property name for getter methods .
   
   @param method
   *            method
   @return null if not starts with is or get
   */
  private String getPropertyAccessor(Method method) {
    return propertyAccessor(method, IS, GET);
  }

  /**
   * check if the method starts with given prefix and if yes retriev the
   * property name.
   
   @param method
   *            method
   @param prefixs
   *            potential prefix s
   @return null is not available
   */
  private String propertyAccessor(Method method, String... prefixs) {
    String name = method.getName();
    String property;
    String prefix = null;
    for (String prefixCandidate : prefixs) {
      if (name.startsWith(prefixCandidate)) {
        prefix = prefixCandidate;
        break;
      }
    }

    // if not qualified accessor return null
    if (prefix == null)
      return null;
    if (name.length() < prefix.length() 1)
      return null;
    property = name.substring(prefix.length(), prefix.length() 1)
        .toLowerCase(Locale.ENGLISH);
    if (name.length() > prefix.length() 2)
      property += name.substring(prefix.length() 1);

    return property;
  }

  /**
   * checks if there is any valid prefix: is,get,get.
   
   @param method
   *            method to be check
   @return true if there is any parameter
   */
  private boolean isPropertyAccessor(Method method) {
    String name = method.getName();
    return name.startsWith(IS|| name.startsWith(GET)
        || name.startsWith(SET);
  }

  /**
   * property handle property.
   
   @author altuure
   */
  public class NestedHandler {
    /**
     * list of access members
     */
    private List<Member> members;
    private List<Member> setMembers;

    /**
     * single method handler.
     
     @param member
     *            delegated member
     */
    public NestedHandler(Member member) {
      members = new ArrayList<Member>(1);
      members.add(member);

    }

    /**
     * create instance for given class for given property.
     
     @param property
     *            property eg: name or product.name
     @param writeOperation
     *            true if set else false
     */
    public NestedHandler(String property, boolean writeOperation) {
      initThis(writeOperation, property);
    }

    /**
     * parse property and find access method.
     
     @param writeOperation
     *            true if set else false
     @param property
     *            property
     */
    private void initThis(boolean writeOperation, String property) {
      String[] split = splitDot(property);
      members = new ArrayList<Member>(split.length - 1);
      setMembers = new ArrayList<Member>(split.length - 1);
      Class currentClass = adaptedClass;

      for (int i = 0; i < split.length - 1; i++) {
        String string = split[i];
        Member member;
        member = findAccessor(currentClass, i, string, GET, IS);
        Member setMember = findAccessor(currentClass, i, string, SET);
        if (member == null)
          throw new IllegalArgumentException(
              "no such property found " + currentClass.getName()
                  "." + string);
        members.add(member);
        setMembers.add(setMember);
        if (member instanceof Method) {
          Method m = (Methodmember;
          currentClass = m.getReturnType();
        else if (member instanceof Field) {
          Field m = (Fieldmember;
          currentClass = m.getType();
        }
      }
      Member lastMember;
      String lastProperty = split[split.length - 1];
      if (writeOperation) {
        lastMember = findAccessor(currentClass, split.length - 1,
            lastProperty, SET);
      else {
        lastMember = findAccessor(currentClass, split.length - 1,
            lastProperty, GET, IS);
      }
      if (lastMember == null)
        throw new IllegalArgumentException("no such property found "
            + currentClass.getName() "." + lastProperty);
      members.add(lastMember);

    }

    /**
     * find access method or field for given class.
     
     @param currentClass
     *            given class
     @param i
     *            depth
     @param property
     *            property with no .
     @param prefixs
     *            possible method prefixs
     @return null if not found
     */
    @SuppressWarnings("unchecked")
    private Member findAccessor(Class currentClass, int i, String property,
        String... prefixs) {
      Member member = null;
      if (i == && getters.containsKey(property)) {
        member = getters.get(property).getLastMember();
      else {

        for (String prefix : prefixs) {
          try {
            member = findMethod(currentClass, property, prefix);
            break;
          catch (NoSuchMethodException e) {
            if (log.isDebugEnabled())
              log.debug("method not found: "
                  + currentClass.getName() "#" + prefix
                  + capitilize(property));

          catch (SecurityException e) {
            if (log.isDebugEnabled())
              log.debug("method is not accessible: "
                  + currentClass.getName() "#" + prefix
                  + capitilize(property));
          }

        }

        try {
          if (member == null) {
            final Field field = currentClass.getField(property);
            field.setAccessible(true);
            member = field;
          }

        catch (NoSuchFieldException e) {
          if (log.isDebugEnabled())
            log.debug("field is not found: "
                + currentClass.getName() "#" + property);

        }
      }
      return member;
    }

    private Method findMethod(Class currentClass, String property,
        String prefixthrows NoSuchMethodException {
      String name = prefix + capitilize(property);

      try {
        return currentClass.getMethod(name);
      catch (NoSuchMethodException e) {
        log.debug("method not found", e);
      }
      Method[] methods = currentClass.getMethods();
      for (Method method : methods) {
        if (method.getName().equals(name))
          return method;
      }
      throw new NoSuchMethodException("no such method found in "
          + currentClass.getName() ":" + name);
    }

    /**
     * get object property value.
     
     @param obj
     *            object
     @return value
     @throws IllegalArgumentException
     *             underlying exception
     @see {@link Method#invoke(Object, Object...)}
     @throws IllegalAccessException
     *             underlying exception
     @see {@link Method#invoke(Object, Object...)}
     @throws InvocationTargetException
     *             underlying exception
     @see {@link Method#invoke(Object, Object...)}
     */
    public Object get(Object objthrows IllegalArgumentException,
        IllegalAccessException, InvocationTargetException {
      Object currentObject = obj;
      for (Member member : members) {
        currentObject = executeGetterMember(currentObject, member);
      }
      return currentObject;
    }

    /**
     * set object property value.
     
     @param obj
     *            object
     @param value
     *            property value
     @throws IllegalArgumentException
     *             underlying exception
     @see {@link Method#invoke(Object, Object...)}
     @throws IllegalAccessException
     *             underlying exception
     @see {@link Method#invoke(Object, Object...)}
     @throws InvocationTargetException
     *             underlying exception
     @throws InstantiationException
     *             new instance error
     @see {@link Method#invoke(Object, Object...)}
     */
    public void set(Object obj, Object value)
        throws IllegalArgumentException, IllegalAccessException,
        InvocationTargetException, InstantiationException {
      Object currentObject = obj;
      for (int i = 0; i < members.size(); i++) {
        Member member = members.get(i);

        if (i < members.size() 1) {
          Object tempObject = executeGetterMember(currentObject,
              member);
          if (tempObject == null) {
            Member setMember = setMembers.get(i);
            tempObject = initSetterMember(currentObject, setMember);
          }
          currentObject = tempObject;
        else {
          currentObject = executeSetterMember(currentObject, member,
              value);

        }
      }
    }

    /**
     * execute setter method or field.
     
     @param currentObject
     *            obj
     @param member
     *            member
     @param value
     *            set value
     @return get value
     @throws IllegalAccessException
     *             delegated exception
     @throws java.lang.reflect.InvocationTargetException
     *             delegated exception
     */
    private Object executeSetterMember(Object currentObject, Member member,
        Object valuethrows IllegalAccessException,
        InvocationTargetException {
      if (member instanceof Method) {
        Method m = (Methodmember;
        currentObject = m.invoke(currentObject, value);
      else if (member instanceof Field) {
        Field m = (Fieldmember;
        m.set(currentObject, value);
        currentObject = null;
      }
      return currentObject;
    }

    private Object initSetterMember(Object currentObject, Member member)
        throws IllegalAccessException, InvocationTargetException,
        InstantiationException {
      Object value = null;
      if (member instanceof Method) {
        Method m = (Methodmember;
        value = m.getParameterTypes()[0].newInstance();
        m.invoke(currentObject, value);
      else if (member instanceof Field) {
        Field m = (Fieldmember;
        value = m.getType().newInstance();
        m.set(currentObject, value);

      }
      return value;
    }

    /**
     * Execute getter method or field.
     
     @param currentObject
     *            obj
     @param member
     *            executed value
     @return return value
     @throws IllegalAccessException
     *             delegated exception
     @throws java.lang.reflect.InvocationTargetException
     *             delegated exception
     */
    private Object executeGetterMember(Object currentObject, Member member)
        throws IllegalAccessException, InvocationTargetException {
      if (member instanceof Method) {
        Method m = (Methodmember;
        currentObject = m.invoke(currentObject);
      else if (member instanceof Field) {
        Field m = (Fieldmember;
        currentObject = m.get(currentObject);
      }
      return currentObject;
    }

    /**
     * last property field or method.
     
     @return member
     */
    public Member getLastMember() {
      return members.get(members.size() 1);
    }

  }

  /**
   * upperCase only first string.
   
   @param text
   *            whole input text
   @return capitilized text
   */
  public static String capitilize(String text) {
    if (text == null)
      return null;
    if (text.length() == 0)
      return text;
    String result = text.substring(01).toUpperCase(Locale.ENGLISH);
    if (text.length() 1)
      result += text.substring(1);
    return result;
  }

  /**
   * split text with dot seperator.
   
   @param text
   *            text to split
   @return splitted text
   */
  public static String[] splitDot(String text) {
    String DOT_SEPERATOR_REGEX = "\\.";
    return text.split(DOT_SEPERATOR_REGEX);
  }

}

   
    
    
    
    
    
    
    
  
Related examples in the same category
1.Field Reflection
2.How to set public field objects
3.Class Reflection: field informationClass Reflection: field information
4.Object Reflection: get field valueObject Reflection: get field value
5.Object Reflection: set valueObject Reflection: set value
6.Get field of a class object and set or get its value
7.All Fields Snippet
8.Field modifiers: isSynthetic, isEnumConstant
9.Field with annotations
10.Set private field value
11.Get fields of a class object
12.Get all object accessible public fields
13.Getting the Field Objects of a Class Object: By obtaining a list of all declared fields.
14.Getting the Field Objects of a Class Object: By obtaining a list of all public fields, both declared and inherited.
15.Getting the Field Objects of a Class Object: By obtaining a particular Field object.
16.Get all declared fields from a class
17.Retrieving a Predefined Color by Name
18.Get a variable value from the variable name
19.Fetches all fields of all access types from the supplied class and super classes
20.Checks whether the specified class contains a field matching the specified name.
21.whether given field is a "public static final" constant
22.Process bean properties getter by applying the JavaBean naming conventions.
23.Fetches the property descriptor for the named property of the supplied class
24.Find Field
25.Return a list of all fields (whatever access status, and on whatever superclass they were defined) that can be found on this class.
26.Get all fields of a class.
27.Find field 2
28.Get class field/property
29.Accessible Field Iterator
30.Adds all Fields (from Class.getFields) to the list
31.Retrieve a value from a property
32.Set the value of the field of the object to the given value.
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.