Open Source Repository

Home /hibernate/hibernate-3.2.4.ga | Repository Home


org/hibernate/property/PropertyAccessorFactory.java
//$Id: PropertyAccessorFactory.java 8451 2005-10-24 08:45:37Z maxcsaucdk $
package org.hibernate.property;

import java.util.Map;

import org.hibernate.MappingException;
import org.hibernate.EntityMode;
import org.hibernate.type.Type;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.mapping.Property;
import org.hibernate.util.ReflectHelper;
import org.hibernate.util.StringHelper;

/**
 * A factory for building/retrieving PropertyAccessor instances.
 *
 @author Gavin King
 @author Steve Ebersole
 */
public final class PropertyAccessorFactory {

  private static final PropertyAccessor BASIC_PROPERTY_ACCESSOR = new BasicPropertyAccessor();
  private static final PropertyAccessor DIRECT_PROPERTY_ACCESSOR = new DirectPropertyAccessor();
  private static final PropertyAccessor MAP_ACCESSOR = new MapAccessor();
  private static final PropertyAccessor NOOP_ACCESSOR = new NoopAccessor();
  private static final PropertyAccessor EMBEDDED_PROPERTY_ACCESSOR = new EmbeddedPropertyAccessor();

  //TODO: ideally we need the construction of PropertyAccessor to take the following:
  //      1) EntityMode
  //      2) EntityMode-specific data (i.e., the classname for pojo entities)
  //      3) Property-specific data based on the EntityMode (i.e., property-name or dom4j-node-name)
  // The easiest way, with the introduction of the new runtime-metamodel classes, would be the
  // the following predicates:
  //      1) PropertyAccessorFactory.getPropertyAccessor() takes references to both a
  //          org.hibernate.metadata.EntityModeMetadata and org.hibernate.metadata.Property
  //      2) What is now termed a "PropertyAccessor" stores any values needed from those two
  //          pieces of information
  //      3) Code can then simply call PropertyAccess.getGetter() with no parameters; likewise with
  //          PropertyAccessor.getSetter()

    /**
     * Retrieves a PropertyAccessor instance based on the given property definition and
     * entity mode.
     *
     @param property The property for which to retrieve an accessor.
     @param mode The mode for the resulting entity.
     @return An appropriate accessor.
     @throws MappingException
     */
  public static PropertyAccessor getPropertyAccessor(Property property, EntityMode modethrows MappingException {
    //TODO: this is temporary in that the end result will probably not take a Property reference per-se.
      if null == mode || EntityMode.POJO.equalsmode ) ) {
        return getPojoPropertyAccessorproperty.getPropertyAccessorName() );
      }
      else if EntityMode.MAP.equalsmode ) ) {
        return getDynamicMapPropertyAccessor();
      }
      else if EntityMode.DOM4J.equalsmode ) ) {
        //TODO: passing null here, because this method is not really used for DOM4J at the moment
        //      but it is still a bug, if we don't get rid of this!
        return getDom4jPropertyAccessorproperty.getAccessorPropertyNamemode ), property.getType()null );
      }
      else {
        throw new MappingException"Unknown entity mode [" + mode + "]" );
      }
  }  /**
   * Retreives a PropertyAccessor specific for a PojoRepresentation with the given access strategy.
   *
   @param pojoAccessorStrategy The access strategy.
   @return An appropriate accessor.
   */
  private static PropertyAccessor getPojoPropertyAccessor(String pojoAccessorStrategy) {
    if StringHelper.isEmptypojoAccessorStrategy || "property".equalspojoAccessorStrategy ) ) {
      return BASIC_PROPERTY_ACCESSOR;
    }
    else if "field".equalspojoAccessorStrategy ) ) {
      return DIRECT_PROPERTY_ACCESSOR;
    }
    else if "embedded".equalspojoAccessorStrategy ) ) {
      return EMBEDDED_PROPERTY_ACCESSOR;
    }
    else if "noop".equals(pojoAccessorStrategy) ) {
      return NOOP_ACCESSOR;
    }
    else {
      return resolveCustomAccessorpojoAccessorStrategy );
    }
  }

  public static PropertyAccessor getDynamicMapPropertyAccessor() throws MappingException {
    return MAP_ACCESSOR;
  }

  public static PropertyAccessor getDom4jPropertyAccessor(String nodeName, Type type, SessionFactoryImplementor factory
  throws MappingException {
    //TODO: need some caching scheme? really comes down to decision 
    //      regarding amount of state (if any) kept on PropertyAccessors
    return new Dom4jAccessornodeName, type, factory );
  }

  private static PropertyAccessor resolveCustomAccessor(String accessorName) {
    Class accessorClass;
    try {
      accessorClass = ReflectHelper.classForName(accessorName);
    }
    catch (ClassNotFoundException cnfe) {
      throw new MappingException("could not find PropertyAccessor class: " + accessorName, cnfe);
    }
    try {
      return (PropertyAccessoraccessorClass.newInstance();
    }
    catch (Exception e) {
      throw new MappingException("could not instantiate PropertyAccessor class: " + accessorName, e);
    }
  }

  private PropertyAccessorFactory() {}

  // todo : this eventually needs to be removed
  public static PropertyAccessor getPropertyAccessor(Class optionalClass, String typethrows MappingException {
    if type==null type = optionalClass==null || optionalClass==Map.class "map" "property";
    return getPropertyAccessor(type);
  }

  // todo : this eventually needs to be removed
  public static PropertyAccessor getPropertyAccessor(String typethrows MappingException {
    if type==null || "property".equals(type) ) return BASIC_PROPERTY_ACCESSOR;
    if "field".equals(type) ) return DIRECT_PROPERTY_ACCESSOR;
    if "map".equals(type) ) return MAP_ACCESSOR;
    if "embedded".equals(type) ) return EMBEDDED_PROPERTY_ACCESSOR;
    if "noop".equals(type)) return NOOP_ACCESSOR;
    
    return resolveCustomAccessor(type);
  }
}