Throw exceptions in AdvancedBeanInitializer instead of logging only
authorAndreas Müller <a.mueller@bgbm.org>
Wed, 21 Oct 2015 12:57:33 +0000 (14:57 +0200)
committerAndreas Müller <a.mueller@bgbm.org>
Wed, 21 Oct 2015 12:57:33 +0000 (14:57 +0200)
#5077

cdmlib-persistence/src/main/java/eu/etaxonomy/cdm/persistence/dao/initializer/AdvancedBeanInitializer.java

index b8fc91131466053d4e6035d0240b675dec28646e..40107713b33dd9375e7afe48cabd5b7f2989a59c 100644 (file)
-/**\r
- *\r
- */\r
-package eu.etaxonomy.cdm.persistence.dao.initializer;\r
-\r
-import java.beans.PropertyDescriptor;\r
-import java.io.Serializable;\r
-import java.lang.reflect.InvocationTargetException;\r
-import java.lang.reflect.Method;\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.Collections;\r
-import java.util.HashSet;\r
-import java.util.List;\r
-import java.util.Map;\r
-import java.util.Set;\r
-\r
-import org.apache.commons.beanutils.PropertyUtils;\r
-import org.apache.log4j.Logger;\r
-import org.hibernate.Hibernate;\r
-import org.hibernate.HibernateException;\r
-import org.hibernate.Query;\r
-import org.hibernate.collection.internal.AbstractPersistentCollection;\r
-import org.hibernate.collection.internal.PersistentMap;\r
-import org.hibernate.proxy.HibernateProxy;\r
-import org.springframework.beans.factory.annotation.Autowired;\r
-\r
-import eu.etaxonomy.cdm.model.common.CdmBase;\r
-import eu.etaxonomy.cdm.persistence.dao.common.ICdmGenericDao;\r
-import eu.etaxonomy.cdm.persistence.dao.hibernate.HibernateBeanInitializer;\r
-\r
-/**\r
- * For now this is a test if we can improve performance for bean initializing\r
- * @author a.mueller\r
- * @date 2013-10-25\r
- *\r
- */\r
-public class AdvancedBeanInitializer extends HibernateBeanInitializer {\r
-\r
-        public static final Logger logger = Logger.getLogger(AdvancedBeanInitializer.class);\r
-\r
-        @Autowired\r
-        ICdmGenericDao genericDao;\r
-\r
-        @Override\r
-        public void initialize(Object bean, List<String> propertyPaths) {\r
-            List<Object> beanList = new ArrayList<Object>(1);\r
-            beanList.add(bean);\r
-            initializeAll(beanList, propertyPaths);\r
-        }\r
-\r
-        //TODO optimize algorithm ..\r
-        @Override\r
-        public <C extends Collection<?>> C initializeAll(C beanList,  List<String> propertyPaths) {\r
-\r
-            if (beanList == null || beanList.isEmpty()){\r
-                return beanList;\r
-            }\r
-\r
-            //autoinitialize\r
-            for (Object bean : beanList){\r
-                autoinitializeBean(bean);\r
-            }\r
-\r
-            if(propertyPaths == null){\r
-                return beanList;\r
-            }\r
-\r
-\r
-            //new\r
-             BeanInitNode rootPath = BeanInitNode.createInitTree(propertyPaths);\r
-            if (logger.isTraceEnabled()){logger.trace(rootPath.toStringTree());}\r
-\r
-\r
-            if(logger.isDebugEnabled()){ logger.debug(">> starting to initialize beanlist ; class(e.g.):" + beanList.iterator().next().getClass().getSimpleName());}\r
-            rootPath.addBeans(beanList);\r
-            initializeNodeRecursive(rootPath);\r
-\r
-\r
-            //old - keep for safety (this may help to initialize those beans that are not yet correctly initialized by the AdvancedBeanInitializer\r
-            if(logger.isTraceEnabled()){logger.trace("Start old initalizer ... ");};\r
-            for (Object bean :beanList){\r
-                Collections.sort(propertyPaths);\r
-                for(String propPath : propertyPaths){\r
-//                         initializePropertyPath(bean, propPath);\r
-                }\r
-            }\r
-\r
-            if(logger.isDebugEnabled()){ logger.debug("   Completed initialization of beanlist "); }\r
-            return beanList;\r
-\r
-        }\r
-\r
-\r
-        //new\r
-        private void initializeNodeRecursive(BeanInitNode rootPath) {\r
-            initializeNode(rootPath);\r
-            for (BeanInitNode childPath : rootPath.getChildrenList()){\r
-                initializeNodeRecursive(childPath);\r
-            }\r
-            rootPath.resetBeans();\r
-        }\r
-\r
-        /**\r
-         * Initializes the given single <code>propPath</code> String.\r
-         *\r
-         * @param bean\r
-         * @param propPath\r
-         */\r
-        private void initializeNode(BeanInitNode node) {\r
-            if(logger.isDebugEnabled()){logger.debug(" processing " + node.toString());}\r
-            if (node.isRoot()){\r
-                return;\r
-            }else if (node.isWildcard()){\r
-                initializeNodeWildcard(node);\r
-            } else {\r
-                initializeNodeNoWildcard(node);\r
-            }\r
-        }\r
-\r
-        // if propPath only contains a wildcard (* or $)\r
-        // => do a batch initialization of *toOne or *toMany relations\r
-        private void initializeNodeWildcard(BeanInitNode node) {\r
-//                     boolean initToMany = node.isToManyWildcard();\r
-            Map<Class<?>, Set<Object>> parentBeans = node.getParentBeans();\r
-            for (Class<?> clazz : parentBeans.keySet()){\r
-                //new\r
-                for (Object bean : parentBeans.get(clazz)){\r
-\r
-                    if(Collection.class.isAssignableFrom(bean.getClass())){\r
-//                                     old: initializeAllEntries((Collection<?>)bean, true, initToMany);  //TODO is this a possible case at all??\r
-                        throw new RuntimeException("Collection no longer expected in 'initializeNodeWildcard()'. Therefore an exception is thrown.");\r
-                    } else if(Map.class.isAssignableFrom(bean.getClass())) {\r
-//                                     old: initializeAllEntries(((Map<?,?>)bean).values(), true, initToMany);  ////TODO is this a possible case at all??\r
-                        throw new RuntimeException("Map no longer expected in 'initializeNodeWildcard()'. Therefore an exception is thrown.");\r
-                    } else{\r
-                        prepareBeanWildcardForBulkLoad(node, bean);\r
-                    }\r
-                }\r
-                //end new\r
-\r
-//                     initializeNodeWildcardOld(initToMany, beans, clazz);  //if switched on move bulkLoadLazies up\r
-            }\r
-\r
-            //\r
-            bulkLoadLazies(node);\r
-        }\r
-\r
-        /**\r
-         * @param initToMany\r
-         * @param beans\r
-         * @param clazz\r
-         */\r
-        private void initializeNodeWildcardOld(boolean initToMany,\r
-                Map<Class<?>, Set<Object>> beans, Class<?> clazz) {\r
-            for (Object bean : beans.get(clazz)){\r
-\r
-                if(Collection.class.isAssignableFrom(bean.getClass())){\r
-                    initializeAllEntries((Collection<?>)bean, true, initToMany);\r
-                } else if(Map.class.isAssignableFrom(bean.getClass())) {\r
-                    initializeAllEntries(((Map<?,?>)bean).values(), true, initToMany);\r
-                } else{\r
-                    initializeBean(bean, true, initToMany);\r
-                }\r
-            }\r
-        }\r
-\r
-        private void prepareBeanWildcardForBulkLoad(BeanInitNode node, Object bean){\r
-\r
-            if(logger.isTraceEnabled()){logger.trace(">> prepare bulk wildcard initialization of a bean of type " + bean.getClass().getSimpleName()); }\r
-            Set<Class<?>> restrictions = new HashSet<Class<?>>();\r
-            restrictions.add(CdmBase.class);\r
-            if(node.isToManyWildcard()){\r
-                restrictions.add(Collection.class);\r
-            }\r
-            Set<PropertyDescriptor> props = getProperties(bean, restrictions);\r
-            for(PropertyDescriptor propertyDescriptor : props){\r
-                try {\r
-                    String property = propertyDescriptor.getName();\r
-\r
-//                  invokeInitialization(bean, propertyDescriptor);\r
-                    Object propertyValue = PropertyUtils.getProperty( bean, property);\r
-\r
-                    preparePropertyValueForBulkLoadOrStore(node, bean, property,  propertyValue );\r
-\r
-                } catch (IllegalAccessException e) {\r
-                    logger.error("Illegal access on property " + propertyDescriptor.getName());\r
-                } catch (InvocationTargetException e) {\r
-                    logger.info("Cannot invoke property " + propertyDescriptor.getName() + " not found");\r
-                } catch (NoSuchMethodException e) {\r
-                    logger.info("Property " + propertyDescriptor.getName() + " not found");\r
-                }\r
-            }\r
-            if(logger.isTraceEnabled()){logger.trace(" completed bulk wildcard initialization of a bean");}\r
-        }\r
-\r
-\r
-\r
-        // propPath contains either a single field or a nested path\r
-        // split next path token off and keep the remaining as nestedPath\r
-        private void initializeNodeNoWildcard(BeanInitNode node) {\r
-\r
-            String property = node.getPath();\r
-            int pos;\r
-\r
-            // is the property indexed?\r
-            Integer index = null;\r
-            if((pos = property.indexOf('[')) > 0){\r
-                String indexString = property.substring(pos + 1, property.indexOf(']'));\r
-                index = Integer.valueOf(indexString);\r
-                property = property.substring(0, pos);\r
-            }\r
-\r
-            //Class targetClass = HibernateProxyHelper.getClassWithoutInitializingProxy(bean); // used for debugging\r
-\r
-            for (Class<?> parentClazz : node.getParentBeans().keySet()){\r
-                if (logger.isTraceEnabled()){logger.trace(" invoke initialization on "+ node.toString()+ " beans of class " + parentClazz.getSimpleName() + " ... ");}\r
-\r
-                Set<Object> parentBeans = node.getParentBeans().get(parentClazz);\r
-\r
-                if (index != null){\r
-                    logger.warn("Property path index not yet implemented for 'new'");\r
-                }\r
-                //new\r
-                for (Object parentBean : parentBeans){\r
-                    String propertyName = mapFieldToPropertyName(property, parentBean.getClass().getSimpleName());\r
-                    try{\r
-                        Object propertyValue = PropertyUtils.getProperty(parentBean, propertyName);\r
-                        preparePropertyValueForBulkLoadOrStore(node, parentBean, property, propertyValue);\r
-                    } catch (IllegalAccessException e) {\r
-                        logger.error("Illegal access on property " + property);\r
-                    } catch (InvocationTargetException e) {\r
-                        logger.error("Cannot invoke property " + property + " not found");\r
-                    } catch (NoSuchMethodException e) {\r
-                        if (logger.isDebugEnabled()){logger.debug("Property " + propertyName + " not found for class " + parentClazz);}\r
-                    }\r
-                }\r
-\r
-                //end new\r
-\r
-//                             initializeNodeNoWildcardOld(node, property, index, parentBeans);  //move bulkLoadLazies up again, if uncomment this line\r
-            }\r
-            bulkLoadLazies(node);\r
-\r
-        }\r
-\r
-        /**\r
-         * @param node\r
-         * @param property\r
-         * @param index\r
-         * @param parentBeans\r
-         * @throws IllegalAccessException\r
-         * @throws InvocationTargetException\r
-         * @throws NoSuchMethodException\r
-         */\r
-        private void initializeNodeNoWildcardOld(BeanInitNode node,\r
-                String property, Integer index, Set<Object> parentBeans)\r
-                throws IllegalAccessException, InvocationTargetException,\r
-                NoSuchMethodException {\r
-            for (Object bean : parentBeans){\r
-\r
-                PropertyDescriptor propertyDescriptor = PropertyUtils.getPropertyDescriptor(bean, property);\r
-                if (logger.isTraceEnabled()){logger.trace("   unwrap " + node.toStringNoWildcard() + " ... ");}\r
-                // [1] initialize the bean named by property\r
-                Object unwrappedPropertyBean = invokeInitialization(bean, propertyDescriptor);\r
-                if (logger.isTraceEnabled()){logger.trace("   unwrap " + node.toStringNoWildcard() + " - DONE ");}\r
-\r
-\r
-                // [2]\r
-                // handle property\r
-                if(unwrappedPropertyBean != null ){\r
-                    initializeNodeSinglePropertyOld(node, property, index, bean, unwrappedPropertyBean);\r
-                }\r
-            }\r
-        }\r
-\r
-        /**\r
-         * @param node\r
-         * @param propertyValue\r
-         * @param parentBean\r
-         * @param param\r
-         */\r
-        private void preparePropertyValueForBulkLoadOrStore(BeanInitNode node, Object parentBean, String param, Object propertyValue) {\r
-            BeanInitNode sibling = node.getSibling(param);\r
-\r
-            if (propertyValue instanceof AbstractPersistentCollection ){\r
-                //collections\r
-                if (!node.hasWildcardToManySibling()){  //if wildcard sibling exists the lazies are already prepared there\r
-                    AbstractPersistentCollection collection = (AbstractPersistentCollection)propertyValue;\r
-                    if (collection.wasInitialized()){\r
-                        storeInitializedCollection(collection, node, param);\r
-                    }else{\r
-//                                             Class<?> parentClass = parentBean.getClass();\r
-//                                             int parentId = ((CdmBase)parentBean).getId();\r
-                        if (sibling != null){\r
-                            sibling.putLazyCollection(collection);\r
-                        }else{\r
-                            node.putLazyCollection(collection);\r
-                        }\r
-                    }\r
-                }\r
-            }else{\r
-                //singles\r
-                if (!node.hasWildcardToOneSibling()){  //if wildcard exists the lazies are already prepared there\r
-                    if (! Hibernate.isInitialized(propertyValue)){\r
-                        if (propertyValue instanceof HibernateProxy){\r
-                            Serializable id = ((HibernateProxy)propertyValue).getHibernateLazyInitializer().getIdentifier();\r
-                            Class<?> persistedClass = ((HibernateProxy)propertyValue).getHibernateLazyInitializer().getPersistentClass();\r
-                            if (sibling != null){\r
-                                sibling.putLazyBean(persistedClass, id);\r
-                            }else{\r
-                                node.putLazyBean(persistedClass, id);\r
-                            }\r
-\r
-                        }else{\r
-                            logger.warn("Lazy value is not of type HibernateProxy. This is not yet handled.");\r
-                        }\r
-                    }else if (propertyValue == null){\r
-                        // do nothing\r
-                    }else{\r
-                        if (propertyValue instanceof HibernateProxy){  //TODO remove hibernate dependency\r
-                            propertyValue = initializeInstance(propertyValue);\r
-                        }\r
-                        autoinitializeBean(propertyValue);\r
-                        node.addBean(propertyValue);\r
-                    }\r
-                }\r
-            }\r
-        }\r
-\r
-        private void autoinitializeBean(Object bean) {\r
-            invokePropertyAutoInitializers(bean);\r
-        }\r
-\r
-        private void autoinitializeBean(CdmBase bean, AutoInit autoInit) {\r
-            for(AutoPropertyInitializer<CdmBase> init : autoInit.initlializers) {\r
-                init.initialize(bean);\r
-            }\r
-        }\r
-\r
-               private void storeInitializedCollection(AbstractPersistentCollection persistedCollection,\r
-                               BeanInitNode node, String param) {\r
-                       Collection<?> collection;\r
-\r
-                       if (persistedCollection  instanceof Collection) {\r
-                               collection = (Collection<?>) persistedCollection;\r
-                       }else if (persistedCollection instanceof Map) {\r
-                               collection = ((Map<?,?>)persistedCollection).values();\r
-                       }else{\r
-                               throw new RuntimeException ("Non Map and non Collection cas not handled in storeInitializedCollection()");\r
-                       }\r
-                       for (Object value : collection){\r
-                               preparePropertyValueForBulkLoadOrStore(node, null, param, value);\r
-                       }\r
-               }\r
-\r
-               private void bulkLoadLazies(BeanInitNode node) {\r
-\r
-                       if (logger.isTraceEnabled()){logger.trace("bulk load " +  node);}\r
-\r
-                       //beans\r
-                       for (Class<?> clazz : node.getLazyBeans().keySet()){\r
-                               Set<Serializable> idSet = node.getLazyBeans().get(clazz);\r
-                               if (idSet != null && ! idSet.isEmpty()){\r
-\r
-                                       if (logger.isTraceEnabled()){logger.trace("bulk load beans of class " +  clazz.getSimpleName());}\r
-                                       //TODO use entity name\r
-                                       String hql = " SELECT c FROM %s as c %s WHERE c.id IN (:idSet) ";\r
-                                       AutoInit autoInit = addAutoinitFetchLoading(clazz, "c");\r
-                    hql = String.format(hql, clazz.getSimpleName(), autoInit.leftJoinFetch);\r
-                                       if (logger.isTraceEnabled()){logger.trace(hql);}\r
-                                       Query query = genericDao.getHqlQuery(hql);\r
-                                       query.setParameterList("idSet", idSet);\r
-                                       List<Object> list = query.list();\r
-\r
-                                       if (logger.isTraceEnabled()){logger.trace("initialize bulk loaded beans of class " +  clazz.getSimpleName());}\r
-                                       for (Object object : list){\r
-                                               if (object instanceof HibernateProxy){  //TODO remove hibernate dependency\r
-                                                       object = initializeInstance(object);\r
-                                               }\r
-                                               autoinitializeBean((CdmBase)object, autoInit);\r
-                                               node.addBean(object);\r
-                                       }\r
-                                       if (logger.isTraceEnabled()){logger.trace("bulk load - DONE");}\r
-                               }\r
-                       }\r
-                       node.resetLazyBeans();\r
-\r
-                       //collections\r
-                       for (Class<?> ownerClazz : node.getLazyCollections().keySet()){\r
-                               Map<String, Set<Serializable>> lazyParams = node.getLazyCollections().get(ownerClazz);\r
-                               for (String param : lazyParams.keySet()){\r
-                                       Set<Serializable> idSet = lazyParams.get(param);\r
-                                       if (idSet != null && ! idSet.isEmpty()){\r
-                                               if (logger.isTraceEnabled()){logger.trace("bulk load " + node + " collections ; ownerClass=" +  ownerClazz.getSimpleName() + " ; param = " + param);}\r
-\r
-                                               Type collectionEntitiyType = null;\r
-                                               PropertyDescriptor[] descriptors = PropertyUtils.getPropertyDescriptors(ownerClazz);\r
-                                               for(PropertyDescriptor d : descriptors) {\r
-                                                   if(d.getName().equals(param)) {\r
-                                                       Method readMethod = d.getReadMethod();\r
-                                ParameterizedType pt = (ParameterizedType) readMethod.getGenericReturnType();\r
-                                Type[] actualTypeArguments = pt.getActualTypeArguments();\r
-                                if(actualTypeArguments.length == 2) {\r
-                                    // this must be a map of <Language, String> (aka LanguageString) there is no other case like this in the cdm\r
-                                    // in case of Maps the returned Collection will be the Collection of the values, so collectionEntitiyType is the\r
-                                    // second typeArgument\r
-                                    collectionEntitiyType = actualTypeArguments[1];\r
-                                } else {\r
-                                    collectionEntitiyType = actualTypeArguments[0];\r
-                                }\r
-                                if(collectionEntitiyType instanceof TypeVariable) {\r
-                                    collectionEntitiyType = ((TypeVariable)collectionEntitiyType).getBounds()[0];\r
-                                }\r
-                                                   }\r
-                                               }\r
-\r
-                                               //TODO use entity name ??\r
-                                               //get from repository\r
-                                               List<Object[]> list;\r
-                                               String hql = "SELECT oc " +\r
-                                                               " FROM %s as oc LEFT JOIN FETCH oc.%s as col %s" +\r
-                                                               " WHERE oc.id IN (:idSet) ";\r
-\r
-                                               AutoInit autoInit = addAutoinitFetchLoading((Class)collectionEntitiyType, "col");\r
-                        hql = String.format(hql, ownerClazz.getSimpleName(), param,\r
-                                                       autoInit.leftJoinFetch);\r
-\r
-                                               try {\r
-                                                       if (logger.isTraceEnabled()){logger.trace(hql);}\r
-                                                       Query query = genericDao.getHqlQuery(hql);\r
-                                                       query.setParameterList("idSet", idSet);\r
-                                                       list = query.list();\r
-                                                       if (logger.isTraceEnabled()){logger.trace("size of retrieved list is " + list.size());}\r
-                                               } catch (HibernateException e) {\r
-                                                       e.printStackTrace();\r
-                                                       throw e;\r
-                                               }\r
-\r
-                                               //getTarget and add to child node\r
-                                               if (logger.isTraceEnabled()){logger.trace("initialize bulk loaded " + node + " collections - DONE");}\r
-                                               for (Object parentBean : list){\r
-                            try {\r
-                                                           Object propValue = PropertyUtils.getProperty(\r
-                                                                   parentBean,\r
-                                                                   mapFieldToPropertyName(param, parentBean.getClass().getSimpleName())\r
-                                                                 );\r
-\r
-                                                       if (propValue == null){\r
-                                                           logger.trace("Collection is null");\r
-                                                       }else {\r
-                                                           if(propValue instanceof PersistentMap) {\r
-                                                               propValue = ((PersistentMap)propValue).values();\r
-                                                           }\r
-                                                           for(Object newBean : (Collection<Object>)propValue ) {\r
-                                                               if(newBean instanceof HibernateProxy){\r
-                                                                   newBean = initializeInstance(newBean);\r
-                                                               }\r
-\r
-                                                               autoinitializeBean((CdmBase)newBean, autoInit);\r
-\r
-                                                               node.addBean(newBean);\r
-                                                           }\r
-                                                       }\r
-                            } catch (Exception e) {\r
-                                // TODO better throw an exception ?\r
-                                logger.error("error while getting collection property", e);\r
-                            }\r
-                                               }\r
-                                               if (logger.isTraceEnabled()){logger.trace("bulk load " + node + " collections - DONE");}\r
-                                       }\r
-                               }\r
-                       }\r
-                       for (AbstractPersistentCollection collection : node.getUninitializedCollections()){\r
-                               if (! collection.wasInitialized()){  //should not happen anymore\r
-                                       collection.forceInitialization();\r
-                                       if (logger.isTraceEnabled()){logger.trace("forceInitialization of collection " + collection);}\r
-                               } else {\r
-                                   if (logger.isTraceEnabled()){logger.trace("collection " + collection + " is initialized - OK!");}\r
-                               }\r
-                       }\r
-\r
-                       node.resetLazyCollections();\r
-\r
-                       if (logger.isDebugEnabled()){logger.debug("bulk load " +  node + " - DONE ");}\r
-\r
-               }\r
-\r
-\r
-        private AutoInit addAutoinitFetchLoading(Class<?> clazz, String beanAlias) {\r
-\r
-            AutoInit autoInit = new AutoInit();\r
-            if(clazz != null) {\r
-                Set<AutoPropertyInitializer<CdmBase>> inits = getAutoInitializers(clazz);\r
-                for (AutoPropertyInitializer<CdmBase> init: inits){\r
-                    try {\r
-                        autoInit.leftJoinFetch +=init.hibernateFetchJoin(clazz, beanAlias);\r
-                    } catch (Exception e) {\r
-                        // the AutoPropertyInitializer is not supporting LEFT JOIN FETCH so it needs to be\r
-                        // used explicitly\r
-                        autoInit.initlializers.add(init);\r
-                    }\r
-\r
-                }\r
-            }\r
-            return autoInit;\r
-        }\r
-\r
-        private Set<AutoPropertyInitializer<CdmBase>> getAutoInitializers(Class<?> clazz) {\r
-            Set<AutoPropertyInitializer<CdmBase>> result = new HashSet<AutoPropertyInitializer<CdmBase>>();\r
-            for(Class<? extends CdmBase> superClass : getBeanAutoInitializers().keySet()){\r
-                if(superClass.isAssignableFrom(clazz)){\r
-                    result.add(getBeanAutoInitializers().get(superClass));\r
-                }\r
-            }\r
-            return result;\r
-        }\r
-\r
-        /**\r
-         * Rename hibernate (field) attribute to Bean property name, due to bean inconsistencies\r
-         * #3841\r
-         * @param param\r
-         * @param ownerClass\r
-         * @return\r
-         */\r
-        private String mapFieldToPropertyName(String param, String ownerClass) {\r
-            if (ownerClass.contains("Description") && param.equals("descriptionElements")){\r
-                return "elements";\r
-            }\r
-            if (ownerClass.startsWith("FeatureNode") && param.equals("children")) {\r
-                return "childNodes";\r
-            }\r
-            if (ownerClass.startsWith("Media") && param.equals("description")) {\r
-                return "allDescriptions";\r
-            }\r
-            else{\r
-                return param;\r
-            }\r
-        }\r
-\r
-        /**\r
-         * @param node\r
-         * @param property\r
-         * @param index\r
-         * @param bean\r
-         * @param unwrappedPropertyBean\r
-         */\r
-        private void initializeNodeSinglePropertyOld(BeanInitNode node, String property,\r
-                Integer index, Object bean, Object unwrappedPropertyBean) {\r
-            Collection<?> collection = null;\r
-            if(Map.class.isAssignableFrom(unwrappedPropertyBean.getClass())) {\r
-                collection = ((Map<?,?>)unwrappedPropertyBean).values();\r
-            }else if (Collection.class.isAssignableFrom(unwrappedPropertyBean.getClass())) {\r
-                collection =  (Collection<?>) unwrappedPropertyBean;\r
-            }\r
-            if (collection != null){\r
-                //collection or map\r
-                if (logger.isTraceEnabled()){logger.trace(" initialize collection for " + node.toStringNoWildcard() + " ... ");}\r
-                int i = 0;\r
-                for (Object entrybean : collection) {\r
-                    if(index == null){\r
-                        node.addBean(entrybean);\r
-                    } else if(index.equals(i)){\r
-                        node.addBean(entrybean);\r
-                        break;\r
-                    }\r
-                    i++;\r
-                }\r
-                if (logger.isTraceEnabled()){logger.trace(" initialize collection for " + node.toString() + " - DONE ");}\r
-\r
-            }else {\r
-                // nested bean\r
-                node.addBean(unwrappedPropertyBean);\r
-                setProperty(bean, property, unwrappedPropertyBean);\r
-            }\r
-        }\r
-\r
-        private class AutoInit{\r
-\r
-            String leftJoinFetch = "";\r
-            Set<AutoPropertyInitializer<CdmBase>> initlializers = new HashSet<AutoPropertyInitializer<CdmBase>>();\r
-\r
-            /**\r
-             * @param leftJoinFetch\r
-             * @param initlializers\r
-             */\r
-            public AutoInit() {\r
-            }\r
-        }\r
-\r
-}\r
+/**
+ *
+ */
+package eu.etaxonomy.cdm.persistence.dao.initializer;
+
+import java.beans.PropertyDescriptor;
+import java.io.Serializable;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.beanutils.PropertyUtils;
+import org.apache.log4j.Logger;
+import org.hibernate.Hibernate;
+import org.hibernate.HibernateException;
+import org.hibernate.Query;
+import org.hibernate.collection.internal.AbstractPersistentCollection;
+import org.hibernate.collection.internal.PersistentMap;
+import org.hibernate.proxy.HibernateProxy;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import eu.etaxonomy.cdm.model.common.CdmBase;
+import eu.etaxonomy.cdm.persistence.dao.common.ICdmGenericDao;
+import eu.etaxonomy.cdm.persistence.dao.hibernate.HibernateBeanInitializer;
+
+/**
+ * For now this is a test if we can improve performance for bean initializing
+ * @author a.mueller
+ * @date 2013-10-25
+ *
+ */
+public class AdvancedBeanInitializer extends HibernateBeanInitializer {
+
+    public static final Logger logger = Logger.getLogger(AdvancedBeanInitializer.class);
+
+    @Autowired
+    ICdmGenericDao genericDao;
+
+    @Override
+    public void initialize(Object bean, List<String> propertyPaths) {
+        List<Object> beanList = new ArrayList<Object>(1);
+        beanList.add(bean);
+        initializeAll(beanList, propertyPaths);
+    }
+
+    //TODO optimize algorithm ..
+    @Override
+    public <C extends Collection<?>> C initializeAll(C beanList,  List<String> propertyPaths) {
+
+        if (beanList == null || beanList.isEmpty()){
+            return beanList;
+        }
+
+        //autoinitialize
+        for (Object bean : beanList){
+            autoinitializeBean(bean);
+        }
+
+        if(propertyPaths == null){
+            return beanList;
+        }
+
+
+        //new
+         BeanInitNode rootPath = BeanInitNode.createInitTree(propertyPaths);
+        if (logger.isTraceEnabled()){logger.trace(rootPath.toStringTree());}
+
+
+        if(logger.isDebugEnabled()){ logger.debug(">> starting to initialize beanlist ; class(e.g.):" + beanList.iterator().next().getClass().getSimpleName());}
+        rootPath.addBeans(beanList);
+        initializeNodeRecursive(rootPath);
+
+
+        //old - keep for safety (this may help to initialize those beans that are not yet correctly initialized by the AdvancedBeanInitializer
+        if(logger.isTraceEnabled()){logger.trace("Start old initalizer ... ");};
+        for (Object bean :beanList){
+            Collections.sort(propertyPaths);
+            for(String propPath : propertyPaths){
+//                         initializePropertyPath(bean, propPath);
+            }
+        }
+
+        if(logger.isDebugEnabled()){ logger.debug("   Completed initialization of beanlist "); }
+        return beanList;
+
+    }
+
+
+    //new
+    private void initializeNodeRecursive(BeanInitNode rootPath) {
+        initializeNode(rootPath);
+        for (BeanInitNode childPath : rootPath.getChildrenList()){
+            initializeNodeRecursive(childPath);
+        }
+        rootPath.resetBeans();
+    }
+
+    /**
+     * Initializes the given single <code>propPath</code> String.
+     *
+     * @param bean
+     * @param propPath
+     */
+    private void initializeNode(BeanInitNode node) {
+        if(logger.isDebugEnabled()){logger.debug(" processing " + node.toString());}
+        if (node.isRoot()){
+            return;
+        }else if (node.isWildcard()){
+            initializeNodeWildcard(node);
+        } else {
+            initializeNodeNoWildcard(node);
+        }
+    }
+
+    // if propPath only contains a wildcard (* or $)
+    // => do a batch initialization of *toOne or *toMany relations
+    private void initializeNodeWildcard(BeanInitNode node) {
+//                     boolean initToMany = node.isToManyWildcard();
+        Map<Class<?>, Set<Object>> parentBeans = node.getParentBeans();
+        for (Class<?> clazz : parentBeans.keySet()){
+            //new
+            for (Object bean : parentBeans.get(clazz)){
+
+                if(Collection.class.isAssignableFrom(bean.getClass())){
+//                                     old: initializeAllEntries((Collection<?>)bean, true, initToMany);  //TODO is this a possible case at all??
+                    throw new RuntimeException("Collection no longer expected in 'initializeNodeWildcard()'. Therefore an exception is thrown.");
+                } else if(Map.class.isAssignableFrom(bean.getClass())) {
+//                                     old: initializeAllEntries(((Map<?,?>)bean).values(), true, initToMany);  ////TODO is this a possible case at all??
+                    throw new RuntimeException("Map no longer expected in 'initializeNodeWildcard()'. Therefore an exception is thrown.");
+                } else{
+                    prepareBeanWildcardForBulkLoad(node, bean);
+                }
+            }
+            //end new
+
+//                     initializeNodeWildcardOld(initToMany, beans, clazz);  //if switched on move bulkLoadLazies up
+        }
+
+        //
+        bulkLoadLazies(node);
+    }
+
+    /**
+     * @param initToMany
+     * @param beans
+     * @param clazz
+     */
+    private void initializeNodeWildcardOld(boolean initToMany,
+            Map<Class<?>, Set<Object>> beans, Class<?> clazz) {
+        for (Object bean : beans.get(clazz)){
+
+            if(Collection.class.isAssignableFrom(bean.getClass())){
+                initializeAllEntries((Collection<?>)bean, true, initToMany);
+            } else if(Map.class.isAssignableFrom(bean.getClass())) {
+                initializeAllEntries(((Map<?,?>)bean).values(), true, initToMany);
+            } else{
+                initializeBean(bean, true, initToMany);
+            }
+        }
+    }
+
+    private void prepareBeanWildcardForBulkLoad(BeanInitNode node, Object bean){
+
+        if(logger.isTraceEnabled()){logger.trace(">> prepare bulk wildcard initialization of a bean of type " + bean.getClass().getSimpleName()); }
+        Set<Class<?>> restrictions = new HashSet<Class<?>>();
+        restrictions.add(CdmBase.class);
+        if(node.isToManyWildcard()){
+            restrictions.add(Collection.class);
+        }
+        Set<PropertyDescriptor> props = getProperties(bean, restrictions);
+        for(PropertyDescriptor propertyDescriptor : props){
+            try {
+                String property = propertyDescriptor.getName();
+
+//                  invokeInitialization(bean, propertyDescriptor);
+                Object propertyValue = PropertyUtils.getProperty( bean, property);
+
+                preparePropertyValueForBulkLoadOrStore(node, bean, property,  propertyValue );
+
+            } catch (IllegalAccessException e) {
+                logger.error("Illegal access on property " + propertyDescriptor.getName());
+            } catch (InvocationTargetException e) {
+                logger.info("Cannot invoke property " + propertyDescriptor.getName() + " not found");
+            } catch (NoSuchMethodException e) {
+                logger.info("Property " + propertyDescriptor.getName() + " not found");
+            }
+        }
+        if(logger.isTraceEnabled()){logger.trace(" completed bulk wildcard initialization of a bean");}
+    }
+
+
+
+    // propPath contains either a single field or a nested path
+    // split next path token off and keep the remaining as nestedPath
+    private void initializeNodeNoWildcard(BeanInitNode node) {
+
+        String property = node.getPath();
+        int pos;
+
+        // is the property indexed?
+        Integer index = null;
+        if((pos = property.indexOf('[')) > 0){
+            String indexString = property.substring(pos + 1, property.indexOf(']'));
+            index = Integer.valueOf(indexString);
+            property = property.substring(0, pos);
+        }
+
+        //Class targetClass = HibernateProxyHelper.getClassWithoutInitializingProxy(bean); // used for debugging
+
+        for (Class<?> parentClazz : node.getParentBeans().keySet()){
+            if (logger.isTraceEnabled()){logger.trace(" invoke initialization on "+ node.toString()+ " beans of class " + parentClazz.getSimpleName() + " ... ");}
+
+            Set<Object> parentBeans = node.getParentBeans().get(parentClazz);
+
+            if (index != null){
+                logger.warn("Property path index not yet implemented for 'new'");
+            }
+            //new
+            for (Object parentBean : parentBeans){
+                String propertyName = mapFieldToPropertyName(property, parentBean.getClass().getSimpleName());
+                try{
+                    Object propertyValue = PropertyUtils.getProperty(parentBean, propertyName);
+                    preparePropertyValueForBulkLoadOrStore(node, parentBean, property, propertyValue);
+                } catch (IllegalAccessException e) {
+                    String message = "Illegal access on property " + property;
+                    logger.error(message);
+                    throw new RuntimeException(message, e);
+                } catch (InvocationTargetException e) {
+                    String message = "Cannot invoke property " + property + " not found";
+                    logger.error(message);
+                    throw new RuntimeException(message, e);
+                } catch (NoSuchMethodException e) {
+                    String message = "Property " + propertyName + " not found for class " + parentClazz;
+                    logger.error(message);
+                    throw new RuntimeException(message, e);
+                }
+            }
+
+            //end new
+
+//                      initializeNodeNoWildcardOld(node, property, index, parentBeans);  //move bulkLoadLazies up again, if uncomment this line
+        }
+        bulkLoadLazies(node);
+
+    }
+
+    /**
+     * @param node
+     * @param property
+     * @param index
+     * @param parentBeans
+     * @throws IllegalAccessException
+     * @throws InvocationTargetException
+     * @throws NoSuchMethodException
+     */
+    private void initializeNodeNoWildcardOld(BeanInitNode node,
+            String property, Integer index, Set<Object> parentBeans)
+            throws IllegalAccessException, InvocationTargetException,
+            NoSuchMethodException {
+        for (Object bean : parentBeans){
+
+            PropertyDescriptor propertyDescriptor = PropertyUtils.getPropertyDescriptor(bean, property);
+            if (logger.isTraceEnabled()){logger.trace("   unwrap " + node.toStringNoWildcard() + " ... ");}
+            // [1] initialize the bean named by property
+            Object unwrappedPropertyBean = invokeInitialization(bean, propertyDescriptor);
+            if (logger.isTraceEnabled()){logger.trace("   unwrap " + node.toStringNoWildcard() + " - DONE ");}
+
+
+            // [2]
+            // handle property
+            if(unwrappedPropertyBean != null ){
+                initializeNodeSinglePropertyOld(node, property, index, bean, unwrappedPropertyBean);
+            }
+        }
+    }
+
+    /**
+     * @param node
+     * @param propertyValue
+     * @param parentBean
+     * @param param
+     */
+    private void preparePropertyValueForBulkLoadOrStore(BeanInitNode node, Object parentBean, String param, Object propertyValue) {
+        BeanInitNode sibling = node.getSibling(param);
+
+        if (propertyValue instanceof AbstractPersistentCollection ){
+            //collections
+            if (!node.hasWildcardToManySibling()){  //if wildcard sibling exists the lazies are already prepared there
+                AbstractPersistentCollection collection = (AbstractPersistentCollection)propertyValue;
+                if (collection.wasInitialized()){
+                    storeInitializedCollection(collection, node, param);
+                }else{
+//                                             Class<?> parentClass = parentBean.getClass();
+//                                             int parentId = ((CdmBase)parentBean).getId();
+                    if (sibling != null){
+                        sibling.putLazyCollection(collection);
+                    }else{
+                        node.putLazyCollection(collection);
+                    }
+                }
+            }
+        }else{
+            //singles
+            if (!node.hasWildcardToOneSibling()){  //if wildcard exists the lazies are already prepared there
+                if (! Hibernate.isInitialized(propertyValue)){
+                    if (propertyValue instanceof HibernateProxy){
+                        Serializable id = ((HibernateProxy)propertyValue).getHibernateLazyInitializer().getIdentifier();
+                        Class<?> persistedClass = ((HibernateProxy)propertyValue).getHibernateLazyInitializer().getPersistentClass();
+                        if (sibling != null){
+                            sibling.putLazyBean(persistedClass, id);
+                        }else{
+                            node.putLazyBean(persistedClass, id);
+                        }
+
+                    }else{
+                        logger.warn("Lazy value is not of type HibernateProxy. This is not yet handled.");
+                    }
+                }else if (propertyValue == null){
+                    // do nothing
+                }else{
+                    if (propertyValue instanceof HibernateProxy){  //TODO remove hibernate dependency
+                        propertyValue = initializeInstance(propertyValue);
+                    }
+                    autoinitializeBean(propertyValue);
+                    node.addBean(propertyValue);
+                }
+            }
+        }
+    }
+
+    private void autoinitializeBean(Object bean) {
+        invokePropertyAutoInitializers(bean);
+    }
+
+    private void autoinitializeBean(CdmBase bean, AutoInit autoInit) {
+        for(AutoPropertyInitializer<CdmBase> init : autoInit.initlializers) {
+            init.initialize(bean);
+        }
+    }
+
+       private void storeInitializedCollection(AbstractPersistentCollection persistedCollection,
+                       BeanInitNode node, String param) {
+               Collection<?> collection;
+
+               if (persistedCollection  instanceof Collection) {
+                       collection = (Collection<?>) persistedCollection;
+               }else if (persistedCollection instanceof Map) {
+                       collection = ((Map<?,?>)persistedCollection).values();
+               }else{
+                       throw new RuntimeException ("Non Map and non Collection cas not handled in storeInitializedCollection()");
+               }
+               for (Object value : collection){
+                       preparePropertyValueForBulkLoadOrStore(node, null, param, value);
+               }
+       }
+
+       private void bulkLoadLazies(BeanInitNode node) {
+
+               if (logger.isTraceEnabled()){logger.trace("bulk load " +  node);}
+
+               //beans
+               for (Class<?> clazz : node.getLazyBeans().keySet()){
+                       Set<Serializable> idSet = node.getLazyBeans().get(clazz);
+                       if (idSet != null && ! idSet.isEmpty()){
+
+                               if (logger.isTraceEnabled()){logger.trace("bulk load beans of class " +  clazz.getSimpleName());}
+                               //TODO use entity name
+                               String hql = " SELECT c FROM %s as c %s WHERE c.id IN (:idSet) ";
+                               AutoInit autoInit = addAutoinitFetchLoading(clazz, "c");
+                hql = String.format(hql, clazz.getSimpleName(), autoInit.leftJoinFetch);
+                               if (logger.isTraceEnabled()){logger.trace(hql);}
+                               Query query = genericDao.getHqlQuery(hql);
+                               query.setParameterList("idSet", idSet);
+                               List<Object> list = query.list();
+
+                               if (logger.isTraceEnabled()){logger.trace("initialize bulk loaded beans of class " +  clazz.getSimpleName());}
+                               for (Object object : list){
+                                       if (object instanceof HibernateProxy){  //TODO remove hibernate dependency
+                                               object = initializeInstance(object);
+                                       }
+                                       autoinitializeBean((CdmBase)object, autoInit);
+                                       node.addBean(object);
+                               }
+                               if (logger.isTraceEnabled()){logger.trace("bulk load - DONE");}
+                       }
+               }
+               node.resetLazyBeans();
+
+               //collections
+               for (Class<?> ownerClazz : node.getLazyCollections().keySet()){
+                       Map<String, Set<Serializable>> lazyParams = node.getLazyCollections().get(ownerClazz);
+                       for (String param : lazyParams.keySet()){
+                               Set<Serializable> idSet = lazyParams.get(param);
+                               if (idSet != null && ! idSet.isEmpty()){
+                                       if (logger.isTraceEnabled()){logger.trace("bulk load " + node + " collections ; ownerClass=" +  ownerClazz.getSimpleName() + " ; param = " + param);}
+
+                                       Type collectionEntitiyType = null;
+                                       PropertyDescriptor[] descriptors = PropertyUtils.getPropertyDescriptors(ownerClazz);
+                                       for(PropertyDescriptor d : descriptors) {
+                                           if(d.getName().equals(param)) {
+                                               Method readMethod = d.getReadMethod();
+                            ParameterizedType pt = (ParameterizedType) readMethod.getGenericReturnType();
+                            Type[] actualTypeArguments = pt.getActualTypeArguments();
+                            if(actualTypeArguments.length == 2) {
+                                // this must be a map of <Language, String> (aka LanguageString) there is no other case like this in the cdm
+                                // in case of Maps the returned Collection will be the Collection of the values, so collectionEntitiyType is the
+                                // second typeArgument
+                                collectionEntitiyType = actualTypeArguments[1];
+                            } else {
+                                collectionEntitiyType = actualTypeArguments[0];
+                            }
+                            if(collectionEntitiyType instanceof TypeVariable) {
+                                collectionEntitiyType = ((TypeVariable)collectionEntitiyType).getBounds()[0];
+                            }
+                                           }
+                                       }
+
+                                       //TODO use entity name ??
+                                       //get from repository
+                                       List<Object[]> list;
+                                       String hql = "SELECT oc " +
+                                                       " FROM %s as oc LEFT JOIN FETCH oc.%s as col %s" +
+                                                       " WHERE oc.id IN (:idSet) ";
+
+                                       AutoInit autoInit = addAutoinitFetchLoading((Class)collectionEntitiyType, "col");
+                    hql = String.format(hql, ownerClazz.getSimpleName(), param,
+                                               autoInit.leftJoinFetch);
+
+                                       try {
+                                               if (logger.isTraceEnabled()){logger.trace(hql);}
+                                               Query query = genericDao.getHqlQuery(hql);
+                                               query.setParameterList("idSet", idSet);
+                                               list = query.list();
+                                               if (logger.isTraceEnabled()){logger.trace("size of retrieved list is " + list.size());}
+                                       } catch (HibernateException e) {
+                                               e.printStackTrace();
+                                               throw e;
+                                       }
+
+                                       //getTarget and add to child node
+                                       if (logger.isTraceEnabled()){logger.trace("initialize bulk loaded " + node + " collections - DONE");}
+                                       for (Object parentBean : list){
+                        try {
+                                                   Object propValue = PropertyUtils.getProperty(
+                                                           parentBean,
+                                                           mapFieldToPropertyName(param, parentBean.getClass().getSimpleName())
+                                                         );
+
+                                                       if (propValue == null){
+                                                           logger.trace("Collection is null");
+                                                       }else {
+                                                           if(propValue instanceof PersistentMap) {
+                                                               propValue = ((PersistentMap)propValue).values();
+                                                           }
+                                                           for(Object newBean : (Collection<Object>)propValue ) {
+                                                               if(newBean instanceof HibernateProxy){
+                                                                   newBean = initializeInstance(newBean);
+                                                               }
+
+                                                               autoinitializeBean((CdmBase)newBean, autoInit);
+
+                                                               node.addBean(newBean);
+                                                           }
+                                                       }
+                        } catch (Exception e) {
+                            // TODO better throw an exception ?
+                            logger.error("error while getting collection property", e);
+                        }
+                                       }
+                                       if (logger.isTraceEnabled()){logger.trace("bulk load " + node + " collections - DONE");}
+                               }
+                       }
+               }
+               for (AbstractPersistentCollection collection : node.getUninitializedCollections()){
+                       if (! collection.wasInitialized()){  //should not happen anymore
+                               collection.forceInitialization();
+                               if (logger.isTraceEnabled()){logger.trace("forceInitialization of collection " + collection);}
+                       } else {
+                           if (logger.isTraceEnabled()){logger.trace("collection " + collection + " is initialized - OK!");}
+                       }
+               }
+
+               node.resetLazyCollections();
+
+               if (logger.isDebugEnabled()){logger.debug("bulk load " +  node + " - DONE ");}
+
+       }
+
+
+    private AutoInit addAutoinitFetchLoading(Class<?> clazz, String beanAlias) {
+
+        AutoInit autoInit = new AutoInit();
+        if(clazz != null) {
+            Set<AutoPropertyInitializer<CdmBase>> inits = getAutoInitializers(clazz);
+            for (AutoPropertyInitializer<CdmBase> init: inits){
+                try {
+                    autoInit.leftJoinFetch +=init.hibernateFetchJoin(clazz, beanAlias);
+                } catch (Exception e) {
+                    // the AutoPropertyInitializer is not supporting LEFT JOIN FETCH so it needs to be
+                    // used explicitly
+                    autoInit.initlializers.add(init);
+                }
+
+            }
+        }
+        return autoInit;
+    }
+
+    private Set<AutoPropertyInitializer<CdmBase>> getAutoInitializers(Class<?> clazz) {
+        Set<AutoPropertyInitializer<CdmBase>> result = new HashSet<AutoPropertyInitializer<CdmBase>>();
+        for(Class<? extends CdmBase> superClass : getBeanAutoInitializers().keySet()){
+            if(superClass.isAssignableFrom(clazz)){
+                result.add(getBeanAutoInitializers().get(superClass));
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Rename hibernate (field) attribute to Bean property name, due to bean inconsistencies
+     * #3841
+     * @param param
+     * @param ownerClass
+     * @return
+     */
+    private String mapFieldToPropertyName(String param, String ownerClass) {
+        if (ownerClass.contains("Description") && param.equals("descriptionElements")){
+            return "elements";
+        }
+        if (ownerClass.startsWith("FeatureNode") && param.equals("children")) {
+            return "childNodes";
+        }
+        if (ownerClass.startsWith("Media") && param.equals("description")) {
+            return "allDescriptions";
+        }
+        else{
+            return param;
+        }
+    }
+
+    /**
+     * @param node
+     * @param property
+     * @param index
+     * @param bean
+     * @param unwrappedPropertyBean
+     */
+    private void initializeNodeSinglePropertyOld(BeanInitNode node, String property,
+            Integer index, Object bean, Object unwrappedPropertyBean) {
+        Collection<?> collection = null;
+        if(Map.class.isAssignableFrom(unwrappedPropertyBean.getClass())) {
+            collection = ((Map<?,?>)unwrappedPropertyBean).values();
+        }else if (Collection.class.isAssignableFrom(unwrappedPropertyBean.getClass())) {
+            collection =  (Collection<?>) unwrappedPropertyBean;
+        }
+        if (collection != null){
+            //collection or map
+            if (logger.isTraceEnabled()){logger.trace(" initialize collection for " + node.toStringNoWildcard() + " ... ");}
+            int i = 0;
+            for (Object entrybean : collection) {
+                if(index == null){
+                    node.addBean(entrybean);
+                } else if(index.equals(i)){
+                    node.addBean(entrybean);
+                    break;
+                }
+                i++;
+            }
+            if (logger.isTraceEnabled()){logger.trace(" initialize collection for " + node.toString() + " - DONE ");}
+
+        }else {
+            // nested bean
+            node.addBean(unwrappedPropertyBean);
+            setProperty(bean, property, unwrappedPropertyBean);
+        }
+    }
+
+    private class AutoInit{
+
+        String leftJoinFetch = "";
+        Set<AutoPropertyInitializer<CdmBase>> initlializers = new HashSet<AutoPropertyInitializer<CdmBase>>();
+
+        /**
+         * @param leftJoinFetch
+         * @param initlializers
+         */
+        public AutoInit() {
+        }
+    }
+}