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 }