Save This Page
Home » hibernate-distribution-3.3.1.GA-dist » org.hibernate » tuple » [javadoc | source]
    1   // $Id: AbstractEntityTuplizer.java 7516 2005-07-16 22:20:48Z oneovthafew $
    2   package org.hibernate.tuple;
    3   
    4   import java.io.Serializable;
    5   import java.util.Iterator;
    6   import java.util.Map;
    7   import java.util.Set;
    8   
    9   import org.hibernate.EntityMode;
   10   import org.hibernate.HibernateException;
   11   import org.hibernate.MappingException;
   12   import org.hibernate.engine.SessionFactoryImplementor;
   13   import org.hibernate.engine.SessionImplementor;
   14   import org.hibernate.id.Assigned;
   15   import org.hibernate.intercept.LazyPropertyInitializer;
   16   import org.hibernate.mapping.Component;
   17   import org.hibernate.mapping.PersistentClass;
   18   import org.hibernate.mapping.Property;
   19   import org.hibernate.property.Getter;
   20   import org.hibernate.property.Setter;
   21   import org.hibernate.proxy.ProxyFactory;
   22   import org.hibernate.type.AbstractComponentType;
   23   import org.hibernate.type.ComponentType;
   24   
   25   
   26   /**
   27    * Support base class for EntityTuplizer implementations.
   28    *
   29    * @author Steve Ebersole
   30    */
   31   public abstract class AbstractEntityTuplizer implements EntityTuplizer {
   32   
   33   	//TODO: currently keeps Getters and Setters (instead of PropertyAccessors) because of the way getGetter() and getSetter() are implemented currently; yuck!
   34   
   35   	private final EntityMetamodel entityMetamodel;
   36   
   37   	private final Getter idGetter;
   38   	private final Setter idSetter;
   39   
   40   	protected final Getter[] getters;
   41   	protected final Setter[] setters;
   42   	protected final int propertySpan;
   43   	protected final boolean hasCustomAccessors;
   44   	private final Instantiator instantiator;
   45   	private final ProxyFactory proxyFactory;
   46   	private final AbstractComponentType identifierMapperType;
   47   
   48   
   49   	/**
   50   	 * Return the entity-mode handled by this tuplizer instance.
   51   	 *
   52   	 * @return The entity-mode
   53   	 */
   54   	protected abstract EntityMode getEntityMode();
   55   
   56   	/**
   57   	 * Build an appropriate Getter for the given property.
   58   	 *
   59   	 * @param mappedProperty The property to be accessed via the built Getter.
   60   	 * @param mappedEntity The entity information regarding the mapped entity owning this property.
   61   	 * @return An appropriate Getter instance.
   62   	 */
   63   	protected abstract Getter buildPropertyGetter(Property mappedProperty, PersistentClass mappedEntity);
   64   
   65   	/**
   66   	 * Build an appropriate Setter for the given property.
   67   	 *
   68   	 * @param mappedProperty The property to be accessed via the built Setter.
   69   	 * @param mappedEntity The entity information regarding the mapped entity owning this property.
   70   	 * @return An appropriate Setter instance.
   71   	 */
   72   	protected abstract Setter buildPropertySetter(Property mappedProperty, PersistentClass mappedEntity);
   73   
   74   	/**
   75   	 * Build an appropriate Instantiator for the given mapped entity.
   76   	 *
   77   	 * @param mappingInfo The mapping information regarding the mapped entity.
   78   	 * @return An appropriate Instantiator instance.
   79   	 */
   80   	protected abstract Instantiator buildInstantiator(PersistentClass mappingInfo);
   81   
   82   	/**
   83   	 * Build an appropriate ProxyFactory for the given mapped entity.
   84   	 *
   85   	 * @param mappingInfo The mapping information regarding the mapped entity.
   86   	 * @param idGetter The constructed Getter relating to the entity's id property.
   87   	 * @param idSetter The constructed Setter relating to the entity's id property.
   88   	 * @return An appropriate ProxyFactory instance.
   89   	 */
   90   	protected abstract ProxyFactory buildProxyFactory(PersistentClass mappingInfo, Getter idGetter, Setter idSetter);
   91   
   92   	/**
   93   	 * Constructs a new AbstractEntityTuplizer instance.
   94   	 *
   95   	 * @param entityMetamodel The "interpreted" information relating to the mapped entity.
   96   	 * @param mappingInfo The parsed "raw" mapping data relating to the given entity.
   97   	 */
   98   	public AbstractEntityTuplizer(EntityMetamodel entityMetamodel, PersistentClass mappingInfo) {
   99   		this.entityMetamodel = entityMetamodel;
  100   
  101   		if ( !entityMetamodel.getIdentifierProperty().isVirtual() ) {
  102   			idGetter = buildPropertyGetter( mappingInfo.getIdentifierProperty(), mappingInfo );
  103   			idSetter = buildPropertySetter( mappingInfo.getIdentifierProperty(), mappingInfo );
  104   		}
  105   		else {
  106   			idGetter = null;
  107   			idSetter = null;
  108   		}
  109   
  110   		propertySpan = entityMetamodel.getPropertySpan();
  111   
  112           getters = new Getter[propertySpan];
  113   		setters = new Setter[propertySpan];
  114   
  115   		Iterator iter = mappingInfo.getPropertyClosureIterator();
  116   		boolean foundCustomAccessor=false;
  117   		int i=0;
  118   		while ( iter.hasNext() ) {
  119   			//TODO: redesign how PropertyAccessors are acquired...
  120   			Property property = (Property) iter.next();
  121   			getters[i] = buildPropertyGetter(property, mappingInfo);
  122   			setters[i] = buildPropertySetter(property, mappingInfo);
  123   			if ( !property.isBasicPropertyAccessor() ) foundCustomAccessor = true;
  124   			i++;
  125   		}
  126   		hasCustomAccessors = foundCustomAccessor;
  127   
  128           instantiator = buildInstantiator( mappingInfo );
  129   
  130   		if ( entityMetamodel.isLazy() ) {
  131   			proxyFactory = buildProxyFactory( mappingInfo, idGetter, idSetter );
  132   		}
  133   		else {
  134   			proxyFactory = null;
  135   		}
  136   		
  137   		Component mapper = mappingInfo.getIdentifierMapper();
  138   		identifierMapperType = mapper==null ? null : (AbstractComponentType) mapper.getType();
  139   	}
  140   
  141   	/** Retreives the defined entity-name for the tuplized entity.
  142   	 *
  143   	 * @return The entity-name.
  144   	 */
  145   	protected String getEntityName() {
  146   		return entityMetamodel.getName();
  147   	}
  148   
  149   	/**
  150   	 * Retreives the defined entity-names for any subclasses defined for this
  151   	 * entity.
  152   	 *
  153   	 * @return Any subclass entity-names.
  154   	 */
  155   	protected Set getSubclassEntityNames() {
  156   		return entityMetamodel.getSubclassEntityNames();
  157   	}
  158   
  159   	public Serializable getIdentifier(Object entity) throws HibernateException {
  160   		final Object id;
  161   		if ( entityMetamodel.getIdentifierProperty().isEmbedded() ) {
  162   			id = entity;
  163   		}
  164   		else {
  165   			if ( idGetter == null ) {
  166   				if (identifierMapperType==null) {
  167   					throw new HibernateException( "The class has no identifier property: " + getEntityName() );
  168   				}
  169   				else {
  170   					ComponentType copier = (ComponentType) entityMetamodel.getIdentifierProperty().getType();
  171   					id = copier.instantiate( getEntityMode() );
  172   					copier.setPropertyValues( id, identifierMapperType.getPropertyValues( entity, getEntityMode() ), getEntityMode() );
  173   				}
  174   			}
  175   			else {
  176   				id = idGetter.get( entity );
  177   			}
  178   		}
  179   
  180   		try {
  181   			return (Serializable) id;
  182   		}
  183   		catch ( ClassCastException cce ) {
  184   			StringBuffer msg = new StringBuffer( "Identifier classes must be serializable. " );
  185   			if ( id != null ) {
  186   				msg.append( id.getClass().getName() + " is not serializable. " );
  187   			}
  188   			if ( cce.getMessage() != null ) {
  189   				msg.append( cce.getMessage() );
  190   			}
  191   			throw new ClassCastException( msg.toString() );
  192   		}
  193   	}
  194   
  195   
  196   	public void setIdentifier(Object entity, Serializable id) throws HibernateException {
  197   		if ( entityMetamodel.getIdentifierProperty().isEmbedded() ) {
  198   			if ( entity != id ) {
  199   				AbstractComponentType copier = (AbstractComponentType) entityMetamodel.getIdentifierProperty().getType();
  200   				copier.setPropertyValues( entity, copier.getPropertyValues( id, getEntityMode() ), getEntityMode() );
  201   			}
  202   		}
  203   		else if ( idSetter != null ) {
  204   			idSetter.set( entity, id, getFactory() );
  205   		}
  206   	}
  207   
  208   	public void resetIdentifier(Object entity, Serializable currentId, Object currentVersion) {
  209   		if ( entityMetamodel.getIdentifierProperty().getIdentifierGenerator() instanceof Assigned ) {
  210   			//return currentId;
  211   		}
  212   		else {
  213   			//reset the id
  214   			Serializable result = entityMetamodel.getIdentifierProperty()
  215   					.getUnsavedValue()
  216   					.getDefaultValue( currentId );
  217   			setIdentifier( entity, result );
  218   			//reset the version
  219   			VersionProperty versionProperty = entityMetamodel.getVersionProperty();
  220   			if ( entityMetamodel.isVersioned() ) {
  221   				setPropertyValue(
  222   				        entity,
  223   				        entityMetamodel.getVersionPropertyIndex(),
  224   						versionProperty.getUnsavedValue().getDefaultValue( currentVersion )
  225   					);
  226   			}
  227   			//return the id, so we can use it to reset the proxy id
  228   			//return result;
  229   		}
  230   	}
  231   
  232   	public Object getVersion(Object entity) throws HibernateException {
  233   		if ( !entityMetamodel.isVersioned() ) return null;
  234   		return getters[ entityMetamodel.getVersionPropertyIndex() ].get( entity );
  235   	}
  236   
  237   	protected boolean shouldGetAllProperties(Object entity) {
  238   		return !hasUninitializedLazyProperties( entity );
  239   	}
  240   
  241   	public Object[] getPropertyValues(Object entity) throws HibernateException {
  242   		boolean getAll = shouldGetAllProperties( entity );
  243   		final int span = entityMetamodel.getPropertySpan();
  244   		final Object[] result = new Object[span];
  245   
  246   		for ( int j = 0; j < span; j++ ) {
  247   			StandardProperty property = entityMetamodel.getProperties()[j];
  248   			if ( getAll || !property.isLazy() ) {
  249   				result[j] = getters[j].get( entity );
  250   			}
  251   			else {
  252   				result[j] = LazyPropertyInitializer.UNFETCHED_PROPERTY;
  253   			}
  254   		}
  255   		return result;
  256   	}
  257   
  258   	public Object[] getPropertyValuesToInsert(Object entity, Map mergeMap, SessionImplementor session) 
  259   	throws HibernateException {
  260   		final int span = entityMetamodel.getPropertySpan();
  261   		final Object[] result = new Object[span];
  262   
  263   		for ( int j = 0; j < span; j++ ) {
  264   			result[j] = getters[j].getForInsert( entity, mergeMap, session );
  265   		}
  266   		return result;
  267   	}
  268   
  269   	public Object getPropertyValue(Object entity, int i) throws HibernateException {
  270   		return getters[i].get( entity );
  271   	}
  272   
  273   	public Object getPropertyValue(Object entity, String propertyPath) throws HibernateException {
  274   		
  275   		int loc = propertyPath.indexOf('.');
  276   		String basePropertyName = loc>0 ?
  277   			propertyPath.substring(0, loc) : propertyPath;
  278   			
  279   		int index = entityMetamodel.getPropertyIndex( basePropertyName );
  280   		Object baseValue = getPropertyValue( entity, index );
  281   		if ( loc>0 ) {
  282   			ComponentType type = (ComponentType) entityMetamodel.getPropertyTypes()[index];
  283   			return getComponentValue( type, baseValue, propertyPath.substring(loc+1) );
  284   		}
  285   		else {
  286   			return baseValue;
  287   		}
  288   	}
  289   
  290   	/**
  291   	 * Extract a component property value.
  292   	 *
  293   	 * @param type The component property types.
  294   	 * @param component The component instance itself.
  295   	 * @param propertyPath The property path for the property to be extracted.
  296   	 * @return The property value extracted.
  297   	 */
  298   	protected Object getComponentValue(ComponentType type, Object component, String propertyPath) {
  299   		
  300   		int loc = propertyPath.indexOf('.');
  301   		String basePropertyName = loc>0 ?
  302   			propertyPath.substring(0, loc) : propertyPath;
  303   		
  304   		String[] propertyNames = type.getPropertyNames();
  305   		int index=0;
  306   		for ( ; index<propertyNames.length; index++ ) {
  307   			if ( basePropertyName.equals( propertyNames[index] ) ) break;
  308   		}
  309   		if (index==propertyNames.length) {
  310   			throw new MappingException( "component property not found: " + basePropertyName );
  311   		}
  312   		
  313   		Object baseValue = type.getPropertyValue( component, index, getEntityMode() );
  314   		
  315   		if ( loc>0 ) {
  316   			ComponentType subtype = (ComponentType) type.getSubtypes()[index];
  317   			return getComponentValue( subtype, baseValue, propertyPath.substring(loc+1) );
  318   		}
  319   		else {
  320   			return baseValue;
  321   		}
  322   		
  323   	}
  324   
  325   	public void setPropertyValues(Object entity, Object[] values) throws HibernateException {
  326   		boolean setAll = !entityMetamodel.hasLazyProperties();
  327   
  328   		for ( int j = 0; j < entityMetamodel.getPropertySpan(); j++ ) {
  329   			if ( setAll || values[j] != LazyPropertyInitializer.UNFETCHED_PROPERTY ) {
  330   				setters[j].set( entity, values[j], getFactory() );
  331   			}
  332   		}
  333   	}
  334   
  335   	public void setPropertyValue(Object entity, int i, Object value) throws HibernateException {
  336   		setters[i].set( entity, value, getFactory() );
  337   	}
  338   
  339   	public void setPropertyValue(Object entity, String propertyName, Object value) throws HibernateException {
  340   		setters[ entityMetamodel.getPropertyIndex( propertyName ) ].set( entity, value, getFactory() );
  341   	}
  342   
  343   	public final Object instantiate(Serializable id) throws HibernateException {
  344   		Object result = getInstantiator().instantiate( id );
  345   		if ( id != null ) {
  346   			setIdentifier( result, id );
  347   		}
  348   		return result;
  349   	}
  350   
  351   	public final Object instantiate() throws HibernateException {
  352   		return instantiate( null );
  353   	}
  354   
  355   	public void afterInitialize(Object entity, boolean lazyPropertiesAreUnfetched, SessionImplementor session) {}
  356   
  357   	public boolean hasUninitializedLazyProperties(Object entity) {
  358   		// the default is to simply not lazy fetch properties for now...
  359   		return false;
  360   	}
  361   
  362   	public final boolean isInstance(Object object) {
  363           return getInstantiator().isInstance( object );
  364   	}
  365   
  366   	public boolean hasProxy() {
  367   		return entityMetamodel.isLazy();
  368   	}
  369   
  370   	public final Object createProxy(Serializable id, SessionImplementor session)
  371   	throws HibernateException {
  372   		return getProxyFactory().getProxy( id, session );
  373   	}
  374   
  375   	public boolean isLifecycleImplementor() {
  376   		return false;
  377   	}
  378   
  379   	public boolean isValidatableImplementor() {
  380   		return false;
  381   	}
  382   	
  383   	protected final EntityMetamodel getEntityMetamodel() {
  384   		return entityMetamodel;
  385   	}
  386   
  387   	protected final SessionFactoryImplementor getFactory() {
  388   		return entityMetamodel.getSessionFactory();
  389   	}
  390   
  391   	protected final Instantiator getInstantiator() {
  392   		return instantiator;
  393   	}
  394   
  395   	protected final ProxyFactory getProxyFactory() {
  396   		return proxyFactory;
  397   	}
  398   	
  399   	public String toString() {
  400   		return getClass().getName() + '(' + getEntityMetamodel().getName() + ')';
  401   	}
  402   
  403   }

Save This Page
Home » hibernate-distribution-3.3.1.GA-dist » org.hibernate » tuple » [javadoc | source]