Project

General

Profile

« Previous | Next » 

Revision 21d1be03

Added by Andreas Müller over 8 years ago

Fix bug for embeddable classes in AdvancedBeanInitializer #5383

View differences:

cdmlib-model/src/main/java/eu/etaxonomy/cdm/hibernate/HibernateProxyHelper.java
1
/**
2
* Copyright (C) 2007 EDIT
3
* European Distributed Institute of Taxonomy
4
* http://www.e-taxonomy.eu
5
*
6
* The contents of this file are subject to the Mozilla Public License Version 1.1
7
* See LICENSE.TXT at the top of this package for the full license terms.
8
*/
9

  
10
package eu.etaxonomy.cdm.hibernate;
11

  
12
import java.io.Serializable;
13

  
14
import org.apache.log4j.Logger;
15
import org.hibernate.proxy.HibernateProxy;
16
import org.hibernate.proxy.LazyInitializer;
17

  
18
/**
19
 * @author a.mueller
20
 * @created 03.03.2009
21
 * @version 1.0
22
 */
23
public class HibernateProxyHelper {
24
	@SuppressWarnings("unused")
25
	private static final Logger logger = Logger.getLogger(HibernateProxyHelper.class);
26

  
27

  
28
	// ************************** Hibernate proxies *******************/
29
	/* (non-Javadoc)
30
	 * @see eu.etaxonomy.cdm.model.common.IProxyHelper#deproxy(java.lang.Object, java.lang.Class)
31
	 */
32
	 public static <T> T deproxy(Object object, Class<T> clazz) throws ClassCastException {
33
	     if (object instanceof HibernateProxy) {
34
	         return clazz.cast(((HibernateProxy) object).getHibernateLazyInitializer().getImplementation());
35
	     } else {
36
	         return clazz.cast(object);
37
	     }
38
	 }
39

  
40
		/**
41
		 * Unwrap the target instance from the proxy.
42
		 */
43
		public static Object deproxy(Object object){
44
			if(object instanceof HibernateProxy) {
45
				LazyInitializer lazyInitializer = ((HibernateProxy)object).getHibernateLazyInitializer();
46
				return lazyInitializer.getImplementation();
47
			} else {
48
				return object;
49
			}
50
		}
51

  
52

  
53
	public static boolean isInstanceOf(Object object, Class clazz) throws ClassCastException {
54
	     if (clazz == null){
55
	    	 return false;
56
	     }
57
		 if (object instanceof HibernateProxy) {
58
	    	 Object impl =  ((HibernateProxy) object).getHibernateLazyInitializer().getImplementation();
59
	         Class<?> implClass = impl.getClass();
60
	         return clazz.isAssignableFrom(implClass);
61
	     } else {
62
	         return clazz.isAssignableFrom(object.getClass());
63
	     }
64
	 }
65

  
66
	public static Serializable getIdentifierOf(Object object) {
67
        if (object instanceof HibernateProxy) {
68
            return  ((HibernateProxy) object).getHibernateLazyInitializer().getIdentifier();
69
        } else {
70
            throw new ClassCastException("Cannot cast the given Object to a known Hibernate proxy.");
71
        }
72
    }
73

  
74
	/**
75
	 * Get the class of an instance or the underlying class
76
	 * of a proxy (without initializing the proxy!). It is
77
	 * almost always better to use the entity name!
78
	 *
79
	 * delegates calls to {@link org.hibernate.proxy.HibernateProxyHelper}
80
	 */
81
	public static Class getClassWithoutInitializingProxy(Object object) {
82
		return org.hibernate.proxy.HibernateProxyHelper.getClassWithoutInitializingProxy(object);
83
	}
84
}
1
/**
2
* Copyright (C) 2007 EDIT
3
* European Distributed Institute of Taxonomy
4
* http://www.e-taxonomy.eu
5
*
6
* The contents of this file are subject to the Mozilla Public License Version 1.1
7
* See LICENSE.TXT at the top of this package for the full license terms.
8
*/
9

  
10
package eu.etaxonomy.cdm.hibernate;
11

  
12
import java.io.Serializable;
13

  
14
import org.apache.log4j.Logger;
15
import org.hibernate.proxy.HibernateProxy;
16
import org.hibernate.proxy.LazyInitializer;
17

  
18
/**
19
 * @author a.mueller
20
 * @created 03.03.2009
21
 * @version 1.0
22
 */
23
public class HibernateProxyHelper {
24
	@SuppressWarnings("unused")
25
	private static final Logger logger = Logger.getLogger(HibernateProxyHelper.class);
26

  
27

  
28
	// ************************** Hibernate proxies *******************/
29
	 public static <T> T deproxy(Object object, Class<T> clazz) throws ClassCastException {
30
	     if (object instanceof HibernateProxy) {
31
	         return clazz.cast(((HibernateProxy) object).getHibernateLazyInitializer().getImplementation());
32
	     } else {
33
	         return clazz.cast(object);
34
	     }
35
	 }
36

  
37
		/**
38
		 * Unwrap the target instance from the proxy.
39
		 */
40
		public static Object deproxy(Object object){
41
			if(object instanceof HibernateProxy) {
42
				LazyInitializer lazyInitializer = ((HibernateProxy)object).getHibernateLazyInitializer();
43
				return lazyInitializer.getImplementation();
44
			} else {
45
				return object;
46
			}
47
		}
48

  
49

  
50
	public static boolean isInstanceOf(Object object, Class clazz) throws ClassCastException {
51
	     if (clazz == null){
52
	    	 return false;
53
	     }
54
		 if (object instanceof HibernateProxy) {
55
	    	 Object impl =  ((HibernateProxy) object).getHibernateLazyInitializer().getImplementation();
56
	         Class<?> implClass = impl.getClass();
57
	         return clazz.isAssignableFrom(implClass);
58
	     } else {
59
	         return clazz.isAssignableFrom(object.getClass());
60
	     }
61
	 }
62

  
63
	public static Serializable getIdentifierOf(Object object) {
64
        if (object instanceof HibernateProxy) {
65
            return  ((HibernateProxy) object).getHibernateLazyInitializer().getIdentifier();
66
        } else {
67
            throw new ClassCastException("Cannot cast the given Object to a known Hibernate proxy.");
68
        }
69
    }
70

  
71
	/**
72
	 * Get the class of an instance or the underlying class
73
	 * of a proxy (without initializing the proxy!). It is
74
	 * almost always better to use the entity name!
75
	 *
76
	 * delegates calls to {@link org.hibernate.proxy.HibernateProxyHelper}
77
	 */
78
	public static Class getClassWithoutInitializingProxy(Object object) {
79
		return org.hibernate.proxy.HibernateProxyHelper.getClassWithoutInitializingProxy(object);
80
	}
81
}
cdmlib-persistence/src/main/java/eu/etaxonomy/cdm/persistence/dao/hibernate/HibernateBeanInitializer.java
1
// $Id$
2
/**
3
* Copyright (C) 2009 EDIT
4
* European Distributed Institute of Taxonomy
5
* http://www.e-taxonomy.eu
6
*
7
* The contents of this file are subject to the Mozilla Public License Version 1.1
8
* See LICENSE.TXT at the top of this package for the full license terms.
9
*/
10
package eu.etaxonomy.cdm.persistence.dao.hibernate;
11

  
12
import org.apache.log4j.Logger;
13
import org.hibernate.HibernateException;
14
import org.hibernate.collection.spi.PersistentCollection;
15
import org.hibernate.envers.entities.mapper.relation.lazy.proxy.CollectionProxy;
16
import org.hibernate.envers.entities.mapper.relation.lazy.proxy.MapProxy;
17
import org.hibernate.proxy.HibernateProxy;
18

  
19
import eu.etaxonomy.cdm.persistence.dao.initializer.AbstractBeanInitializer;
20

  
21
/**
22
 * @author a.kohlbecker
23
 * @date 25.03.2009
24
 *
25
 */
26
//@Component("defaultBeanInitializer")
27
public class HibernateBeanInitializer extends AbstractBeanInitializer{
28

  
29
    @SuppressWarnings("unused")
30
	private static final Logger logger = Logger.getLogger(HibernateBeanInitializer.class);
31

  
32
    @Override
33
    public Object initializeInstance(Object bean) {
34
        initialize(bean);
35
        return HibernateProxyHelperExtended.getProxyTarget(bean);
36
    }
37

  
38
    public static void initialize(Object proxy) throws HibernateException {
39
        if ( proxy == null ) {
40
            return;
41
        }
42
        else if ( proxy instanceof HibernateProxy ) {
43
            ( ( HibernateProxy ) proxy ).getHibernateLazyInitializer().initialize();
44
        } else if ( proxy instanceof PersistentCollection ) {
45
            ( ( PersistentCollection ) proxy ).forceInitialization();
46
        } else if(proxy instanceof CollectionProxy) {
47
            ( ( CollectionProxy ) proxy ).isEmpty(); // checkInit is protected, unfortunately;
48
        } else if(proxy instanceof MapProxy) {
49
            ( ( MapProxy ) proxy ).isEmpty(); // checkInit is protected, unfortunately;
50
        }
51
    }
52

  
53

  
54

  
55
}
1
// $Id$
2
/**
3
* Copyright (C) 2009 EDIT
4
* European Distributed Institute of Taxonomy
5
* http://www.e-taxonomy.eu
6
*
7
* The contents of this file are subject to the Mozilla Public License Version 1.1
8
* See LICENSE.TXT at the top of this package for the full license terms.
9
*/
10
package eu.etaxonomy.cdm.persistence.dao.hibernate;
11

  
12
import org.apache.log4j.Logger;
13
import org.hibernate.HibernateException;
14
import org.hibernate.collection.spi.PersistentCollection;
15
import org.hibernate.envers.internal.entities.mapper.relation.lazy.proxy.CollectionProxy;
16
import org.hibernate.envers.internal.entities.mapper.relation.lazy.proxy.MapProxy;
17
import org.hibernate.proxy.HibernateProxy;
18

  
19
import eu.etaxonomy.cdm.persistence.dao.initializer.AbstractBeanInitializer;
20

  
21
/**
22
 * @author a.kohlbecker
23
 * @date 25.03.2009
24
 *
25
 */
26
//@Component("defaultBeanInitializer")
27
public class HibernateBeanInitializer extends AbstractBeanInitializer{
28

  
29
    @SuppressWarnings("unused")
30
	private static final Logger logger = Logger.getLogger(HibernateBeanInitializer.class);
31

  
32
    @Override
33
    public Object initializeInstance(Object bean) {
34
        initialize(bean);
35
        return HibernateProxyHelperExtended.getProxyTarget(bean);
36
    }
37

  
38
    public static void initialize(Object proxy) throws HibernateException {
39
        if ( proxy == null ) {
40
            return;
41
        }
42
        else if ( proxy instanceof HibernateProxy ) {
43
            ( ( HibernateProxy ) proxy ).getHibernateLazyInitializer().initialize();
44
        } else if ( proxy instanceof PersistentCollection ) {
45
            ( ( PersistentCollection ) proxy ).forceInitialization();
46
        } else if(proxy instanceof CollectionProxy) {
47
            ( ( CollectionProxy<?,?> ) proxy ).isEmpty(); // checkInit is protected, unfortunately;
48
        } else if(proxy instanceof MapProxy) {
49
            ( ( MapProxy<?,?> ) proxy ).isEmpty(); // checkInit is protected, unfortunately;
50
        }
51
    }
52

  
53

  
54

  
55
}
cdmlib-persistence/src/main/java/eu/etaxonomy/cdm/persistence/dao/initializer/BeanInitNode.java
1
/**
2
 *
3
 */
4
package eu.etaxonomy.cdm.persistence.dao.initializer;
5

  
6
import java.io.Serializable;
7
import java.util.ArrayList;
8
import java.util.Collection;
9
import java.util.Collections;
10
import java.util.HashMap;
11
import java.util.HashSet;
12
import java.util.List;
13
import java.util.Map;
14
import java.util.Set;
15

  
16
import org.apache.commons.lang.StringUtils;
17
import org.hibernate.collection.internal.AbstractPersistentCollection;
18

  
19
import eu.etaxonomy.cdm.common.CdmUtils;
20

  
21
/**
22
 * @author a.mueller
23
 * @date 2013-10-25
24
 */
25
public class BeanInitNode implements Comparable<BeanInitNode>{
26

  
27
	// ************************ ATTRIBUTES *******************************/
28

  
29
	private final BeanInitNode parent;
30

  
31
	private final Map<String, BeanInitNode> children = new HashMap<String, BeanInitNode>();
32

  
33
	private final String path;
34

  
35
	private boolean isToManyInitialized = false;
36

  
37
	private boolean isToOneInitialized = false;
38

  
39
	private BeanInitNode wildcardChildCache;
40

  
41

  
42
	private final  Map<Class<?>, Set<Object>> beans = new HashMap<Class<?>, Set<Object>>();
43

  
44
	private final  Map<Class<?>, Set<Serializable>> lazyBeans = new HashMap<Class<?>, Set<Serializable>>();
45

  
46
	private final  Map<Class<?>, Map<String, Set<Serializable>>> lazyCollections = new HashMap<Class<?>, Map<String,Set<Serializable>>>();
47

  
48
	//java.util.Set is  not possible here to avoid initializing of collection during .add()
49
	private final List<AbstractPersistentCollection> uninitializedCollections = new ArrayList<AbstractPersistentCollection>();
50

  
51
// *************************** STATIC METHODS *****************************************/
52

  
53
	public static BeanInitNode createInitTree(List<String> propertyPaths) {
54

  
55
		//sort paths  //TODO needed?
56
		Collections.sort(propertyPaths);
57

  
58
	    BeanInitNode root = new BeanInitNode(null, "");
59

  
60
	    for (String fullPath : propertyPaths){
61
	    	String[] parts = fullPath.split("\\.");
62
	    	BeanInitNode lastNode = root;
63
	    	for (String part : parts){
64
	    		BeanInitNode child = lastNode.children.get(part);
65
	    		if (child == null){
66
	    			child = new BeanInitNode(lastNode, part);
67
	    		}
68
    			lastNode = child;
69
	    	}
70
	    }
71

  
72
		return root;
73
	}
74

  
75
	private static boolean isWildcard(String pathPart) {
76
		return pathPart.equals(AbstractBeanInitializer.LOAD_2ONE_WILDCARD) ||
77
				pathPart.equals(AbstractBeanInitializer.LOAD_2ONE_2MANY_WILDCARD);
78
	}
79

  
80

  
81
//***************************** CONSTRUCTOR RELATED ****************************************/
82

  
83
	public BeanInitNode(BeanInitNode parent, String part) {
84
		this.path = CdmUtils.Nz(part);
85
		this.parent = parent;
86
		this.isToManyInitialized = this.path.equals(AbstractBeanInitializer.LOAD_2ONE_2MANY_WILDCARD);
87
		this.isToOneInitialized = this.path.equals(AbstractBeanInitializer.LOAD_2ONE_WILDCARD) || this.isToManyInitialized;
88
		if (parent != null){
89
			parent.addChild(part, this);
90
		}
91
	}
92

  
93
	private void addChild(String part, BeanInitNode child) {
94
		children.put(part, child);
95
		if (child.isWildcard()){
96
			//set wildcard child if not exists or if child is stronger then existing wildcard child
97
			if (this.wildcardChildCache == null || (! this.wildcardChildCache.isToManyInitialized) && child.isToManyInitialized ){
98
				this.wildcardChildCache = child;
99
			}
100
		}
101
	}
102

  
103
// ************************** 	***********************************************************/
104

  
105
	public BeanInitNode getChild(String param){
106
		return children.get(param);
107
	}
108

  
109

  
110

  
111
	public List<BeanInitNode> getChildrenList() {
112
		List<BeanInitNode> result = new ArrayList<BeanInitNode>(children.values());
113
		Collections.sort(result);
114
		return result;
115
	}
116

  
117
	public BeanInitNode getSibling(String param) {
118
		if (getPath().equals(param) || parent == null){
119
			return null;
120
		}else{
121
			return parent.getChild(param);
122
		}
123
	}
124

  
125
	public String getPath() {
126
		return path;
127
	}
128

  
129
	public boolean isRoot() {
130
		return StringUtils.isBlank(path);
131
	}
132

  
133
	public boolean hasChildren() {
134
		return children.size() > 0;
135
	}
136

  
137
	public BeanInitNode getWildcardChild(){
138
		return this.wildcardChildCache;
139
	}
140
	public boolean isWildcard() {
141
		return this.isToManyInitialized || this.isToOneInitialized;
142
	}
143
	public boolean hasWildcardChild() {
144
		return this.wildcardChildCache != null;
145
	}
146
	public boolean hasToManyWildcardChild() {
147
		return this.wildcardChildCache != null;
148
	}
149

  
150
	public boolean hasWildcardToManySibling() {
151
		BeanInitNode sibl = getWildcardSibling();
152
		return (sibl != null && sibl.isToManyInitialized);
153
	}
154

  
155
	private BeanInitNode getWildcardSibling() {
156
		if (!isWildcard() && parent == null){
157
			return parent.getWildcardChild();
158
		}else{
159
			return null;
160
		}
161
	}
162

  
163

  
164
	public boolean isToManyWildcard() {
165
		return path.equals(AbstractBeanInitializer.LOAD_2ONE_2MANY_WILDCARD);
166
	}
167

  
168

  
169
// ******************* LAZY COLLECTION *****************************************/
170

  
171
	public void putLazyCollection(AbstractPersistentCollection collection) {
172
		String role = collection.getRole();
173
		String parameter = role.substring(role.lastIndexOf(".") + 1);
174
		//for embeddable classes we need also the parent parameter
175
		//TODO also allow recursive embedding
176
		String parentRole = role.substring(0, role.lastIndexOf("."));
177
		String parentParameter = parentRole.substring(parentRole.lastIndexOf(".") + 1);
178
		Class<?> ownerClass = collection.getOwner().getClass();
179
		if (Character.isLowerCase(parentParameter.charAt(0))){
180
		    parameter = parentParameter + "." + parameter;
181
		}
182
		putLazyCollection(ownerClass, parameter, collection.getKey());
183
		this.uninitializedCollections.add(collection);
184
	}
185

  
186
    private void putLazyCollection(Class<?> ownerClazz, String parameter, Serializable id) {
187
		if (ownerClazz != null && parameter != null && id != null){
188
			Map<String, Set<Serializable>> lazyParams = lazyCollections.get(ownerClazz);
189
			if (lazyParams == null){
190
				lazyParams = new HashMap<String, Set<Serializable>>();
191
				lazyCollections.put(ownerClazz, lazyParams);
192
			}
193
			Set<Serializable> layzIds = lazyParams.get(parameter);
194
			if (layzIds == null){
195
				layzIds = new HashSet<Serializable>();
196
				lazyParams.put(parameter, layzIds);
197
			}
198
			layzIds.add(id);
199
		}else{
200
			throw new IllegalArgumentException("Class, parameter and id should not be null");
201
		}
202
	}
203
	public Map<Class<?>, Map<String, Set<Serializable>>> getLazyCollections(){
204
		return this.lazyCollections;
205
	}
206
	public List<AbstractPersistentCollection> getUninitializedCollections(){
207
		return this.uninitializedCollections;
208
	}
209
	public void resetLazyCollections(){
210
		this.lazyCollections.clear();
211
		this.uninitializedCollections.clear();
212
	}
213

  
214

  
215
// ******************* LAZY BEAN *****************************************/
216

  
217
	public void putLazyBean(Class<?> clazz, Serializable id) {
218
		if (clazz != null && id != null){
219
			Set<Serializable> classedLazies= lazyBeans.get(clazz);
220
			if (classedLazies == null){
221
				classedLazies = new HashSet<Serializable>();
222
				lazyBeans.put(clazz, classedLazies);
223
			}
224
			classedLazies.add(id);
225
		}else{
226
			throw new IllegalArgumentException("Class and id should not be null");
227
		}
228
	}
229
	public Map<Class<?>, Set<Serializable>> getLazyBeans(){
230
		return this.lazyBeans;
231
	}
232
	public void resetLazyBeans(){
233
		this.lazyBeans.clear();
234
	}
235

  
236
// ********************* BEANS ******************************/
237

  
238
	private Map<Class<?>, Set<Object>> getClassedBeans(){
239
		return this.beans;
240
	}
241

  
242

  
243
	/**
244
	 * Returns beans represented by this node, split into implementing
245
	 * classes.
246
	 * @return
247
	 */
248
	public Map<Class<?>, Set<Object>> getBeans() {
249
		return this.beans;
250
	}
251

  
252
	public Map<Class<?>, Set<Object>> getParentBeans() {
253
		if (parent == null){
254
			return new HashMap<Class<?>, Set<Object>>();
255
		}else{
256
			return parent.getClassedBeans();
257
		}
258
	}
259

  
260
	/**
261
	 * Add a bean represented by this node
262
	 * @param bean
263
	 */
264
	public void addBean(Object bean) {
265
		if (! isWildcard()){
266
			if (bean != null){
267
				Class<?> key = bean.getClass();
268
				Set<Object> classedBeans = beans.get(key);
269
				if (classedBeans == null){
270
					classedBeans = new HashSet<Object>();
271
					beans.put(key, classedBeans);
272
				}
273
				classedBeans.add(bean);
274
			}
275
		}
276
	}
277
	/**
278
     * Adds beans represented by this node
279
     * @param beans a collection of beans to be added
280
     */
281
	public void addBeans(Collection<?> beans) {
282
		for (Object bean : beans){
283
			addBean(bean);
284
		}
285
	}
286

  
287
	/**
288
	 * Removes all beans representing this node.
289
	 */
290
	public void resetBeans(){
291
		beans.clear();
292
	}
293

  
294

  
295
// ************************* OVERRIDES **********************************/
296

  
297
	@Override
298
	public int compareTo(BeanInitNode o) {
299
		String toMany = AbstractBeanInitializer.LOAD_2ONE_2MANY_WILDCARD;
300
		String toOne = AbstractBeanInitializer.LOAD_2ONE_WILDCARD;
301
		if (this.path.equals(toMany)){
302
			return -1;
303
		}else if (o.path.equals(toMany)){
304
			return 1;
305
		}else if (this.path.equals(toOne)){
306
			return -1;
307
		}else if (o.path.equals(toOne)){
308
			return 1;
309
		}else{
310
			return path.compareTo(o.path);
311
		}
312
	}
313

  
314

  
315
	@Override
316
	public String toString() {
317

  
318
		if(parent == null){
319
			return "/";    //for root node
320
		}else{
321
			String result = parent.toString() + ((parent.parent == null) ? "" : ".") + path;
322
			return result;
323
		}
324
	}
325

  
326
	public String toStringNoWildcard(){
327
		return toString().replace(".$", "").replace(".*", "");
328
	}
329

  
330
	public String toStringTree() {
331

  
332
		String result = (path.equals("") ? "/" : path) + "\n";
333

  
334
		for (BeanInitNode child : getChildrenList()){
335
			result += toString() + (result.endsWith("/\n") ? "" : ".") + child.toStringTree();
336
		}
337

  
338
		return result;
339
	}
340

  
341
	public boolean hasWildcardToOneSibling() {
342
		BeanInitNode sibl = getWildcardSibling();
343
		return (sibl != null && sibl.isToOneInitialized);
344
	}
345

  
346

  
347
}
1
/**
2
 *
3
 */
4
package eu.etaxonomy.cdm.persistence.dao.initializer;
5

  
6
import java.io.Serializable;
7
import java.util.ArrayList;
8
import java.util.Collection;
9
import java.util.Collections;
10
import java.util.HashMap;
11
import java.util.HashSet;
12
import java.util.List;
13
import java.util.Map;
14
import java.util.Set;
15

  
16
import org.apache.commons.lang.StringUtils;
17
import org.hibernate.collection.internal.AbstractPersistentCollection;
18

  
19
import eu.etaxonomy.cdm.common.CdmUtils;
20

  
21
/**
22
 * @author a.mueller
23
 * @date 2013-10-25
24
 */
25
public class BeanInitNode implements Comparable<BeanInitNode>{
26

  
27
	// ************************ ATTRIBUTES *******************************/
28

  
29
	private final BeanInitNode parent;
30

  
31
	private final Map<String, BeanInitNode> children = new HashMap<String, BeanInitNode>();
32

  
33
	private final String path;
34

  
35
	private boolean isToManyInitialized = false;
36

  
37
	private boolean isToOneInitialized = false;
38

  
39
	private BeanInitNode wildcardChildCache;
40

  
41

  
42
	private final  Map<Class<?>, Set<Object>> beans = new HashMap<Class<?>, Set<Object>>();
43

  
44
	private final  Map<Class<?>, Set<Serializable>> lazyBeans = new HashMap<Class<?>, Set<Serializable>>();
45

  
46
	private final  Map<Class<?>, Map<String, Set<Serializable>>> lazyCollections = new HashMap<Class<?>, Map<String,Set<Serializable>>>();
47

  
48
	//java.util.Set is  not possible here to avoid initializing of collection during .add()
49
	private final List<AbstractPersistentCollection> uninitializedCollections = new ArrayList<AbstractPersistentCollection>();
50

  
51
// *************************** STATIC METHODS *****************************************/
52

  
53
	public static BeanInitNode createInitTree(List<String> propertyPaths) {
54

  
55
		//sort paths  //TODO needed?
56
		Collections.sort(propertyPaths);
57

  
58
	    BeanInitNode root = new BeanInitNode(null, "");
59

  
60
	    for (String fullPath : propertyPaths){
61
	    	String[] parts = fullPath.split("\\.");
62
	    	BeanInitNode lastNode = root;
63
	    	for (String part : parts){
64
	    		BeanInitNode child = lastNode.children.get(part);
65
	    		if (child == null){
66
	    			child = new BeanInitNode(lastNode, part);
67
	    		}
68
    			lastNode = child;
69
	    	}
70
	    }
71

  
72
		return root;
73
	}
74

  
75
	private static boolean isWildcard(String pathPart) {
76
		return pathPart.equals(AbstractBeanInitializer.LOAD_2ONE_WILDCARD) ||
77
				pathPart.equals(AbstractBeanInitializer.LOAD_2ONE_2MANY_WILDCARD);
78
	}
79

  
80

  
81
//***************************** CONSTRUCTOR RELATED ****************************************/
82

  
83
	public BeanInitNode(BeanInitNode parent, String part) {
84
		this.path = CdmUtils.Nz(part);
85
		this.parent = parent;
86
		this.isToManyInitialized = this.path.equals(AbstractBeanInitializer.LOAD_2ONE_2MANY_WILDCARD);
87
		this.isToOneInitialized = this.path.equals(AbstractBeanInitializer.LOAD_2ONE_WILDCARD) || this.isToManyInitialized;
88
		if (parent != null){
89
			parent.addChild(part, this);
90
		}
91
	}
92

  
93
	private void addChild(String part, BeanInitNode child) {
94
		children.put(part, child);
95
		if (child.isWildcard()){
96
			//set wildcard child if not exists or if child is stronger then existing wildcard child
97
			if (this.wildcardChildCache == null || (! this.wildcardChildCache.isToManyInitialized) && child.isToManyInitialized ){
98
				this.wildcardChildCache = child;
99
			}
100
		}
101
	}
102

  
103
// ************************** 	***********************************************************/
104

  
105
	public BeanInitNode getChild(String param){
106
		return children.get(param);
107
	}
108

  
109

  
110

  
111
	public List<BeanInitNode> getChildrenList() {
112
		List<BeanInitNode> result = new ArrayList<BeanInitNode>(children.values());
113
		Collections.sort(result);
114
		return result;
115
	}
116

  
117
	public BeanInitNode getSibling(String param) {
118
		if (getPath().equals(param) || parent == null){
119
			return null;
120
		}else{
121
			return parent.getChild(param);
122
		}
123
	}
124

  
125
	public String getPath() {
126
		return path;
127
	}
128

  
129
	public boolean isRoot() {
130
		return StringUtils.isBlank(path);
131
	}
132

  
133
	public boolean hasChildren() {
134
		return children.size() > 0;
135
	}
136

  
137
	public BeanInitNode getWildcardChild(){
138
		return this.wildcardChildCache;
139
	}
140
	public boolean isWildcard() {
141
		return this.isToManyInitialized || this.isToOneInitialized;
142
	}
143
	public boolean hasWildcardChild() {
144
		return this.wildcardChildCache != null;
145
	}
146
	public boolean hasToManyWildcardChild() {
147
		return this.wildcardChildCache != null;
148
	}
149

  
150
	public boolean hasWildcardToManySibling() {
151
		BeanInitNode sibl = getWildcardSibling();
152
		return (sibl != null && sibl.isToManyInitialized);
153
	}
154

  
155
	private BeanInitNode getWildcardSibling() {
156
		if (!isWildcard() && parent == null){
157
			return parent.getWildcardChild();
158
		}else{
159
			return null;
160
		}
161
	}
162

  
163

  
164
	public boolean isToManyWildcard() {
165
		return path.equals(AbstractBeanInitializer.LOAD_2ONE_2MANY_WILDCARD);
166
	}
167

  
168

  
169
// ******************* LAZY COLLECTION *****************************************/
170

  
171
	public void putLazyCollection(AbstractPersistentCollection collection) {
172
		String role = collection.getRole();
173
		String parameter = role.substring(role.lastIndexOf(".") + 1);
174
		//for embeddable classes we need also the parent parameter
175
		//TODO also allow recursive embedding
176
		String parentRole = role.substring(0, role.lastIndexOf("."));
177
		String parentParameter = parentRole.substring(parentRole.lastIndexOf(".") + 1);
178
		Class<?> ownerClass = collection.getOwner().getClass();
179
		if (Character.isLowerCase(parentParameter.charAt(0))){
180
		    parameter = parentParameter + "." + parameter;
181
		}
182
		putLazyCollection(ownerClass, parameter, collection.getKey());
183
		this.uninitializedCollections.add(collection);
184
	}
185

  
186
    private void putLazyCollection(Class<?> ownerClazz, String parameter, Serializable id) {
187
		if (ownerClazz != null && parameter != null && id != null){
188
			Map<String, Set<Serializable>> lazyParams = lazyCollections.get(ownerClazz);
189
			if (lazyParams == null){
190
				lazyParams = new HashMap<String, Set<Serializable>>();
191
				lazyCollections.put(ownerClazz, lazyParams);
192
			}
193
			Set<Serializable> layzIds = lazyParams.get(parameter);
194
			if (layzIds == null){
195
				layzIds = new HashSet<Serializable>();
196
				lazyParams.put(parameter, layzIds);
197
			}
198
			layzIds.add(id);
199
		}else{
200
			throw new IllegalArgumentException("Class, parameter and id should not be null");
201
		}
202
	}
203
	public Map<Class<?>, Map<String, Set<Serializable>>> getLazyCollections(){
204
		return this.lazyCollections;
205
	}
206
	public List<AbstractPersistentCollection> getUninitializedCollections(){
207
		return this.uninitializedCollections;
208
	}
209
	public void resetLazyCollections(){
210
		this.lazyCollections.clear();
211
		this.uninitializedCollections.clear();
212
	}
213

  
214

  
215
// ******************* LAZY BEAN *****************************************/
216

  
217
	public void putLazyBean(Class<?> clazz, Serializable id) {
218
		if (clazz != null && id != null){
219
			Set<Serializable> classedLazies= lazyBeans.get(clazz);
220
			if (classedLazies == null){
221
				classedLazies = new HashSet<Serializable>();
222
				lazyBeans.put(clazz, classedLazies);
223
			}
224
			classedLazies.add(id);
225
		}else{
226
			throw new IllegalArgumentException("Class and id should not be null");
227
		}
228
	}
229
	public Map<Class<?>, Set<Serializable>> getLazyBeans(){
230
		return this.lazyBeans;
231
	}
232
	public void resetLazyBeans(){
233
		this.lazyBeans.clear();
234
	}
235

  
236
// ********************* BEANS ******************************/
237

  
238
	private Map<Class<?>, Set<Object>> getClassedBeans(){
239
		return this.beans;
240
	}
241

  
242

  
243
	/**
244
	 * Returns beans represented by this node, split into implementing
245
	 * classes.
246
	 * @return
247
	 */
248
	public Map<Class<?>, Set<Object>> getBeans() {
249
		return this.beans;
250
	}
251

  
252
	public Map<Class<?>, Set<Object>> getParentBeans() {
253
		if (parent == null){
254
			return new HashMap<Class<?>, Set<Object>>();
255
		}else{
256
			return parent.getClassedBeans();
257
		}
258
	}
259

  
260
	/**
261
	 * Add a bean represented by this node
262
	 * @param bean
263
	 */
264
	public void addBean(Object bean) {
265
		if (! isWildcard()){
266
			if (bean != null){
267
				Class<?> key = bean.getClass();
268
				Set<Object> classedBeans = beans.get(key);
269
				if (classedBeans == null){
270
					classedBeans = new HashSet<Object>();
271
					beans.put(key, classedBeans);
272
				}
273
				classedBeans.add(bean);
274
			}
275
		}
276
	}
277
	/**
278
     * Adds beans represented by this node
279
     * @param beans a collection of beans to be added
280
     */
281
	public void addBeans(Collection<?> beans) {
282
		for (Object bean : beans){
283
			addBean(bean);
284
		}
285
	}
286

  
287
	/**
288
	 * Removes all beans representing this node.
289
	 */
290
	public void resetBeans(){
291
		beans.clear();
292
	}
293

  
294

  
295
// ************************* OVERRIDES **********************************/
296

  
297
	@Override
298
	public int compareTo(BeanInitNode o) {
299
		String toMany = AbstractBeanInitializer.LOAD_2ONE_2MANY_WILDCARD;
300
		String toOne = AbstractBeanInitializer.LOAD_2ONE_WILDCARD;
301
		if (this.path.equals(toMany)){
302
			return -1;
303
		}else if (o.path.equals(toMany)){
304
			return 1;
305
		}else if (this.path.equals(toOne)){
306
			return -1;
307
		}else if (o.path.equals(toOne)){
308
			return 1;
309
		}else{
310
			return path.compareTo(o.path);
311
		}
312
	}
313

  
314

  
315
	@Override
316
	public String toString() {
317

  
318
		if(parent == null){
319
			return "/";    //for root node
320
		}else{
321
			String result = parent.toString() + ((parent.parent == null) ? "" : ".") + path;
322
			return result;
323
		}
324
	}
325

  
326
	public String toStringNoWildcard(){
327
		return toString().replace(".$", "").replace(".*", "");
328
	}
329

  
330
	public String toStringTree() {
331

  
332
		String result = (path.equals("") ? "/" : path) + "\n";
333

  
334
		for (BeanInitNode child : getChildrenList()){
335
			result += toString() + (result.endsWith("/\n") ? "" : ".") + child.toStringTree();
336
		}
337

  
338
		return result;
339
	}
340

  
341
	public boolean hasWildcardToOneSibling() {
342
		BeanInitNode sibl = getWildcardSibling();
343
		return (sibl != null && sibl.isToOneInitialized);
344
	}
345

  
346

  
347
}

Also available in: Unified diff