Menu

Objects replication - How to use partial copy

Help
2005-12-14
2013-04-25
  • Thomas COUSIN

    Thomas COUSIN - 2005-12-14

    (Previous post was made on Hibernate's forum : http://forum.hibernate.org/viewtopic.php?t=944303\)

    Hi hanson,

    This is the way I use the beanLib to do a partial copy of my objects graph. To test your lib, I just   ask it to replicate the root object.

    [code]
        Object replicateObject = new Object();
        BeanPopulatable vetoer = new MyVetoer(this.hibernateSessionProvider.getSession());
       
        Set setEntityBean = new HashSet();
        Class[] arrayEntityBean = {MySuperClass.class};
        setEntityBean.addAll(Arrays.asList(arrayEntityBean));
       
        Set setProperties = new HashSet();
        String[] arrayProperties = {"onePropertyNameFromMySuperClass", "otherPropertyNameFromMySuperClass"};
        CollectionPropertyName[]  tabCollectionPropertyName =     CollectionPropertyName.createCollectionPropertyNames(MySuperClass.class, arrayProperties);
        setProperties.addAll(Arrays.asList(arrayProperties));
       
        HibernateBeanReplicator replicator = new Hibernate3BeanReplicator()
                                                                        .initVetoer(vetoer)
                                                                        .initCollectionPropertyNameSet(setProperties)
                                                                        .initEntityBeanClassSet(setEntityBean);

        replicateObject = replicator.copy(object);
    [/code]

    This code is wrapped in a method that I made just to test the lib and MyVetoer is basically, the one that you give in the previous post.

    Hope this help you to understand what I am trying to do.

     
    • Joe D. Velopar

      Joe D. Velopar - 2005-12-14

      Hi Thomas,

      The main problem seems to be the argument passed to HibernateBeanReplicator.initCollectionPropertyNameSet() being a set of strings instead of CollectionPropertyName instances.

      See below for details.

      Hanson

      1) The code of:

          Object replicateObject = new Object();

      Doesn't make sense to me.  This will just replicate an Object instance.  Do you mean to initialize the replicateObject with an instance of a subclass of MySuperClass ?

      2) The argument passed to HibernateBeanReplicator.initCollectionPropertyNameSet() is a set of CollectionPropertyName instances, not String instances.

      In your case, it should probably be something like:

          Set setProperties = new HashSet();
            String[] arrayProperties = {"onePropertyNameFromMySuperClass", "otherPropertyNameFromMySuperClass"};
          CollectionPropertyName[]  tabCollectionPropertyName =
          CollectionPropertyName.createCollectionPropertyNames(MySuperClass.class, arrayProperties);
          // Note setProperties needs to be a set of CollectionPropertyName instance.
          setProperties.addAll(Arrays.asList(tabCollectionPropertyName));

      3) Make sure "onePropertyNameFromMySuperClass" and "otherPropertyNameFromMySuperClass" are the actual field names declared in MySuperClass, and that they are subtype of java.util.Collection.

          String[] arrayProperties = {"onePropertyNameFromMySuperClass", "otherPropertyNameFromMySuperClass"};

       
    • Thomas COUSIN

      Thomas COUSIN - 2005-12-15

      Thanks for your attention, and thanks to you I realize that I was going to a bad direction. First of all, let me answer the three points:

      1. I tried to clean my code to show you something a bit more generic ... my bad
      2. I don't understand what you mean by a Set because I think that what I made is not wrong (certainly not clean) but I finally send to the initializer a Set of CollectionPropertyName
      3. And this point show me the light. I didn't catch the fact that CollectionPropertyName is especially made to specify children of the current object.

      So, I think that I need in my case to use a DetailledBeanPopulatable to tell HibernateBeanReplicator which field in each object I want that it replicate.

      Thanks again

       
    • Jorge E

      Jorge E - 2007-07-27

      Hi . so when we need to tell HibernateBeanReplicator wich field in each object are replicable we use DetailledBeanPopulatable ? right ? But how? because the interface DetailledBeanPopulatable have only one method shouldPopulate(.....) and it return true o false for one specific property .. so .. it need to be call each time we want to replicate a property ..  and what about voters?, it's not an  DetailledBeanPopulatable  too ?
      Please .. don't follow the idea ..

       
      • Hanson Char

        Hanson Char - 2007-07-27

        If you can put this into some small sample classes and explain what you want to populate and what not, I can show the sample code to achieve that.

         
        • Jorge E

          Jorge E - 2007-08-01

          Sorry for delay, i was on vacations.
          And example of my code would be
          public class A {
          private List<F> af;
          ...
          }
          public class F {
          private C c;
          private List<D> fd;
          ...
          }
          public class C {
          private List<A> ca ;
          private List<D> cd;
          ...
          }
          public class D {
          private String someField;
          ...
          }
          So, what i want to do is to replicate A, but objects F can only replicate c object, not list of D ..
          It's an example but thats my question, don't now how to tell to each object if can replicate or not ..
          Thanks

           
          • Hanson Char

            Hanson Char - 2007-08-02

            >So, what i want to do is to replicate A, but objects F can only replicate c object, not list of D .. 

            I suppose you are asking how this can be done with Hibernate3BeanReplicator.  There are multiple ways.  Two obvious ones are
            1) explicitly/positively specify all the collection member fields you want to replicate; or
            2) negatively specify a vetoer

            Using your given example, see below for some sample code to do that.  Let me know if this works for you.

            Sample code for (1):

                    A a1 = ...;

                    Set<CollectionPropertyName> collectionProperties = new HashSet<CollectionPropertyName>();
                    collectionProperties.add(new CollectionPropertyName(A.class, "af"));
                    collectionProperties.add(new CollectionPropertyName(C.class, "ca"));
                    collectionProperties.add(new CollectionPropertyName(C.class, "cd"));
                   
                    A a2 = new Hibernate3BeanReplicator().initCollectionPropertyNameSet(collectionProperties)
                                                         .copy(a1);

            Sample code for (2):

                    A a1 = ...
                   
                    A a2 = new Hibernate3BeanReplicator()
                           .initVetoer(new BeanPopulatable() {
                                public boolean shouldPopulate(String propertyName, Method readerMethod) {
                                    return readerMethod.getDeclaringClass() != F.class || !propertyName.equals("fd");
                                }
                    }).copy(a1);

             
            • Hanson Char

              Hanson Char - 2007-08-02

              If, however, you are not using Hibernate, you can also achieve the partial copying with BeanReplicator.  Example:

                      A a1 = ...
                     
                      A a2 = BeanReplicator.newBeanReplicatable(
                          BeanTransformer.newBeanTransformer()
                                         .initBeanPopulatable(
                                                 new BeanPopulatable() {
                          public boolean shouldPopulate(String propertyName, Method readerMethod) {
                              return readerMethod.getDeclaringClass() != F.class || !propertyName.equals("fd");
                          }
                      })).replicateBean(a1);

               
    • Jorge E

      Jorge E - 2007-08-02

      I be able to test the code presented, but when the object i whant to exclude is a Bean, the readerMethod.getDeclaringClass() return a CGLIB proxy, not the Class it self ..
      Be aware that it is not a collection, like the sample you post, is that a problem ?

       
      • Hanson Char

        Hanson Char - 2007-08-02

        >the readerMethod.getDeclaringClass() return a CGLIB proxy, not the Class it self .. 

        Try:

            UnEnhancer.unenhance(readerMethod.getDeclaringClass())

        >Be aware that it is not a collection, like the sample you post, is that a problem ?

        CollectionPropertyName can be used for any member field which is either an instance of Collection or Map, if that's what you are concerned about.

         

Log in to post a comment.