fix #9728 completing bean property Team.nomenclaturalTitleCache
[cdmlib.git] / cdmlib-model / src / main / java / eu / etaxonomy / cdm / model / EntityCollectionSetterAdapter.java
index 0124b97c6c476f78c109058c04e47545ae4d2e1c..efd735aea749b8a2d42a23fa79e91830f58def99 100644 (file)
@@ -8,6 +8,7 @@
 */
 package eu.etaxonomy.cdm.model;
 
+import java.io.Serializable;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.util.ArrayList;
@@ -28,30 +29,30 @@ import eu.etaxonomy.cdm.model.common.CdmBase;
  * <p>
  * Usage example:
  * <pre>
- *   &#64;Transient
- *   &#64;Transient
- *   private EntityCollectionSetterAdapter<Team, Person> teamMembersSetterAdapter = new EntityCollectionSetterAdapter<Team, Person>(Team.class, Person.class, "teamMembers");
- *
  *   public void setTeamMembers(List<Person> teamMembers) throws SetterAdapterException {
- *       teamMembersSetterAdapter.setCollection(this, teamMembers);
+ *      new EntityCollectionSetterAdapter<Team, Person>(Team.class, Person.class, "teamMembers").setCollection(this, teamMembers);
  *   }
- </pre>
</pre>
  *
  * see https://dev.e-taxonomy.eu/redmine/issues/7600
  *
  * @author a.kohlbecker
  * @since Nov 15, 2018
- *
  */
-public class EntityCollectionSetterAdapter<CDM extends CdmBase, T extends CdmBase> {
+public class EntityCollectionSetterAdapter<CDM extends CdmBase, T extends CdmBase> implements Serializable {
+
+    private static final long serialVersionUID = -996721690408449555L;
+
+    private static final String GETTER_PREFIX = "get";
 
     private Class<T> propertyItemType;
-    private Method getMethod;
-    private Method addMethod;
-    private Method removeMethod;
-    private Exception getMethodException;
-    private Exception addMethodException;
-    private Exception removeMethodException;
+
+    private Class<CDM> beanClass;
+
+    private String propertyName;
+    private String addMethodName;
+
+    private String removMethodName;
 
     public EntityCollectionSetterAdapter(Class<CDM> beanClass, Class<T> propertyItemType, String propertyName){
         this(beanClass,
@@ -64,38 +65,26 @@ public class EntityCollectionSetterAdapter<CDM extends CdmBase, T extends CdmBas
 
     public EntityCollectionSetterAdapter(Class<CDM> beanClass, Class<T> propertyItemType, String propertyName, String addMethodName, String removMethodName){
 
+        this.beanClass = beanClass;
         this.propertyItemType = propertyItemType;
-        try {
-            getMethod = beanClass.getDeclaredMethod("get" + StringUtils.capitalize(propertyName));
-        } catch (NoSuchMethodException | SecurityException e) {
-            getMethodException = e;
-        }
-        try {
-            addMethod = beanClass.getDeclaredMethod(addMethodName, propertyItemType);
-        } catch (NoSuchMethodException | SecurityException e) {
-            addMethodException = e;
-        }
-        try {
-            removeMethod = beanClass.getDeclaredMethod(removMethodName, propertyItemType);
-        } catch (NoSuchMethodException | SecurityException e) {
-            removeMethodException = e;
-        }
+
+        this.propertyName = propertyName;
+        this.addMethodName = addMethodName;
+        this.removMethodName = removMethodName;
     }
 
     public void setCollection(CDM bean, Collection<T> items) throws SetterAdapterException {
 
-        if(getMethodException != null){
-            throw new SetterAdapterException("No getter method due to previous exception.", getMethodException);
-        }
-        if(addMethodException != null){
-            throw new SetterAdapterException("No add method due to previous exception.", addMethodException);
-        }
-        if(removeMethodException != null){
-            throw new SetterAdapterException("No remove method due to previous exception.", removeMethodException);
-        }
+        Method getterMethod = null;
+        Method addMethod;
+        Method removeMethod;
 
         try{
-            Collection<T> getterCollection = (Collection<T>) getMethod.invoke(bean);
+            getterMethod = beanClass.getDeclaredMethod(GETTER_PREFIX + StringUtils.capitalize(propertyName));
+            addMethod = beanClass.getDeclaredMethod(addMethodName, propertyItemType);
+            removeMethod = beanClass.getDeclaredMethod(removMethodName, propertyItemType);
+
+            Collection<T> getterCollection = (Collection<T>) getterMethod.invoke(bean);
             List<T> currentItems = new ArrayList<>(getterCollection);
             List<T> itemsSeen = new ArrayList<>();
             for(T a : items){
@@ -111,28 +100,32 @@ public class EntityCollectionSetterAdapter<CDM extends CdmBase, T extends CdmBas
                 if(!itemsSeen.contains(a)){
                     removeMethod.invoke(bean, a);
                 }
-        }
+            }
         } catch(ClassCastException e){
-            throw new SetterAdapterException("getter return type (" + getMethod.getReturnType() + ") incompatible with expected  property type " + propertyItemType, e);
+            throw new SetterAdapterException("getter return type (" + (getterMethod != null ? getterMethod.getReturnType() : "NULL") + ") incompatible with expected  property type " + propertyItemType, e);
         } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
             throw new SetterAdapterException("error invoking method", e);
+        } catch (NoSuchMethodException | SecurityException e) {
+            throw new SetterAdapterException("Property related method not found", e);
         }
     }
 
     public static class SetterAdapterException extends Exception {
 
-        private static final long serialVersionUID = 1L;
+        private static final long serialVersionUID = 6011462992846535903L;
 
-        /**
-         * @param message
-         * @param cause
-         */
         public SetterAdapterException(String message, Throwable cause) {
             super(message, cause);
         }
+    }
 
+    public void setAddMethodName(String addMethodName) {
+        this.addMethodName = addMethodName;
+    }
 
-
+    public void setRemovMethodName(String removMethodName) {
+        this.removMethodName = removMethodName;
     }
 
+
 }