Project

General

Profile

Download (27.6 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
 *
3
 */
4
package eu.etaxonomy.cdm.persistence.dao.initializer;
5

    
6
import java.beans.PropertyDescriptor;
7
import java.io.Serializable;
8
import java.lang.reflect.InvocationTargetException;
9
import java.lang.reflect.Method;
10
import java.lang.reflect.ParameterizedType;
11
import java.lang.reflect.Type;
12
import java.lang.reflect.TypeVariable;
13
import java.util.ArrayList;
14
import java.util.Collection;
15
import java.util.Collections;
16
import java.util.HashSet;
17
import java.util.List;
18
import java.util.Map;
19
import java.util.Set;
20

    
21
import org.apache.commons.beanutils.PropertyUtils;
22
import org.apache.log4j.Logger;
23
import org.hibernate.Hibernate;
24
import org.hibernate.HibernateException;
25
import org.hibernate.Query;
26
import org.hibernate.collection.internal.AbstractPersistentCollection;
27
import org.hibernate.collection.internal.PersistentMap;
28
import org.hibernate.envers.internal.entities.mapper.relation.lazy.proxy.CollectionProxy;
29
import org.hibernate.envers.internal.entities.mapper.relation.lazy.proxy.MapProxy;
30
import org.hibernate.envers.internal.entities.mapper.relation.lazy.proxy.SortedMapProxy;
31
import org.hibernate.proxy.HibernateProxy;
32
import org.springframework.beans.factory.annotation.Autowired;
33

    
34
import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl;
35
import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
36
import eu.etaxonomy.cdm.model.common.CdmBase;
37
import eu.etaxonomy.cdm.persistence.dao.common.ICdmGenericDao;
38
import eu.etaxonomy.cdm.persistence.dao.hibernate.HibernateBeanInitializer;
39

    
40
/**
41
 * For now this is a test if we can improve performance for bean initializing
42
 * @author a.mueller
43
 * @date 2013-10-25
44
 *
45
 */
46
public class AdvancedBeanInitializer extends HibernateBeanInitializer {
47

    
48
    public static final Logger logger = Logger.getLogger(AdvancedBeanInitializer.class);
49

    
50
    @Autowired
51
    ICdmGenericDao genericDao;
52

    
53
    @Override
54
    public void initialize(Object bean, List<String> propertyPaths) {
55
        List<Object> beanList = new ArrayList<Object>(1);
56
        beanList.add(bean);
57
        initializeAll(beanList, propertyPaths);
58
    }
59

    
60
    //TODO optimize algorithm ..
61
    @Override
62
    public <C extends Collection<?>> C initializeAll(C beanList,  List<String> propertyPaths) {
63

    
64
        if (beanList == null || beanList.isEmpty()){
65
            return beanList;
66
        }
67

    
68
        //autoinitialize
69
        for (Object bean : beanList){
70
            autoinitializeBean(bean);
71
        }
72

    
73
        if(propertyPaths == null){
74
            return beanList;
75
        }
76

    
77

    
78
        //new
79
         BeanInitNode rootPath = BeanInitNode.createInitTree(propertyPaths);
80
        if (logger.isTraceEnabled()){logger.trace(rootPath.toStringTree());}
81

    
82

    
83
        if(logger.isDebugEnabled()){ logger.debug(">> starting to initialize beanlist ; class(e.g.):" + beanList.iterator().next().getClass().getSimpleName());}
84
        rootPath.addBeans(beanList);
85
        initializeNodeRecursive(rootPath);
86

    
87

    
88
        //old - keep for safety (this may help to initialize those beans that are not yet correctly initialized by the AdvancedBeanInitializer
89
        if(logger.isTraceEnabled()){logger.trace("Start old initalizer ... ");};
90
        for (Object bean :beanList){
91
            Collections.sort(propertyPaths);
92
            for(String propPath : propertyPaths){
93
//		            initializePropertyPath(bean, propPath);
94
            }
95
        }
96

    
97
        if(logger.isDebugEnabled()){ logger.debug("   Completed initialization of beanlist "); }
98
        return beanList;
99

    
100
    }
101

    
102

    
103
    //new
104
    private void initializeNodeRecursive(BeanInitNode rootPath) {
105
        initializeNode(rootPath);
106
        for (BeanInitNode childPath : rootPath.getChildrenList()){
107
            initializeNodeRecursive(childPath);
108
        }
109
        rootPath.resetBeans();
110
    }
111

    
112
    /**
113
     * Initializes the given single <code>propPath</code> String.
114
     *
115
     * @param bean
116
     * @param propPath
117
     */
118
    private void initializeNode(BeanInitNode node) {
119
        if(logger.isDebugEnabled()){logger.debug(" processing " + node.toString());}
120
        if (node.isRoot()){
121
            return;
122
        }else if (node.isWildcard()){
123
            initializeNodeWildcard(node);
124
        } else {
125
            initializeNodeNoWildcard(node);
126
        }
127
    }
128

    
129
    // if propPath only contains a wildcard (* or $)
130
    // => do a batch initialization of *toOne or *toMany relations
131
    private void initializeNodeWildcard(BeanInitNode node) {
132
//			boolean initToMany = node.isToManyWildcard();
133
        Map<Class<?>, Set<Object>> parentBeans = node.getParentBeans();
134
        for (Class<?> clazz : parentBeans.keySet()){
135
            //new
136
            for (Object bean : parentBeans.get(clazz)){
137

    
138
                if(Collection.class.isAssignableFrom(bean.getClass())){
139
//				        old: initializeAllEntries((Collection<?>)bean, true, initToMany);  //TODO is this a possible case at all??
140
                    throw new RuntimeException("Collection no longer expected in 'initializeNodeWildcard()'. Therefore an exception is thrown.");
141
                } else if(Map.class.isAssignableFrom(bean.getClass())) {
142
//				        old: initializeAllEntries(((Map<?,?>)bean).values(), true, initToMany);  ////TODO is this a possible case at all??
143
                    throw new RuntimeException("Map no longer expected in 'initializeNodeWildcard()'. Therefore an exception is thrown.");
144
                } else{
145
                    prepareBeanWildcardForBulkLoad(node, bean);
146
                }
147
            }
148
            //end new
149

    
150
//		    	initializeNodeWildcardOld(initToMany, beans, clazz);  //if switched on move bulkLoadLazies up
151
        }
152

    
153
        //
154
        bulkLoadLazies(node);
155
    }
156

    
157
    /**
158
     * @param initToMany
159
     * @param beans
160
     * @param clazz
161
     */
162
    private void initializeNodeWildcardOld(boolean initToMany,
163
            Map<Class<?>, Set<Object>> beans, Class<?> clazz) {
164
        for (Object bean : beans.get(clazz)){
165

    
166
            if(Collection.class.isAssignableFrom(bean.getClass())){
167
                initializeAllEntries((Collection<?>)bean, true, initToMany);
168
            } else if(Map.class.isAssignableFrom(bean.getClass())) {
169
                initializeAllEntries(((Map<?,?>)bean).values(), true, initToMany);
170
            } else{
171
                initializeBean(bean, true, initToMany);
172
            }
173
        }
174
    }
175

    
176
    private void prepareBeanWildcardForBulkLoad(BeanInitNode node, Object bean){
177

    
178
        if(logger.isTraceEnabled()){logger.trace(">> prepare bulk wildcard initialization of a bean of type " + bean.getClass().getSimpleName()); }
179
        Set<Class<?>> restrictions = new HashSet<Class<?>>();
180
        restrictions.add(CdmBase.class);
181
        if(node.isToManyWildcard()){
182
            restrictions.add(Collection.class);
183
        }
184
        Set<PropertyDescriptor> props = getProperties(bean, restrictions);
185
        for(PropertyDescriptor propertyDescriptor : props){
186
            try {
187
                String property = propertyDescriptor.getName();
188

    
189
//                  invokeInitialization(bean, propertyDescriptor);
190
                Object propertyValue = PropertyUtils.getProperty( bean, property);
191

    
192
                preparePropertyValueForBulkLoadOrStore(node, bean, property,  propertyValue );
193

    
194
            } catch (IllegalAccessException e) {
195
                logger.error("Illegal access on property " + propertyDescriptor.getName());
196
            } catch (InvocationTargetException e) {
197
                logger.info("Cannot invoke property " + propertyDescriptor.getName() + " not found");
198
            } catch (NoSuchMethodException e) {
199
                logger.info("Property " + propertyDescriptor.getName() + " not found");
200
            }
201
        }
202
        if(logger.isTraceEnabled()){logger.trace(" completed bulk wildcard initialization of a bean");}
203
    }
204

    
205

    
206
    /**
207
     * Initializes all objects matching the given node, where the
208
     * node does not represent a wildcard but a single field or
209
     * a nested path. Splits the next path token off and keeps
210
     * the remaining as nestedPath
211
     *
212
     * @param node
213
     */
214
    private void initializeNodeNoWildcard(BeanInitNode node) {
215

    
216
        String property = node.getPath();
217
        int pos;
218

    
219
        // is the property indexed?
220
        Integer index = null;
221
        if((pos = property.indexOf('[')) > 0){
222
            String indexString = property.substring(pos + 1, property.indexOf(']'));
223
            index = Integer.valueOf(indexString);
224
            property = property.substring(0, pos);
225
        }
226

    
227
        //Class targetClass = HibernateProxyHelper.getClassWithoutInitializingProxy(bean); // used for debugging
228

    
229
        for (Class<?> parentClazz : node.getParentBeans().keySet()){
230
            if (logger.isTraceEnabled()){logger.trace(" invoke initialization on "+ node.toString()+ " beans of class " + parentClazz.getSimpleName() + " ... ");}
231

    
232
            Set<Object> parentBeans = node.getParentBeans().get(parentClazz);
233

    
234
            if (index != null){
235
                logger.warn("Property path index not yet implemented for 'new'");
236
            }
237
            //new
238
            for (Object parentBean : parentBeans){
239
                preparePropertyForSingleBean(node, property, parentClazz, parentBean);
240
            }//end for
241
            //end new
242
//			 initializeNodeNoWildcardOld(node, property, index, parentBeans);  //move bulkLoadLazies up again, if uncomment this line
243
        } //end for
244
        bulkLoadLazies(node);
245
    }
246

    
247
    /**
248
     * Prepare a single property of a non-collection bean. Collections are handled elsewhere.
249
     */
250
    private void preparePropertyForSingleBean(BeanInitNode node, String property, Class<?> parentClazz, Object bean) {
251
        String propertyName = mapFieldToPropertyName(property, bean.getClass().getSimpleName());
252
        try{
253
            Object propertyValue = PropertyUtils.getProperty(bean, propertyName);
254
            preparePropertyValueForBulkLoadOrStore(node, bean, property, propertyValue);
255
        } catch (IllegalAccessException e) {
256
            String message = "Illegal access on property " + property;
257
            logger.error(message);
258
            throw new RuntimeException(message, e);
259
        } catch (InvocationTargetException e) {
260
            String message = "Cannot invoke property " + property + " not found";
261
            logger.error(message);
262
            throw new RuntimeException(message, e);
263
        } catch (NoSuchMethodException e) {
264
            String message = "Property " + propertyName + " not found for class " + parentClazz;
265
            logger.info(message);
266
            //don't throw exception as sometimes property paths will include non matching property names due to subclassing
267
            //#5077  comment 12
268
        }
269
    }
270

    
271
//    /**
272
//     * @param node
273
//     * @param property
274
//     * @param index
275
//     * @param parentBeans
276
//     * @throws IllegalAccessException
277
//     * @throws InvocationTargetException
278
//     * @throws NoSuchMethodException
279
//     */
280
//    private void initializeNodeNoWildcardOld(BeanInitNode node,
281
//                String property,
282
//                Integer index,
283
//                Set<Object> parentBeans)
284
//            throws IllegalAccessException, InvocationTargetException, NoSuchMethodException
285
//    {
286
//        for (Object bean : parentBeans){
287
//
288
//            PropertyDescriptor propertyDescriptor = PropertyUtils.getPropertyDescriptor(bean, property);
289
//            if (logger.isTraceEnabled()){logger.trace("   unwrap " + node.toStringNoWildcard() + " ... ");}
290
//            // [1] initialize the bean named by property
291
//            Object unwrappedPropertyBean = invokeInitialization(bean, propertyDescriptor);
292
//            if (logger.isTraceEnabled()){logger.trace("   unwrap " + node.toStringNoWildcard() + " - DONE ");}
293
//
294
//
295
//            // [2]
296
//            // handle property
297
//            if(unwrappedPropertyBean != null ){
298
//                initializeNodeSinglePropertyOld(node, property, index, bean, unwrappedPropertyBean);
299
//            }
300
//        }
301
//    }
302

    
303
    /**
304
     * @param node
305
     * @param propertyValue
306
     * @param parentBean
307
     * @param param
308
     */
309
    private void preparePropertyValueForBulkLoadOrStore(BeanInitNode node,
310
            Object parentBean,
311
            String param,
312
            Object propertyValue)
313
    {
314
        BeanInitNode sibling = node.getSibling(param);
315

    
316
        if (propertyValue instanceof AbstractPersistentCollection ){
317
            //collections
318
            if (!node.hasWildcardToManySibling()){  //if wildcard sibling exists the lazies are already prepared there
319
                AbstractPersistentCollection collection = (AbstractPersistentCollection)propertyValue;
320
                if (collection.wasInitialized()){
321
                    storeInitializedCollection(collection, node, param);
322
                }else{
323
//						Class<?> parentClass = parentBean.getClass();
324
//						int parentId = ((CdmBase)parentBean).getId();
325
                    if (sibling != null){
326
                        sibling.putLazyCollection(collection);
327
                    }else{
328
                        node.putLazyCollection(collection);
329
                    }
330
                }
331
            }
332
        } else if (propertyValue instanceof CollectionProxy
333
                || propertyValue instanceof MapProxy<?, ?>
334
                || propertyValue instanceof SortedMapProxy<?, ?>){
335
            //hibernate envers collections
336
            //TODO check if other code works with audited data at all as we use HQL queries
337
            if (!node.hasWildcardToManySibling()){  //if wildcard sibling exists the lazies are already prepared there
338
                Collection<?> collection = (Collection<?>)propertyValue;
339
                //TODO it is difficult to find out if an envers collection is initiallized
340
                //but possiblie via reflection. If the "delegate" parameter is null it is not yet initialized.
341
                //However, as we do not know if envers initialization works at all together with the AdvancedBeanInitializer
342
                //we initialize each collection immediately here by calling size()
343
                collection.size();  //initialize
344
                storeInitializedEnversCollection(collection, node, param);
345
            }
346
        }else{
347
            //singles
348
            if (!node.hasWildcardToOneSibling()){  //if wildcard exists the lazies are already prepared there
349
                if (! Hibernate.isInitialized(propertyValue)){
350
                    if (propertyValue instanceof HibernateProxy){
351
                        Serializable id = ((HibernateProxy)propertyValue).getHibernateLazyInitializer().getIdentifier();
352
                        Class<?> persistedClass = ((HibernateProxy)propertyValue).getHibernateLazyInitializer().getPersistentClass();
353
                        if (sibling != null){
354
                            sibling.putLazyBean(persistedClass, id);
355
                        }else{
356
                            node.putLazyBean(persistedClass, id);
357
                        }
358

    
359
                    }else{
360
                        logger.warn("Lazy value is not of type HibernateProxy. This is not yet handled.");
361
                    }
362
                }else if (propertyValue == null){
363
                    // do nothing
364
                }else{
365
                    if (propertyValue instanceof HibernateProxy){  //TODO remove hibernate dependency
366
                        propertyValue = initializeInstance(propertyValue);
367
                    }
368
                    autoinitializeBean(propertyValue);
369
                    node.addBean(propertyValue);
370
                }
371
            }
372
        }
373
    }
374

    
375
    private void autoinitializeBean(Object bean) {
376
        invokePropertyAutoInitializers(bean);
377
    }
378

    
379
    private void autoinitializeBean(CdmBase bean, AutoInit autoInit) {
380
        for(AutoPropertyInitializer<CdmBase> init : autoInit.initlializers) {
381
            init.initialize(bean);
382
        }
383
    }
384

    
385
	private void storeInitializedCollection(AbstractPersistentCollection persistedCollection,
386
			BeanInitNode node, String param) {
387

    
388
	    Collection<?> collection;
389
		if (persistedCollection  instanceof Collection) {
390
			collection = (Collection<?>) persistedCollection;
391
		}else if (persistedCollection instanceof Map) {
392
			collection = ((Map<?,?>)persistedCollection).values();
393
		}else{
394
			throw new RuntimeException ("Non Map and non Collection cas not handled in storeInitializedCollection()");
395
		}
396
		for (Object value : collection){
397
			preparePropertyValueForBulkLoadOrStore(node, null, param, value);
398
		}
399
	}
400

    
401
	/**
402
	 * @see #storeInitializedCollection(AbstractPersistentCollection, BeanInitNode, String)alizedCollection
403
	 */
404
	private void storeInitializedEnversCollection(Collection<?> enversCollection,
405
            BeanInitNode node, String param) {
406
	    if (enversCollection instanceof CollectionProxy
407
                || enversCollection instanceof MapProxy<?, ?>
408
                || enversCollection instanceof SortedMapProxy<?, ?>){
409
	        Collection<?> collection;
410
	        if (enversCollection instanceof MapProxy
411
	                || enversCollection instanceof SortedMapProxy<?, ?>) {
412
	            collection = ((Map<?,?>)enversCollection).values();
413
	        }else if (enversCollection instanceof CollectionProxy) {
414
	            collection = enversCollection;
415
	        }else{
416
	            throw new RuntimeException ("Non MapProxy and non CollectionProxy case not handled in storeInitializedEnversCollection()");
417
	        }
418
	        for (Object value : collection){
419
	            preparePropertyValueForBulkLoadOrStore(node, null, param, value);
420
	        }
421
	    }
422
    }
423

    
424

    
425
	/**
426
	 * Load all beans which are added to the node
427
	 * and which are not yet initialized in bulk.
428
	 * @param node
429
	 */
430
	private void bulkLoadLazies(BeanInitNode node) {
431
		if (logger.isTraceEnabled()){logger.trace("bulk load " +  node);}
432
		//beans
433
		bulkLoadLazyBeans(node);
434
		//collections
435
		bulkLoadLazyCollections(node);
436
		if (logger.isDebugEnabled()){logger.debug("bulk load " +  node + " - DONE ");}
437
	}
438

    
439

    
440
    /**
441
     * Loads all lazy beans added to the node and empty the lazy bean collection of the node.
442
     * Lazy collections are initialized elsewhere: {@link #bulkLoadLazyCollections(BeanInitNode)}
443
     * @param node the {@link BeanInitNode} to load the lazy beans for
444
     */
445
    private void bulkLoadLazyBeans(BeanInitNode node) {
446
        for (Class<?> clazz : node.getLazyBeans().keySet()){
447
            Set<Serializable> idSet = node.getLazyBeans().get(clazz);
448
            if (idSet != null && ! idSet.isEmpty()){
449

    
450
                if (logger.isTraceEnabled()){logger.trace("bulk load beans of class " +  clazz.getSimpleName());}
451
                //TODO use entity name
452
                String hql = " SELECT c FROM %s as c %s WHERE c.id IN (:idSet) ";
453
                AutoInit autoInit = addAutoinitFetchLoading(clazz, "c");
454
                hql = String.format(hql, clazz.getSimpleName(), autoInit.leftJoinFetch);
455
                if (logger.isTraceEnabled()){logger.trace(hql);}
456
                Query query = genericDao.getHqlQuery(hql);
457
                query.setParameterList("idSet", idSet);
458
                List<Object> list = query.list();
459

    
460
                if (logger.isTraceEnabled()){logger.trace("initialize bulk loaded beans of class " +  clazz.getSimpleName());}
461
                for (Object object : list){
462
                    if (object instanceof HibernateProxy){  //TODO remove hibernate dependency
463
                        object = initializeInstance(object);
464
                    }
465
                    autoinitializeBean((CdmBase)object, autoInit);
466
                    node.addBean(object);
467
                }
468
                if (logger.isTraceEnabled()){logger.trace("bulk load - DONE");}
469
            }
470
        }
471
        node.resetLazyBeans();
472
    }
473

    
474
    /**
475
     * Loads all lazy collections added to the node and empty the lazy collections collection of the node.
476
     * Lazy beans are initialized elsewhere: {@link #bulkLoadLazyBeans(BeanInitNode)}
477
     * @param node the {@link BeanInitNode} to load the lazy beans for
478
     */
479
    private void bulkLoadLazyCollections(BeanInitNode node) {
480
        for (Class<?> ownerClazz : node.getLazyCollections().keySet()){
481
			Map<String, Set<Serializable>> lazyParams = node.getLazyCollections().get(ownerClazz);
482
			for (String param : lazyParams.keySet()){
483
				Set<Serializable> idSet = lazyParams.get(param);
484
				if (idSet != null && ! idSet.isEmpty()){
485
					if (logger.isTraceEnabled()){logger.trace("bulk load " + node + " collections ; ownerClass=" +  ownerClazz.getSimpleName() + " ; param = " + param);}
486

    
487
					Type collectionEntitiyType = null;
488
					PropertyDescriptor[] descriptors = PropertyUtils.getPropertyDescriptors(ownerClazz);
489
					for(PropertyDescriptor d : descriptors) {
490
					    if(d.getName().equals(param)) {
491
					        Method readMethod = d.getReadMethod();
492
                            ParameterizedType pt = (ParameterizedType) readMethod.getGenericReturnType();
493
                            Type[] actualTypeArguments = pt.getActualTypeArguments();
494
                            if(actualTypeArguments.length == 2) {
495
                                // this must be a map of <Language, String> (aka LanguageString) there is no other case like this in the cdm
496
                                // in case of Maps the returned Collection will be the Collection of the values, so collectionEntitiyType is the
497
                                // second typeArgument
498
                                collectionEntitiyType = actualTypeArguments[1];
499
                            } else {
500
                                collectionEntitiyType = actualTypeArguments[0];
501
                            }
502
                            if(collectionEntitiyType instanceof TypeVariable) {
503
                                collectionEntitiyType = ((TypeVariable)collectionEntitiyType).getBounds()[0];
504
                            }
505
					    }
506
					}
507

    
508
					//TODO use entity name ??
509
					//get from repository
510
					List<Object[]> list;
511
					String hql = "SELECT oc " +
512
							" FROM %s as oc LEFT JOIN FETCH oc.%s as col %s" +
513
							" WHERE oc.id IN (:idSet) ";
514

    
515
					if (collectionEntitiyType instanceof ParameterizedTypeImpl){
516
					    collectionEntitiyType = ((ParameterizedTypeImpl)collectionEntitiyType).getRawType();
517
					}
518
					AutoInit autoInit = addAutoinitFetchLoading((Class<?>)collectionEntitiyType, "col");
519
                    hql = String.format(hql, ownerClazz.getSimpleName(), param,
520
					        autoInit.leftJoinFetch);
521

    
522
					try {
523
						if (logger.isTraceEnabled()){logger.trace(hql);}
524
						Query query = genericDao.getHqlQuery(hql);
525
						query.setParameterList("idSet", idSet);
526
						list = query.list();
527
						if (logger.isTraceEnabled()){logger.trace("size of retrieved list is " + list.size());}
528
					} catch (HibernateException e) {
529
						e.printStackTrace();
530
						throw e;
531
					}
532

    
533
					//getTarget and add to child node
534
					if (logger.isTraceEnabled()){logger.trace("initialize bulk loaded " + node + " collections - DONE");}
535
					for (Object parentBean : list){
536
                        try {
537
						    Object propValue = PropertyUtils.getProperty(
538
						            parentBean,
539
						            mapFieldToPropertyName(param, parentBean.getClass().getSimpleName())
540
						          );
541

    
542
							if (propValue == null){
543
							    logger.trace("Collection is null");
544
							}else {
545
							    if(propValue instanceof PersistentMap) {
546
							        propValue = ((PersistentMap)propValue).values();
547
							    }
548
							    for(Object newBean : (Collection<Object>)propValue ) {
549
							        if(newBean instanceof HibernateProxy){
550
							            newBean = initializeInstance(newBean);
551
							        }
552

    
553
							        if (HibernateProxyHelper.isInstanceOf(newBean, CdmBase.class)){
554
							            autoinitializeBean((CdmBase)newBean, autoInit);
555
							        }
556
							        node.addBean(newBean);
557
							    }
558
							}
559
                        } catch (Exception e) {
560
                            // TODO better throw an exception ?
561
                            logger.error("error while getting collection property", e);
562
                        }
563
					}
564
					if (logger.isTraceEnabled()){logger.trace("bulk load " + node + " collections - DONE");}
565
				}
566
			}
567
		}
568
		for (AbstractPersistentCollection collection : node.getUninitializedCollections()){
569
			if (! collection.wasInitialized()){  //should not happen anymore
570
				collection.forceInitialization();
571
				if (logger.isTraceEnabled()){logger.trace("forceInitialization of collection " + collection);}
572
			} else {
573
			    if (logger.isTraceEnabled()){logger.trace("collection " + collection + " is initialized - OK!");}
574
			}
575
		}
576

    
577
		node.resetLazyCollections();
578
    }
579

    
580
    private AutoInit addAutoinitFetchLoading(Class<?> clazz, String beanAlias) {
581

    
582
        AutoInit autoInit = new AutoInit();
583
        if(clazz != null) {
584
            Set<AutoPropertyInitializer<CdmBase>> inits = getAutoInitializers(clazz);
585
            for (AutoPropertyInitializer<CdmBase> init: inits){
586
                try {
587
                    autoInit.leftJoinFetch +=init.hibernateFetchJoin(clazz, beanAlias);
588
                } catch (Exception e) {
589
                    // the AutoPropertyInitializer is not supporting LEFT JOIN FETCH so it needs to be
590
                    // used explicitly
591
                    autoInit.initlializers.add(init);
592
                }
593

    
594
            }
595
        }
596
        return autoInit;
597
    }
598

    
599
    private Set<AutoPropertyInitializer<CdmBase>> getAutoInitializers(Class<?> clazz) {
600
        Set<AutoPropertyInitializer<CdmBase>> result = new HashSet<AutoPropertyInitializer<CdmBase>>();
601
        for(Class<? extends CdmBase> superClass : getBeanAutoInitializers().keySet()){
602
            if(superClass.isAssignableFrom(clazz)){
603
                result.add(getBeanAutoInitializers().get(superClass));
604
            }
605
        }
606
        return result;
607
    }
608

    
609
    /**
610
     * Rename hibernate (field) attribute to Bean property name, due to bean inconsistencies
611
     * #3841
612
     * @param param
613
     * @param ownerClass
614
     * @return
615
     */
616
    private String mapFieldToPropertyName(String param, String ownerClass) {
617
        if (ownerClass.contains("Description") && param.equals("descriptionElements")){
618
            return "elements";
619
        }
620
        if (ownerClass.startsWith("FeatureNode") && param.equals("children")) {
621
            return "childNodes";
622
        }
623
        if (ownerClass.startsWith("Media") && param.equals("description")) {
624
            return "allDescriptions";
625
        }
626
        else{
627
            return param;
628
        }
629
    }
630

    
631
    /**
632
     * @param node
633
     * @param property
634
     * @param index
635
     * @param bean
636
     * @param unwrappedPropertyBean
637
     */
638
    private void initializeNodeSinglePropertyOld(BeanInitNode node, String property,
639
            Integer index, Object bean, Object unwrappedPropertyBean) {
640
        Collection<?> collection = null;
641
        if(Map.class.isAssignableFrom(unwrappedPropertyBean.getClass())) {
642
            collection = ((Map<?,?>)unwrappedPropertyBean).values();
643
        }else if (Collection.class.isAssignableFrom(unwrappedPropertyBean.getClass())) {
644
            collection =  (Collection<?>) unwrappedPropertyBean;
645
        }
646
        if (collection != null){
647
            //collection or map
648
            if (logger.isTraceEnabled()){logger.trace(" initialize collection for " + node.toStringNoWildcard() + " ... ");}
649
            int i = 0;
650
            for (Object entrybean : collection) {
651
                if(index == null){
652
                    node.addBean(entrybean);
653
                } else if(index.equals(i)){
654
                    node.addBean(entrybean);
655
                    break;
656
                }
657
                i++;
658
            }
659
            if (logger.isTraceEnabled()){logger.trace(" initialize collection for " + node.toString() + " - DONE ");}
660

    
661
        }else {
662
            // nested bean
663
            node.addBean(unwrappedPropertyBean);
664
            setProperty(bean, property, unwrappedPropertyBean);
665
        }
666
    }
667

    
668
    private class AutoInit{
669

    
670
        String leftJoinFetch = "";
671
        Set<AutoPropertyInitializer<CdmBase>> initlializers = new HashSet<AutoPropertyInitializer<CdmBase>>();
672

    
673
        /**
674
         * @param leftJoinFetch
675
         * @param initlializers
676
         */
677
        public AutoInit() {
678
        }
679
    }
680
}
(2-2/13)