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 boolean isSecure = KRADUtils.isSecure(keyPropertyName, dataObjectClass);
133
134 if (StringUtils.endsWith(keyPropertyValue, EncryptionService.ENCRYPTION_POST_PREFIX)) {
135 keyPropertyValue = StringUtils.removeEnd(keyPropertyValue, EncryptionService.ENCRYPTION_POST_PREFIX);
136 isSecure = true;
137 }
138
139
140 if (isSecure) {
141 try {
142 if (CoreApiServiceLocator.getEncryptionService().isEnabled()) {
143 keyPropertyValue = getEncryptionService().decrypt(keyPropertyValue);
144 }
145 } catch (GeneralSecurityException e) {
146 String message = "Data object class " + dataObjectClass + " property " + keyPropertyName
147 + " should have been encrypted, but there was a problem decrypting it.";
148 LOG.error(message, e);
149
150 throw new RuntimeException(message, e);
151 }
152 }
153
154 keyPropertyValues.put(keyPropertyName, keyPropertyValue);
155 }
156
157
158 Object dataObject = null;
159
160 Map<String, Object> translatedValues = KRADUtils.coerceRequestParameterTypes(
161 (Class<? extends ExternalizableBusinessObject>) getDataObjectClass(), keyPropertyValues);
162
163 ModuleService moduleService = KRADServiceLocatorWeb.getKualiModuleService().getResponsibleModuleService(
164 getDataObjectClass());
165 if (moduleService != null && moduleService.isExternalizable(getDataObjectClass())) {
166 dataObject = moduleService.getExternalizableBusinessObject(getDataObjectClass().asSubclass(
167 ExternalizableBusinessObject.class), translatedValues);
168 } else if ( KradDataServiceLocator.getDataObjectService().supports(getDataObjectClass())) {
169 dataObject = KradDataServiceLocator.getDataObjectService().find(getDataObjectClass(), new CompoundKey(translatedValues));
170 } else if (BusinessObject.class.isAssignableFrom(getDataObjectClass())) {
171 dataObject = getLegacyDataAdapter().findByPrimaryKey(getDataObjectClass().asSubclass(
172 BusinessObject.class), translatedValues);
173 } else {
174 throw new IllegalArgumentException( "ERROR: Unsupported object type passed to inquiry: " + getDataObjectClass() + " / keys=" + keyPropertyValues );
175 }
176 return dataObject;
177 }
178
179
180
181
182
183
184
185
186
187
188 protected List<String> retrieveKeySetFromMap(List<List<String>> potentialKeySets, Map<String, String> parameters) {
189 List<String> foundKeySet = null;
190
191 for (List<String> potentialKeySet : potentialKeySets) {
192 boolean keySetMatch = true;
193 for (String keyName : potentialKeySet) {
194 if (!parameters.containsKey(keyName) || StringUtils.isBlank(parameters.get(keyName))) {
195 keySetMatch = false;
196 }
197 }
198
199 if (keySetMatch) {
200 foundKeySet = potentialKeySet;
201 break;
202 }
203 }
204
205 return foundKeySet;
206 }
207
208
209
210
211
212
213
214
215 protected List<List<String>> getAlternateKeysForClass(Class<?> clazz) {
216 KualiModuleService kualiModuleService = getKualiModuleService();
217 ModuleService moduleService = kualiModuleService.getResponsibleModuleService(clazz);
218
219 List<List<String>> altKeys = null;
220 if (moduleService != null) {
221 altKeys = moduleService.listAlternatePrimaryKeyFieldNames(clazz);
222 }
223
224 return altKeys != null ? altKeys : new ArrayList<List<String>>();
225 }
226
227
228
229
230
231 @Override
232 public void buildInquirableLink(Object dataObject, String propertyName, Inquiry inquiry) {
233 Class<?> inquiryObjectClass = null;
234
235
236 Class<?> objectClass = KRADUtils.materializeClassForProxiedObject(dataObject);
237 if (propertyName.equals(KRADServiceLocatorWeb.getLegacyDataAdapter().getTitleAttribute(objectClass))) {
238 inquiryObjectClass = objectClass;
239 } else if (PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName)) {
240 String nestedPropertyName = KRADUtils.getNestedAttributePrefix(propertyName);
241 Object nestedPropertyObject = KRADUtils.getNestedValue(dataObject, nestedPropertyName);
242
243 if (KRADUtils.isNotNull(nestedPropertyObject)) {
244 String nestedPropertyPrimitive = KRADUtils.getNestedAttributePrimitive(propertyName);
245 Class<?> nestedPropertyObjectClass = KRADUtils.materializeClassForProxiedObject(nestedPropertyObject);
246
247 if (nestedPropertyPrimitive.equals(KRADServiceLocatorWeb.getLegacyDataAdapter().getTitleAttribute(
248 nestedPropertyObjectClass))) {
249 inquiryObjectClass = nestedPropertyObjectClass;
250 }
251 }
252 }
253
254
255 if (inquiryObjectClass == null) {
256 inquiryObjectClass = getLegacyDataAdapter().getInquiryObjectClassIfNotTitle(dataObject,propertyName);
257 }
258
259
260 if (inquiryObjectClass == null) {
261 inquiry.setRender(false);
262
263 return;
264 }
265
266 if (DocumentHeader.class.isAssignableFrom(inquiryObjectClass)) {
267 String documentNumber = (String) KradDataServiceLocator.getDataObjectService().wrap(dataObject).getPropertyValueNullSafe(propertyName);
268 if (StringUtils.isNotBlank(documentNumber)) {
269 inquiry.getInquiryLink().setHref(getConfigurationService().getPropertyValueAsString(
270 KRADConstants.WORKFLOW_URL_KEY)
271 + KRADConstants.DOCHANDLER_DO_URL
272 + documentNumber
273 + KRADConstants.DOCHANDLER_URL_CHUNK);
274 inquiry.getInquiryLink().setLinkText(documentNumber);
275 inquiry.setRender(true);
276 }
277
278 return;
279 }
280
281 synchronized (SUPER_CLASS_TRANSLATOR_LIST) {
282 for (Class<?> clazz : SUPER_CLASS_TRANSLATOR_LIST) {
283 if (clazz.isAssignableFrom(inquiryObjectClass)) {
284 inquiryObjectClass = clazz;
285 break;
286 }
287 }
288 }
289
290 if (!inquiryObjectClass.isInterface() && ExternalizableBusinessObject.class.isAssignableFrom(
291 inquiryObjectClass)) {
292 inquiryObjectClass = ExternalizableBusinessObjectUtils.determineExternalizableBusinessObjectSubInterface(
293 inquiryObjectClass);
294 }
295
296
297 List<String> keys = new ArrayList<String>(getLegacyDataAdapter().listPrimaryKeyFieldNames(
298 inquiryObjectClass));
299
300 if (keys == null) {
301 keys = Collections.emptyList();
302 }
303
304
305 Map<String, String> inquiryParameters = getLegacyDataAdapter().getInquiryParameters(dataObject,keys,propertyName);
306
307 inquiry.buildInquiryLink(dataObject, propertyName, inquiryObjectClass, inquiryParameters);
308 }
309
310
311
312
313 @Override
314 public Class<?> getDataObjectClass() {
315 return this.dataObjectClass;
316 }
317
318
319
320
321 @Override
322 public void setDataObjectClass(Class<?> dataObjectClass) {
323 this.dataObjectClass = dataObjectClass;
324 }
325
326 protected LegacyDataAdapter getLegacyDataAdapter() {
327 return KRADServiceLocatorWeb.getLegacyDataAdapter();
328 }
329
330 protected KualiModuleService getKualiModuleService() {
331 return KRADServiceLocatorWeb.getKualiModuleService();
332 }
333
334 @Override
335 public DataDictionaryService getDataDictionaryService() {
336 return KRADServiceLocatorWeb.getDataDictionaryService();
337 }
338
339 protected DataObjectAuthorizationService getDataObjectAuthorizationService() {
340 return KRADServiceLocatorWeb.getDataObjectAuthorizationService();
341 }
342
343 protected EncryptionService getEncryptionService() {
344 return CoreApiServiceLocator.getEncryptionService();
345 }
346
347 }