Save This Page
Home » Hibernate-3.3.2.GA » 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   	 * Build an appropriate Getter for the given property.
   78   	 *
   79   	 * @param mappedProperty The property to be accessed via the built Getter.
   80   	 * @param mappedEntity The entity information regarding the mapped entity owning this property.
   81   	 * @return An appropriate Getter instance.
   82   	 */
   83   	protected abstract Getter buildPropertyGetter(Property mappedProperty, PersistentClass mappedEntity);
   84   
   85   	/**
   86   	 * Build an appropriate Setter for the given property.
   87   	 *
   88   	 * @param mappedProperty The property to be accessed via the built Setter.
   89   	 * @param mappedEntity The entity information regarding the mapped entity owning this property.
   90   	 * @return An appropriate Setter instance.
   91   	 */
   92   	protected abstract Setter buildPropertySetter(Property mappedProperty, PersistentClass mappedEntity);
   93   
   94   	/**
   95   	 * Build an appropriate Instantiator for the given mapped entity.
   96   	 *
   97   	 * @param mappingInfo The mapping information regarding the mapped entity.
   98   	 * @return An appropriate Instantiator instance.
   99   	 */
  100   	protected abstract Instantiator buildInstantiator(PersistentClass mappingInfo);
  101   
  102   	/**
  103   	 * Build an appropriate ProxyFactory for the given mapped entity.
  104   	 *
  105   	 * @param mappingInfo The mapping information regarding the mapped entity.
  106   	 * @param idGetter The constructed Getter relating to the entity's id property.
  107   	 * @param idSetter The constructed Setter relating to the entity's id property.
  108   	 * @return An appropriate ProxyFactory instance.
  109   	 */
  110   	protected abstract ProxyFactory buildProxyFactory(PersistentClass mappingInfo, Getter idGetter, Setter idSetter);
  111   
  112   	/**
  113   	 * Constructs a new AbstractEntityTuplizer instance.
  114   	 *
  115   	 * @param entityMetamodel The "interpreted" information relating to the mapped entity.
  116   	 * @param mappingInfo The parsed "raw" mapping data relating to the given entity.
  117   	 */
  118   	public AbstractEntityTuplizer(EntityMetamodel entityMetamodel, PersistentClass mappingInfo) {
  119   		this.entityMetamodel = entityMetamodel;
  120   
  121   		if ( !entityMetamodel.getIdentifierProperty().isVirtual() ) {
  122   			idGetter = buildPropertyGetter( mappingInfo.getIdentifierProperty(), mappingInfo );
  123   			idSetter = buildPropertySetter( mappingInfo.getIdentifierProperty(), mappingInfo );
  124   		}
  125   		else {
  126   			idGetter = null;
  127   			idSetter = null;
  128   		}
  129   
  130   		propertySpan = entityMetamodel.getPropertySpan();
  131   
  132           getters = new Getter[propertySpan];
  133   		setters = new Setter[propertySpan];
  134   
  135   		Iterator iter = mappingInfo.getPropertyClosureIterator();
  136   		boolean foundCustomAccessor=false;
  137   		int i=0;
  138   		while ( iter.hasNext() ) {
  139   			//TODO: redesign how PropertyAccessors are acquired...
  140   			Property property = (Property) iter.next();
  141   			getters[i] = buildPropertyGetter(property, mappingInfo);
  142   			setters[i] = buildPropertySetter(property, mappingInfo);
  143   			if ( !property.isBasicPropertyAccessor() ) foundCustomAccessor = true;
  144   			i++;
  145   		}
  146   		hasCustomAccessors = foundCustomAccessor;
  147   
  148           instantiator = buildInstantiator( mappingInfo );
  149   
  150   		if ( entityMetamodel.isLazy() ) {
  151   			proxyFactory = buildProxyFactory( mappingInfo, idGetter, idSetter );
  152   			if (proxyFactory == null) {
  153   				entityMetamodel.setLazy( false );
  154   			}
  155   		}
  156   		else {
  157   			proxyFactory = null;
  158   		}
  159   		
  160   		Component mapper = mappingInfo.getIdentifierMapper();
  161   		identifierMapperType = mapper==null ? null : (AbstractComponentType) mapper.getType();
  162   	}
  163   
  164   	/** Retreives the defined entity-name for the tuplized entity.
  165   	 *
  166   	 * @return The entity-name.
  167   	 */
  168   	protected String getEntityName() {
  169   		return entityMetamodel.getName();
  170   	}
  171   
  172   	/**
  173   	 * Retreives the defined entity-names for any subclasses defined for this
  174   	 * entity.
  175   	 *
  176   	 * @return Any subclass entity-names.
  177   	 */
  178   	protected Set getSubclassEntityNames() {
  179   		return entityMetamodel.getSubclassEntityNames();
  180   	}
  181   
  182   	public Serializable getIdentifier(Object entity) throws HibernateException {
  183   		final Object id;
  184   		if ( entityMetamodel.getIdentifierProperty().isEmbedded() ) {
  185   			id = entity;
  186   		}
  187   		else {
  188   			if ( idGetter == null ) {
  189   				if (identifierMapperType==null) {
  190   					throw new HibernateException( "The class has no identifier property: " + getEntityName() );
  191   				}
  192   				else {
  193   					ComponentType copier = (ComponentType) entityMetamodel.getIdentifierProperty().getType();
  194   					id = copier.instantiate( getEntityMode() );
  195   					copier.setPropertyValues( id, identifierMapperType.getPropertyValues( entity, getEntityMode() ), getEntityMode() );
  196   				}
  197   			}
  198   			else {
  199   				id = idGetter.get( entity );
  200   			}
  201   		}
  202   
  203   		try {
  204   			return (Serializable) id;
  205   		}
  206   		catch ( ClassCastException cce ) {
  207   			StringBuffer msg = new StringBuffer( "Identifier classes must be serializable. " );
  208   			if ( id != null ) {
  209   				msg.append( id.getClass().getName() + " is not serializable. " );
  210   			}
  211   			if ( cce.getMessage() != null ) {
  212   				msg.append( cce.getMessage() );
  213   			}
  214   			throw new ClassCastException( msg.toString() );
  215   		}
  216   	}
  217   
  218   
  219   	public void setIdentifier(Object entity, Serializable id) throws HibernateException {
  220   		if ( entityMetamodel.getIdentifierProperty().isEmbedded() ) {
  221   			if ( entity != id ) {
  222   				AbstractComponentType copier = (AbstractComponentType) entityMetamodel.getIdentifierProperty().getType();
  223   				copier.setPropertyValues( entity, copier.getPropertyValues( id, getEntityMode() ), getEntityMode() );
  224   			}
  225   		}
  226   		else if ( idSetter != null ) {
  227   			idSetter.set( entity, id, getFactory() );
  228   		}
  229   	}
  230   
  231   	public void resetIdentifier(Object entity, Serializable currentId, Object currentVersion) {
  232   		if ( entityMetamodel.getIdentifierProperty().getIdentifierGenerator() instanceof Assigned ) {
  233   			//return currentId;
  234   		}
  235   		else {
  236   			//reset the id
  237   			Serializable result = entityMetamodel.getIdentifierProperty()
  238   					.getUnsavedValue()
  239   					.getDefaultValue( currentId );
  240   			setIdentifier( entity, result );
  241   			//reset the version
  242   			VersionProperty versionProperty = entityMetamodel.getVersionProperty();
  243   			if ( entityMetamodel.isVersioned() ) {
  244   				setPropertyValue(
  245   				        entity,
  246   				        entityMetamodel.getVersionPropertyIndex(),
  247   						versionProperty.getUnsavedValue().getDefaultValue( currentVersion )
  248   					);
  249   			}
  250   			//return the id, so we can use it to reset the proxy id
  251   			//return result;
  252   		}
  253   	}
  254   
  255   	public Object getVersion(Object entity) throws HibernateException {
  256   		if ( !entityMetamodel.isVersioned() ) return null;
  257   		return getters[ entityMetamodel.getVersionPropertyIndex() ].get( entity );
  258   	}
  259   
  260   	protected boolean shouldGetAllProperties(Object entity) {
  261   		return !hasUninitializedLazyProperties( entity );
  262   	}
  263   
  264   	public Object[] getPropertyValues(Object entity) throws HibernateException {
  265   		boolean getAll = shouldGetAllProperties( entity );
  266   		final int span = entityMetamodel.getPropertySpan();
  267   		final Object[] result = new Object[span];
  268   
  269   		for ( int j = 0; j < span; j++ ) {
  270   			StandardProperty property = entityMetamodel.getProperties()[j];
  271   			if ( getAll || !property.isLazy() ) {
  272   				result[j] = getters[j].get( entity );
  273   			}
  274   			else {
  275   				result[j] = LazyPropertyInitializer.UNFETCHED_PROPERTY;
  276   			}
  277   		}
  278   		return result;
  279   	}
  280   
  281   	public Object[] getPropertyValuesToInsert(Object entity, Map mergeMap, SessionImplementor session) 
  282   	throws HibernateException {
  283   		final int span = entityMetamodel.getPropertySpan();
  284   		final Object[] result = new Object[span];
  285   
  286   		for ( int j = 0; j < span; j++ ) {
  287   			result[j] = getters[j].getForInsert( entity, mergeMap, session );
  288   		}
  289   		return result;
  290   	}
  291   
  292   	public Object getPropertyValue(Object entity, int i) throws HibernateException {
  293   		return getters[i].get( entity );
  294   	}
  295   
  296   	public Object getPropertyValue(Object entity, String propertyPath) throws HibernateException {
  297   		
  298   		int loc = propertyPath.indexOf('.');
  299   		String basePropertyName = loc>0 ?
  300   			propertyPath.substring(0, loc) : propertyPath;
  301   			
  302   		int index = entityMetamodel.getPropertyIndex( basePropertyName );
  303   		Object baseValue = getPropertyValue( entity, index );
  304   		if ( loc>0 ) {
  305   			ComponentType type = (ComponentType) entityMetamodel.getPropertyTypes()[index];
  306   			return getComponentValue( type, baseValue, propertyPath.substring(loc+1) );
  307   		}
  308   		else {
  309   			return baseValue;
  310   		}
  311   	}
  312   
  313   	/**
  314   	 * Extract a component property value.
  315   	 *
  316   	 * @param type The component property types.
  317   	 * @param component The component instance itself.
  318   	 * @param propertyPath The property path for the property to be extracted.
  319   	 * @return The property value extracted.
  320   	 */
  321   	protected Object getComponentValue(ComponentType type, Object component, String propertyPath) {
  322   		int loc = propertyPath.indexOf('.');
  323   		String basePropertyName = loc>0 ?
  324   			propertyPath.substring(0, loc) : propertyPath;
  325   		
  326   		String[] propertyNames = type.getPropertyNames();
  327   		int index=0;
  328   		for ( ; index<propertyNames.length; index++ ) {
  329   			if ( basePropertyName.equals( propertyNames[index] ) ) break;
  330   		}
  331   		if (index==propertyNames.length) {
  332   			throw new MappingException( "component property not found: " + basePropertyName );
  333   		}
  334   		
  335   		Object baseValue = type.getPropertyValue( component, index, getEntityMode() );
  336   		
  337   		if ( loc>0 ) {
  338   			ComponentType subtype = (ComponentType) type.getSubtypes()[index];
  339   			return getComponentValue( subtype, baseValue, propertyPath.substring(loc+1) );
  340   		}
  341   		else {
  342   			return baseValue;
  343   		}
  344   		
  345   	}
  346   
  347   	public void setPropertyValues(Object entity, Object[] values) throws HibernateException {
  348   		boolean setAll = !entityMetamodel.hasLazyProperties();
  349   
  350   		for ( int j = 0; j < entityMetamodel.getPropertySpan(); j++ ) {
  351   			if ( setAll || values[j] != LazyPropertyInitializer.UNFETCHED_PROPERTY ) {
  352   				setters[j].set( entity, values[j], getFactory() );
  353   			}
  354   		}
  355   	}
  356   
  357   	public void setPropertyValue(Object entity, int i, Object value) throws HibernateException {
  358   		setters[i].set( entity, value, getFactory() );
  359   	}
  360   
  361   	public void setPropertyValue(Object entity, String propertyName, Object value) throws HibernateException {
  362   		setters[ entityMetamodel.getPropertyIndex( propertyName ) ].set( entity, value, getFactory() );
  363   	}
  364   
  365   	public final Object instantiate(Serializable id) throws HibernateException {
  366   		Object result = getInstantiator().instantiate( id );
  367   		if ( id != null ) {
  368   			setIdentifier( result, id );
  369   		}
  370   		return result;
  371   	}
  372   
  373   	public final Object instantiate() throws HibernateException {
  374   		return instantiate( null );
  375   	}
  376   
  377   	public void afterInitialize(Object entity, boolean lazyPropertiesAreUnfetched, SessionImplementor session) {}
  378   
  379   	public boolean hasUninitializedLazyProperties(Object entity) {
  380   		// the default is to simply not lazy fetch properties for now...
  381   		return false;
  382   	}
  383   
  384   	public final boolean isInstance(Object object) {
  385           return getInstantiator().isInstance( object );
  386   	}
  387   
  388   	public boolean hasProxy() {
  389   		return entityMetamodel.isLazy();
  390   	}
  391   
  392   	public final Object createProxy(Serializable id, SessionImplementor session)
  393   	throws HibernateException {
  394   		return getProxyFactory().getProxy( id, session );
  395   	}
  396   
  397   	public boolean isLifecycleImplementor() {
  398   		return false;
  399   	}
  400   
  401   	public boolean isValidatableImplementor() {
  402   		return false;
  403   	}
  404   	
  405   	protected final EntityMetamodel getEntityMetamodel() {
  406   		return entityMetamodel;
  407   	}
  408   
  409   	protected final SessionFactoryImplementor getFactory() {
  410   		return entityMetamodel.getSessionFactory();
  411   	}
  412   
  413   	protected final Instantiator getInstantiator() {
  414   		return instantiator;
  415   	}
  416   
  417   	protected final ProxyFactory getProxyFactory() {
  418   		return proxyFactory;
  419   	}
  420   	
  421   	public String toString() {
  422   		return getClass().getName() + '(' + getEntityMetamodel().getName() + ')';
  423   	}
  424   
  425   }

Save This Page
Home » Hibernate-3.3.2.GA » org.hibernate » tuple » entity » [javadoc | source]