Property.java :  » Testing » Ejb3Unit » com » bm » introspectors » Java Open Source

Java Open Source » Testing » Ejb3Unit 
Ejb3Unit » com » bm » introspectors » Property.java
package com.bm.introspectors;

import java.beans.PropertyDescriptor;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.log4j.Logger;

import com.bm.ejb3metadata.annotations.metadata.FieldAnnotationMetadata;
import com.bm.utils.Ejb3Utils;

/**
 * Every persistent property of a EJB3 entity bean can be defined as field
 * access or method access (using setter/getters). The property class abstracts
 * from the access method and represtets a field (AccessType.FIELD) OR
 * getter/setter (AccessType.PROPERTY)
 * 
 * @author Daniel Wiese
 * 
 */
public class Property {

  private static final Logger log = Logger.getLogger(Property.class);

  private final String propertyName;

  private final Field fieldName;

  private final PropertyDescriptor property;

  private final Class declaringClass;

  private final boolean accessTypeField;

  /**
   * Contructor using getter/setter access.
   * 
   * @param declaringClass -
   *            the class wich declares the property
   * 
   * @param property -
   *            the property descriptor
   */
  public Property(Class declaringClass, PropertyDescriptor property) {
    this.propertyName = property.getName();
    this.property = property;
    this.fieldName = null;
    this.accessTypeField = false;
    this.declaringClass = declaringClass;
  }

  /**
   * Contructor using field access. Ejb3 metadata is passed directly.
   * 
   * @param metaData
   *            the ejb3 metadata information
   * 
   */
  public Property(FieldAnnotationMetadata metaData) {
    this.propertyName = metaData.getFieldName();
    this.property = null;
    this.accessTypeField = true;
    try {
      this.declaringClass = Thread.currentThread()
          .getContextClassLoader().loadClass(
              metaData.getClassAnnotationMetadata()
                  .getClassName().replace('/', '.'));
    } catch (ClassNotFoundException e) {
      throw new RuntimeException("The class ("
          + metaData.getClassAnnotationMetadata().getClassName()
          + ") was not found");
    }

    try {
      this.fieldName = this.declaringClass
          .getDeclaredField(this.propertyName);
    } catch (SecurityException e) {
      throw new RuntimeException("The field (" + this.propertyName
          + ") in Class  ("
          + metaData.getClassAnnotationMetadata().getClassName()
          + ") was not found");
    } catch (NoSuchFieldException e) {
      throw new RuntimeException("The field (" + this.propertyName
          + ") in Class  ("
          + metaData.getClassAnnotationMetadata().getClassName()
          + ") was not found");
    }
  }

  /**
   * Contructor uing field access.
   * 
   * @param fieldName -
   *            der name des feldes
   */
  public Property(Field fieldName) {
    this.propertyName = fieldName.getName();
    this.fieldName = fieldName;
    this.property = null;
    this.accessTypeField = true;
    this.declaringClass = fieldName.getDeclaringClass();
  }

  /**
   * Sets a value of the field / getterMethod.
   * 
   * @author Daniel Wiese
   * @param instance -
   *            the instance (Typed)
   * @param value -
   *            the new value
   * @throws IllegalAccessException -
   *             in error case
   */
  public void setField(Object instance, Object value)
      throws IllegalAccessException {
    try {
      if (this.accessTypeField) {
        // access type property
        if (!this.fieldName.isAccessible()) {
          this.fieldName.setAccessible(true);
          this.fieldName.set(instance, value);
          this.fieldName.setAccessible(false);
        } else {
          this.fieldName.set(instance, value);
        }
      } else {
        try {
          // acces type property
          PropertyUtils.setProperty(instance, this.propertyName,
              value);
        } catch (InvocationTargetException e) {
          log.error("Cant set the value (" + value
              + ") in property: " + this.propertyName);
          throw new IllegalAccessException(
              "Cant invoke the setter method set"
                  + this.propertyName);
        } catch (NoSuchMethodException e) {
          log.error("Cant set the value (" + value
              + ") in property: " + this.propertyName);
          throw new IllegalAccessException(
              "Cant invoke the setter method set"
                  + this.propertyName);
        } catch (IllegalArgumentException e) {
          log.error("Cant set the value (" + value
              + ") in property: " + this.propertyName);
          throw e;
        }
      }
    } catch (IllegalAccessException ex) {
      log.error("Cant set the value (" + value + ") in property: "
          + this.propertyName, ex);
      throw ex;
    } catch (RuntimeException ruex) {

      log.error("Cant set the value (" + value + ") in property: "
          + this.propertyName, ruex);
      throw ruex;

    }
  }

  /**
   * Returns a value of an field.
   * 
   * @author Daniel Wiese
   * @param instance -
   *            the instance
   * @return - the value of the paremeter of the instance
   * @throws IllegalAccessException -
   *             in error case
   */
  public Object getField(Object instance) throws IllegalAccessException {
    Object back = null;
    if (this.accessTypeField) {
      // access type property
      if (!this.fieldName.isAccessible()) {
        this.fieldName.setAccessible(true);
        back = this.fieldName.get(instance);
        this.fieldName.setAccessible(false);
      } else {
        back = this.fieldName.get(instance);
      }
    } else {
      try {
        // acces type property
        back = PropertyUtils.getProperty(instance, this.propertyName);
      } catch (InvocationTargetException e) {
        throw new IllegalAccessException(
            "Cant invoke the getter method get"
                + this.propertyName);
      } catch (NoSuchMethodException e) {
        throw new IllegalAccessException(
            "Cant invoke the getter method get"
                + this.propertyName);
      }
    }
    return back;
  }

  /**
   * Returns the type of the property.
   * 
   * @return - the type
   */
  public Class getType() {
    if (this.accessTypeField) {
      return this.fieldName.getType();
    }
    final Method method = this.property.getReadMethod();
    return method.getReturnType();

  }

  /**
   * Returns the generic Type of this property. E.g. id the proprty is.
   * Collection/Order/ then Order will be returned.
   * 
   * @author Daniel Wiese
   * @since 28.10.2005
   * @return the generic Type of this property
   */
  public Type getGenericType() {
    if (this.accessTypeField) {
      return this.fieldName.getGenericType();
    }
    final Method methodToFind = this.property.getReadMethod();
    return methodToFind.getGenericReturnType();
  }

  /**
   * If the propety represents a genericType (e.g. Collection/Order/) ! Typed
   * class thit ONE type) -> then the type is returned.
   * 
   * @return - the type of the typed class or null
   */
  @SuppressWarnings("unchecked")
  public Class<Object> getGenericTypeClass() {
    if (this.getGenericType() instanceof ParameterizedType) {
      final ParameterizedType type = (ParameterizedType) this
          .getGenericType();
      if (type.getActualTypeArguments().length == 1) {
        Class<Object> ty = (Class<Object>) type
            .getActualTypeArguments()[0];
        return ty;
      }
    }
    return null;
  }

  /**
   * Return the name.
   * 
   * @return - the name
   */
  public String getName() {
    return this.propertyName;
  }

  /**
   * Returns the class where the property is declared.
   * 
   * @return Returns the declaringClass.
   */
  public Class getDeclaringClass() {
    return this.declaringClass;
  }

  /**
   * Equals.
   * 
   * @param other
   *            the other to compare
   * @return - true if equal
   * @see java.lang.Object#equals(java.lang.Object)
   */
  @Override
  public boolean equals(Object other) {
    if (other instanceof Property) {
      final Property otherC = (Property) other;
      final EqualsBuilder eqBuilder = new EqualsBuilder();
      eqBuilder.append(this.accessTypeField, otherC.accessTypeField);
      eqBuilder.append(this.fieldName, otherC.fieldName);
      eqBuilder.append(this.property, otherC.property);
      return eqBuilder.isEquals();

    }
    return false;
  }

  /**
   * Hash Code.
   * 
   * @return the hash code
   * @see java.lang.Object#hashCode()
   */
  @Override
  public int hashCode() {
    final HashCodeBuilder hcBuilder = new HashCodeBuilder(3, 17);
    hcBuilder.append(this.accessTypeField);
    hcBuilder.append(this.fieldName);
    hcBuilder.append(this.property);
    return hcBuilder.toHashCode();
  }

  /**
   * Returns the property.
   * 
   * @return Returns the property.
   */
  public PropertyDescriptor getProperty() {
    return property;
  }

  /**
   * Returns null if the accestype is field.
   * 
   * @return Returns the propertyName.
   */
  public String getPropertyName() {
    return propertyName;
  }

  /**
   * Returns a annotation for the current property if present.
   * 
   * @param <T>
   *            the annotation type.
   * @param annnotation
   *            the annotation class
   * @return the annotation instance
   */
  public <T extends Annotation> T getAnnotation(Class<T> annnotation) {
    if (this.accessTypeField) {
      return this.fieldName.getAnnotation(annnotation);
    }
    return this.property.getReadMethod().getAnnotation(annnotation);
  }

  /**
   * To String.
   * 
   * @return - formatted string
   * @see java.lang.Object#toString()
   */
  @Override
  public String toString() {
    final StringBuilder sb = new StringBuilder();
    sb.append("Declared in Class: (").append(
        Ejb3Utils.getShortClassName(this.getDeclaringClass())).append(
        ") Prop.Name: (").append(this.propertyName)
        .append(") - Type (").append(
            Ejb3Utils.getShortClassName(this.getType()))
        .append(")");
    return sb.toString();
  }
}
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.