Merge branch 'release/3.7.0'
[taxeditor.git] / eu.etaxonomy.taxeditor.cdmlib / src / main / java / eu / etaxonomy / cdm / api / lazyloading / CdmLazyLoader.java
1 package eu.etaxonomy.cdm.api.lazyloading;
2
3 import java.util.ArrayList;
4 import java.util.HashMap;
5 import java.util.HashSet;
6 import java.util.List;
7 import java.util.Map;
8 import java.util.Set;
9 import java.util.TreeMap;
10 import java.util.TreeSet;
11
12 import org.aspectj.lang.ProceedingJoinPoint;
13 import org.aspectj.lang.annotation.Around;
14 import org.aspectj.lang.annotation.Aspect;
15 import org.aspectj.lang.annotation.Pointcut;
16 import org.hibernate.collection.internal.PersistentList;
17 import org.hibernate.collection.internal.PersistentMap;
18 import org.hibernate.collection.internal.PersistentSet;
19 import org.hibernate.collection.internal.PersistentSortedMap;
20 import org.hibernate.collection.internal.PersistentSortedSet;
21 import org.hibernate.collection.spi.PersistentCollection;
22 import org.hibernate.proxy.LazyInitializer;
23 import org.springframework.beans.factory.annotation.Autowire;
24 import org.springframework.beans.factory.annotation.Autowired;
25 import org.springframework.beans.factory.annotation.Configurable;
26 import org.springframework.stereotype.Component;
27
28 import eu.etaxonomy.cdm.api.service.ICommonService;
29 import eu.etaxonomy.cdm.model.common.CdmBase;
30 import eu.etaxonomy.cdm.model.common.PersistentMultiLanguageText;
31
32
33 @Aspect
34 @Component
35 @Configurable(autowire = Autowire.BY_TYPE)
36 public class CdmLazyLoader {
37
38
39 private final Set classes = new HashSet();
40
41 public static boolean enableWeaving = true;
42 private static Set<String> classesToIgnore = new HashSet<String>();
43
44
45 @Autowired
46 private ICommonService commonService;
47
48 public CdmLazyLoader() {
49 //classesToIgnore.add("eu.etaxonomy.cdm.model.common.TermVocabulary");
50 //classesToIgnore.add("eu.etaxonomy.cdm.model.common.OrderedTermVocabulary");
51
52 }
53
54 /**
55 * Point cut for the 'initialize' method of the AbstractLazyInitializer.
56 *
57 */
58 @Pointcut("execution(* org.hibernate.proxy.AbstractLazyInitializer.initialize())")
59 public void possibleEntityLazyInitializationException() {
60 }
61
62
63 /**
64 * 'Around' advice for the initialization of CDM Entity Objects
65 *
66 */
67 @Around(value = "possibleEntityLazyInitializationException()")
68 public Object preloadEntityOnDemand(ProceedingJoinPoint pjp) throws Throwable {
69 if(enableWeaving) {
70 LazyInitializer ll = (LazyInitializer)pjp.getTarget();
71 if(ll.isUninitialized()) {
72 int classid = ((Integer)ll.getIdentifier()).intValue();
73 System.out.print("--> AspectJ Compile-Time Weaving " + ll.getEntityName() + " with id " + classid);
74 Class clazz = Class.forName(ll.getEntityName());
75 CdmBase cdmBase = CdmBase.deproxy(commonService.find(clazz,classid),clazz);
76 ll.setImplementation(cdmBase);
77 System.out.println("....Done");
78 }
79 }
80 return pjp.proceed();
81 }
82
83
84 /**
85 * Point cut for the 'initialize' method of the AbstractPersistentCollection.
86 *
87 */
88 @Pointcut("execution(protected final void org.hibernate.collection.internal.AbstractPersistentCollection.initialize(..))")
89 public void possibleCollectionLazyInitializationException() {
90 }
91
92 /**
93 * 'Around' advice for the initialization of Collection objects
94 *
95 */
96 @Around(value = "possibleCollectionLazyInitializationException()")
97 public Object preloadCollectionOnDemand(ProceedingJoinPoint pjp) throws Throwable {
98 if(enableWeaving) {
99 PersistentCollection ps = (PersistentCollection) pjp.getTarget();
100 if (ps.getOwner() != null && !classesToIgnore.contains(ps.getOwner().getClass().getName()) && !ps.wasInitialized() && !classes.contains(ps.getKey())) {
101 System.out.print("--> AspectJCompile-Time Weaving " + ps.getRole());
102 classes.add(ps.getKey());
103 try {
104 String role = ps.getRole();
105 String fieldName = role.substring(role.lastIndexOf(".") + 1);
106 System.out.print(", field : " + fieldName);
107 Object owner = ps.getOwner();
108
109 Object col = commonService.initializeCollection(((CdmBase)owner).getUuid(), fieldName);
110 ps.afterInitialize();
111
112 // Class<?> clazz = ps.getClass();
113 // if (clazz != null) {
114 // CollectionField cf = getCollectionField(col);
115 // Field field = clazz.getDeclaredField(cf.getFieldName());
116 // field.setAccessible(true);
117 // field.set(ps, cf.getCollection());
118 // }
119
120 } catch (Exception ex) {
121 ex.printStackTrace();
122 System.out.println("Error in ReattachSessionAspect : " + ex.getMessage());
123 } finally {
124 classes.remove(ps.getKey());
125 System.out.println("....Done");
126 throw new Exception("This code is invalid");
127 }
128 }
129 }
130 return pjp.proceed();
131
132 }
133
134 private CollectionField getCollectionField(PersistentCollection pc) {
135 if(pc != null) {
136 if(pc instanceof PersistentSet) {
137 return new CollectionField(new HashSet((Set)pc), "set");
138 }
139 if(pc instanceof PersistentSortedSet) {
140 return new CollectionField(new TreeSet((Set)pc), "set");
141 }
142 if(pc instanceof PersistentList) {
143 return new CollectionField(new ArrayList((List)pc), "list");
144 }
145 if(pc instanceof PersistentMap || pc instanceof PersistentMultiLanguageText) {
146 return new CollectionField(new HashMap((Map)pc), "map");
147 }
148 if(pc instanceof PersistentSortedMap) {
149 return new CollectionField(new TreeMap((Map)pc), "map");
150 }
151 }
152 return null;
153 }
154
155 private String getCollectionFieldName(PersistentCollection pc) {
156 if(pc != null) {
157 if(pc instanceof PersistentSet || pc instanceof PersistentSortedSet) {
158 return "set";
159 }
160 if(pc instanceof PersistentList) {
161 return "list";
162 }
163 if(pc instanceof PersistentMap || pc instanceof PersistentMultiLanguageText) {
164 return "map";
165 }
166 }
167 return null;
168 }
169
170 private class CollectionField {
171 private final Object col;
172 private final String fieldName;
173 public CollectionField(Object col, String fieldName) {
174 this.col = col;
175 this.fieldName = fieldName;
176 }
177
178 public Object getCollection() {
179 return this.col;
180 }
181
182 public String getFieldName() {
183 return this.fieldName;
184 }
185 }
186
187 }