1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.krad.inquiry;
17
18 import org.apache.commons.lang.StringUtils;
19 import org.kuali.rice.core.api.CoreApiServiceLocator;
20 import org.kuali.rice.core.api.encryption.EncryptionService;
21 import org.kuali.rice.krad.bo.BusinessObject;
22 import org.kuali.rice.krad.bo.DocumentHeader;
23 import org.kuali.rice.krad.bo.ExternalizableBusinessObject;
24 import org.kuali.rice.krad.data.CompoundKey;
25 import org.kuali.rice.krad.data.KradDataServiceLocator;
26 import org.kuali.rice.krad.datadictionary.exception.UnknownBusinessClassAttributeException;
27 import org.kuali.rice.krad.service.DataDictionaryService;
28 import org.kuali.rice.krad.service.DataObjectAuthorizationService;
29 import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
30 import org.kuali.rice.krad.service.KualiModuleService;
31 import org.kuali.rice.krad.service.LegacyDataAdapter;
32 import org.kuali.rice.krad.service.ModuleService;
33 import org.kuali.rice.krad.uif.service.impl.ViewHelperServiceImpl;
34 import org.kuali.rice.krad.uif.widget.Inquiry;
35 import org.kuali.rice.krad.util.ExternalizableBusinessObjectUtils;
36 import org.kuali.rice.krad.util.KRADConstants;
37 import org.kuali.rice.krad.util.KRADUtils;
38 import org.springframework.beans.PropertyAccessorUtils;
39
40 import java.security.GeneralSecurityException;
41 import java.util.ArrayList;
42 import java.util.Collections;
43 import java.util.HashMap;
44 import java.util.List;
45 import java.util.Map;
46
47
48
49
50
51
52
53
54
55
56
57
58
59 public class InquirableImpl extends ViewHelperServiceImpl implements Inquirable {
60 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(InquirableImpl.class);
61
62 protected Class<?> dataObjectClass;
63
64
65
66
67
68
69
70 public static List<Class<?>> SUPER_CLASS_TRANSLATOR_LIST = new ArrayList<Class<?>>();
71
72
73
74
75
76
77
78
79
80
81
82
83
84 @Override
85 public Object retrieveDataObject(Map<String, String> parameters) {
86 if (dataObjectClass == null) {
87 LOG.error("Data object class must be set in inquirable before retrieving the object");
88 throw new RuntimeException("Data object class must be set in inquirable before retrieving the object");
89 }
90
91
92 List<String> pkPropertyNames = getLegacyDataAdapter().listPrimaryKeyFieldNames(dataObjectClass);
93
94
95 List<List<String>> alternateKeyNameSets = getAlternateKeysForClass(dataObjectClass);
96
97
98 alternateKeyNameSets.add(0, pkPropertyNames);
99
100 List<String> dataObjectKeySet = retrieveKeySetFromMap(alternateKeyNameSets, parameters);
101 if ((dataObjectKeySet == null) || dataObjectKeySet.isEmpty()) {
102 LOG.warn("Matching key set not found in request for class: " + getDataObjectClass());
103
104 return null;
105 }
106
107
108 Map<String, String> keyPropertyValues = new HashMap<String, String>();
109 for (String keyPropertyName : dataObjectKeySet) {
110 String keyPropertyValue = parameters.get(keyPropertyName);
111
112
113 Boolean forceUppercase = Boolean.FALSE;
114 try {
115 forceUppercase = getDataDictionaryService().getAttributeForceUppercase(dataObjectClass,
116 keyPropertyName);
117 } catch (UnknownBusinessClassAttributeException ex) {
118
119
120 LOG.warn("Data object class "
121 + dataObjectClass
122 + " property "
123 + keyPropertyName
124 + " should probably have a DD definition.", ex);
125 }
126
127 if (forceUppercase.booleanValue() && (keyPropertyValue != null)) {
128 keyPropertyValue = keyPropertyValue.toUpperCase();
129 }
130
131
132 if (getDataObjectAuthorizationService().attributeValueNeedsToBeEncryptedOnFormsAndLinks(dataObjectClass,
133 keyPropertyName)) {
134 try {
135 if(CoreApiServiceLocator.getEncryptionService().isEnabled()) {
136 keyPropertyValue = getEncryptionService().decrypt(keyPropertyValue);
137 }
138 } catch (GeneralSecurityException e) {
139 LOG.error("Data object class "
140 + dataObjectClass
141 + " property "
142 + keyPropertyName
143 + " should have been encrypted, but there was a problem decrypting it.", e);
144 throw new RuntimeException("Data object class "
145 + dataObjectClass
146 + " property "
147 + keyPropertyName
148 + " should have been encrypted, but there was a problem decrypting it.", e);
149 }
150 }
151
152 keyPropertyValues.put(keyPropertyName, keyPropertyValue);
153 }
154
155
156 Object dataObject = null;
157
158 Map<String, Object> translatedValues = KRADUtils.coerceRequestParameterTypes(
159 (Class<? extends ExternalizableBusinessObject>) getDataObjectClass(), keyPropertyValues);
160
161 ModuleService moduleService = KRADServiceLocatorWeb.getKualiModuleService().getResponsibleModuleService(
162 getDataObjectClass());
163 if (moduleService != null && moduleService.isExternalizable(getDataObjectClass())) {
164 dataObject = moduleService.getExternalizableBusinessObject(getDataObjectClass().asSubclass(
165 ExternalizableBusinessObject.class), translatedValues);
166 } else if ( KradDataServiceLocator.getDataObjectService().supports(getDataObjectClass())) {
167 dataObject = KradDataServiceLocator.getDataObjectService().find(getDataObjectClass(), new CompoundKey(translatedValues));
168 } else if (BusinessObject.class.isAssignableFrom(getDataObjectClass())) {
169 dataObject = getLegacyDataAdapter().findByPrimaryKey(getDataObjectClass().asSubclass(
170 BusinessObject.class), translatedValues);
171 } else {
172 throw new IllegalArgumentException( "ERROR: Unsupported object type passed to inquiry: " + getDataObjectClass() + " / keys=" + keyPropertyValues );
173 }
174 return dataObject;
175 }
176
177
178
179
180
181
182
183
184
185
186 protected List<String> retrieveKeySetFromMap(List<List<String>> potentialKeySets, Map<String, String> parameters) {
187 List<String> foundKeySet = null;
188
189 for (List<String> potentialKeySet : potentialKeySets) {
190 boolean keySetMatch = true;
191 for (String keyName : potentialKeySet) {
192 if (!parameters.containsKey(keyName) || StringUtils.isBlank(parameters.get(keyName))) {
193 keySetMatch = false;
194 }
195 }
196
197 if (keySetMatch) {
198 foundKeySet = potentialKeySet;
199 break;
200 }
201 }
202
203 return foundKeySet;
204 }
205
206
207
208
209
210
211
212
213 protected List<List<String>> getAlternateKeysForClass(Class<?> clazz) {
214 KualiModuleService kualiModuleService = getKualiModuleService();
215 ModuleService moduleService = kualiModuleService.getResponsibleModuleService(clazz);
216
217 List<List<String>> altKeys = null;
218 if (moduleService != null) {
219 altKeys = moduleService.listAlternatePrimaryKeyFieldNames(clazz);
220 }
221
222 return altKeys != null ? altKeys : new ArrayList<List<String>>();
223 }
224
225
226
227
228
229 @Override
230 public void buildInquirableLink(Object dataObject, String propertyName, Inquiry inquiry) {
231 Class<?> inquiryObjectClass = null;
232
233
234 Class<?> objectClass = KRADUtils.materializeClassForProxiedObject(dataObject);
235 if (propertyName.equals(KRADServiceLocatorWeb.getLegacyDataAdapter().getTitleAttribute(objectClass))) {
236 inquiryObjectClass = objectClass;
237 } else if (PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName)) {
238 String nestedPropertyName = KRADUtils.getNestedAttributePrefix(propertyName);
239 Object nestedPropertyObject = KRADUtils.getNestedValue(dataObject, nestedPropertyName);
240
241 if (KRADUtils.isNotNull(nestedPropertyObject)) {
242 String nestedPropertyPrimitive = KRADUtils.getNestedAttributePrimitive(propertyName);
243 Class<?> nestedPropertyObjectClass = KRADUtils.materializeClassForProxiedObject(nestedPropertyObject);
244
245 if (nestedPropertyPrimitive.equals(KRADServiceLocatorWeb.getLegacyDataAdapter().getTitleAttribute(
246 nestedPropertyObjectClass))) {
247 inquiryObjectClass = nestedPropertyObjectClass;
248 }
249 }
250 }
251
252
253 if (inquiryObjectClass == null) {
254 inquiryObjectClass = getLegacyDataAdapter().getInquiryObjectClassIfNotTitle(dataObject,propertyName);
255 }
256
257
258 if (inquiryObjectClass == null) {
259 inquiry.setRender(false);
260
261 return;
262 }
263
264 if (DocumentHeader.class.isAssignableFrom(inquiryObjectClass)) {
265 String documentNumber = (String) KradDataServiceLocator.getDataObjectService().wrap(dataObject).getPropertyValueNullSafe(propertyName);
266 if (StringUtils.isNotBlank(documentNumber)) {
267 inquiry.getInquiryLink().setHref(getConfigurationService().getPropertyValueAsString(
268 KRADConstants.WORKFLOW_URL_KEY)
269 + KRADConstants.DOCHANDLER_DO_URL
270 + documentNumber
271 + KRADConstants.DOCHANDLER_URL_CHUNK);
272 inquiry.getInquiryLink().setLinkText(documentNumber);
273 inquiry.setRender(true);
274 }
275
276 return;
277 }
278
279 synchronized (SUPER_CLASS_TRANSLATOR_LIST) {
280 for (Class<?> clazz : SUPER_CLASS_TRANSLATOR_LIST) {
281 if (clazz.isAssignableFrom(inquiryObjectClass)) {
282 inquiryObjectClass = clazz;
283 break;
284 }
285 }
286 }
287
288 if (!inquiryObjectClass.isInterface() && ExternalizableBusinessObject.class.isAssignableFrom(
289 inquiryObjectClass)) {
290 inquiryObjectClass = ExternalizableBusinessObjectUtils.determineExternalizableBusinessObjectSubInterface(
291 inquiryObjectClass);
292 }
293
294
295 List<String> keys = new ArrayList<String>(getLegacyDataAdapter().listPrimaryKeyFieldNames(
296 inquiryObjectClass));
297
298 if (keys == null) {
299 keys = Collections.emptyList();
300 }
301
302
303 Map<String, String> inquiryParameters = getLegacyDataAdapter().getInquiryParameters(dataObject,keys,propertyName);
304
305 inquiry.buildInquiryLink(dataObject, propertyName, inquiryObjectClass, inquiryParameters);
306 }
307
308
309
310
311 @Override
312 public Class<?> getDataObjectClass() {
313 return this.dataObjectClass;
314 }
315
316
317
318
319 @Override
320 public void setDataObjectClass(Class<?> dataObjectClass) {
321 this.dataObjectClass = dataObjectClass;
322 }
323
324 protected LegacyDataAdapter getLegacyDataAdapter() {
325 return KRADServiceLocatorWeb.getLegacyDataAdapter();
326 }
327
328 protected KualiModuleService getKualiModuleService() {
329 return KRADServiceLocatorWeb.getKualiModuleService();
330 }
331
332 @Override
333 public DataDictionaryService getDataDictionaryService() {
334 return KRADServiceLocatorWeb.getDataDictionaryService();
335 }
336
337 protected DataObjectAuthorizationService getDataObjectAuthorizationService() {
338 return KRADServiceLocatorWeb.getDataObjectAuthorizationService();
339 }
340
341 protected EncryptionService getEncryptionService() {
342 return CoreApiServiceLocator.getEncryptionService();
343 }
344
345
346
347
348
349
350 public InquirableImpl copy() {
351 InquirableImpl inquirableImplCopy = KRADUtils.createNewObjectFromClass(getClass());
352
353 if (this.getDataObjectClass() != null) {
354 inquirableImplCopy.setDataObjectClass(this.getDataObjectClass());
355 }
356
357 if (this.getConfigurationService() != null) {
358 inquirableImplCopy.setConfigurationService(this.getConfigurationService());
359 }
360
361 if (this.getDataDictionaryService() != null) {
362 inquirableImplCopy.setDataDictionaryService(this.getDataDictionaryService());
363 }
364
365 if (this.getLegacyDataAdapter() != null) {
366 inquirableImplCopy.setLegacyDataAdapter(this.getLegacyDataAdapter());
367 }
368
369 if (this.getDataObjectService() != null) {
370 inquirableImplCopy.setDataObjectService(this.getDataObjectService());
371 }
372
373 if (this.getViewDictionaryService() != null) {
374 inquirableImplCopy.setViewDictionaryService(this.getViewDictionaryService());
375 }
376
377 if (this.getExpressionEvaluatorFactory() != null) {
378 inquirableImplCopy.setExpressionEvaluatorFactory(this.getExpressionEvaluatorFactory());
379 }
380
381 return inquirableImplCopy;
382 }
383 }