1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.krad.data.provider.impl;
17
18 import java.util.Set;
19
20 import org.kuali.rice.core.api.criteria.QueryByCriteria;
21 import org.kuali.rice.core.api.criteria.QueryResults;
22 import org.kuali.rice.krad.data.CompoundKey;
23 import org.kuali.rice.krad.data.CopyOption;
24 import org.kuali.rice.krad.data.DataObjectService;
25 import org.kuali.rice.krad.data.DataObjectWrapper;
26 import org.kuali.rice.krad.data.PersistenceOption;
27 import org.kuali.rice.krad.data.metadata.DataObjectAttributeRelationship;
28 import org.kuali.rice.krad.data.metadata.DataObjectMetadata;
29 import org.kuali.rice.krad.data.metadata.DataObjectRelationship;
30 import org.kuali.rice.krad.data.metadata.MetadataChild;
31 import org.kuali.rice.krad.data.metadata.MetadataRepository;
32 import org.kuali.rice.krad.data.provider.PersistenceProvider;
33 import org.kuali.rice.krad.data.provider.ProviderRegistry;
34 import org.kuali.rice.krad.data.util.ReferenceLinker;
35 import org.springframework.beans.factory.annotation.Required;
36 import org.springframework.dao.IncorrectResultSizeDataAccessException;
37
38 import com.google.common.collect.Sets;
39
40
41
42
43
44
45 public class ProviderBasedDataObjectService implements DataObjectService {
46 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger
47 .getLogger(ProviderBasedDataObjectService.class);
48
49
50
51
52 protected ProviderRegistry providerRegistry;
53
54
55
56
57 protected MetadataRepository metadataRepository;
58
59
60
61
62 protected ReferenceLinker referenceLinker;
63
64
65
66
67 @Override
68 public <T> T find(Class<T> type, Object id) {
69 return persistenceProviderForType(type).find(type, reduceCompoundKey(id));
70 }
71
72
73
74
75
76
77
78
79
80
81 protected Object reduceCompoundKey(Object id) {
82 if (id instanceof CompoundKey) {
83 CompoundKey compoundKey = (CompoundKey)id;
84 if (compoundKey.getKeys().size() == 1) {
85 id = compoundKey.getKeys().values().iterator().next();
86 }
87 }
88 return id;
89 }
90
91
92
93
94 @Override
95 public <T> QueryResults<T> findMatching(Class<T> type, QueryByCriteria queryByCriteria) {
96 return persistenceProviderForType(type).findMatching(type, queryByCriteria);
97 }
98
99
100
101
102 @Override
103 public <T> QueryResults<T> findAll(Class<T> type) {
104 return persistenceProviderForType(type).findAll(type);
105 }
106
107
108
109
110 @Override
111 public <T> T findUnique(Class<T> type, QueryByCriteria queryByCriteria) {
112 QueryResults<T> results = findMatching(type, queryByCriteria);
113 if (results.getResults().isEmpty()) {
114 return null;
115 } else if (results.getResults().size() > 1) {
116 throw new IncorrectResultSizeDataAccessException("Attempted to find single result but found more than "
117 + "one for class " + type + " and criteria " + queryByCriteria, 1, results.getResults().size());
118 } else {
119 return results.getResults().get(0);
120 }
121 }
122
123
124
125
126 @Override
127 public void delete(Object dataObject) {
128 persistenceProviderForObject(dataObject).delete(dataObject);
129 }
130
131
132
133
134 @Override
135 public <T> void deleteMatching(Class<T> type, QueryByCriteria queryByCriteria) {
136 persistenceProviderForType(type).deleteMatching(type, queryByCriteria);
137 }
138
139
140
141
142
143 @Override
144 public <T> void deleteAll(Class<T> type) {
145 persistenceProviderForType(type).deleteAll(type);
146 }
147
148
149
150
151 @Override
152 public <T> T save(T dataObject, PersistenceOption... options) {
153 Set<PersistenceOption> optionSet = Sets.newHashSet(options);
154 pushOneToOneKeysToChildObjects(dataObject);
155 T saved = persistenceProviderForObject(dataObject).save(dataObject, options);
156 if (optionSet.contains(PersistenceOption.LINK_KEYS)) {
157 DataObjectWrapper<T> wrapper = wrap(saved);
158 wrapper.linkForeignKeys(true);
159 }
160 return saved;
161 }
162
163 protected void pushOneToOneKeysToChildObjects(Object dataObject) {
164 DataObjectWrapper<Object> wrappedParent = wrap(dataObject);
165 if (wrappedParent.getMetadata() == null) {
166 return;
167 }
168
169 for (DataObjectRelationship rel : wrappedParent.getMetadata().getRelationships()) {
170
171 if (rel.isSavedWithParent() && rel.isDeletedWithParent()) {
172 Object child = wrappedParent.getPropertyValueNullSafe(rel.getName());
173
174 if (child == null) {
175 continue;
176 }
177 DataObjectWrapper<Object> wrappedChild = wrap(child);
178
179
180
181
182
183
184
185
186 MetadataChild inverseRelationship = rel.getInverseRelationship();
187 if (inverseRelationship != null && inverseRelationship instanceof DataObjectRelationship) {
188 try {
189 wrappedChild.setPropertyValue(inverseRelationship.getName(), dataObject);
190 for (DataObjectAttributeRelationship attr : inverseRelationship.getAttributeRelationships()) {
191
192
193
194 wrappedChild.setPropertyValue(attr.getParentAttributeName(),
195 wrappedParent.getPropertyValueNullSafe(attr.getChildAttributeName()));
196 }
197 } catch (Exception ex) {
198 LOG.warn("Unable to set 1:1 child keys. Persistance of child object may not be correct. Parent Object.property: "
199 + dataObject.getClass().getName()
200 + "."
201 + rel.getName()
202 + " / Child Type: "
203 + child.getClass().getName(), ex);
204 }
205 }
206 }
207 }
208
209 }
210
211
212
213
214 @Override
215 public MetadataRepository getMetadataRepository() {
216 return metadataRepository;
217 }
218
219
220
221
222 @Override
223 public <T> T copyInstance(T dataObject, CopyOption... options) {
224 return persistenceProviderForObject(dataObject).copyInstance(dataObject, options);
225 }
226
227
228
229
230 @Override
231 public <T> DataObjectWrapper<T> wrap(T dataObject) {
232 if (dataObject == null) {
233 throw new IllegalArgumentException("data object was null");
234 }
235 DataObjectMetadata metadata = getMetadataRepository().getMetadata(dataObject.getClass());
236
237
238 if (metadata == null) {
239 LOG.warn("Non KRAD Data object passed - no metadata found for: " + dataObject.getClass());
240
241
242 }
243 return new DataObjectWrapperImpl<T>(dataObject, metadata, this, referenceLinker);
244 }
245
246
247
248
249 @Override
250 public <T> boolean supports(Class<T> type) {
251 return providerRegistry.getPersistenceProvider(type) != null;
252 }
253
254
255
256
257
258
259
260
261
262
263 protected PersistenceProvider persistenceProviderForType(Class<?> type) {
264 PersistenceProvider provider = providerRegistry.getPersistenceProvider(type);
265 if (provider == null) {
266 throw new RuntimeException("No PersistenceProvider handles type: " + type);
267 }
268 return provider;
269 }
270
271
272
273
274
275
276
277
278
279
280
281 protected PersistenceProvider persistenceProviderForObject(Object object) {
282 if (object == null) {
283 throw new IllegalArgumentException("data object was null");
284 }
285 return persistenceProviderForType(object.getClass());
286 }
287
288
289
290
291 @Override
292 public void flush(Class<?> type){
293 PersistenceProvider persistenceProvider = persistenceProviderForType(type);
294 if (persistenceProvider == null) {
295 throw new RuntimeException("No PersistenceProvider handles type: " + type);
296 }
297 persistenceProvider.flush(type);
298 }
299
300
301
302
303
304
305 @Required
306 public void setProviderRegistry(ProviderRegistry providerRegistry) {
307 this.providerRegistry = providerRegistry;
308 }
309
310
311
312
313
314
315 @Required
316 public void setMetadataRepository(MetadataRepository metadataRepository) {
317 this.metadataRepository = metadataRepository;
318 }
319
320
321
322
323
324
325 public ReferenceLinker getReferenceLinker() {
326 return referenceLinker;
327 }
328
329
330
331
332
333
334 @Required
335 public void setReferenceLinker(ReferenceLinker referenceLinker) {
336 this.referenceLinker = referenceLinker;
337 }
338
339
340
341
342
343 private static final class DataObjectWrapperImpl<T> extends DataObjectWrapperBase<T> {
344
345
346
347
348
349
350
351
352
353 private DataObjectWrapperImpl(T dataObject, DataObjectMetadata metadata, DataObjectService dataObjectService,
354 ReferenceLinker referenceLinker) {
355 super(dataObject, metadata, dataObjectService, referenceLinker);
356 }
357 }
358
359 }