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.lang.reflect.Method;
   28   import java.lang.reflect.Modifier;
   29   import java.util.HashSet;
   30   import java.util.Iterator;
   31   import java.util.Map;
   32   import java.util.Set;
   33   
   34   import org.slf4j.Logger;
   35   import org.slf4j.LoggerFactory;
   36   import org.hibernate.EntityMode;
   37   import org.hibernate.HibernateException;
   38   import org.hibernate.MappingException;
   39   import org.hibernate.EntityNameResolver;
   40   import org.hibernate.tuple.Instantiator;
   41   import org.hibernate.tuple.PojoInstantiator;
   42   import org.hibernate.bytecode.ReflectionOptimizer;
   43   import org.hibernate.cfg.Environment;
   44   import org.hibernate.classic.Lifecycle;
   45   import org.hibernate.classic.Validatable;
   46   import org.hibernate.engine.SessionImplementor;
   47   import org.hibernate.engine.SessionFactoryImplementor;
   48   import org.hibernate.intercept.FieldInterceptor;
   49   import org.hibernate.intercept.FieldInterceptionHelper;
   50   import org.hibernate.mapping.PersistentClass;
   51   import org.hibernate.mapping.Property;
   52   import org.hibernate.mapping.Subclass;
   53   import org.hibernate.property.Getter;
   54   import org.hibernate.property.Setter;
   55   import org.hibernate.proxy.HibernateProxy;
   56   import org.hibernate.proxy.ProxyFactory;
   57   import org.hibernate.type.AbstractComponentType;
   58   import org.hibernate.util.ReflectHelper;
   59   
   60   /**
   61    * An {@link EntityTuplizer} specific to the pojo entity mode.
   62    *
   63    * @author Steve Ebersole
   64    * @author Gavin King
   65    */
   66   public class PojoEntityTuplizer extends AbstractEntityTuplizer {
   67   
   68   	static final Logger log = LoggerFactory.getLogger( PojoEntityTuplizer.class );
   69   
   70   	private final Class mappedClass;
   71   	private final Class proxyInterface;
   72   	private final boolean lifecycleImplementor;
   73   	private final boolean validatableImplementor;
   74   	private final Set lazyPropertyNames = new HashSet();
   75   	private final ReflectionOptimizer optimizer;
   76   
   77   	public PojoEntityTuplizer(EntityMetamodel entityMetamodel, PersistentClass mappedEntity) {
   78   		super( entityMetamodel, mappedEntity );
   79   		this.mappedClass = mappedEntity.getMappedClass();
   80   		this.proxyInterface = mappedEntity.getProxyInterface();
   81   		this.lifecycleImplementor = Lifecycle.class.isAssignableFrom( mappedClass );
   82   		this.validatableImplementor = Validatable.class.isAssignableFrom( mappedClass );
   83   
   84   		Iterator iter = mappedEntity.getPropertyClosureIterator();
   85   		while ( iter.hasNext() ) {
   86   			Property property = (Property) iter.next();
   87   			if ( property.isLazy() ) {
   88   				lazyPropertyNames.add( property.getName() );
   89   			}
   90   		}
   91   
   92   		String[] getterNames = new String[propertySpan];
   93   		String[] setterNames = new String[propertySpan];
   94   		Class[] propTypes = new Class[propertySpan];
   95   		for ( int i = 0; i < propertySpan; i++ ) {
   96   			getterNames[i] = getters[i].getMethodName();
   97   			setterNames[i] = setters[i].getMethodName();
   98   			propTypes[i] = getters[i].getReturnType();
   99   		}
  100   
  101   		if ( hasCustomAccessors || !Environment.useReflectionOptimizer() ) {
  102   			optimizer = null;
  103   		}
  104   		else {
  105   			// todo : YUCK!!!
  106   			optimizer = Environment.getBytecodeProvider().getReflectionOptimizer( mappedClass, getterNames, setterNames, propTypes );
  107   //			optimizer = getFactory().getSettings().getBytecodeProvider().getReflectionOptimizer(
  108   //					mappedClass, getterNames, setterNames, propTypes
  109   //			);
  110   		}
  111   	
  112   	}
  113   
  114   	/**
  115   	 * {@inheritDoc}
  116   	 */
  117   	protected ProxyFactory buildProxyFactory(PersistentClass persistentClass, Getter idGetter, Setter idSetter) {
  118   		// determine the id getter and setter methods from the proxy interface (if any)
  119           // determine all interfaces needed by the resulting proxy
  120   		HashSet proxyInterfaces = new HashSet();
  121   		proxyInterfaces.add( HibernateProxy.class );
  122   		
  123   		Class mappedClass = persistentClass.getMappedClass();
  124   		Class proxyInterface = persistentClass.getProxyInterface();
  125   
  126   		if ( proxyInterface!=null && !mappedClass.equals( proxyInterface ) ) {
  127   			if ( !proxyInterface.isInterface() ) {
  128   				throw new MappingException(
  129   				        "proxy must be either an interface, or the class itself: " + 
  130   				        getEntityName()
  131   					);
  132   			}
  133   			proxyInterfaces.add( proxyInterface );
  134   		}
  135   
  136   		if ( mappedClass.isInterface() ) {
  137   			proxyInterfaces.add( mappedClass );
  138   		}
  139   
  140   		Iterator iter = persistentClass.getSubclassIterator();
  141   		while ( iter.hasNext() ) {
  142   			Subclass subclass = ( Subclass ) iter.next();
  143   			Class subclassProxy = subclass.getProxyInterface();
  144   			Class subclassClass = subclass.getMappedClass();
  145   			if ( subclassProxy!=null && !subclassClass.equals( subclassProxy ) ) {
  146   				if ( !proxyInterface.isInterface() ) {
  147   					throw new MappingException(
  148   					        "proxy must be either an interface, or the class itself: " + 
  149   					        subclass.getEntityName()
  150   					);
  151   				}
  152   				proxyInterfaces.add( subclassProxy );
  153   			}
  154   		}
  155   
  156   		Iterator properties = persistentClass.getPropertyIterator();
  157   		Class clazz = persistentClass.getMappedClass();
  158   		while ( properties.hasNext() ) {
  159   			Property property = (Property) properties.next();
  160   			Method method = property.getGetter(clazz).getMethod();
  161   			if ( method != null && Modifier.isFinal( method.getModifiers() ) ) {
  162   				log.error(
  163   						"Getters of lazy classes cannot be final: " + persistentClass.getEntityName() + 
  164   						"." + property.getName() 
  165   					);
  166   			}
  167   			method = property.getSetter(clazz).getMethod();
  168               if ( method != null && Modifier.isFinal( method.getModifiers() ) ) {
  169   				log.error(
  170   						"Setters of lazy classes cannot be final: " + persistentClass.getEntityName() + 
  171   						"." + property.getName() 
  172   					);
  173   			}
  174   		}
  175   
  176   		Method idGetterMethod = idGetter==null ? null : idGetter.getMethod();
  177   		Method idSetterMethod = idSetter==null ? null : idSetter.getMethod();
  178   
  179   		Method proxyGetIdentifierMethod = idGetterMethod==null || proxyInterface==null ? 
  180   				null :
  181   		        ReflectHelper.getMethod(proxyInterface, idGetterMethod);
  182   		Method proxySetIdentifierMethod = idSetterMethod==null || proxyInterface==null  ? 
  183   				null :
  184   		        ReflectHelper.getMethod(proxyInterface, idSetterMethod);
  185   
  186   		ProxyFactory pf = buildProxyFactoryInternal( persistentClass, idGetter, idSetter );
  187   		try {
  188   			pf.postInstantiate(
  189   					getEntityName(),
  190   					mappedClass,
  191   					proxyInterfaces,
  192   					proxyGetIdentifierMethod,
  193   					proxySetIdentifierMethod,
  194   					persistentClass.hasEmbeddedIdentifier() ?
  195   			                (AbstractComponentType) persistentClass.getIdentifier().getType() :
  196   			                null
  197   			);
  198   		}
  199   		catch ( HibernateException he ) {
  200   			log.warn( "could not create proxy factory for:" + getEntityName(), he );
  201   			pf = null;
  202   		}
  203   		return pf;
  204   	}
  205   
  206   	protected ProxyFactory buildProxyFactoryInternal(PersistentClass persistentClass, Getter idGetter, Setter idSetter) {
  207   		// TODO : YUCK!!!  fix after HHH-1907 is complete
  208   		return Environment.getBytecodeProvider().getProxyFactoryFactory().buildProxyFactory();
  209   //		return getFactory().getSettings().getBytecodeProvider().getProxyFactoryFactory().buildProxyFactory();
  210   	}
  211   
  212   	/**
  213   	 * {@inheritDoc}
  214   	 */
  215   	protected Instantiator buildInstantiator(PersistentClass persistentClass) {
  216   		if ( optimizer == null ) {
  217   			return new PojoInstantiator( persistentClass, null );
  218   		}
  219   		else {
  220   			return new PojoInstantiator( persistentClass, optimizer.getInstantiationOptimizer() );
  221   		}
  222   	}
  223   
  224   	/**
  225   	 * {@inheritDoc}
  226   	 */
  227   	public void setPropertyValues(Object entity, Object[] values) throws HibernateException {
  228   		if ( !getEntityMetamodel().hasLazyProperties() && optimizer != null && optimizer.getAccessOptimizer() != null ) {
  229   			setPropertyValuesWithOptimizer( entity, values );
  230   		}
  231   		else {
  232   			super.setPropertyValues( entity, values );
  233   		}
  234   	}
  235   
  236   	/**
  237   	 * {@inheritDoc}
  238   	 */
  239   	public Object[] getPropertyValues(Object entity) throws HibernateException {
  240   		if ( shouldGetAllProperties( entity ) && optimizer != null && optimizer.getAccessOptimizer() != null ) {
  241   			return getPropertyValuesWithOptimizer( entity );
  242   		}
  243   		else {
  244   			return super.getPropertyValues( entity );
  245   		}
  246   	}
  247   
  248   	/**
  249   	 * {@inheritDoc}
  250   	 */
  251   	public Object[] getPropertyValuesToInsert(Object entity, Map mergeMap, SessionImplementor session) throws HibernateException {
  252   		if ( shouldGetAllProperties( entity ) && optimizer != null && optimizer.getAccessOptimizer() != null ) {
  253   			return getPropertyValuesWithOptimizer( entity );
  254   		}
  255   		else {
  256   			return super.getPropertyValuesToInsert( entity, mergeMap, session );
  257   		}
  258   	}
  259   
  260   	protected void setPropertyValuesWithOptimizer(Object object, Object[] values) {
  261   		optimizer.getAccessOptimizer().setPropertyValues( object, values );
  262   	}
  263   
  264   	protected Object[] getPropertyValuesWithOptimizer(Object object) {
  265   		return optimizer.getAccessOptimizer().getPropertyValues( object );
  266   	}
  267   
  268   	/**
  269   	 * {@inheritDoc}
  270   	 */
  271   	public EntityMode getEntityMode() {
  272   		return EntityMode.POJO;
  273   	}
  274   
  275   	/**
  276   	 * {@inheritDoc}
  277   	 */
  278   	public Class getMappedClass() {
  279   		return mappedClass;
  280   	}
  281   
  282   	/**
  283   	 * {@inheritDoc}
  284   	 */
  285   	public boolean isLifecycleImplementor() {
  286   		return lifecycleImplementor;
  287   	}
  288   
  289   	/**
  290   	 * {@inheritDoc}
  291   	 */
  292   	public boolean isValidatableImplementor() {
  293   		return validatableImplementor;
  294   	}
  295   
  296   	/**
  297   	 * {@inheritDoc}
  298   	 */
  299   	protected Getter buildPropertyGetter(Property mappedProperty, PersistentClass mappedEntity) {
  300   		return mappedProperty.getGetter( mappedEntity.getMappedClass() );
  301   	}
  302   
  303   	/**
  304   	 * {@inheritDoc}
  305   	 */
  306   	protected Setter buildPropertySetter(Property mappedProperty, PersistentClass mappedEntity) {
  307   		return mappedProperty.getSetter( mappedEntity.getMappedClass() );
  308   	}
  309   
  310   	/**
  311   	 * {@inheritDoc}
  312   	 */
  313   	public Class getConcreteProxyClass() {
  314   		return proxyInterface;
  315   	}
  316   
  317       //TODO: need to make the majority of this functionality into a top-level support class for custom impl support
  318   
  319   	/**
  320   	 * {@inheritDoc}
  321   	 */
  322   	public void afterInitialize(Object entity, boolean lazyPropertiesAreUnfetched, SessionImplementor session) {
  323   		if ( isInstrumented() ) {
  324   			Set lazyProps = lazyPropertiesAreUnfetched && getEntityMetamodel().hasLazyProperties() ?
  325   					lazyPropertyNames : null;
  326   			//TODO: if we support multiple fetch groups, we would need
  327   			//      to clone the set of lazy properties!
  328   			FieldInterceptionHelper.injectFieldInterceptor( entity, getEntityName(), lazyProps, session );
  329   		}
  330   	}
  331   
  332   	/**
  333   	 * {@inheritDoc}
  334   	 */
  335   	public boolean hasUninitializedLazyProperties(Object entity) {
  336   		if ( getEntityMetamodel().hasLazyProperties() ) {
  337   			FieldInterceptor callback = FieldInterceptionHelper.extractFieldInterceptor( entity );
  338   			return callback != null && !callback.isInitialized();
  339   		}
  340   		else {
  341   			return false;
  342   		}
  343   	}
  344   
  345   	/**
  346   	 * {@inheritDoc}
  347   	 */
  348   	public boolean isInstrumented() {
  349   		return FieldInterceptionHelper.isInstrumented( getMappedClass() );
  350   	}
  351   
  352   	/**
  353   	 * {@inheritDoc}
  354   	 */
  355   	public String determineConcreteSubclassEntityName(Object entityInstance, SessionFactoryImplementor factory) {
  356   		final Class concreteEntityClass = entityInstance.getClass();
  357   		if ( concreteEntityClass == getMappedClass() ) {
  358   			return getEntityName();
  359   		}
  360   		else {
  361   			String entityName = getEntityMetamodel().findEntityNameByEntityClass( concreteEntityClass );
  362   			if ( entityName == null ) {
  363   				throw new HibernateException(
  364   						"Unable to resolve entity name from Class [" + concreteEntityClass.getName() + "]"
  365   								+ " expected instance/subclass of [" + getEntityName() + "]"
  366   				);
  367   			}
  368   			return entityName;
  369   		}
  370   	}
  371   
  372   	/**
  373   	 * {@inheritDoc}
  374   	 */
  375   	public EntityNameResolver[] getEntityNameResolvers() {
  376   		return null;
  377   	}
  378   }

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