merge-update from trunk
[cdmlib.git] / cdmlib-model / src / main / java / eu / etaxonomy / cdm / strategy / merge / DefaultMergeStrategy.java
index 23235eab54637aaec48f11ebb06f775c16c9f66a..d8f2ad77f5ca15d2c995e7dfd92ddfa476728c33 100644 (file)
@@ -14,8 +14,9 @@ import java.lang.annotation.Annotation;
 import java.lang.reflect.Field;\r
 import java.lang.reflect.GenericDeclaration;\r
 import java.lang.reflect.Method;\r
-import java.lang.reflect.Modifier;\r
+import java.lang.reflect.ParameterizedType;\r
 import java.lang.reflect.Type;\r
+import java.lang.reflect.TypeVariable;\r
 import java.util.ArrayList;\r
 import java.util.Collection;\r
 import java.util.HashMap;\r
@@ -25,20 +26,13 @@ import java.util.Map;
 import java.util.Set;\r
 import java.util.UUID;\r
 \r
-import javax.persistence.Transient;\r
-\r
 import org.apache.log4j.Logger;\r
-import org.joda.time.DateTime;\r
 \r
-import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl;\r
-import sun.reflect.generics.reflectiveObjects.TypeVariableImpl;\r
-import eu.etaxonomy.cdm.model.agent.Contact;\r
+import eu.etaxonomy.cdm.common.CdmUtils;\r
 import eu.etaxonomy.cdm.model.common.CdmBase;\r
 import eu.etaxonomy.cdm.model.common.ICdmBase;\r
 import eu.etaxonomy.cdm.model.common.IRelated;\r
-import eu.etaxonomy.cdm.model.common.LSID;\r
 import eu.etaxonomy.cdm.model.common.RelationshipBase;\r
-import eu.etaxonomy.cdm.model.common.TimePeriod;\r
 import eu.etaxonomy.cdm.strategy.StrategyBase;\r
 \r
 /**\r
@@ -71,7 +65,7 @@ public class DefaultMergeStrategy extends StrategyBase implements IMergeStrategy
                boolean includeStatic = false;\r
                boolean includeTransient = false;\r
                boolean makeAccessible = true;\r
-               this.mergeFields = getAllNonStaticNonTransientFields(mergeClazz, includeStatic, includeTransient, makeAccessible);\r
+               this.mergeFields = CdmUtils.getAllFields(mergeClass, CdmBase.class, includeStatic, includeTransient, makeAccessible, true);\r
                initMergeModeMap();\r
        }\r
 \r
@@ -159,7 +153,6 @@ public class DefaultMergeStrategy extends StrategyBase implements IMergeStrategy
                                throw new MergeException("Identifier must always have merge mode MergeMode.FIRST");\r
                        }\r
                }\r
-               \r
        }\r
 \r
        public <T extends IMergable> Set<ICdmBase> invoke(T mergeFirst, T mergeSecond) throws MergeException {\r
@@ -192,6 +185,8 @@ public class DefaultMergeStrategy extends StrategyBase implements IMergeStrategy
                                        mergeSingleCdmBaseField(mergeFirst, mergeSecond, field, deleteSet);\r
                                }else if(fieldType.isInterface()){\r
                                        mergeInterfaceField(mergeFirst, mergeSecond, field, deleteSet);\r
+                               }else if(fieldType.isEnum()){\r
+                                       mergeEnumField(mergeFirst, mergeSecond, field, deleteSet);\r
                                }else{\r
                                        throw new RuntimeException("Unknown Object type for merging: " + fieldType);\r
                                }\r
@@ -213,10 +208,23 @@ public class DefaultMergeStrategy extends StrategyBase implements IMergeStrategy
                if (mergeMode != MergeMode.FIRST){\r
                        mergeCdmBaseValue(mergeFirst, mergeSecond, field, deleteSet);\r
                }\r
-               System.out.println(propertyName + ": " + mergeMode + ", " + field.getType().getName());\r
+               logger.debug(propertyName + ": " + mergeMode + ", " + field.getType().getName());\r
+               \r
+       }\r
+\r
+       /**\r
+        * @throws Exception \r
+        * \r
+        */\r
+       private <T extends IMergable> void mergeEnumField(T mergeFirst, T mergeSecond, Field field, Set<ICdmBase> deleteSet) throws Exception {\r
+               String propertyName = field.getName();\r
+               MergeMode mergeMode =  this.getMergeMode(propertyName);\r
+               if (mergeMode != MergeMode.FIRST){\r
+                       mergeCdmBaseValue(mergeFirst, mergeSecond, field, deleteSet);\r
+               }\r
+               logger.debug(propertyName + ": " + mergeMode + ", " + field.getType().getName());\r
                \r
        }\r
-       \r
        \r
        /**\r
         * @throws Exception \r
@@ -228,7 +236,7 @@ public class DefaultMergeStrategy extends StrategyBase implements IMergeStrategy
                if (mergeMode != MergeMode.FIRST){\r
                        mergeCdmBaseValue(mergeFirst, mergeSecond, field, deleteSet);\r
                }\r
-               System.out.println(propertyName + ": " + mergeMode + ", " + field.getType().getName());\r
+               logger.debug(propertyName + ": " + mergeMode + ", " + field.getType().getName());\r
                \r
        }\r
        \r
@@ -265,7 +273,7 @@ public class DefaultMergeStrategy extends StrategyBase implements IMergeStrategy
                        Object value = getMergeValue(mergeFirst, mergeSecond, field);\r
                        field.set(mergeFirst, value);\r
                }\r
-               System.out.println(propertyName + ": " + mergeMode + ", " + fieldType.getName());\r
+               logger.debug(propertyName + ": " + mergeMode + ", " + fieldType.getName());\r
        }\r
        \r
        /**\r
@@ -291,7 +299,7 @@ public class DefaultMergeStrategy extends StrategyBase implements IMergeStrategy
                if (mergeMode != MergeMode.FIRST){\r
                        mergeCollectionFieldNoFirst(mergeFirst, mergeSecond, field, mergeMode, deleteSet, clonedObjects);\r
                }\r
-               System.out.println(propertyName + ": " + mergeMode + ", " + fieldType.getName());\r
+               logger.debug(propertyName + ": " + mergeMode + ", " + fieldType.getName());\r
                \r
        }\r
 \r
@@ -305,6 +313,7 @@ public class DefaultMergeStrategy extends StrategyBase implements IMergeStrategy
                        if (Set.class.isAssignableFrom(fieldType) || List.class.isAssignableFrom(fieldType)){\r
                                Collection<ICdmBase> secondCollection = (Collection<ICdmBase>)field.get(mergeSecond);\r
                                List<ICdmBase> removeList = new ArrayList<ICdmBase>();\r
+                               if(secondCollection != null) {\r
                                for (ICdmBase obj : secondCollection){\r
                                        Object objectToAdd; \r
                                        if (mergeMode == MergeMode.ADD){\r
@@ -319,6 +328,7 @@ public class DefaultMergeStrategy extends StrategyBase implements IMergeStrategy
                                        addMethod.invoke(mergeFirst, objectToAdd);\r
                                        removeList.add(obj);\r
                                }\r
+                               }\r
                                for (ICdmBase removeObj : removeList ){\r
                                        //removeMethod.invoke(mergeSecond, removeObj);\r
                                        if ((removeObj instanceof CdmBase)&& mergeMode == MergeMode.ADD_CLONE) {\r
@@ -414,7 +424,7 @@ public class DefaultMergeStrategy extends StrategyBase implements IMergeStrategy
                        Object value = getMergeValue(mergeFirst, mergeSecond, field);\r
                        field.set(mergeFirst, value);\r
                }\r
-               System.out.println(propertyName + ": " + mergeMode + ", " + fieldType.getName());\r
+               logger.debug(propertyName + ": " + mergeMode + ", " + fieldType.getName());\r
                \r
        }\r
        \r
@@ -430,7 +440,7 @@ public class DefaultMergeStrategy extends StrategyBase implements IMergeStrategy
                        Object value = getMergeValue(mergeFirst, mergeSecond, field);\r
                        field.set(mergeFirst, value);\r
                }\r
-               System.out.println(propertyName + ": " + mergeMode + ", " + fieldType.getName());\r
+               logger.debug(propertyName + ": " + mergeMode + ", " + fieldType.getName());\r
                \r
        }\r
 \r
@@ -448,61 +458,6 @@ public class DefaultMergeStrategy extends StrategyBase implements IMergeStrategy
                        return false;\r
                }\r
        }\r
-       \r
-       /**\r
-        * @param fieldType\r
-        * @return\r
-        */\r
-       private boolean isPrimitive(Class<?> fieldType) {\r
-               if (fieldType.isPrimitive()){\r
-                       return true;\r
-               }else{\r
-                       return false;\r
-               }\r
-       }\r
-\r
-       /**\r
-        * @param fieldType\r
-        * @return\r
-        */\r
-       private boolean isSingleCdmBaseObject(Class<?> fieldType) {\r
-               if (CdmBase.class.isAssignableFrom(fieldType)){\r
-                       return true;\r
-               }else{\r
-                       return false;\r
-               }\r
-       }\r
-\r
-\r
-\r
-       /**\r
-        * @param fieldType\r
-        * @return\r
-        */\r
-       private boolean isCollection(Class<?> fieldType) {\r
-               if (Collection.class.isAssignableFrom(fieldType) ){\r
-                       return true;\r
-               }else{\r
-                       return false;\r
-               }\r
-       }\r
-\r
-\r
-       /**\r
-        * @param fieldType\r
-        * @return\r
-        */\r
-       private boolean isUserType(Class<?> fieldType) {\r
-               if (    fieldType == TimePeriod.class ||\r
-                               fieldType == DateTime.class ||\r
-                               fieldType == LSID.class ||\r
-                               fieldType == Contact.class\r
-                       ){\r
-                       return true;\r
-               }else{\r
-                       return false;\r
-               }\r
-       }\r
 \r
 \r
        /**\r
@@ -536,62 +491,20 @@ public class DefaultMergeStrategy extends StrategyBase implements IMergeStrategy
                }\r
        }\r
 \r
-       /**\r
-        * Computes all fields recursively\r
-        * @param clazz\r
-        * @return\r
-        */\r
-       protected Map<String, Field> getAllNonStaticNonTransientFields(Class clazz, boolean includeStatic, boolean includeTransient, boolean makeAccessible) {\r
-               Map<String, Field> result = new HashMap<String, Field>();\r
-               //exclude static\r
-               for (Field field: clazz.getDeclaredFields()){\r
-                       if (includeStatic || ! Modifier.isStatic(field.getModifiers())){\r
-                               if (includeTransient || ! isTransient(field)){\r
-                                       field.setAccessible(makeAccessible);\r
-                                       result.put(field.getName(), field);\r
-                               }\r
-                       }\r
-               }\r
-               \r
-               //include superclass fields\r
-               Class superclass = clazz.getSuperclass();\r
-               if (CdmBase.class.isAssignableFrom(superclass)){\r
-                       result.putAll(getAllNonStaticNonTransientFields(superclass, includeStatic, includeTransient, makeAccessible));\r
-               }\r
-               return result;\r
-       }\r
-\r
-\r
-\r
-       /**\r
-        * Returns true, if field has an annotation of type javax.persistence.Annotation\r
-        * @param field\r
-        * @return\r
-        */\r
-       private boolean isTransient(Field field) {\r
-               for (Annotation annotation : field.getAnnotations()){\r
-                       //if (Transient.class.isAssignableFrom(annotation.annotationType())){\r
-                       if (annotation.annotationType() == Transient.class){\r
-                               return true;\r
-                       }\r
-               }\r
-               return false;\r
-       }\r
-\r
        \r
        private static Class getCollectionType(Field field) throws MergeException{\r
-               Type genericType = (ParameterizedTypeImpl)field.getGenericType();\r
-               if (genericType instanceof ParameterizedTypeImpl){\r
-                       ParameterizedTypeImpl paraType = (ParameterizedTypeImpl)genericType;\r
-                       Class<?> rawType = paraType.getRawType();\r
+               Type genericType = (ParameterizedType)field.getGenericType();\r
+               if (genericType instanceof ParameterizedType/*Impl*/){\r
+                       ParameterizedType paraType = (ParameterizedType)genericType;\r
+                       Type rawType = paraType.getRawType();\r
                        Type[] arguments = paraType.getActualTypeArguments();\r
-                       //System.out.println(arguments.length);\r
+\r
                        if (arguments.length == 1){\r
                                Class collectionClass;\r
                                if (arguments[0] instanceof Class){\r
                                        collectionClass = (Class)arguments[0];\r
-                               }else if(arguments[0] instanceof TypeVariableImpl){\r
-                                       TypeVariableImpl typeVariable = (TypeVariableImpl)arguments[0];\r
+                               }else if(arguments[0] instanceof TypeVariable/*Impl*/){\r
+                                       TypeVariable typeVariable = (TypeVariable)arguments[0];\r
                                        GenericDeclaration genericDeclaration = typeVariable.getGenericDeclaration();\r
                                        collectionClass = (Class)genericDeclaration;\r
                                }else{\r