Project

General

Profile

Download (9.61 KB) Statistics
| Branch: | Tag: | Revision:
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
 * @since 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
}
(5-5/15)