KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > hibernate > tuple > PojoEntityTuplizer


1 // $Id: PojoEntityTuplizer.java,v 1.2 2005/07/16 22:20:48 oneovthafew Exp $
2
package org.hibernate.tuple;
3
4 import java.lang.reflect.Method JavaDoc;
5 import java.lang.reflect.Modifier JavaDoc;
6 import java.util.HashSet JavaDoc;
7 import java.util.Iterator JavaDoc;
8 import java.util.Map JavaDoc;
9 import java.util.Set JavaDoc;
10
11 import net.sf.cglib.beans.BulkBean;
12 import net.sf.cglib.reflect.FastClass;
13 import net.sf.cglib.transform.impl.InterceptFieldEnabled;
14
15 import org.apache.commons.logging.Log;
16 import org.apache.commons.logging.LogFactory;
17 import org.hibernate.EntityMode;
18 import org.hibernate.HibernateException;
19 import org.hibernate.MappingException;
20 import org.hibernate.PropertyAccessException;
21 import org.hibernate.cfg.Environment;
22 import org.hibernate.classic.Lifecycle;
23 import org.hibernate.classic.Validatable;
24 import org.hibernate.engine.SessionImplementor;
25 import org.hibernate.intercept.FieldInterceptor;
26 import org.hibernate.mapping.PersistentClass;
27 import org.hibernate.mapping.Property;
28 import org.hibernate.mapping.Subclass;
29 import org.hibernate.property.Getter;
30 import org.hibernate.property.Setter;
31 import org.hibernate.proxy.CGLIBProxyFactory;
32 import org.hibernate.proxy.HibernateProxy;
33 import org.hibernate.proxy.ProxyFactory;
34 import org.hibernate.type.AbstractComponentType;
35 import org.hibernate.util.ReflectHelper;
36
37 /**
38  * POJO-based implementation of an EntityTuplizer.
39  *
40  * @author Steve Ebersole
41  */

42 public class PojoEntityTuplizer extends AbstractEntityTuplizer {
43
44     static final Log log = LogFactory.getLog( PojoEntityTuplizer.class );
45
46     private final Class JavaDoc mappedClass;
47     private final Class JavaDoc proxyInterface;
48     private final boolean lifecycleImplementor;
49     private final boolean validatableImplementor;
50     private final Set JavaDoc lazyPropertyNames = new HashSet JavaDoc();
51     private BulkBean optimizer;
52     private FastClass fastClass;
53
54     public PojoEntityTuplizer(EntityMetamodel entityMetamodel, PersistentClass mappedEntity) {
55         super( entityMetamodel, mappedEntity );
56         this.mappedClass = mappedEntity.getMappedClass();
57         this.proxyInterface = mappedEntity.getProxyInterface();
58         this.lifecycleImplementor = Lifecycle.class.isAssignableFrom( mappedClass );
59         this.validatableImplementor = Validatable.class.isAssignableFrom( mappedClass );
60
61         Iterator JavaDoc iter = mappedEntity.getPropertyClosureIterator();
62         while ( iter.hasNext() ) {
63             Property property = (Property) iter.next();
64             if ( property.isLazy() ) {
65                 lazyPropertyNames.add( property.getName() );
66             }
67         }
68
69         String JavaDoc[] getterNames = new String JavaDoc[propertySpan];
70         String JavaDoc[] setterNames = new String JavaDoc[propertySpan];
71         Class JavaDoc[] propTypes = new Class JavaDoc[propertySpan];
72         for ( int i = 0; i < propertySpan; i++ ) {
73             getterNames[i] = getters[i].getMethodName();
74             setterNames[i] = setters[i].getMethodName();
75             propTypes[i] = getters[i].getReturnType();
76         }
77
78         if ( hasCustomAccessors || !Environment.useReflectionOptimizer() ) {
79             fastClass = null;
80             optimizer = null;
81         }
82         else {
83             fastClass = ReflectHelper.getFastClass( mappedClass );
84             optimizer = ReflectHelper.getBulkBean( mappedClass, getterNames, setterNames, propTypes, fastClass );
85             if (optimizer==null) fastClass = null;
86         }
87     
88     }
89
90     protected ProxyFactory buildProxyFactory(PersistentClass persistentClass, Getter idGetter, Setter idSetter) {
91         // determine the id getter and setter methods from the proxy interface (if any)
92
// determine all interfaces needed by the resulting proxy
93
HashSet JavaDoc proxyInterfaces = new HashSet JavaDoc();
94         proxyInterfaces.add( HibernateProxy.class );
95         
96         Class JavaDoc mappedClass = persistentClass.getMappedClass();
97         Class JavaDoc proxyInterface = persistentClass.getProxyInterface();
98
99         if ( proxyInterface!=null && !mappedClass.equals( proxyInterface ) ) {
100             if ( !proxyInterface.isInterface() ) {
101                 throw new MappingException(
102                         "proxy must be either an interface, or the class itself: " +
103                         getEntityName()
104                 );
105             }
106             proxyInterfaces.add( proxyInterface );
107         }
108
109         if ( mappedClass.isInterface() ) {
110             proxyInterfaces.add( mappedClass );
111         }
112
113         Iterator JavaDoc iter = persistentClass.getSubclassIterator();
114         while ( iter.hasNext() ) {
115             Subclass subclass = ( Subclass ) iter.next();
116             Class JavaDoc subclassProxy = subclass.getProxyInterface();
117             Class JavaDoc subclassClass = subclass.getMappedClass();
118             if ( subclassProxy!=null && !subclassClass.equals( subclassProxy ) ) {
119                 if ( !proxyInterface.isInterface() ) {
120                     throw new MappingException(
121                             "proxy must be either an interface, or the class itself: " +
122                             subclass.getEntityName()
123                     );
124                 }
125                 proxyInterfaces.add( subclassProxy );
126             }
127         }
128
129         Iterator JavaDoc properties = persistentClass.getPropertyIterator();
130         Class JavaDoc clazz = persistentClass.getMappedClass();
131         while ( properties.hasNext() ) {
132             Property property = (Property) properties.next();
133             Method JavaDoc method = property.getGetter(clazz).getMethod();
134             if ( method != null && Modifier.isFinal( method.getModifiers() ) ) {
135                 log.error("Getters of lazy classes cannot be final: " + persistentClass.getEntityName() + "." + property.getName() );
136             }
137             method = property.getSetter(clazz).getMethod();
138             if ( method != null && Modifier.isFinal( method.getModifiers() ) ) {
139                 log.error("Setters of lazy classes cannot be final: " + persistentClass.getEntityName() + "." + property.getName() );
140             }
141         }
142
143         Method JavaDoc idGetterMethod = idGetter==null ? null : idGetter.getMethod();
144         Method JavaDoc idSetterMethod = idSetter==null ? null : idSetter.getMethod();
145
146         Method JavaDoc proxyGetIdentifierMethod = idGetterMethod==null || proxyInterface==null ?
147                 null :
148                 ReflectHelper.getMethod(proxyInterface, idGetterMethod);
149         Method JavaDoc proxySetIdentifierMethod = idSetterMethod==null || proxyInterface==null ?
150                 null :
151                 ReflectHelper.getMethod(proxyInterface, idSetterMethod);
152
153         ProxyFactory pf = new CGLIBProxyFactory();
154         try {
155             pf.postInstantiate(
156                     getEntityName(),
157                     mappedClass,
158                     proxyInterfaces,
159                     proxyGetIdentifierMethod,
160                     proxySetIdentifierMethod,
161                     persistentClass.hasEmbeddedIdentifier() ?
162                             (AbstractComponentType) persistentClass.getIdentifier().getType() :
163                             null
164             );
165         }
166         catch ( HibernateException he ) {
167             log.warn( "could not create proxy factory for:" + getEntityName(), he );
168             pf = null;
169         }
170         return pf;
171     }
172
173     protected Instantiator buildInstantiator(PersistentClass persistentClass) {
174         return new PojoInstantiator( persistentClass, fastClass );
175     }
176
177     public void setPropertyValues(Object JavaDoc entity, Object JavaDoc[] values) throws HibernateException {
178         if ( !getEntityMetamodel().hasLazyProperties() && optimizer != null ) {
179             setPropertyValuesWithOptimizer( entity, values );
180         }
181         else {
182             super.setPropertyValues( entity, values );
183         }
184     }
185
186     public Object JavaDoc[] getPropertyValues(Object JavaDoc entity) throws HibernateException {
187         if ( shouldGetAllProperties( entity ) && optimizer != null ) {
188             return getPropertyValuesWithOptimizer( entity );
189         }
190         else {
191             return super.getPropertyValues( entity );
192         }
193     }
194
195     public Object JavaDoc[] getPropertyValuesToInsert(Object JavaDoc entity, Map JavaDoc mergeMap, SessionImplementor session) throws HibernateException {
196         if ( shouldGetAllProperties( entity ) && optimizer != null ) {
197             return getPropertyValuesWithOptimizer( entity );
198         }
199         else {
200             return super.getPropertyValuesToInsert( entity, mergeMap, session );
201         }
202     }
203
204     protected void setPropertyValuesWithOptimizer(Object JavaDoc object, Object JavaDoc[] values) {
205         try {
206             optimizer.setPropertyValues( object, values );
207         }
208         catch ( Throwable JavaDoc t ) {
209             throw new PropertyAccessException( t,
210                     ReflectHelper.PROPERTY_SET_EXCEPTION,
211                     true,
212                     mappedClass,
213                     ReflectHelper.getPropertyName( t, optimizer )
214                 );
215         }
216     }
217
218     protected Object JavaDoc[] getPropertyValuesWithOptimizer(Object JavaDoc object) {
219         try {
220             return optimizer.getPropertyValues( object );
221         }
222         catch ( Throwable JavaDoc t ) {
223             throw new PropertyAccessException( t,
224                     ReflectHelper.PROPERTY_GET_EXCEPTION,
225                     false,
226                     mappedClass,
227                     ReflectHelper.getPropertyName( t, optimizer )
228                 );
229         }
230     }
231
232     public EntityMode getEntityMode() {
233         return EntityMode.POJO;
234     }
235
236     public Class JavaDoc getMappedClass() {
237         return mappedClass;
238     }
239
240     public boolean isLifecycleImplementor() {
241         return lifecycleImplementor;
242     }
243
244     public boolean isValidatableImplementor() {
245         return validatableImplementor;
246     }
247
248     protected Getter buildPropertyGetter(Property mappedProperty, PersistentClass mappedEntity) {
249         return mappedProperty.getGetter( mappedEntity.getMappedClass() );
250     }
251
252     protected Setter buildPropertySetter(Property mappedProperty, PersistentClass mappedEntity) {
253         return mappedProperty.getSetter( mappedEntity.getMappedClass() );
254     }
255
256     public Class JavaDoc getConcreteProxyClass() {
257         return proxyInterface;
258     }
259
260     //TODO: need to make the majority of this functionality into a top-level support class for custom impl support
261

262     public void afterInitialize(Object JavaDoc entity, boolean lazyPropertiesAreUnfetched, SessionImplementor session) {
263         //if ( lazyPropertiesAreUnfetched && getEntityMetamodel().hasLazyProperties() ) {
264
if ( isInstrumented() ) {
265             Set JavaDoc lazyProps = lazyPropertiesAreUnfetched && getEntityMetamodel().hasLazyProperties() ?
266                     lazyPropertyNames : null;
267             //TODO: if we support multiple fetch groups, we would need
268
// to clone the set of lazy properties!
269
FieldInterceptor.initFieldInterceptor( entity, getEntityName(), session, lazyProps );
270         }
271     }
272
273     public boolean hasUninitializedLazyProperties(Object JavaDoc entity) {
274         if ( getEntityMetamodel().hasLazyProperties() ) {
275             FieldInterceptor callback = FieldInterceptor.getFieldInterceptor(entity);
276             return callback != null && !callback.isInitialized();
277         }
278         else {
279             return false;
280         }
281     }
282
283     public boolean isInstrumented() {
284         return InterceptFieldEnabled.class.isAssignableFrom( getMappedClass() );
285     }
286
287 }
288
Popular Tags