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

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