1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.kns.web.struts.form;
17
18 import org.apache.commons.beanutils.PropertyUtils;
19 import org.apache.commons.lang.StringUtils;
20 import org.apache.struts.upload.FormFile;
21 import org.kuali.rice.core.api.CoreApiServiceLocator;
22 import org.kuali.rice.core.api.config.ConfigurationException;
23 import org.kuali.rice.kns.authorization.AuthorizationConstants;
24 import org.kuali.rice.core.api.encryption.EncryptionService;
25 import org.kuali.rice.kns.datadictionary.BusinessObjectEntry;
26 import org.kuali.rice.kns.document.MaintenanceDocumentBase;
27 import org.kuali.rice.kns.inquiry.Inquirable;
28 import org.kuali.rice.kns.service.BusinessObjectAuthorizationService;
29 import org.kuali.rice.kns.service.BusinessObjectMetaDataService;
30 import org.kuali.rice.kns.service.KNSServiceLocator;
31 import org.kuali.rice.krad.bo.Exporter;
32 import org.kuali.rice.krad.bo.PersistableBusinessObject;
33 import org.kuali.rice.krad.datadictionary.exception.UnknownBusinessClassAttributeException;
34 import org.kuali.rice.krad.datadictionary.exception.UnknownDocumentTypeException;
35 import org.kuali.rice.krad.document.Document;
36 import org.kuali.rice.krad.service.DataDictionaryService;
37 import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
38 import org.kuali.rice.krad.service.KualiModuleService;
39 import org.kuali.rice.krad.service.ModuleService;
40 import org.kuali.rice.krad.util.KRADConstants;
41 import org.kuali.rice.krad.util.ObjectUtils;
42
43 import javax.servlet.http.HttpServletRequest;
44 import java.lang.reflect.Constructor;
45 import java.lang.reflect.InvocationTargetException;
46 import java.security.GeneralSecurityException;
47 import java.util.ArrayList;
48 import java.util.Enumeration;
49 import java.util.HashMap;
50 import java.util.List;
51 import java.util.Map;
52 import java.util.regex.Matcher;
53
54
55
56
57 public class InquiryForm extends KualiForm {
58 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(InquiryForm.class);
59
60 private static final long serialVersionUID = 1L;
61 private String fieldConversions;
62 private List sections;
63 private String businessObjectClassName;
64 private Map editingMode;
65 private String formKey;
66 private boolean canExport;
67
68 @Override
69 public void addRequiredNonEditableProperties(){
70 super.addRequiredNonEditableProperties();
71 registerRequiredNonEditableProperty(KRADConstants.BUSINESS_OBJECT_CLASS_ATTRIBUTE);
72 registerRequiredNonEditableProperty(KRADConstants.DISPATCH_REQUEST_PARAMETER);
73 registerRequiredNonEditableProperty(KRADConstants.DOC_FORM_KEY);
74 registerRequiredNonEditableProperty(KRADConstants.FORM_KEY);
75 registerRequiredNonEditableProperty(KRADConstants.FIELDS_CONVERSION_PARAMETER);
76 registerRequiredNonEditableProperty(KRADConstants.BACK_LOCATION);
77 }
78
79
80
81
82
83 private Map<String, String> inquiryPrimaryKeys;
84
85 private Map<String, String> inquiryDecryptedPrimaryKeys;
86
87
88
89
90 private Map<String, Boolean> inactiveRecordDisplay;
91
92 private Inquirable inquirable;
93
94 public InquiryForm() {
95 super();
96 this.editingMode = new HashMap();
97 this.editingMode.put(AuthorizationConstants.EditMode.VIEW_ONLY, "TRUE");
98 this.inactiveRecordDisplay = null;
99 }
100
101 @Override
102 public void populate(HttpServletRequest request) {
103
104
105 this.inquirable = null;
106 super.populate(request);
107 if (request.getParameter("returnLocation") != null) {
108 setBackLocation(request.getParameter("returnLocation"));
109 }
110 if (request.getParameter(KRADConstants.DOC_FORM_KEY) != null) {
111 setFormKey(request.getParameter(KRADConstants.DOC_FORM_KEY));
112 }
113
114 if(!KRADConstants.DOWNLOAD_BO_ATTACHMENT_METHOD.equals(getMethodToCall())){
115 inquirable = getInquirable(getBusinessObjectClassName());
116
117
118 boolean passedFromPreviousInquiry = !KRADConstants.START_METHOD.equals(getMethodToCall()) && !KRADConstants.CONTINUE_WITH_INQUIRY_METHOD_TO_CALL.equals(getMethodToCall()) && !KRADConstants
119 .DOWNLOAD_CUSTOM_BO_ATTACHMENT_METHOD.equals(getMethodToCall());
120
121
122
123
124
125 this.inquiryPrimaryKeys = new HashMap<String, String>();
126 this.inquiryDecryptedPrimaryKeys = new HashMap<String, String>();
127
128 populatePKFieldValues(request, getBusinessObjectClassName(), passedFromPreviousInquiry);
129
130 populateInactiveRecordsInIntoInquirable(inquirable, request);
131 populateExportCapabilities(request, getBusinessObjectClassName());
132 }
133 }
134
135 protected Inquirable getInquirable(String boClassName) {
136 try {
137 Class customInquirableClass = null;
138
139 try {
140 BusinessObjectEntry entry = (BusinessObjectEntry) KRADServiceLocatorWeb.getDataDictionaryService().getDataDictionary().getBusinessObjectEntry(boClassName);
141 customInquirableClass = entry.getInquiryDefinition().getInquirableClass();
142 }
143 catch (Exception e) {
144 LOG.error("Unable to correlate business object class with maintenance document entry");
145 }
146
147 Inquirable kualiInquirable = KNSServiceLocator.getKualiInquirable();
148
149 if (customInquirableClass != null) {
150 Class[] defaultConstructor = new Class[] {};
151 Constructor cons = customInquirableClass.getConstructor(defaultConstructor);
152 kualiInquirable = (Inquirable) cons.newInstance();
153 }
154
155 kualiInquirable.setBusinessObjectClass(Class.forName(boClassName));
156
157 return kualiInquirable;
158 }
159 catch (Exception e) {
160 LOG.error("Error attempting to retrieve inquirable.", e);
161 throw new RuntimeException("Error attempting to retrieve inquirable.");
162 }
163 }
164
165
166
167
168
169
170
171 private List<List<String>> getAltkeys(Class<?> clazz) {
172 final KualiModuleService kualiModuleService = KRADServiceLocatorWeb.getKualiModuleService();
173 final ModuleService moduleService = kualiModuleService.getResponsibleModuleService(clazz);
174
175 List<List<String>> altKeys = null;
176 if (moduleService != null) {
177 altKeys = moduleService.listAlternatePrimaryKeyFieldNames(clazz);
178 }
179
180 return altKeys != null ? altKeys : new ArrayList<List<String>>();
181 }
182
183 protected void populatePKFieldValues(HttpServletRequest request, String boClassName, boolean passedFromPreviousInquiry) {
184 try {
185 EncryptionService encryptionService = CoreApiServiceLocator.getEncryptionService();
186 DataDictionaryService dataDictionaryService = KRADServiceLocatorWeb.getDataDictionaryService();
187 BusinessObjectAuthorizationService businessObjectAuthorizationService = KNSServiceLocator
188 .getBusinessObjectAuthorizationService();
189 BusinessObjectMetaDataService businessObjectMetaDataService = KNSServiceLocator
190 .getBusinessObjectMetaDataService();
191
192 Class businessObjectClass = Class.forName(boClassName);
193
194
195 List<String> boPKeys = businessObjectMetaDataService.listPrimaryKeyFieldNames(businessObjectClass);
196 final List<List<String>> altKeys = this.getAltkeys(businessObjectClass);
197
198 altKeys.add(boPKeys);
199 boolean bFound = false;
200 for(List<String> boKeys : altKeys ){
201 if(bFound)
202 break;
203 int keyCount = boKeys.size();
204 int foundCount = 0;
205 for (String boKey : boKeys) {
206 String pkParamName = boKey;
207 if (passedFromPreviousInquiry) {
208 pkParamName = KRADConstants.INQUIRY_PK_VALUE_PASSED_FROM_PREVIOUS_REQUEST_PREFIX + pkParamName;
209 }
210
211 if (request.getParameter(pkParamName) != null) {
212 foundCount++;
213 String parameter = request.getParameter(pkParamName);
214
215 Boolean forceUppercase = Boolean.FALSE;
216 try {
217 forceUppercase = dataDictionaryService.getAttributeForceUppercase(businessObjectClass, boKey);
218 } catch (UnknownBusinessClassAttributeException ex) {
219
220
221
222 LOG.warn("BO class " + businessObjectClassName + " property " + boKey + " should probably have a DD definition.", ex);
223 }
224 String parameterCopy = parameter;
225 if (forceUppercase) {
226 parameter = parameter.toUpperCase();
227 }
228
229 inquiryPrimaryKeys.put(boKey, parameter);
230 if (businessObjectAuthorizationService.attributeValueNeedsToBeEncryptedOnFormsAndLinks(businessObjectClass, boKey)) {
231 try {
232 inquiryDecryptedPrimaryKeys.put(boKey, encryptionService.decrypt(parameterCopy));
233 } catch (GeneralSecurityException e) {
234 LOG.error("BO class " + businessObjectClassName + " property " + boKey + " should have been encrypted, but there was a problem decrypting it.");
235 throw e;
236 }
237 }
238 else {
239 inquiryDecryptedPrimaryKeys.put(boKey, parameter);
240 }
241 }
242 }
243 if (foundCount == keyCount) {
244 bFound = true;
245 }
246 }
247 if(!bFound){
248 LOG.error("All keys not given to lookup for bo class name " + businessObjectClass.getName());
249 throw new RuntimeException("All keys not given to lookup for bo class name " + businessObjectClass.getName());
250 }
251 }
252 catch (ClassNotFoundException e) {
253 LOG.error("Can't instantiate class: " + boClassName, e);
254 throw new RuntimeException("Can't instantiate class: " + boClassName);
255 }
256 catch (GeneralSecurityException e) {
257 LOG.error("Can't decrypt value", e);
258 throw new RuntimeException("Can't decrypt value");
259 }
260 }
261
262
263
264
265
266 protected void populateExportCapabilities(HttpServletRequest request, String boClassName) {
267 setCanExport(false);
268 BusinessObjectEntry businessObjectEntry = (BusinessObjectEntry) KRADServiceLocatorWeb.getDataDictionaryService().getDataDictionary().getBusinessObjectEntry(boClassName);
269 Class<? extends Exporter> exporterClass = businessObjectEntry.getExporterClass();
270 if (exporterClass != null) {
271 try {
272 Exporter exporter = exporterClass.newInstance();
273 if (exporter.getSupportedFormats(businessObjectEntry.getBusinessObjectClass()).contains(KRADConstants.XML_FORMAT)) {
274 setCanExport(true);
275 }
276 } catch (Exception e) {
277 LOG.error("Failed to locate or create exporter class: " + exporterClass, e);
278 throw new RuntimeException("Failed to locate or create exporter class: " + exporterClass);
279 }
280 }
281 }
282
283
284
285
286
287 public String getFieldConversions() {
288 return fieldConversions;
289 }
290
291
292
293
294
295 public void setFieldConversions(String fieldConversions) {
296 this.fieldConversions = fieldConversions;
297 }
298
299
300
301
302
303 public List getSections() {
304 return sections;
305 }
306
307
308
309
310
311 public void setSections(List sections) {
312 this.sections = sections;
313 }
314
315
316
317
318 public String getBusinessObjectClassName() {
319 return businessObjectClassName;
320 }
321
322
323
324
325 public void setBusinessObjectClassName(String businessObjectClassName) {
326 this.businessObjectClassName = businessObjectClassName;
327 }
328
329 public Map getEditingMode() {
330 return editingMode;
331 }
332
333
334
335
336
337
338
339 public Map<String, String> getInquiryPrimaryKeys() {
340 return this.inquiryPrimaryKeys;
341 }
342
343
344
345
346
347
348
349
350 public Map<String, String> retrieveInquiryDecryptedPrimaryKeys() {
351 return this.inquiryDecryptedPrimaryKeys;
352 }
353
354
355
356
357
358
359 public void setInquiryPrimaryKeys(Map<String, String> inquiryPrimaryKeys) {
360 this.inquiryPrimaryKeys = inquiryPrimaryKeys;
361 }
362
363
364
365
366
367
368 public Map<String, Boolean> getInactiveRecordDisplay() {
369 return getInquirable().getInactiveRecordDisplay();
370 }
371
372 public Inquirable getInquirable() {
373 return inquirable;
374 }
375
376 protected void populateInactiveRecordsInIntoInquirable(Inquirable inquirable, HttpServletRequest request) {
377 for (Enumeration e = request.getParameterNames(); e.hasMoreElements();) {
378 String paramName = (String) e.nextElement();
379 if (paramName.startsWith(KRADConstants.INACTIVE_RECORD_DISPLAY_PARAM_PREFIX)) {
380 String collectionName = StringUtils.substringAfter(paramName, KRADConstants.INACTIVE_RECORD_DISPLAY_PARAM_PREFIX);
381 Boolean showInactive = Boolean.parseBoolean(request.getParameter(paramName));
382 inquirable.setShowInactiveRecords(collectionName, showInactive);
383 }
384 }
385 }
386
387 public String getFormKey() {
388 return this.formKey;
389 }
390
391 public void setFormKey(String formKey) {
392 this.formKey = formKey;
393 }
394
395
396
397
398 public boolean isCanExport() {
399 return this.canExport;
400 }
401
402
403
404
405 public void setCanExport(boolean canExport) {
406 this.canExport = canExport;
407 }
408
409
410 }