1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.krad.data.jpa.eclipselink;
17
18 import org.apache.commons.lang.StringUtils;
19 import org.eclipse.persistence.config.SessionCustomizer;
20 import org.eclipse.persistence.descriptors.ClassDescriptor;
21 import org.eclipse.persistence.exceptions.DescriptorException;
22 import org.eclipse.persistence.internal.databaseaccess.Accessor;
23 import org.eclipse.persistence.internal.descriptors.OptimisticLockingPolicy;
24 import org.eclipse.persistence.internal.sessions.AbstractSession;
25 import org.eclipse.persistence.mappings.DatabaseMapping;
26 import org.eclipse.persistence.sequencing.Sequence;
27 import org.eclipse.persistence.sessions.DatabaseLogin;
28 import org.eclipse.persistence.sessions.JNDIConnector;
29 import org.eclipse.persistence.sessions.Session;
30 import org.kuali.rice.krad.data.jpa.DisableVersioning;
31 import org.kuali.rice.krad.data.jpa.Filter;
32 import org.kuali.rice.krad.data.jpa.FilterGenerator;
33 import org.kuali.rice.krad.data.jpa.FilterGenerators;
34 import org.kuali.rice.krad.data.jpa.PortableSequenceGenerator;
35 import org.kuali.rice.krad.data.jpa.RemoveMapping;
36 import org.kuali.rice.krad.data.jpa.RemoveMappings;
37 import org.kuali.rice.krad.data.platform.MaxValueIncrementerFactory;
38 import org.springframework.core.annotation.AnnotationUtils;
39 import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer;
40
41 import javax.sql.DataSource;
42 import java.lang.reflect.Field;
43 import java.lang.reflect.Method;
44 import java.util.ArrayList;
45 import java.util.Arrays;
46 import java.util.List;
47 import java.util.Map;
48 import java.util.Vector;
49 import java.util.concurrent.ConcurrentHashMap;
50 import java.util.concurrent.ConcurrentMap;
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65 public class KradEclipseLinkCustomizer implements SessionCustomizer {
66
67 private static ConcurrentMap<String, List<Sequence>> sequenceMap = new ConcurrentHashMap<String, List<Sequence>>(8,
68 0.9f, 1);
69
70
71 private static ConcurrentMap<String, Boolean> modDescMap = new ConcurrentHashMap<String, Boolean>();
72
73 private static ConcurrentMap<String, List<FilterGenerator>> queryCustomizerMap =
74 new ConcurrentHashMap<String, List<FilterGenerator>>();
75
76
77
78
79 @Override
80 public void customize(Session session) throws Exception {
81 String sessionName = session.getName();
82
83
84 List<Sequence> sequences = sequenceMap.get(sessionName);
85 if (sequences == null) {
86 sequences = sequenceMap.putIfAbsent(sessionName, loadSequences(session));
87 if (sequences == null) {
88 sequences = sequenceMap.get(sessionName);
89 }
90 }
91
92 loadQueryCustomizers(session);
93
94 DatabaseLogin login = session.getLogin();
95 for (Sequence sequence : sequences) {
96 login.addSequence(sequence);
97 }
98
99 handleDescriptorModifications(session);
100
101 }
102
103
104
105
106
107
108 protected void loadQueryCustomizers(Session session) {
109 Map<Class, ClassDescriptor> descriptors = session.getDescriptors();
110 for (Class<?> entityClass : descriptors.keySet()) {
111 for (Field field : entityClass.getDeclaredFields()) {
112 String queryCustEntry = entityClass.getName() + "_" + field.getName();
113 buildQueryCustomizers(entityClass,field,queryCustEntry);
114
115 List<FilterGenerator> queryCustomizers = queryCustomizerMap.get(queryCustEntry);
116 if (queryCustomizers != null && !queryCustomizers.isEmpty()) {
117 Filter.customizeField(queryCustomizers, descriptors.get(entityClass), field.getName());
118 }
119 }
120 }
121
122 }
123
124
125
126
127
128
129
130
131 protected void buildQueryCustomizers(Class<?> entityClass,Field field, String key){
132 FilterGenerators customizers = field.getAnnotation(FilterGenerators.class);
133 List<FilterGenerator> filterGenerators = new ArrayList<FilterGenerator>();
134 if(customizers != null){
135 filterGenerators.addAll(Arrays.asList(customizers.value()));
136 } else {
137 FilterGenerator customizer = field.getAnnotation(FilterGenerator.class);
138 if(customizer != null){
139 filterGenerators.add(customizer);
140 }
141 }
142 for(FilterGenerator customizer : filterGenerators){
143 List<FilterGenerator> filterCustomizers = queryCustomizerMap.get(key);
144 if (filterCustomizers == null) {
145 filterCustomizers =
146 new ArrayList<FilterGenerator>();
147 filterCustomizers.add(customizer);
148 queryCustomizerMap.putIfAbsent(key, filterCustomizers);
149 } else {
150 filterCustomizers.add(customizer);
151 queryCustomizerMap.put(key,filterCustomizers);
152 }
153 }
154 }
155
156
157
158
159
160
161 protected void handleDescriptorModifications(Session session) {
162 String sessionName = session.getName();
163
164
165 Boolean descModified = modDescMap.get(sessionName);
166 if (descModified == null) {
167 descModified = modDescMap.putIfAbsent(sessionName, Boolean.FALSE);
168 if (descModified == null) {
169 descModified = modDescMap.get(sessionName);
170 }
171 }
172
173 if (Boolean.FALSE.equals(descModified)) {
174 modDescMap.put(sessionName, Boolean.TRUE);
175 handleDisableVersioning(session);
176 handleRemoveMapping(session);
177 }
178 }
179
180
181
182
183
184
185
186 protected void handleDisableVersioning(Session session) {
187 Map<Class, ClassDescriptor> descriptors = session.getDescriptors();
188
189 if (descriptors == null || descriptors.isEmpty()) {
190 return;
191 }
192
193 for (ClassDescriptor classDescriptor : descriptors.values()) {
194 if (classDescriptor != null && AnnotationUtils.findAnnotation(classDescriptor.getJavaClass(),
195 DisableVersioning.class) != null) {
196 OptimisticLockingPolicy olPolicy = classDescriptor.getOptimisticLockingPolicy();
197 if (olPolicy != null) {
198 classDescriptor.setOptimisticLockingPolicy(null);
199 }
200 }
201 }
202 }
203
204
205
206
207
208
209
210 protected void handleRemoveMapping(Session session) {
211 Map<Class, ClassDescriptor> descriptors = session.getDescriptors();
212
213 if (descriptors == null || descriptors.isEmpty()) {
214 return;
215 }
216
217 for (ClassDescriptor classDescriptor : descriptors.values()) {
218 List<RemoveMapping> removeMappings = scanForRemoveMappings(classDescriptor);
219 if (!removeMappings.isEmpty()) {
220 List<DatabaseMapping> mappingsToRemove = new ArrayList<DatabaseMapping>();
221 for (RemoveMapping removeMapping : removeMappings) {
222 if (StringUtils.isBlank(removeMapping.name())) {
223 throw DescriptorException.attributeNameNotSpecified();
224 }
225 DatabaseMapping databaseMapping = classDescriptor.getMappingForAttributeName(removeMapping.name());
226 if (databaseMapping == null) {
227 throw DescriptorException.mappingForAttributeIsMissing(removeMapping.name(), classDescriptor);
228 }
229 mappingsToRemove.add(databaseMapping);
230 }
231 for (DatabaseMapping mappingToRemove : mappingsToRemove) {
232 classDescriptor.removeMappingForAttributeName(mappingToRemove.getAttributeName());
233 }
234 }
235 }
236 }
237
238
239
240
241
242
243
244 protected List<RemoveMapping> scanForRemoveMappings(ClassDescriptor classDescriptor) {
245 List<RemoveMapping> removeMappings = new ArrayList<RemoveMapping>();
246 RemoveMappings removeMappingsAnnotation = AnnotationUtils.findAnnotation(classDescriptor.getJavaClass(),
247 RemoveMappings.class);
248 if (removeMappingsAnnotation == null) {
249 RemoveMapping removeMappingAnnotation = AnnotationUtils.findAnnotation(classDescriptor.getJavaClass(),
250 RemoveMapping.class);
251 if (removeMappingAnnotation != null) {
252 removeMappings.add(removeMappingAnnotation);
253 }
254 } else {
255 for (RemoveMapping removeMapping : removeMappingsAnnotation.value()) {
256 removeMappings.add(removeMapping);
257 }
258 }
259 return removeMappings;
260 }
261
262
263
264
265
266
267
268 protected List<Sequence> loadSequences(Session session) {
269 Map<Class, ClassDescriptor> descriptors = session.getDescriptors();
270 List<PortableSequenceGenerator> sequenceGenerators = new ArrayList<PortableSequenceGenerator>();
271 for (Class<?> entityClass : descriptors.keySet()) {
272 PortableSequenceGenerator sequenceGenerator = AnnotationUtils.findAnnotation(entityClass,
273 PortableSequenceGenerator.class);
274 if (sequenceGenerator != null) {
275 sequenceGenerators.add(sequenceGenerator);
276 }
277 loadFieldSequences(entityClass, sequenceGenerators);
278 for (Method method : entityClass.getMethods()) {
279 PortableSequenceGenerator methodSequenceGenerator = method.getAnnotation(
280 PortableSequenceGenerator.class);
281 if (methodSequenceGenerator != null) {
282 sequenceGenerators.add(methodSequenceGenerator);
283 }
284 }
285 }
286 List<Sequence> sequences = new ArrayList<Sequence>();
287 for (PortableSequenceGenerator sequenceGenerator : sequenceGenerators) {
288 Sequence sequence = new MaxValueIncrementerSequenceWrapper(sequenceGenerator);
289 sequences.add(sequence);
290 }
291 return sequences;
292 }
293
294
295
296
297
298
299
300 protected void loadFieldSequences(Class<?> entityClass, List<PortableSequenceGenerator> sequenceGenerators) {
301 for (Field field : entityClass.getDeclaredFields()) {
302 PortableSequenceGenerator fieldSequenceGenerator = field.getAnnotation(PortableSequenceGenerator.class);
303 if (fieldSequenceGenerator != null) {
304 sequenceGenerators.add(fieldSequenceGenerator);
305 }
306 }
307
308 if (entityClass.getSuperclass() != null) {
309 loadFieldSequences(entityClass.getSuperclass(), sequenceGenerators);
310 }
311 }
312
313
314
315
316 private static final class MaxValueIncrementerSequenceWrapper extends Sequence {
317
318 private static final long serialVersionUID = 2375805962996574386L;
319
320 private final String sequenceName;
321
322
323
324
325
326
327 MaxValueIncrementerSequenceWrapper(PortableSequenceGenerator sequenceGenerator) {
328 super(sequenceGenerator.name(), 0);
329
330 if (StringUtils.isBlank(sequenceGenerator.sequenceName())) {
331 sequenceName = sequenceGenerator.name();
332 } else {
333 sequenceName = sequenceGenerator.sequenceName();
334 }
335 }
336
337
338
339
340 @Override
341 public boolean shouldAcquireValueAfterInsert() {
342 return false;
343 }
344
345
346
347
348 @Override
349 public boolean shouldUseTransaction() {
350 return true;
351 }
352
353
354
355
356 @Override
357 public boolean shouldUsePreallocation() {
358 return false;
359 }
360
361
362
363
364 @Override
365 public Object getGeneratedValue(Accessor accessor, AbstractSession writeSession, String seqName) {
366 DataSource dataSource = ((JNDIConnector) writeSession.getLogin().getConnector()).getDataSource();
367 DataFieldMaxValueIncrementer incrementer = MaxValueIncrementerFactory.getIncrementer(dataSource,
368 sequenceName);
369 return Long.valueOf(incrementer.nextLongValue());
370 }
371
372
373
374
375 @Override
376 public Vector<?> getGeneratedVector(Accessor accessor, AbstractSession writeSession, String seqName, int size) {
377
378 throw new UnsupportedOperationException(getClass().getName() + " does pre-generate sequence ids");
379 }
380
381
382
383
384 @Override
385 public void onConnect() {}
386
387
388
389
390 @Override
391 public void onDisconnect() {}
392
393
394
395
396 @Override
397 public MaxValueIncrementerSequenceWrapper clone() {
398 return (MaxValueIncrementerSequenceWrapper) super.clone();
399 }
400
401 }
402
403 }