001: //$Id: PojoComponentTuplizer.java 9619 2006-03-15 00:12:47Z steve.ebersole@jboss.com $
002: package org.hibernate.tuple.component;
003:
004: import java.lang.reflect.Method;
005: import java.io.Serializable;
006:
007: import org.hibernate.HibernateException;
008: import org.hibernate.AssertionFailure;
009: import org.hibernate.tuple.component.AbstractComponentTuplizer;
010: import org.hibernate.tuple.Instantiator;
011: import org.hibernate.tuple.PojoInstantiator;
012: import org.hibernate.util.ReflectHelper;
013: import org.hibernate.bytecode.ReflectionOptimizer;
014: import org.hibernate.bytecode.BasicProxyFactory;
015: import org.hibernate.cfg.Environment;
016: import org.hibernate.engine.SessionFactoryImplementor;
017: import org.hibernate.mapping.Component;
018: import org.hibernate.mapping.Property;
019: import org.hibernate.property.Getter;
020: import org.hibernate.property.PropertyAccessor;
021: import org.hibernate.property.PropertyAccessorFactory;
022: import org.hibernate.property.Setter;
023:
024: /**
025: * A {@link ComponentTuplizer} specific to the pojo entity mode.
026: *
027: * @author Gavin King
028: * @author Steve Ebersole
029: */
030: public class PojoComponentTuplizer extends AbstractComponentTuplizer {
031:
032: private final Class componentClass;
033: private ReflectionOptimizer optimizer;
034: private final Getter parentGetter;
035: private final Setter parentSetter;
036:
037: public PojoComponentTuplizer(Component component) {
038: super (component);
039:
040: this .componentClass = component.getComponentClass();
041:
042: String[] getterNames = new String[propertySpan];
043: String[] setterNames = new String[propertySpan];
044: Class[] propTypes = new Class[propertySpan];
045: for (int i = 0; i < propertySpan; i++) {
046: getterNames[i] = getters[i].getMethodName();
047: setterNames[i] = setters[i].getMethodName();
048: propTypes[i] = getters[i].getReturnType();
049: }
050:
051: final String parentPropertyName = component.getParentProperty();
052: if (parentPropertyName == null) {
053: parentSetter = null;
054: parentGetter = null;
055: } else {
056: PropertyAccessor pa = PropertyAccessorFactory
057: .getPropertyAccessor(null);
058: parentSetter = pa.getSetter(componentClass,
059: parentPropertyName);
060: parentGetter = pa.getGetter(componentClass,
061: parentPropertyName);
062: }
063:
064: if (hasCustomAccessors || !Environment.useReflectionOptimizer()) {
065: optimizer = null;
066: } else {
067: // TODO: here is why we need to make bytecode provider global :(
068: // TODO : again, fix this after HHH-1907 is complete
069: optimizer = Environment.getBytecodeProvider()
070: .getReflectionOptimizer(componentClass,
071: getterNames, setterNames, propTypes);
072: }
073: }
074:
075: public Class getMappedClass() {
076: return componentClass;
077: }
078:
079: public Object[] getPropertyValues(Object component)
080: throws HibernateException {
081: if (optimizer != null && optimizer.getAccessOptimizer() != null) {
082: return optimizer.getAccessOptimizer().getPropertyValues(
083: component);
084: } else {
085: return super .getPropertyValues(component);
086: }
087: }
088:
089: public void setPropertyValues(Object component, Object[] values)
090: throws HibernateException {
091: if (optimizer != null && optimizer.getAccessOptimizer() != null) {
092: optimizer.getAccessOptimizer().setPropertyValues(component,
093: values);
094: } else {
095: super .setPropertyValues(component, values);
096: }
097:
098: }
099:
100: public Object getParent(Object component) {
101: return parentGetter.get(component);
102: }
103:
104: public boolean hasParentProperty() {
105: return parentGetter != null;
106: }
107:
108: public boolean isMethodOf(Method method) {
109: for (int i = 0; i < propertySpan; i++) {
110: final Method getterMethod = getters[i].getMethod();
111: if (getterMethod != null && getterMethod.equals(method))
112: return true;
113: }
114: return false;
115: }
116:
117: public void setParent(Object component, Object parent,
118: SessionFactoryImplementor factory) {
119: parentSetter.set(component, parent, factory);
120: }
121:
122: protected Instantiator buildInstantiator(Component component) {
123: if (component.isEmbedded()
124: && ReflectHelper.isAbstractClass(component
125: .getComponentClass())) {
126: return new ProxiedInstantiator(component);
127: }
128: if (optimizer == null) {
129: return new PojoInstantiator(component, null);
130: } else {
131: return new PojoInstantiator(component, optimizer
132: .getInstantiationOptimizer());
133: }
134: }
135:
136: protected Getter buildGetter(Component component, Property prop) {
137: return prop.getGetter(component.getComponentClass());
138: }
139:
140: protected Setter buildSetter(Component component, Property prop) {
141: return prop.getSetter(component.getComponentClass());
142: }
143:
144: private static class ProxiedInstantiator implements Instantiator {
145: private final Class proxiedClass;
146: private final BasicProxyFactory factory;
147:
148: public ProxiedInstantiator(Component component) {
149: proxiedClass = component.getComponentClass();
150: if (proxiedClass.isInterface()) {
151: factory = Environment.getBytecodeProvider()
152: .getProxyFactoryFactory()
153: .buildBasicProxyFactory(null,
154: new Class[] { proxiedClass });
155: } else {
156: factory = Environment.getBytecodeProvider()
157: .getProxyFactoryFactory()
158: .buildBasicProxyFactory(proxiedClass, null);
159: }
160: }
161:
162: public Object instantiate(Serializable id) {
163: throw new AssertionFailure(
164: "ProxiedInstantiator can only be used to instantiate component");
165: }
166:
167: public Object instantiate() {
168: return factory.getProxy();
169: }
170:
171: public boolean isInstance(Object object) {
172: return proxiedClass.isInstance(object);
173: }
174: }
175: }
|