1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.kns.dao.impl;
17
18 import java.lang.reflect.Field;
19 import java.util.Collection;
20 import java.util.HashMap;
21 import java.util.List;
22 import java.util.Map;
23
24 import javax.persistence.EntityManager;
25 import javax.persistence.EntityNotFoundException;
26 import javax.persistence.PersistenceContext;
27
28 import org.apache.commons.lang.StringUtils;
29 import org.hibernate.proxy.HibernateProxy;
30 import org.kuali.rice.core.framework.persistence.jpa.metadata.CollectionDescriptor;
31 import org.kuali.rice.core.framework.persistence.jpa.metadata.EntityDescriptor;
32 import org.kuali.rice.core.framework.persistence.jpa.metadata.JoinColumnDescriptor;
33 import org.kuali.rice.core.framework.persistence.jpa.metadata.MetadataManager;
34 import org.kuali.rice.core.framework.persistence.jpa.metadata.ObjectDescriptor;
35 import org.kuali.rice.kns.dao.PersistenceDao;
36 import org.kuali.rice.kns.service.KNSServiceLocator;
37
38 public class PersistenceDaoJpa implements PersistenceDao {
39 static org.apache.commons.logging.Log LOG = org.apache.commons.logging.LogFactory.getLog(PersistenceDaoJpa.class);
40
41 @PersistenceContext
42 private EntityManager entityManager;
43
44
45
46
47 public void clearCache() {}
48
49
50
51
52 public Object resolveProxy(Object o) {
53 if (o instanceof HibernateProxy) {
54 try {
55 final Object realObject = ((HibernateProxy) o).getHibernateLazyInitializer().getImplementation();
56 return realObject;
57 } catch (EntityNotFoundException enfe) {
58 return null;
59 }
60 }
61 return o;
62 }
63
64
65
66
67 public void retrieveAllReferences(Object o) {
68 EntityDescriptor ed = MetadataManager.getEntityDescriptor(o.getClass());
69 for (ObjectDescriptor od : ed.getObjectRelationships()) {
70 retrieveReference(o, od.getAttributeName());
71 }
72 for (CollectionDescriptor cd : ed.getCollectionRelationships()) {
73 retrieveReference(o, cd.getAttributeName());
74 }
75 }
76
77
78
79
80 public void retrieveReference(Object o, String referenceName) {
81 try {
82 if (getEntityManager().contains(o)) {
83 LOG.debug("the entity manager contains the object");
84 }
85
86 Field field = getField(o.getClass(), referenceName);
87 field.setAccessible(true);
88
89 String fk = null;
90 String foreignPK = null;
91
92 if (isReferenceCollection(o, referenceName)) {
93 Collection reference = retrieveCollectionReference(o, referenceName);
94 field.set(o, reference);
95 } else {
96 Object reference = retrieveObjectReference(o, referenceName);
97 field.set(o, reference);
98 }
99 } catch (Exception e) {
100 e.printStackTrace();
101 }
102 }
103
104 private Field getField(Class clazz, String name) throws NoSuchFieldException {
105 if (clazz.equals(Object.class)) {
106 throw new NoSuchFieldException(name);
107 }
108 Field field = null;
109 try {
110 field = clazz.getDeclaredField(name);
111 } catch (Exception e) {}
112 if (field == null) {
113 field = getField(clazz.getSuperclass(), name);
114 }
115 return field;
116 }
117
118
119
120
121
122
123
124
125 protected boolean isReferenceCollection(Object o, String referenceName) {
126 EntityDescriptor ed = MetadataManager.getEntityDescriptor(o.getClass());
127 return ed.getCollectionDescriptorByName(referenceName) != null;
128 }
129
130
131
132
133
134
135
136
137
138
139
140 protected Collection retrieveCollectionReference(Object o, String referenceName) throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
141 final EntityDescriptor ed = MetadataManager.getEntityDescriptor(o.getClass());
142 final CollectionDescriptor cd = ed.getCollectionDescriptorByName(referenceName);
143 final EntityDescriptor foreignEntityDescriptor = MetadataManager.getEntityDescriptor(cd.getTargetEntity());
144
145 Map<String, Object> searchKey = new HashMap<String, Object>();
146 for (String foreignKey : cd.getForeignKeyFields()) {
147 Field localField = getField(o.getClass(), foreignKey);
148 localField.setAccessible(true);
149 final Object localValue = localField.get(o);
150
151 final String foreignKeyProperty = getForeignKeyPropertyForKeyWithPossibleInverse(foreignKey, ed, foreignEntityDescriptor, cd);
152
153 searchKey.put(foreignKeyProperty, localValue);
154 }
155 return KNSServiceLocator.getBusinessObjectService().findMatching(cd.getTargetEntity(), searchKey);
156 }
157
158
159
160
161
162
163
164
165
166
167 protected String getForeignKeyPropertyForKeyWithPossibleInverse(String foreignKey, EntityDescriptor localEntityDescriptor, EntityDescriptor foreignEntityDescriptor, CollectionDescriptor collectionDescriptor) {
168 final String foreignKeyColumn = localEntityDescriptor.getFieldByName(foreignKey).getColumn();
169
170 int count = 0;
171 JoinColumnDescriptor joinColumnDescriptor = null;
172 JoinColumnDescriptor inverseColumnDescriptor = null;
173 while (count < collectionDescriptor.getJoinColumnDescriptors().size() && joinColumnDescriptor == null) {
174 if (collectionDescriptor.getJoinColumnDescriptors().get(count).getName().equalsIgnoreCase(foreignKeyColumn)) {
175 joinColumnDescriptor = collectionDescriptor.getJoinColumnDescriptors().get(count);
176 if (count < collectionDescriptor.getInverseJoinColumnDescriptors().size()) {
177 inverseColumnDescriptor = collectionDescriptor.getInverseJoinColumnDescriptors().get(count);
178 }
179 }
180 count += 1;
181 }
182
183 if (inverseColumnDescriptor != null) {
184 return foreignEntityDescriptor.getFieldByColumnName(inverseColumnDescriptor.getName()).getName();
185 }
186
187 if (!StringUtils.isBlank(joinColumnDescriptor.getReferencedColumName())) {
188 return foreignEntityDescriptor.getFieldByColumnName(joinColumnDescriptor.getReferencedColumName()).getName();
189 }
190
191 return foreignEntityDescriptor.getFieldByColumnName(joinColumnDescriptor.getName()).getName();
192
193 }
194
195
196
197
198
199
200
201
202
203
204
205
206
207 protected Object retrieveObjectReference(Object o, String referenceName) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, InstantiationException, ClassNotFoundException {
208 final EntityDescriptor ed = MetadataManager.getEntityDescriptor(o.getClass());
209 final ObjectDescriptor od = ed.getObjectDescriptorByName(referenceName);
210
211 final Object foreignKeyObject = buildForeignKeyObject(o, ed, od);
212 return getEntityManager().find(od.getTargetEntity(), foreignKeyObject);
213 }
214
215
216
217
218
219
220
221
222
223
224
225
226
227 protected Object buildForeignKeyObject(Object o, EntityDescriptor localEntityDescriptor, ObjectDescriptor objectDescriptor) throws IllegalArgumentException, NoSuchFieldException, IllegalAccessException, InstantiationException {
228 return (objectDescriptor.getForeignKeyFields().size() == 1) ?
229 buildSingleKeyForeignKeyObject(o, objectDescriptor.getForeignKeyFields().get(0)) :
230 buildCompositeForeignKeyObject(o, localEntityDescriptor, objectDescriptor);
231 }
232
233
234
235
236
237
238
239
240
241
242
243
244 private Object buildCompositeForeignKeyObject(Object o, EntityDescriptor localEntityDescriptor, ObjectDescriptor objectDescriptor) throws InstantiationException, IllegalAccessException, NoSuchFieldException {
245 final Map<String, JoinColumnDescriptor> joinColumnDescriptors = buildJoinColumnDescriptorMap(objectDescriptor.getJoinColumnDescriptors());
246
247 final EntityDescriptor foreignEntityDescriptor = MetadataManager.getEntityDescriptor(objectDescriptor.getTargetEntity());
248 final Class foreignEntityIdClass = foreignEntityDescriptor.getIdClass();
249
250 Object foreignEntityId = foreignEntityIdClass.newInstance();
251 for (String foreignKey : objectDescriptor.getForeignKeyFields()) {
252
253 Field localField = getField(o.getClass(), foreignKey);
254 localField.setAccessible(true);
255 final Object localValue = localField.get(o);
256
257 final String foreignKeyProperty = getForeignKeyPropertyForKey(foreignKey, localEntityDescriptor, foreignEntityDescriptor, joinColumnDescriptors);
258
259 Field foreignField = getField(foreignEntityId.getClass(), foreignKeyProperty);
260 foreignField.setAccessible(true);
261 foreignField.set(foreignEntityId, localValue);
262 }
263 return foreignEntityId;
264 }
265
266
267
268
269
270
271
272
273
274
275 protected String getForeignKeyPropertyForKey(String foreignKey, EntityDescriptor localEntityDescriptor, EntityDescriptor foreignEntityDescriptor, Map<String, JoinColumnDescriptor> joinColumnDescriptors) {
276 final String foreignKeyColumn = localEntityDescriptor.getFieldByName(foreignKey).getColumn();
277 final JoinColumnDescriptor joinColumnDescriptor = joinColumnDescriptors.get(foreignKeyColumn);
278
279 return (!StringUtils.isBlank(joinColumnDescriptor.getReferencedColumName())) ?
280 foreignEntityDescriptor.getFieldByColumnName(joinColumnDescriptor.getReferencedColumName()).getName() :
281 foreignEntityDescriptor.getFieldByColumnName(joinColumnDescriptor.getName()).getName();
282
283 }
284
285
286
287
288
289
290
291 protected Map<String, JoinColumnDescriptor> buildJoinColumnDescriptorMap(List<JoinColumnDescriptor> joinColumnDescriptors) {
292 Map<String, JoinColumnDescriptor> descriptorMap = new HashMap<String, JoinColumnDescriptor>();
293 for (JoinColumnDescriptor joinColumnDescriptor : joinColumnDescriptors) {
294 descriptorMap.put(joinColumnDescriptor.getName(), joinColumnDescriptor);
295 }
296 return descriptorMap;
297 }
298
299
300
301
302
303
304
305
306
307
308
309 protected Object buildSingleKeyForeignKeyObject(Object o, String singleForeignKeyFieldName) throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
310 Field singleFKField = getField(o.getClass(), singleForeignKeyFieldName);
311 singleFKField.setAccessible(true);
312 return singleFKField.get(o);
313 }
314
315
316
317
318
319
320 public boolean isProxied(Object object) {
321 return (object instanceof HibernateProxy);
322 }
323
324
325
326
327 public EntityManager getEntityManager() {
328 return this.entityManager;
329 }
330
331
332
333
334 public void setEntityManager(EntityManager entityManager) {
335 this.entityManager = entityManager;
336 }
337 }