Index: C:/Prototype/Mavenized/Product/trails/trunk/trails/modules/trails-hibernate/src/main/java/org/trails/component/HibernateAssociationMgt.java =================================================================== --- C:/Prototype/Mavenized/Product/trails/trunk/trails/modules/trails-hibernate/src/main/java/org/trails/component/HibernateAssociationMgt.java (revision 0) +++ C:/Prototype/Mavenized/Product/trails/trunk/trails/modules/trails-hibernate/src/main/java/org/trails/component/HibernateAssociationMgt.java (revision 0) @@ -0,0 +1,63 @@ +package org.trails.component; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.tapestry.IAsset; +import org.apache.tapestry.IPage; +import org.apache.tapestry.annotations.Asset; +import org.apache.tapestry.annotations.ComponentClass; +import org.apache.tapestry.annotations.InjectObject; +import org.hibernate.NonUniqueObjectException; +import org.trails.page.EditPage; +import org.trails.page.PageType; +import org.trails.persistence.HibernatePersistenceService; +import org.trails.util.Utils; + +/** + * @OneToOne use case.

+ * + * This guy manages the owning side user interface of a OneToOne association. + *

Owner-<>-----Association + * + * @author kenneth.colassi nhhockeyplayer@hotmail.com + */ +@ComponentClass(allowBody = true, allowInformalParameters = true) +public abstract class HibernateAssociationMgt extends AssociationMgt { + @Asset(value = "/org/trails/component/AssociationMgt.html") + public abstract IAsset get$template(); + + protected static final Log LOG = LogFactory + .getLog(HibernateAssociationMgt.class); + + /** + * @todo: remove when the components reuse issue goes away + */ + @InjectObject("service:trails.hibernate.PersistenceService") + public abstract HibernatePersistenceService getHibernatePersistenceService(); + + /** + * @todo: remove when the components reuse issue goes away + */ + @Override + public HibernatePersistenceService getPersistenceService() { + return getHibernatePersistenceService(); + } + + public IPage edit(Object member) + { + + EditPage editPage = (EditPage) getPageResolver().resolvePage( + getPage().getRequestCycle(), + Utils.checkForCGLIB(member.getClass()), + PageType.EDIT); + try + { + getPersistenceService().reattach(member); + } catch (NonUniqueObjectException e) + { + } + editPage.setModel(member); + return editPage; + } + +} Index: C:/Prototype/Mavenized/Product/trails/trunk/trails/modules/trails-hibernate/src/main/java/org/trails/hibernate/HibernateDescriptorDecorator.java =================================================================== --- C:/Prototype/Mavenized/Product/trails/trunk/trails/modules/trails-hibernate/src/main/java/org/trails/hibernate/HibernateDescriptorDecorator.java (revision 921) +++ C:/Prototype/Mavenized/Product/trails/trunk/trails/modules/trails-hibernate/src/main/java/org/trails/hibernate/HibernateDescriptorDecorator.java (working copy) @@ -395,56 +395,84 @@ } } - public IPropertyDescriptor decorateAssociationDescriptor(Class type, Property mappingProperty, - IPropertyDescriptor descriptor, IClassDescriptor parentClassDescriptor) + public IPropertyDescriptor decorateAssociationDescriptor(Class origin, Property mappingProperty, + IPropertyDescriptor propertyDescriptorOffOfOrigin, IClassDescriptor parentClassDescriptor) { Type hibernateType = mappingProperty.getType(); Class parentClassType = parentClassDescriptor.getType(); - ObjectReferenceDescriptor descriptorReference = new ObjectReferenceDescriptor(type, descriptor, hibernateType + ObjectReferenceDescriptor descriptorReference = new ObjectReferenceDescriptor(origin, propertyDescriptorOffOfOrigin, hibernateType .getReturnedClass()); - try { - Field propertyField = parentClassType.getDeclaredField(descriptor.getName()); + Field propertyField = parentClassType.getDeclaredField(propertyDescriptorOffOfOrigin.getName()); PropertyDescriptor beanPropDescriptor = (PropertyDescriptor) Ognl.getValue( - "propertyDescriptors.{? name == '" + descriptor.getName() + "'}[0]", Introspector + "propertyDescriptors.{? name == '" + propertyDescriptorOffOfOrigin.getName() + "'}[0]", Introspector .getBeanInfo(parentClassType)); Method readMethod = beanPropDescriptor.getReadMethod(); - // Start by checking for and retrieving mappedBy attribute inside - // the annotation + /** + * Sometimes OneToOne is not coded across classes. Sometimes it is + * using mappedBy to characterize the opposing inverse property on + * the other side of the class boundary. + * + * In the case where either actually is, this infrastructure serves + * to accomodate inverse support across the association. + * + * Start by checking for and retrieving mappedBy attribute inside + * the annotation + */ String inverseProperty = ""; - if (readMethod.isAnnotationPresent(javax.persistence.OneToOne.class)) - { - inverseProperty = readMethod.getAnnotation(javax.persistence.OneToOne.class).mappedBy(); - } else if (propertyField.isAnnotationPresent(javax.persistence.OneToOne.class)) - { - inverseProperty = propertyField.getAnnotation(javax.persistence.OneToOne.class).mappedBy(); - } else + if ( readMethod.isAnnotationPresent(javax.persistence.OneToOne.class) || + propertyField.isAnnotationPresent(javax.persistence.OneToOne.class) ) { - // If there is none then just return the - // ObjectReferenceDescriptor - return descriptorReference; - } + if ( readMethod.isAnnotationPresent(javax.persistence.OneToOne.class) ) + inverseProperty = readMethod.getAnnotation(javax.persistence.OneToOne.class).mappedBy(); + else if ( propertyField.isAnnotationPresent(javax.persistence.OneToOne.class) ) + inverseProperty = propertyField.getAnnotation(javax.persistence.OneToOne.class).mappedBy(); - if ("".equals(inverseProperty)) - { - // http://forums.hibernate.org/viewtopic.php?t=974287&sid=12d018b08dffe07e263652190cfc4e60 - // Caution... this does not support multiple - // class references across the OneToOne relationship - Class returnType = readMethod.getReturnType(); - for (int i = 0; i < returnType.getDeclaredMethods().length; i++) + if ( "".equals(inverseProperty) ) { - if (returnType.getDeclaredMethods()[i].getReturnType().equals(propertyField.getDeclaringClass())) + /* + * Not found yet, Drill into class structure and get it + * + * It is highly likely this is an owner now, since no mappedBy + * + * Origin------<>------OtherSide + * + * search for a get method on OtherSide returning the Origin + * + * We could be traversing owner or association... which one ? It + * does not matter... we are starting with an Origin... it + * could be association or owner... all we need to do is process the + * retrieval of the inverse on the other side that operates OneToOne + * + * http://forums.hibernate.org/viewtopic.php?t=974287&sid=12d018b08dffe07e263652190cfc4e60 + * Caution... this does not support multiple associations of + * same type modeled on both sides. + */ + + Class returnType = readMethod.getReturnType(); + for (int i = 0; i < returnType.getDeclaredMethods().length; i++) { + /** + * Search list of methods and retrieve the get method of the property + */ Method theProperty = returnType.getDeclaredMethods()[i]; - /* strips preceding 'get' */ - inverseProperty = theProperty.getName().substring(3).toLowerCase(); - break; + if (returnType.getDeclaredMethods()[i].getReturnType().getName().equals(origin.getName()) ) + { + /* Found it, strip preceding 'get' */ + inverseProperty = theProperty.getName().substring(3).toLowerCase(); + break; + } } } + + /** + * associations that do not operate back OneToOne mappings are + * exempt from being decorated + */ + descriptorReference.setInverseProperty(inverseProperty); } - } catch (SecurityException e) { LOG.error(e.getMessage()); Index: C:/Prototype/Mavenized/Product/trails/trunk/trails/modules/trails-hibernate/src/main/java/org/trails/hibernate/HibernatePersistenceServiceImpl.java =================================================================== --- C:/Prototype/Mavenized/Product/trails/trunk/trails/modules/trails-hibernate/src/main/java/org/trails/hibernate/HibernatePersistenceServiceImpl.java (revision 921) +++ C:/Prototype/Mavenized/Product/trails/trunk/trails/modules/trails-hibernate/src/main/java/org/trails/hibernate/HibernatePersistenceServiceImpl.java (working copy) @@ -11,10 +11,27 @@ */ package org.trails.hibernate; +import java.io.Serializable; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + import ognl.Ognl; import ognl.OgnlException; -import org.hibernate.*; -import org.hibernate.criterion.*; + +import org.hibernate.Criteria; +import org.hibernate.EntityMode; +import org.hibernate.HibernateException; +import org.hibernate.LockMode; +import org.hibernate.Session; +import org.hibernate.TransientObjectException; +import org.hibernate.criterion.CriteriaSpecification; +import org.hibernate.criterion.DetachedCriteria; +import org.hibernate.criterion.Expression; +import org.hibernate.criterion.MatchMode; +import org.hibernate.criterion.Projections; +import org.hibernate.criterion.Restrictions; import org.hibernate.metadata.ClassMetadata; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; @@ -24,7 +41,6 @@ import org.springframework.orm.hibernate3.support.HibernateDaoSupport; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; -import org.trails.util.Utils; import org.trails.descriptor.CollectionDescriptor; import org.trails.descriptor.DescriptorService; import org.trails.descriptor.IClassDescriptor; @@ -31,14 +47,9 @@ import org.trails.descriptor.IPropertyDescriptor; import org.trails.persistence.HibernatePersistenceService; import org.trails.persistence.PersistenceException; +import org.trails.util.Utils; import org.trails.validation.ValidationException; -import java.io.Serializable; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - public class HibernatePersistenceServiceImpl extends HibernateDaoSupport implements HibernatePersistenceService, ApplicationContextAware { @@ -47,7 +58,7 @@ private DescriptorService _descriptorService = null; /** - * We need this because cylcic reference between HibernatePersistenceServiceImpl and TrailsDescriptorService + * We need this because cyclic reference between HibernatePersistenceServiceImpl and TrailsDescriptorService */ public DescriptorService getDescriptorService() { @@ -247,9 +258,21 @@ } @Transactional + public void reattachCollection(Object[] models) + { + if ( models != null && models.length > 0 ) + for ( int i = 0; i < models.length; i++) + reattach (models[i]); + } + + @Transactional public void reattach(Object model) { - getSession().lock(model, LockMode.NONE); + try { + getSession().lock(model, LockMode.NONE); + } catch (org.hibernate.NonUniqueObjectException ex) { + merge(model); + } } @@ -302,6 +325,11 @@ } } + public boolean isDetached(Object data, IClassDescriptor classDescriptor) + { + return getSession().contains(data); + } + @Transactional(readOnly = true, propagation = Propagation.SUPPORTS) public List getInstances(final Object example, final IClassDescriptor classDescriptor) { Index: C:/Prototype/Mavenized/Product/trails/trunk/trails/modules/trails-hibernate/src/main/resources/org/trails/component/HibernateAssociationMgt.jwc =================================================================== --- C:/Prototype/Mavenized/Product/trails/trunk/trails/modules/trails-hibernate/src/main/resources/org/trails/component/HibernateAssociationMgt.jwc (revision 0) +++ C:/Prototype/Mavenized/Product/trails/trunk/trails/modules/trails-hibernate/src/main/resources/org/trails/component/HibernateAssociationMgt.jwc (revision 0) @@ -0,0 +1,5 @@ + + + + + Index: C:/Prototype/Mavenized/Product/trails/trunk/trails/modules/trails-hibernate/src/main/resources/org/trails/page/HibernateEditors.page =================================================================== --- C:/Prototype/Mavenized/Product/trails/trunk/trails/modules/trails-hibernate/src/main/resources/org/trails/page/HibernateEditors.page (revision 921) +++ C:/Prototype/Mavenized/Product/trails/trunk/trails/modules/trails-hibernate/src/main/resources/org/trails/page/HibernateEditors.page (working copy) @@ -81,7 +81,7 @@ model[#this.descriptor.name] descriptor - + model descriptor @@ -88,8 +88,6 @@ - model - model[#this.descriptor.name] model model[#this.descriptor.name] descriptor @@ -94,8 +92,7 @@ model[#this.descriptor.name] descriptor - -