-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 1 post ] 
Author Message
 Post subject: Nested property acessor on hibernate..
PostPosted: Sun Jun 07, 2009 10:28 am 
Newbie

Joined: Sat Jun 06, 2009 10:17 am
Posts: 4
Hi,

I´m just adding this topic since i have seen a solution on hibernate Property accessors.

I just extended the BasicPropertyAccessor with few methods... like invokeNested...
Mapping and code Code as Follows... Persistent class not included.... Anyone has suggestion how i can enhance this nested property acessor? or if one-one is better ?

Regards,

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.aegis.domain.claim" >

<class name="ClaimRecord" table="TCLMREC" >
<meta attribute="sync-DAO">false</meta>

<composite-id name="id" class="com.aegis.domain.claim.ClaimRecordPk">
<key-property name="claimNo" column="Claim_no" type="string"
length="10" />
<key-property name="timestamp" column="Timestamp" type="timestamp"
length="23" />
</composite-id>
<property name="clmFeatureNo" column="Clm_feature_no" type="string"
not-null="true" length="2" />
<property name="clmActObjId" column="clm_act_obj_id" type="integer"
not-null="true" length="10" />

<component name="claimActivity" class="com.aegis.domain.status.ClaimActivity"
insert="true" update="false" lazy="false" >
<property name="id.refGroupCode" column="Clm_office_cd"
type="string" not-null="true" length="6" access="com.bsi.common.hibernate.NestedPropertyAcessor"/>
<property name="id.dataElementCode" column="Clm_activity_cd"
type="string" update="false" not-null="true" length="4" access="com.bsi.common.hibernate.NestedPropertyAcessor"/>
<property name="description" column="Clm_activity_desc"
type="string" not-null="true" length="30" />
<property name="sourceSystemId" column="Source_system_id"
type="string" not-null="true" length="2" />
</component>

<property name="clmActivityDt" column="Clm_activity_dt" type="date"
not-null="true" length="16" />
<property name="remarksTxt" column="Remarks_txt" type="string"
not-null="true" length="150" />

<property name="useridCd" column="Userid_cd" type="string"
not-null="true" length="8" />

</class>
</hibernate-mapping>



Code:

package com.bsi.common.hibernate;
/**
* permits usage of nested properties for component types.
*/
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;

import org.hibernate.HibernateException;
import org.hibernate.PropertyAccessException;
import org.hibernate.PropertyNotFoundException;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.property.BasicPropertyAccessor;
import org.hibernate.property.Getter;
import org.hibernate.property.PropertyAccessor;
import org.hibernate.property.Setter;
import org.hibernate.property.BasicPropertyAccessor.BasicGetter;
import org.hibernate.property.BasicPropertyAccessor.BasicSetter;
import org.hibernate.util.ReflectHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class NestedPropertyAcessor  implements PropertyAccessor {

   private static final Logger log = LoggerFactory.getLogger(BasicPropertyAccessor.class);
   private String targetPropertyName;
   
   public Getter getGetter(Class persistentClass, String propertyName)
   throws PropertyNotFoundException {
//      Method method = NestedPropertyAcessor.getMethod(persistentClass, propertyName, TypeEnum.MUTATOR);
//      Class clazz = method.getDeclaringClass();
      return new NestedGetter(persistentClass , propertyName);
   }

   public Setter getSetter(Class persistentClass, String propertyName)
   throws PropertyNotFoundException {
//      Method method = NestedPropertyAcessor.getMethod(persistentClass, propertyName, TypeEnum.MUTATOR);
//      Class clazz = method.getDeclaringClass();
//      String shortPropertyName = NestedPropertyAcessor.getLastMethodName(propertyName);
      return new NestedSetter (persistentClass , propertyName);
   }

   public static final class NestedSetter implements Setter {
      private Class clazz;
      private final String propertyName;

      private NestedSetter(Class clazz, String propertyName) {
         this.clazz=clazz;
         this.propertyName=propertyName;
      }
      
      
      
      public Setter getSetter(Class theClass, String propertyName)
      throws PropertyNotFoundException {
         return createSetter(theClass, propertyName);
      }
      
      private static Setter createSetter(Class theClass, String propertyName)
      throws PropertyNotFoundException {
         NestedSetter result = getSetterOrNull(theClass, propertyName);
         if (result==null) {
            throw new PropertyNotFoundException(
                  "Could not find a setter for property " +
                  propertyName +
                  " in class " +
                  theClass.getName()
               );
         }
         return result;
      }
      
      
      private static NestedSetter getSetterOrNull(Class theClass, String propertyName) {
         
         Method method = NestedPropertyAcessor.getMethod(theClass, propertyName, TypeEnum.MUTATOR);
         Class clazz = method.getDeclaringClass();
         String shortPropertyName = NestedPropertyAcessor.getLastMethodName(propertyName);

         
         if (theClass==Object.class || theClass==null) return null;

//         Method method = setterMethod(clazz, shortPropertyName);

         if (method!=null) {
            if ( !ReflectHelper.isPublic(clazz, method) ) method.setAccessible(true);
            return new NestedSetter(theClass, propertyName);
         }
         else {
            NestedSetter setter = getSetterOrNull( theClass, propertyName );
            if (setter==null) {
               Class[] interfaces = theClass.getInterfaces();
               for ( int i=0; setter==null && i<interfaces.length; i++ ) {
                  setter=getSetterOrNull( interfaces[i], propertyName );
               }
            }
            return setter;
         }

      }
      
      /**
       *
       * @param clazz - Any class ...
       * @param propertyName - property name to get the mwthods.
       * @param accessorType - Acessor or Mutator. (Get/Set methods)
       * @return
       */
      public static Object invokeNested(Object object , Object[] args, Class clazz , String propertyName , TypeEnum accessorType)
      {    
         Object returnObject = null;
         PropertyDescriptor descriptor;
         Method met = null;
         try {
            String [] methods = propertyName.split("\\.");
            String accumulator = "";
            if (methods.length > 1) {
                     accumulator += methods[0];
                     descriptor = new PropertyDescriptor (methods[0] , clazz);
                     Class innerClass = descriptor.getPropertyType();
                     //Invoke here to get the inner object hold by the parent class.
                     met = descriptor.getReadMethod();
                     returnObject = met.invoke(object, new Object[]{});
                     String remaining = propertyName.substring(accumulator.length() + 1);
                     returnObject =  invokeNested(returnObject, args , innerClass , remaining , accessorType);
            }else {
               descriptor = new PropertyDescriptor (propertyName , clazz);
               if (accessorType.equals(TypeEnum.ACCESSOR)) {
                  met= descriptor.getReadMethod();
               }else if (accessorType.equals(TypeEnum.MUTATOR)){
                  met= descriptor.getWriteMethod();
               }
               returnObject = met.invoke(object, args);
            }
         } catch (IntrospectionException e) {
            throw new PropertyAccessException(
                  e,
                  "Introspection excepption occurred while calling the nested property.",
                  true,
                  clazz,
                  propertyName
               );
         } catch (IllegalArgumentException e) {
            e.printStackTrace();
            throw new PropertyAccessException(
                  e,
                  "IllegalArgumentException exception occurred while calling the nested property.",
                  true,
                  clazz,
                  propertyName
               );
         } catch (IllegalAccessException e) {
            e.printStackTrace();
            throw new PropertyAccessException(
                  e,
                  "IllegalAccessException exception occurred while calling the nested property.",
                  true,
                  clazz,
                  propertyName
               );
         } catch (InvocationTargetException e) {
            e.printStackTrace();
            throw new PropertyAccessException(
                  e,
                  "InvocationTargetException exception occurred while calling the nested property.",
                  true,
                  clazz,
                  propertyName
               );
         }
         return returnObject;
      }
      
      
      public void set(Object target, Object value, SessionFactoryImplementor factory)
      throws HibernateException {
         Method method = null;
         try {
//            method = NestedPropertyAcessor.getMethod(target.getClass(), propertyName, TypeEnum.MUTATOR);
            //FIXME: This need a invoke nested ...
            invokeNested( target, new Object[] { value }, target.getClass() ,  propertyName , TypeEnum.MUTATOR );
         }
         catch (NullPointerException npe) {
            if ( (value==null || method ==null) && method.getParameterTypes()[0].isPrimitive() ) {
               throw new PropertyAccessException(
                     npe,
                     "Null value was assigned to a property of nested primitive type",
                     true,
                     clazz,
                     propertyName
                  );
            }
            else {
               throw new PropertyAccessException(
                     npe,
                     "NullPointerException occurred while calling",
                     true,
                     clazz,
                     propertyName
                  );
            }
         }
         catch (IllegalArgumentException iae) {
            if ( value==null && method.getParameterTypes()[0].isPrimitive() ) {
               throw new PropertyAccessException(
                     iae,
                     "Null value was assigned to a property of primitive type",
                     true,
                     clazz,
                     propertyName
                  );
            }
            else {
               log.error(
                     "IllegalArgumentException in class: " + clazz.getName() +
                     ", setter method of property: " + propertyName
                  );
               log.error(
                     "expected type: " +
                     method.getParameterTypes()[0].getName() +
                     ", actual value: " +
                     ( value==null ? null : value.getClass().getName() )
                  );
               throw new PropertyAccessException(
                     iae,
                     "IllegalArgumentException occurred while calling",
                     true,
                     clazz,
                     propertyName
                  );
            }
         }
      }

      public Method getMethod() {
         
         return NestedPropertyAcessor.getMethod(clazz, propertyName, TypeEnum.MUTATOR);
      }

      public String getMethodName() {
         return NestedPropertyAcessor.getMethod(clazz, propertyName, TypeEnum.MUTATOR).getName();
      }

      Object readResolve() {
         return createSetter(clazz, propertyName);
      }

      public String toString() {
         return "BasicSetter(" + clazz.getName() + '.' + propertyName + ')';
      }
   }
   
   
   public static String getLastMethodName (String nestedProperty)
   {
      String [] methods = nestedProperty.split("\\.");
      return methods[methods.length -1];
   }
   
   
   public static final class  NestedGetter implements Getter {
      private Class clazz;
      private final transient Method method;
      private final String propertyName;
      private final String nestedPropertyName;
       
      private NestedGetter(Class clazz, String propertyName) {
         this.method=NestedPropertyAcessor.getMethod(clazz, propertyName, TypeEnum.ACCESSOR);
         this.clazz=clazz;
         this.nestedPropertyName = propertyName;
         this.propertyName=NestedPropertyAcessor.getLastMethodName(propertyName);
         
      }

      public Object get(Object target) throws HibernateException {
         try {
            
            return invokeNested(target, new Object[]{}, clazz, nestedPropertyName, TypeEnum.ACCESSOR);
         }

         catch (IllegalArgumentException iae) {
            log.error(
                  "IllegalArgumentException in class: " + clazz.getName() +
                  ", getter method of property: " + propertyName
               );
            throw new PropertyAccessException(
                  iae,
                  "IllegalArgumentException occurred calling",
                  false,
                  clazz,
                  propertyName
               );
         }
      }

      
      
      /**
       *
       * @param clazz - Any class ...
       * @param propertyName - property name to get the mwthods.
       * @param accessorType - Acessor or Mutator. (Get/Set methods)
       * @return
       */
      public static Object invokeNested(Object object , Object[] args, Class clazz , String propertyName , TypeEnum accessorType)
      {    
         Object returnObject = null;
         PropertyDescriptor descriptor;
         Method met = null;
         try {
            String [] methods = propertyName.split("\\.");
            String accumulator = "";
            if (methods.length > 1) {
                     accumulator += methods[0];
                     descriptor = new PropertyDescriptor (methods[0] , clazz);
                     Class innerClass = descriptor.getPropertyType();
                     //Invoke here to get the inner object hold by the parent class.
                     met = descriptor.getReadMethod();
                     returnObject = met.invoke(object, new Object[]{});
                     String remaining = propertyName.substring(accumulator.length() + 1);
                     returnObject =  invokeNested(returnObject, args , innerClass , remaining , accessorType);
            }else {
               descriptor = new PropertyDescriptor (propertyName , clazz);
               if (accessorType.equals(TypeEnum.ACCESSOR)) {
                  met= descriptor.getReadMethod();
               }else if (accessorType.equals(TypeEnum.MUTATOR)){
                  met= descriptor.getWriteMethod();
               }
               returnObject = met.invoke(object, args);
            }
         } catch (IntrospectionException e) {
            throw new PropertyAccessException(
                  e,
                  "Introspection excepption occurred while calling the nested property.",
                  true,
                  clazz,
                  propertyName
               );
         } catch (IllegalArgumentException e) {
            e.printStackTrace();
            throw new PropertyAccessException(
                  e,
                  "IllegalArgumentException exception occurred while calling the nested property.",
                  true,
                  clazz,
                  propertyName
               );
         } catch (IllegalAccessException e) {
            e.printStackTrace();
            throw new PropertyAccessException(
                  e,
                  "IllegalAccessException exception occurred while calling the nested property.",
                  true,
                  clazz,
                  propertyName
               );
         } catch (InvocationTargetException e) {
            e.printStackTrace();
            throw new PropertyAccessException(
                  e,
                  "InvocationTargetException exception occurred while calling the nested property.",
                  true,
                  clazz,
                  propertyName
               );
         }
         return returnObject;
      }
      
      public Object getForInsert(Object target, Map mergeMap, SessionImplementor session) {
         return get( target );
      }

      public Class getReturnType() {
         return method.getReturnType();
      }

      public Method getMethod() {
         return method;
      }

      public String getMethodName() {
         return method.getName();
      }

      public String toString() {
         return "BasicGetter(" + clazz.getName() + '.' + propertyName + ')';
      }
      
      Object readResolve() {
         return createGetter(clazz, propertyName);
      }
   }
   
   
   
   public static Getter createGetter(Class theClass, String propertyName)
   throws PropertyNotFoundException {
      NestedGetter result = getGetterOrNull(theClass, propertyName);
      if (result==null) {
         throw new PropertyNotFoundException(
               "Could not find a getter for " +
               propertyName +
               " in class " +
               theClass.getName()
         );
      }
      return result;

   }

   private static NestedGetter getGetterOrNull(Class theClass, String propertyName) {

      Method method1=NestedPropertyAcessor.getMethod(theClass, propertyName, TypeEnum.ACCESSOR);
      Class clazz=method1.getDeclaringClass();
      String shortPropertyName= NestedPropertyAcessor.getLastMethodName(propertyName);
      
      if (theClass==Object.class || theClass==null) return null;

      Method nestedMethod = getterMethod(clazz, shortPropertyName);

      if (nestedMethod!=null) {
         if ( !ReflectHelper.isPublic(clazz, nestedMethod) ) nestedMethod.setAccessible(true);
         return new NestedGetter(clazz,  propertyName);
      }
      else {
         NestedGetter getter = getGetterOrNull( clazz.getSuperclass(), shortPropertyName );
         if (getter==null) {
            Class[] interfaces = theClass.getInterfaces();
            for ( int i=0; getter==null && i<interfaces.length; i++ ) {
               getter=getGetterOrNull( interfaces[i], shortPropertyName );
            }
         }
         return getter;
      }
   }

   private static Method getterMethod(Class theClass, String propertyName) {

      Method[] methods = theClass.getDeclaredMethods();
      for (int i=0; i<methods.length; i++) {
         // only carry on if the method has no parameters
         if ( methods[i].getParameterTypes().length == 0 ) {
            String methodName = methods[i].getName();

            // try "get"
            if ( methodName.startsWith("get") ) {
               String testStdMethod = Introspector.decapitalize( methodName.substring(3) );
               String testOldMethod = methodName.substring(3);
               if ( testStdMethod.equals(propertyName) || testOldMethod.equals(propertyName) ) {
                  return methods[i];
               }

            }

            // if not "get", then try "is"
            if ( methodName.startsWith("is") ) {
               String testStdMethod = Introspector.decapitalize( methodName.substring(2) );
               String testOldMethod = methodName.substring(2);
               if ( testStdMethod.equals(propertyName) || testOldMethod.equals(propertyName) ) {
                  return methods[i];
               }
            }
         }
      }
      return null;
   }
   
   

   
   
   /**
    *
    * @param clazz - Any class ...
    * @param propertyName - property name to get the mwthods.
    * @param accessorType - Acessor or Mutator. (Get/Set methods)
    * @return
    */
   public static Method getMethod(Class clazz , String propertyName , TypeEnum accessorType)
   {    
      Method met = null;
      PropertyDescriptor descriptor;
      try {
         String [] methods = propertyName.split("\\.");
         String accumulator = "";
         if (methods.length > 1) {
                  accumulator += methods[0];
                  descriptor = new PropertyDescriptor (methods[0] , clazz);
                  Class innerClass = descriptor.getPropertyType();
                  String remaining = propertyName.substring(accumulator.length() + 1);
                  met =  getMethod(innerClass , remaining , accessorType);
         }else {
            descriptor = new PropertyDescriptor (propertyName , clazz);
            if (accessorType.equals(TypeEnum.ACCESSOR))
               met= descriptor.getReadMethod();
            else if (accessorType.equals(TypeEnum.MUTATOR)){
               met= descriptor.getWriteMethod();
            }
         }
      } catch (IntrospectionException e) {
         throw new PropertyAccessException(
               e,
               "Introspection excepption occurred while calling the nested property.",
               true,
               clazz,
               propertyName
            );
      }
      return met;
   }


   public enum TypeEnum {
      ACCESSOR,
      MUTATOR;
   }

}



Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 1 post ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.