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<DatabaseMapping> mappingsToRemove = new ArrayList<DatabaseMapping>();
219 List<RemoveMapping> removeMappings = scanForRemoveMappings(classDescriptor);
220
221 for (RemoveMapping removeMapping : removeMappings) {
222 if (StringUtils.isBlank(removeMapping.name())) {
223 throw DescriptorException.attributeNameNotSpecified();
224 }
225
226 DatabaseMapping databaseMapping = classDescriptor.getMappingForAttributeName(removeMapping.name());
227
228 if (databaseMapping == null) {
229 throw DescriptorException.mappingForAttributeIsMissing(removeMapping.name(), classDescriptor);
230 }
231
232 mappingsToRemove.add(databaseMapping);
233 }
234
235 for (DatabaseMapping mappingToRemove : mappingsToRemove) {
236 classDescriptor.removeMappingForAttributeName(mappingToRemove.getAttributeName());
237 }
238 }
239 }
240
241
242
243
244
245
246
247 protected List<RemoveMapping> scanForRemoveMappings(ClassDescriptor classDescriptor) {
248 List<RemoveMapping> removeMappings = new ArrayList<RemoveMapping>();
249 RemoveMappings removeMappingsAnnotation = AnnotationUtils.findAnnotation(classDescriptor.getJavaClass(),
250 RemoveMappings.class);
251 if (removeMappingsAnnotation == null) {
252 RemoveMapping removeMappingAnnotation = AnnotationUtils.findAnnotation(classDescriptor.getJavaClass(),
253 RemoveMapping.class);
254 if (removeMappingAnnotation != null) {
255 removeMappings.add(removeMappingAnnotation);
256 }
257 } else {
258 for (RemoveMapping removeMapping : removeMappingsAnnotation.value()) {
259 removeMappings.add(removeMapping);
260 }
261 }
262 return removeMappings;
263 }
264
265
266
267
268
269
270
271 protected List<Sequence> loadSequences(Session session) {
272 Map<Class, ClassDescriptor> descriptors = session.getDescriptors();
273 List<PortableSequenceGenerator> sequenceGenerators = new ArrayList<PortableSequenceGenerator>();
274 for (Class<?> entityClass : descriptors.keySet()) {
275 PortableSequenceGenerator sequenceGenerator = AnnotationUtils.findAnnotation(entityClass,
276 PortableSequenceGenerator.class);
277 if (sequenceGenerator != null) {
278 sequenceGenerators.add(sequenceGenerator);
279 }
280 loadFieldSequences(entityClass, sequenceGenerators);
281 for (Method method : entityClass.getMethods()) {
282 PortableSequenceGenerator methodSequenceGenerator = method.getAnnotation(
283 PortableSequenceGenerator.class);
284 if (methodSequenceGenerator != null) {
285 sequenceGenerators.add(methodSequenceGenerator);
286 }
287 }
288 }
289 List<Sequence> sequences = new ArrayList<Sequence>();
290 for (PortableSequenceGenerator sequenceGenerator : sequenceGenerators) {
291 Sequence sequence = new MaxValueIncrementerSequenceWrapper(sequenceGenerator);
292 sequences.add(sequence);
293 }
294 return sequences;
295 }
296
297
298
299
300
301
302
303 protected void loadFieldSequences(Class<?> entityClass, List<PortableSequenceGenerator> sequenceGenerators) {
304 for (Field field : entityClass.getDeclaredFields()) {
305 PortableSequenceGenerator fieldSequenceGenerator = field.getAnnotation(PortableSequenceGenerator.class);
306 if (fieldSequenceGenerator != null) {
307 sequenceGenerators.add(fieldSequenceGenerator);
308 }
309 }
310
311 if (entityClass.getSuperclass() != null) {
312 loadFieldSequences(entityClass.getSuperclass(), sequenceGenerators);
313 }
314 }
315
316
317
318
319 private static final class MaxValueIncrementerSequenceWrapper extends Sequence {
320
321 private static final long serialVersionUID = 2375805962996574386L;
322
323 private final String sequenceName;
324
325
326
327
328
329
330 MaxValueIncrementerSequenceWrapper(PortableSequenceGenerator sequenceGenerator) {
331 super(sequenceGenerator.name(), 0);
332
333 if (StringUtils.isBlank(sequenceGenerator.sequenceName())) {
334 sequenceName = sequenceGenerator.name();
335 } else {
336 sequenceName = sequenceGenerator.sequenceName();
337 }
338 }
339
340
341
342
343 @Override
344 public boolean shouldAcquireValueAfterInsert() {
345 return false;
346 }
347
348
349
350
351 @Override
352 public boolean shouldUseTransaction() {
353 return true;
354 }
355
356
357
358
359 @Override
360 public boolean shouldUsePreallocation() {
361 return false;
362 }
363
364
365
366
367 @Override
368 public Object getGeneratedValue(Accessor accessor, AbstractSession writeSession, String seqName) {
369 DataSource dataSource = ((JNDIConnector) writeSession.getLogin().getConnector()).getDataSource();
370 DataFieldMaxValueIncrementer incrementer = MaxValueIncrementerFactory.getIncrementer(dataSource,
371 sequenceName);
372 return Long.valueOf(incrementer.nextLongValue());
373 }
374
375
376
377
378 @Override
379 public Vector<?> getGeneratedVector(Accessor accessor, AbstractSession writeSession, String seqName, int size) {
380
381 throw new UnsupportedOperationException(getClass().getName() + " does pre-generate sequence ids");
382 }
383
384
385
386
387 @Override
388 public void onConnect() {}
389
390
391
392
393 @Override
394 public void onDisconnect() {}
395
396
397
398
399 @Override
400 public MaxValueIncrementerSequenceWrapper clone() {
401 return (MaxValueIncrementerSequenceWrapper) super.clone();
402 }
403
404 }
405
406 }