1   
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  
17  package org.kuali.rice.kns.web.struts.action;
18  
19  import org.apache.commons.beanutils.PropertyUtils;
20  import org.apache.commons.lang.StringUtils;
21  import org.apache.ojb.broker.metadata.ClassNotPersistenceCapableException;
22  import org.apache.struts.action.ActionForm;
23  import org.apache.struts.action.ActionForward;
24  import org.apache.struts.action.ActionMapping;
25  import org.kuali.rice.core.api.CoreApiServiceLocator;
26  import org.kuali.rice.core.api.encryption.EncryptionService;
27  import org.kuali.rice.core.api.util.ClassLoaderUtils;
28  import org.kuali.rice.core.api.util.RiceConstants;
29  import org.kuali.rice.core.api.util.RiceKeyConstants;
30  import org.kuali.rice.core.framework.persistence.jpa.OrmUtils;
31  import org.kuali.rice.core.framework.persistence.jpa.criteria.Criteria;
32  import org.kuali.rice.core.framework.persistence.jpa.criteria.QueryByCriteria;
33  import org.kuali.rice.core.framework.persistence.jpa.metadata.EntityDescriptor;
34  import org.kuali.rice.core.framework.persistence.jpa.metadata.FieldDescriptor;
35  import org.kuali.rice.core.framework.persistence.jpa.metadata.MetadataManager;
36  import org.kuali.rice.core.web.format.Formatter;
37  import org.kuali.rice.kew.util.KEWConstants;
38  import org.kuali.rice.kim.api.identity.Person;
39  import org.kuali.rice.kns.datadictionary.MaintainableCollectionDefinition;
40  import org.kuali.rice.kns.datadictionary.MaintenanceDocumentEntry;
41  import org.kuali.rice.kns.document.MaintenanceDocument;
42  import org.kuali.rice.kns.document.MaintenanceDocumentBase;
43  import org.kuali.rice.kns.document.authorization.MaintenanceDocumentRestrictions;
44  import org.kuali.rice.kns.lookup.LookupResultsService;
45  import org.kuali.rice.kns.maintenance.Maintainable;
46  import org.kuali.rice.kns.rule.event.KualiAddLineEvent;
47  import org.kuali.rice.kns.service.KNSServiceLocator;
48  import org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService;
49  import org.kuali.rice.kns.util.KNSGlobalVariables;
50  import org.kuali.rice.kns.util.MaintenanceUtils;
51  import org.kuali.rice.kns.util.WebUtils;
52  import org.kuali.rice.kns.web.struts.form.KualiDocumentFormBase;
53  import org.kuali.rice.kns.web.struts.form.KualiForm;
54  import org.kuali.rice.kns.web.struts.form.KualiMaintenanceForm;
55  import org.kuali.rice.krad.bo.DocumentAttachment;
56  import org.kuali.rice.krad.bo.PersistableAttachment;
57  import org.kuali.rice.krad.bo.PersistableBusinessObject;
58  import org.kuali.rice.krad.bo.PersistableBusinessObjectExtension;
59  import org.kuali.rice.krad.document.authorization.MaintenanceDocumentAuthorizer;
60  import org.kuali.rice.krad.exception.DocumentTypeAuthorizationException;
61  import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
62  import org.kuali.rice.krad.service.LookupService;
63  import org.kuali.rice.krad.util.GlobalVariables;
64  import org.kuali.rice.krad.util.KRADConstants;
65  import org.kuali.rice.krad.util.KRADPropertyConstants;
66  import org.kuali.rice.krad.util.ObjectUtils;
67  
68  import javax.persistence.PersistenceException;
69  import javax.servlet.http.HttpServletRequest;
70  import javax.servlet.http.HttpServletResponse;
71  import java.lang.reflect.Field;
72  import java.lang.reflect.InvocationTargetException;
73  import java.security.GeneralSecurityException;
74  import java.util.ArrayList;
75  import java.util.Collection;
76  import java.util.Enumeration;
77  import java.util.HashMap;
78  import java.util.Iterator;
79  import java.util.List;
80  import java.util.Map;
81  
82  
83  
84  
85  public class KualiMaintenanceDocumentAction extends KualiDocumentActionBase {
86      protected static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(KualiMaintenanceDocumentAction.class);
87  
88      protected MaintenanceDocumentDictionaryService maintenanceDocumentDictionaryService = null;
89      protected EncryptionService encryptionService;
90      protected LookupService lookupService;
91      protected LookupResultsService lookupResultsService;
92  
93  	public KualiMaintenanceDocumentAction() {
94  		super();
95  		maintenanceDocumentDictionaryService = KNSServiceLocator.getMaintenanceDocumentDictionaryService();
96  		encryptionService = CoreApiServiceLocator.getEncryptionService();
97  	}
98  
99  	@Override
100 	public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {	
101 		request.setAttribute(KRADConstants.PARAM_MAINTENANCE_VIEW_MODE, KRADConstants.PARAM_MAINTENANCE_VIEW_MODE_MAINTENANCE);
102 		return super.execute(mapping, form, request, response);
103 	}
104 
105 	
106 
107 
108 	public ActionForward start(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
109 		request.setAttribute(KRADConstants.MAINTENANCE_ACTN, KRADConstants.MAINTENANCE_NEW_ACTION);
110 		return setupMaintenance(mapping, form, request, response, KRADConstants.MAINTENANCE_NEW_ACTION);
111 	}
112 
113 	
114 
115 
116 	public ActionForward copy(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
117 		
118 		if (request.getParameter("document." + KRADPropertyConstants.DOCUMENT_NUMBER) == null) { 
119 			return setupMaintenance(mapping, form, request, response, KRADConstants.MAINTENANCE_COPY_ACTION);
120 		}
121 		else { 
122 			throw new UnsupportedOperationException("System does not support copying of maintenance documents.");
123 		}
124 	}
125 
126 	
127 
128 
129 	public ActionForward edit(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
130 	
131 		return setupMaintenance(mapping, form, request, response, KRADConstants.MAINTENANCE_EDIT_ACTION);
132 	}
133 
134 	
135 
136 
137 	public ActionForward delete(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
138 		if (isFormRepresentingLockObject((KualiDocumentFormBase)form)) {
139 			 return super.delete(mapping, form, request, response);
140 		}
141 		KNSGlobalVariables.getMessageList().add(RiceKeyConstants.MESSAGE_DELETE);
142 		return setupMaintenance(mapping, form, request, response, KRADConstants.MAINTENANCE_DELETE_ACTION);
143 	}
144 	
145 	
146 
147 
148 	public ActionForward newWithExisting(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
149 		return setupMaintenance(mapping, form, request, response, KRADConstants.MAINTENANCE_NEWWITHEXISTING_ACTION);
150 	}
151 
152 	
153 
154 
155 
156 
157 
158     protected ActionForward setupMaintenance(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response, String maintenanceAction) throws Exception {
159 		KualiMaintenanceForm maintenanceForm = (KualiMaintenanceForm) form;
160 		MaintenanceDocument document = null;
161 
162 		
163 		if (maintenanceForm.getDocument() == null) {
164 			if (StringUtils.isEmpty(maintenanceForm.getBusinessObjectClassName()) && StringUtils.isEmpty(maintenanceForm.getDocTypeName())) {
165 				throw new IllegalArgumentException("Document type name or bo class not given!");
166 			}
167 
168 			String documentTypeName = maintenanceForm.getDocTypeName();
169 			
170 			if (StringUtils.isEmpty(documentTypeName)) {
171 				documentTypeName = maintenanceDocumentDictionaryService.getDocumentTypeName(Class.forName(maintenanceForm.getBusinessObjectClassName()));
172 				maintenanceForm.setDocTypeName(documentTypeName);
173 			}
174 
175 			if (StringUtils.isEmpty(documentTypeName)) {
176 				throw new RuntimeException("documentTypeName is empty; does this Business Object have a maintenance document definition? " + maintenanceForm.getBusinessObjectClassName());
177 			}
178 
179 			
180 			if (KRADConstants.MAINTENANCE_NEW_ACTION.equals(maintenanceAction) || KRADConstants.MAINTENANCE_COPY_ACTION.equals(maintenanceAction)) {
181 				Class boClass = maintenanceDocumentDictionaryService.getDataObjectClass(documentTypeName);
182 				boolean allowsNewOrCopy = getBusinessObjectAuthorizationService().canCreate(boClass, GlobalVariables.getUserSession().getPerson(), documentTypeName);
183 				if (!allowsNewOrCopy) {
184 					LOG.error("Document type " + documentTypeName + " does not allow new or copy actions.");
185 					throw new DocumentTypeAuthorizationException(GlobalVariables.getUserSession().getPerson().getPrincipalId(), "newOrCopy", documentTypeName);
186 				}
187 			}
188 
189 			
190 			document = (MaintenanceDocument) getDocumentService().getNewDocument(maintenanceForm.getDocTypeName());
191 			
192 			
193 			
194 			
195 			
196 			
197 			
198 			
199 			
200 			maintenanceForm.setDocument(document);
201 		}
202 		else {
203 			document = (MaintenanceDocument) maintenanceForm.getDocument();
204 		}
205 
206 		
207 		if (!(KRADConstants.MAINTENANCE_NEW_ACTION.equals(maintenanceAction)) && !(KRADConstants.MAINTENANCE_NEWWITHEXISTING_ACTION.equals(maintenanceAction))) {
208 			Map requestParameters = buildKeyMapFromRequest(document.getNewMaintainableObject(), request);
209             PersistableBusinessObject oldBusinessObject = null;
210             try {
211             	oldBusinessObject = (PersistableBusinessObject) getLookupService().findObjectBySearch(Class.forName(maintenanceForm.getBusinessObjectClassName()), requestParameters);
212             } catch ( ClassNotPersistenceCapableException ex ) {
213             	if ( !document.getOldMaintainableObject().isExternalBusinessObject() ) {
214             		throw new RuntimeException( "BO Class: " + maintenanceForm.getBusinessObjectClassName() + " is not persistable and is not externalizable - configuration error" );
215             	}
216             	
217             }
218 			if (oldBusinessObject == null && !document.getOldMaintainableObject().isExternalBusinessObject()) {
219                 throw new RuntimeException("Cannot retrieve old record for maintenance document, incorrect parameters passed on maint url: " + requestParameters );
220 			} 
221 
222 			if(document.getOldMaintainableObject().isExternalBusinessObject()){
223             	if ( oldBusinessObject == null ) {
224             		try {
225             			oldBusinessObject = (PersistableBusinessObject)document.getOldMaintainableObject().getBoClass().newInstance();
226             		} catch ( Exception ex ) {
227             			throw new RuntimeException( "External BO maintainable was null and unable to instantiate for old maintainable object.", ex );
228             		}
229             	}
230 				populateBOWithCopyKeyValues(request, oldBusinessObject, document.getOldMaintainableObject());
231 				document.getOldMaintainableObject().prepareBusinessObject(oldBusinessObject);
232             	oldBusinessObject = document.getOldMaintainableObject().getBusinessObject();
233 			}
234 
235 			
236 			final String TMP_NM = oldBusinessObject.getClass().getName();
237 			final int START_INDEX = TMP_NM.indexOf('.', TMP_NM.indexOf('.') + 1) + 1;
238 			if ( ( OrmUtils.isJpaEnabled() || OrmUtils.isJpaEnabled(TMP_NM.substring(START_INDEX, TMP_NM.indexOf('.', TMP_NM.indexOf('.', START_INDEX) + 1))) ) &&
239 					OrmUtils.isJpaAnnotated(oldBusinessObject.getClass()) && oldBusinessObject.getExtension() != null && OrmUtils.isJpaAnnotated(oldBusinessObject.getExtension().getClass())) {
240 				if (oldBusinessObject.getExtension() != null) {
241 					PersistableBusinessObjectExtension boe = oldBusinessObject.getExtension();
242 					EntityDescriptor entity = MetadataManager.getEntityDescriptor(oldBusinessObject.getExtension().getClass());
243 					Criteria extensionCriteria = new Criteria(boe.getClass().getName());
244 					for (FieldDescriptor fieldDescriptor : entity.getPrimaryKeys()) {
245 						try {
246 							Field field = oldBusinessObject.getClass().getDeclaredField(fieldDescriptor.getName());
247 							field.setAccessible(true);
248 							extensionCriteria.eq(fieldDescriptor.getName(), field.get(oldBusinessObject));
249 						} catch (Exception e) {
250 							LOG.error(e.getMessage(),e);
251 						}
252 					}				
253 					try {
254 						boe = (PersistableBusinessObjectExtension) new QueryByCriteria(getEntityManagerFactory().createEntityManager(), extensionCriteria).toQuery().getSingleResult();
255 					} catch (PersistenceException e) {}
256 					oldBusinessObject.setExtension(boe);
257 				}
258 			}
259 
260 			PersistableBusinessObject newBusinessObject = (PersistableBusinessObject) ObjectUtils.deepCopy(oldBusinessObject);
261 
262 			
263 			Class<? extends PersistableBusinessObject> businessObjectClass = ClassLoaderUtils.getClass(maintenanceForm.getBusinessObjectClassName(), PersistableBusinessObject.class); 
264 			document.getOldMaintainableObject().setBusinessObject(oldBusinessObject);
265 			document.getOldMaintainableObject().setBoClass(businessObjectClass);
266 			document.getNewMaintainableObject().setBusinessObject(newBusinessObject);
267 			document.getNewMaintainableObject().setBoClass(businessObjectClass);
268 
269 			
270 			
271 			if (KRADConstants.MAINTENANCE_COPY_ACTION.equals(maintenanceAction)) {
272 				if (!document.isFieldsClearedOnCopy()) {
273 					
274 					Class boClass = maintenanceDocumentDictionaryService.getDataObjectClass(
275                             maintenanceForm.getDocTypeName());
276 					if(!maintenanceDocumentDictionaryService.getPreserveLockingKeysOnCopy(boClass))
277 						clearPrimaryKeyFields(document);
278 
279 					clearUnauthorizedNewFields(document);
280 
281 					Maintainable maintainable = document.getNewMaintainableObject();
282 
283 					maintainable.processAfterCopy( document, request.getParameterMap() );
284 
285 					
286 					document.setFieldsClearedOnCopy(true);
287 
288 					
289 					maintainable.setGenerateBlankRequiredValues(maintenanceForm.getDocTypeName());
290 				}
291 			}
292 			else if (KRADConstants.MAINTENANCE_EDIT_ACTION.equals(maintenanceAction)) {
293 				boolean allowsEdit = getBusinessObjectAuthorizationService().canMaintain(oldBusinessObject, GlobalVariables.getUserSession().getPerson(), document.getDocumentHeader().getWorkflowDocument().getDocumentTypeName());
294 				if (!allowsEdit) {
295 					LOG.error("Document type " + document.getDocumentHeader().getWorkflowDocument().getDocumentTypeName() + " does not allow edit actions.");
296 					throw  new DocumentTypeAuthorizationException(GlobalVariables.getUserSession().getPerson().getPrincipalId(), "edit", document.getDocumentHeader().getWorkflowDocument().getDocumentTypeName());
297 				}
298 				document.getNewMaintainableObject().processAfterEdit( document, request.getParameterMap() );
299 			}
300 			
301 			else if (KRADConstants.MAINTENANCE_DELETE_ACTION.equals(maintenanceAction)) {
302 				boolean allowsDelete = getBusinessObjectAuthorizationService().canMaintain(oldBusinessObject, GlobalVariables.getUserSession().getPerson(), document.getDocumentHeader().getWorkflowDocument().getDocumentTypeName());
303 				if (!allowsDelete) {
304 					LOG.error("Document type " + document.getDocumentHeader().getWorkflowDocument().getDocumentTypeName() + " does not allow delete actions.");
305 					throw  new DocumentTypeAuthorizationException(GlobalVariables.getUserSession().getPerson().getPrincipalId(), "delete", document.getDocumentHeader().getWorkflowDocument().getDocumentTypeName());
306 				}	
307 				
308 			}
309 			
310 			
311 			
312 			
313 			
314 			
315 			
316 		}
317 		
318 		if (KRADConstants.MAINTENANCE_NEWWITHEXISTING_ACTION.equals(maintenanceAction)) {
319 			
320 			
321 			
322 			PersistableBusinessObject newBO = document.getNewMaintainableObject().getBusinessObject();
323 			Map<String, String> parameters = buildKeyMapFromRequest(document.getNewMaintainableObject(), request);
324 			copyParametersToBO(parameters, newBO);
325 			newBO.refresh();
326 			document.getNewMaintainableObject().setupNewFromExisting( document, request.getParameterMap() );
327 		}
328 
329 		
330 		if (KRADConstants.MAINTENANCE_NEW_ACTION.equals(maintenanceAction)) {
331 			document.getNewMaintainableObject().setGenerateDefaultValues(maintenanceForm.getDocTypeName());
332 			document.getNewMaintainableObject().processAfterNew( document, request.getParameterMap() );
333 
334 			
335 			MaintenanceUtils.checkForLockingDocument(document.getNewMaintainableObject(), false);
336 		}
337 
338 		
339 		document.getNewMaintainableObject().setMaintenanceAction(maintenanceAction);
340 		maintenanceForm.setMaintenanceAction(maintenanceAction);
341 
342 		
343         MaintenanceDocumentEntry entry =  maintenanceDocumentDictionaryService.getMaintenanceDocumentEntry(document.getDocumentHeader().getWorkflowDocument().getDocumentTypeName());
344 		if (LOG.isDebugEnabled()) {
345 			LOG.debug("maintenanceForm.getAdditionalScriptFiles(): " + maintenanceForm.getAdditionalScriptFiles());
346 		}
347 		if (maintenanceForm.getAdditionalScriptFiles().isEmpty()) {
348 			maintenanceForm.getAdditionalScriptFiles().addAll(entry.getWebScriptFiles());
349 		}
350 
351 		
352 		document.setDisplayTopicFieldInNotes(entry.getDisplayTopicFieldInNotes());
353 
354 		return mapping.findForward(RiceConstants.MAPPING_BASIC);
355 	}
356 
357     protected void populateBOWithCopyKeyValues(HttpServletRequest request, PersistableBusinessObject oldBusinessObject, Maintainable oldMaintainableObject) throws Exception{
358 		List keyFieldNamesToCopy = new ArrayList();
359 		Map<String, String> parametersToCopy;
360 		if (!StringUtils.isBlank(request.getParameter(KRADConstants.COPY_KEYS))) {
361 			String[] copyKeys = request.getParameter(KRADConstants.COPY_KEYS).split(KRADConstants.FIELD_CONVERSIONS_SEPARATOR);
362 			for (String copyKey: copyKeys) {
363 				keyFieldNamesToCopy.add(copyKey);
364 			}
365 		}
366 		parametersToCopy = getRequestParameters(keyFieldNamesToCopy, oldMaintainableObject, request);
367 		if(parametersToCopy!=null && parametersToCopy.size()>0){
368 			copyParametersToBO(parametersToCopy, oldBusinessObject);
369 		}
370 	}
371 
372     protected void copyParametersToBO(Map<String, String> parameters, PersistableBusinessObject newBO) throws Exception{
373 		for (String parmName : parameters.keySet()) {
374 			String propertyValue = parameters.get(parmName);
375 
376 			if (StringUtils.isNotBlank(propertyValue)) {
377 				String propertyName = parmName;
378 				
379 				if (PropertyUtils.isWriteable(newBO, propertyName)) {
380 					Class type = ObjectUtils.easyGetPropertyType(newBO, propertyName);
381 					if (type != null && Formatter.getFormatter(type) != null) {
382 						Formatter formatter = Formatter.getFormatter(type);
383 						Object obj = formatter.convertFromPresentationFormat(propertyValue);
384 						ObjectUtils.setObjectProperty(newBO, propertyName, obj.getClass(), obj);
385 					}
386 					else {
387 						ObjectUtils.setObjectProperty(newBO, propertyName, String.class, propertyValue);
388 					}
389 				}
390 			}
391 		}
392 	}
393 
394 	
395 
396 
397 
398 
399 
400 
401 
402 
403 
404 	public ActionForward downloadAttachment(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
405 		KualiDocumentFormBase documentForm = (KualiDocumentFormBase) form;
406 		MaintenanceDocumentBase document = (MaintenanceDocumentBase) documentForm.getDocument();
407 		document.refreshReferenceObject("attachment");
408 		DocumentAttachment attachment = document.getAttachment();
409 		if(attachment != null) {
410 			streamToResponse(attachment.getAttachmentContent(), attachment.getFileName(), attachment.getContentType(), response); 
411 		}
412 		return null;
413 	}
414 
415 
416 	
417 
418 
419 
420 
421 
422 
423 
424 
425 
426 	public ActionForward replaceAttachment(ActionMapping mapping, ActionForm form, HttpServletRequest request,
427 			HttpServletResponse response) throws Exception {
428 		KualiDocumentFormBase documentForm = (KualiDocumentFormBase) form;
429 		MaintenanceDocumentBase document = (MaintenanceDocumentBase) documentForm.getDocument();
430 		document.refreshReferenceObject("attachment");
431 		getBusinessObjectService().delete(document.getAttachment());
432 		return mapping.findForward(RiceConstants.MAPPING_BASIC);
433 	}
434 
435 	
436 
437 
438 
439 
440 
441 
442 
443 
444 
445 	@Override
446 	public ActionForward route(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
447 		KualiDocumentFormBase documentForm = (KualiDocumentFormBase) form;
448 		MaintenanceDocumentBase document = (MaintenanceDocumentBase) documentForm.getDocument();
449 
450 		ActionForward forward = super.route(mapping, form, request, response);
451 		if(document.getNewMaintainableObject().getBusinessObject() instanceof PersistableAttachment) {
452 			PersistableAttachment bo = (PersistableAttachment) getBusinessObjectService().retrieve(document.getNewMaintainableObject().getBusinessObject());
453 			request.setAttribute("fileName", bo.getFileName());
454 		}
455 
456 		return forward;
457 	}
458 
459 	
460 
461 
462 	@Override
463 	public ActionForward docHandler(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
464 		super.docHandler(mapping, form, request, response);
465 		KualiMaintenanceForm kualiMaintenanceForm = (KualiMaintenanceForm) form;
466 
467 		if (KEWConstants.ACTIONLIST_COMMAND.equals(kualiMaintenanceForm.getCommand()) || KEWConstants.DOCSEARCH_COMMAND.equals(kualiMaintenanceForm.getCommand()) || KEWConstants.SUPERUSER_COMMAND.equals(kualiMaintenanceForm.getCommand()) || KEWConstants.HELPDESK_ACTIONLIST_COMMAND.equals(kualiMaintenanceForm.getCommand()) && kualiMaintenanceForm.getDocId() != null) {
468 			if (kualiMaintenanceForm.getDocument() instanceof MaintenanceDocument) {
469 				kualiMaintenanceForm.setReadOnly(true);
470 				kualiMaintenanceForm.setMaintenanceAction(((MaintenanceDocument) kualiMaintenanceForm.getDocument()).getNewMaintainableObject().getMaintenanceAction());
471 
472 				
473 				Maintainable tmpMaintainable = ((MaintenanceDocument) kualiMaintenanceForm.getDocument()).getNewMaintainableObject();
474 				if(tmpMaintainable.getBusinessObject() instanceof PersistableAttachment) {
475 					PersistableAttachment bo = (PersistableAttachment) getBusinessObjectService().retrieve(tmpMaintainable.getBusinessObject());
476 					if(bo != null)
477 						request.setAttribute("fileName", bo.getFileName());
478 				}
479 			}
480 			else {
481 				LOG.error("Illegal State: document is not a maintenance document");
482 				throw new IllegalStateException("Document is not a maintenance document");
483 			}
484 		}
485 		else if (KEWConstants.INITIATE_COMMAND.equals(kualiMaintenanceForm.getCommand())) {
486 			kualiMaintenanceForm.setReadOnly(false);
487 			return setupMaintenance(mapping, form, request, response, KRADConstants.MAINTENANCE_NEW_ACTION);
488 		}
489 		else {
490 			LOG.error("We should never have gotten to here");
491 			throw new IllegalStateException("docHandler called with invalid parameters");
492 		}
493 		return mapping.findForward(RiceConstants.MAPPING_BASIC);
494 	}
495 
496 	
497 
498 
499 	@Override
500 	public ActionForward refresh(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
501 		KualiMaintenanceForm maintenanceForm = (KualiMaintenanceForm) form;
502 
503 		WebUtils.reuseErrorMapFromPreviousRequest(maintenanceForm);
504 		maintenanceForm.setDerivedValuesOnForm(request);
505 
506 		refreshAdHocRoutingWorkgroupLookups(request, maintenanceForm);
507 		MaintenanceDocument document = (MaintenanceDocument) maintenanceForm.getDocument();
508 
509 		
510 		Map<String, String> requestParams = new HashMap<String, String>();
511 		for (Enumeration i = request.getParameterNames(); i.hasMoreElements();) {
512 			String requestKey = (String) i.nextElement();
513 			String requestValue = request.getParameter(requestKey);
514 			requestParams.put(requestKey, requestValue);
515 		}
516 
517 		
518 		Collection<PersistableBusinessObject> rawValues = null;
519 		if (StringUtils.equals(KRADConstants.MULTIPLE_VALUE, maintenanceForm.getRefreshCaller())) {
520 			String lookupResultsSequenceNumber = maintenanceForm.getLookupResultsSequenceNumber();
521 			if (StringUtils.isNotBlank(lookupResultsSequenceNumber)) {
522 				
523 				String lookupResultsBOClassName = maintenanceForm.getLookupResultsBOClassName();
524 				Class lookupResultsBOClass = Class.forName(lookupResultsBOClassName);
525 
526 				rawValues = getLookupResultsService().retrieveSelectedResultBOs(lookupResultsSequenceNumber, lookupResultsBOClass, GlobalVariables.getUserSession().getPerson().getPrincipalId());
527 			}
528 		}
529 
530 		if (rawValues != null) { 
531 			
532 			
533 			
534 			
535 			String collectionName = maintenanceForm.getLookedUpCollectionName();
536 			
537 			
538 			
539 			
540 			
541 			
542 			
543 			
544 			
545 			
546 			
547 			
548 			
549 			document.getNewMaintainableObject().addMultipleValueLookupResults(document, collectionName, rawValues, false, document.getNewMaintainableObject().getBusinessObject());
550 			if (LOG.isInfoEnabled()) {
551 				LOG.info("********************doing editing 3 in refersh()***********************.");
552 			}
553 			boolean isEdit = KRADConstants.MAINTENANCE_EDIT_ACTION.equals(maintenanceForm.getMaintenanceAction());
554 			boolean isCopy = KRADConstants.MAINTENANCE_COPY_ACTION.equals(maintenanceForm.getMaintenanceAction());
555 
556 			if (isEdit || isCopy) {
557 				document.getOldMaintainableObject().addMultipleValueLookupResults(document, collectionName, rawValues, true, document.getOldMaintainableObject().getBusinessObject());
558 				document.getOldMaintainableObject().refresh(maintenanceForm.getRefreshCaller(), requestParams, document);
559 			}
560 		}
561 
562 		document.getNewMaintainableObject().refresh(maintenanceForm.getRefreshCaller(), requestParams, document);
563 
564 		
565 		String fullParameter = (String) request.getAttribute(KRADConstants.METHOD_TO_CALL_ATTRIBUTE);
566 		if(StringUtils.contains(fullParameter, KRADConstants.CUSTOM_ACTION)){
567 			String customAction = StringUtils.substringBetween(fullParameter, KRADConstants.METHOD_TO_CALL_PARM1_LEFT_DEL, KRADConstants.METHOD_TO_CALL_PARM1_RIGHT_DEL);
568 			String[] actionValue = new String[1];
569 			actionValue[0]= StringUtils.substringAfter(customAction, ".");
570 			Map<String,String[]> paramMap = request.getParameterMap();
571 			paramMap.put(KRADConstants.CUSTOM_ACTION, actionValue);
572 			doProcessingAfterPost( (KualiMaintenanceForm) form, paramMap );
573 		}
574 
575 		return mapping.findForward(RiceConstants.MAPPING_BASIC);
576 	}
577 
578 	
579 
580 
581 
582     protected Map buildKeyMapFromRequest(Maintainable maintainable, HttpServletRequest request) {
583 		List keyFieldNames = null;
584 		
585 		
586 		if (!StringUtils.isBlank(request.getParameter(KRADConstants.OVERRIDE_KEYS))) {
587 			String[] overrideKeys = request.getParameter(KRADConstants.OVERRIDE_KEYS).split(KRADConstants.FIELD_CONVERSIONS_SEPARATOR);
588 			keyFieldNames = new ArrayList();
589 			for (String overrideKey : overrideKeys) {
590 				keyFieldNames.add(overrideKey);
591 			}
592 		}
593 		else {
594 			keyFieldNames = getBusinessObjectMetaDataService().listPrimaryKeyFieldNames(maintainable.getBusinessObject().getClass());
595 		}
596 		return getRequestParameters(keyFieldNames, maintainable, request);
597 	}
598 
599     protected Map<String, String> getRequestParameters(List keyFieldNames, Maintainable maintainable, HttpServletRequest request){
600 
601 		Map<String, String> requestParameters = new HashMap<String, String>();
602 
603 
604 		for (Iterator iter = keyFieldNames.iterator(); iter.hasNext();) {
605 			String keyPropertyName = (String) iter.next();
606 
607 			if (request.getParameter(keyPropertyName) != null) {
608 				String keyValue = request.getParameter(keyPropertyName);
609 
610 				
611                 if (getBusinessObjectAuthorizationService().attributeValueNeedsToBeEncryptedOnFormsAndLinks(maintainable.getBoClass(), keyPropertyName)) {
612 					try {
613                     	keyValue = StringUtils.removeEnd(keyValue, EncryptionService.ENCRYPTION_POST_PREFIX);
614 						keyValue = encryptionService.decrypt(keyValue);
615 					}
616 					catch (GeneralSecurityException e) {
617 						throw new RuntimeException(e);
618 					}
619 				}
620 
621 
622 				requestParameters.put(keyPropertyName, keyValue);
623 			}
624 		}
625 
626 		return requestParameters;
627 
628 	}
629 
630 	
631 
632 
633 
634 
635 	String extractCollectionName(HttpServletRequest request, String methodToCall) {
636 		
637 		String parameterName = (String) request.getAttribute(KRADConstants.METHOD_TO_CALL_ATTRIBUTE);
638 		String collectionName = null;
639 		if (StringUtils.isNotBlank(parameterName)) {
640 			collectionName = StringUtils.substringBetween(parameterName, methodToCall + ".", ".(");
641 		}
642 		return collectionName;
643 	}
644 
645 	Collection extractCollection(PersistableBusinessObject bo, String collectionName) {
646 		
647 		Collection maintCollection = (Collection) ObjectUtils.getPropertyValue(bo, collectionName);
648 		return maintCollection;
649 	}
650 
651 	Class extractCollectionClass(String docTypeName, String collectionName) {
652 		return maintenanceDocumentDictionaryService.getCollectionBusinessObjectClass(docTypeName, collectionName);
653 	}
654 
655 	
656 
657 
658 	public ActionForward addLine(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
659 		KualiMaintenanceForm maintenanceForm = (KualiMaintenanceForm) form;
660 		MaintenanceDocument document = (MaintenanceDocument) maintenanceForm.getDocument();
661 		Maintainable oldMaintainable = document.getOldMaintainableObject();
662 		Maintainable newMaintainable = document.getNewMaintainableObject();
663 
664 		String collectionName = extractCollectionName(request, KRADConstants.ADD_LINE_METHOD);
665 		if (collectionName == null) {
666 			LOG.error("Unable to get find collection name and class in request.");
667 			throw new RuntimeException("Unable to get find collection name and class in request.");
668 		}
669 
670 		
671 		if ((StringUtils.lastIndexOf(collectionName, "]") + 1) == collectionName.length()) {
672 			collectionName = StringUtils.substringBeforeLast(collectionName, "[");
673 		}
674 
675 		PersistableBusinessObject bo = newMaintainable.getBusinessObject();
676 		Collection maintCollection = extractCollection(bo, collectionName);
677 		Class collectionClass = extractCollectionClass(((MaintenanceDocument) maintenanceForm.getDocument()).getDocumentHeader().getWorkflowDocument().getDocumentTypeName(), collectionName);
678 
679 		
680 
681 		
682 		PersistableBusinessObject addBO = newMaintainable.getNewCollectionLine(collectionName);
683 		if (LOG.isDebugEnabled()) {
684 			LOG.debug("obtained addBO from newCollectionLine: " + addBO);
685 		}
686 
687 		
688 		getBusinessObjectService().linkUserFields(addBO);
689 
690 		
691 		newMaintainable.processBeforeAddLine(collectionName, collectionClass, addBO);
692 		
693 		
694 		boolean rulePassed = false;
695 		if (LOG.isDebugEnabled()) {
696 			LOG.debug("about to call AddLineEvent applyRules: document=" + document + "\ncollectionName=" + collectionName + "\nBO=" + addBO);
697 		}
698 		rulePassed = getKualiRuleService().applyRules(new KualiAddLineEvent(document, collectionName, addBO));
699 
700 		
701 		if (rulePassed) {
702 			if (LOG.isInfoEnabled()) {
703 				LOG.info("********************doing editing 4 in addline()***********************.");
704 			}
705 			
706 			boolean isEdit = KRADConstants.MAINTENANCE_EDIT_ACTION.equals(maintenanceForm.getMaintenanceAction());
707 			boolean isCopy = KRADConstants.MAINTENANCE_COPY_ACTION.equals(maintenanceForm.getMaintenanceAction());
708 
709 
710 			if (isEdit || isCopy) {
711 				PersistableBusinessObject oldBo = oldMaintainable.getBusinessObject();
712 				Collection oldMaintCollection = (Collection) ObjectUtils.getPropertyValue(oldBo, collectionName);
713 
714 				if (oldMaintCollection == null) {
715 					oldMaintCollection = new ArrayList();
716 				}
717 				if (PersistableBusinessObject.class.isAssignableFrom(collectionClass)) {
718 					PersistableBusinessObject placeholder = (PersistableBusinessObject) collectionClass.newInstance();
719 					
720 					
721 
722 					
723 					
724 					placeholder.setNewCollectionRecord(true);
725 					((List) oldMaintCollection).add(placeholder);
726 				}
727 				else {
728 					LOG.warn("Should be a instance of PersistableBusinessObject");
729 					((List) oldMaintCollection).add(collectionClass.newInstance());
730 				}
731 				
732 				ObjectUtils.setObjectProperty(oldBo, collectionName, List.class, oldMaintCollection);
733 			}
734 
735 			newMaintainable.addNewLineToCollection(collectionName);
736 			int subCollectionIndex = 0;
737 			for (Object aSubCollection : maintCollection) {
738 				subCollectionIndex += getSubCollectionIndex(aSubCollection, maintenanceForm.getDocTypeName());
739 			}
740 			
741 			
742 			
743 			
744 			
745 			
746 			
747 			
748 			
749 			
750 			
751 			
752 			
753 			
754 			
755 			
756 			
757 			
758 			
759 			
760 			
761 			
762 			
763 			
764 			
765 			
766 			
767 			
768 
769 
770 			
771 		}
772 		doProcessingAfterPost( (KualiMaintenanceForm) form, request );
773 
774 		return mapping.findForward(RiceConstants.MAPPING_BASIC);
775 	}
776 
777     protected int getSubCollectionIndex(Object object, String documentTypeName) {
778 		int index = 1;
779 		MaintainableCollectionDefinition theCollectionDefinition = null;
780 		for (MaintainableCollectionDefinition maintainableCollectionDefinition : maintenanceDocumentDictionaryService.getMaintainableCollections(documentTypeName)) {
781 			if (maintainableCollectionDefinition.getBusinessObjectClass().equals(object.getClass())) {
782 				
783 				theCollectionDefinition = maintainableCollectionDefinition;
784 				break;
785 			}
786 		}
787 		if (theCollectionDefinition != null) {
788 			for (MaintainableCollectionDefinition subCollDef : theCollectionDefinition.getMaintainableCollections()) {
789 				String name = subCollDef.getName();
790 				String capitalFirst = name.substring(0, 1).toUpperCase();
791 				String methodName = "get" + capitalFirst + name.substring(1);
792 				List subCollectionList = new ArrayList();
793 				try {
794 					subCollectionList = (List) object.getClass().getMethod(methodName).invoke(object);
795 				}
796 				catch (InvocationTargetException ite) {
797 					
798 				}
799 				catch (IllegalAccessException iae) {
800 					
801 				}
802 				catch (NoSuchMethodException nme) {
803 					
804 				}
805 				index += subCollectionList.size();
806 			}
807 		}
808 		return index;
809 	}
810 
811 	
812 
813 
814 
815 
816 	public ActionForward deleteLine(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
817 		KualiMaintenanceForm maintenanceForm = (KualiMaintenanceForm) form;
818 		MaintenanceDocument document = (MaintenanceDocument) maintenanceForm.getDocument();
819 		Maintainable oldMaintainable = document.getOldMaintainableObject();
820 		Maintainable newMaintainable = document.getNewMaintainableObject();
821 
822 		String collectionName = extractCollectionName(request, KRADConstants.DELETE_LINE_METHOD);
823 		if (collectionName == null) {
824 			LOG.error("Unable to get find collection name in request.");
825 			throw new RuntimeException("Unable to get find collection class in request.");
826 		}
827 
828 		PersistableBusinessObject bo = newMaintainable.getBusinessObject();
829 		Collection maintCollection = extractCollection(bo, collectionName);
830 		if (collectionName == null) {
831 			LOG.error("Collection is null in parent business object.");
832 			throw new RuntimeException("Collection is null in parent business object.");
833 		}
834 
835 		int deleteRecordIndex = getLineToDelete(request);
836 		if (deleteRecordIndex < 0 || deleteRecordIndex > maintCollection.size() - 1) {
837 			if (collectionName == null) {
838 				LOG.error("Invalid index for deletion of collection record: " + deleteRecordIndex);
839 				throw new RuntimeException("Invalid index for deletion of collection record: " + deleteRecordIndex);
840 			}
841 		}
842 
843 		((List) maintCollection).remove(deleteRecordIndex);
844 
845 		
846 		if (KRADConstants.MAINTENANCE_EDIT_ACTION.equals(maintenanceForm.getMaintenanceAction()) ||
847 				KRADConstants.MAINTENANCE_COPY_ACTION.equals(maintenanceForm.getMaintenanceAction())) {
848 			bo = oldMaintainable.getBusinessObject();
849 			maintCollection = extractCollection(bo, collectionName);
850 
851 			if (collectionName == null) {
852 				LOG.error("Collection is null in parent business object.");
853 				throw new RuntimeException("Collection is null in parent business object.");
854 			}
855 
856 			((List) maintCollection).remove(deleteRecordIndex);
857 		}
858 
859 		
860 		
861 		
862 		
863 		
864 		
865 
866 
867 		
868 		
869 		
870 		
871 		
872 		
873 		
874 		
875 		
876 		
877 		
878 		
879 		
880 		
881 		
882 		
883 		
884 		
885 		
886 		
887 		
888 		
889 		
890 		
891 		
892 		
893 		
894 		
895 		
896 
897 		doProcessingAfterPost( (KualiMaintenanceForm) form, request );
898 
899 		return mapping.findForward(RiceConstants.MAPPING_BASIC);
900 	}
901 
902 	
903 
904 
905 	public ActionForward toggleInactiveRecordDisplay(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
906 		KualiMaintenanceForm maintenanceForm = (KualiMaintenanceForm) form;
907 		MaintenanceDocument document = (MaintenanceDocument) maintenanceForm.getDocument();
908 		Maintainable oldMaintainable = document.getOldMaintainableObject();
909 		Maintainable newMaintainable = document.getNewMaintainableObject();
910 
911 		String collectionName = extractCollectionName(request, KRADConstants.TOGGLE_INACTIVE_METHOD);
912 		if (collectionName == null) {
913 			LOG.error("Unable to get find collection name in request.");
914 			throw new RuntimeException("Unable to get find collection class in request.");
915 		}  
916 
917 		String parameterName = (String) request.getAttribute(KRADConstants.METHOD_TO_CALL_ATTRIBUTE);
918 		boolean showInactive = Boolean.parseBoolean(StringUtils.substringBetween(parameterName, KRADConstants.METHOD_TO_CALL_BOPARM_LEFT_DEL, "."));
919 
920 		oldMaintainable.setShowInactiveRecords(collectionName, showInactive);
921 		newMaintainable.setShowInactiveRecords(collectionName, showInactive);
922 
923 		return mapping.findForward(RiceConstants.MAPPING_BASIC);
924 	}
925 
926 
927 
928 	
929 
930 
931 
932 
933     protected void clearPrimaryKeyFields(MaintenanceDocument document) {
934 		
935 		PersistableBusinessObject bo = document.getNewMaintainableObject().getBusinessObject();
936 		List<String> keyFieldNames = getBusinessObjectMetaDataService().listPrimaryKeyFieldNames(bo.getClass());
937 
938 		for (String keyFieldName : keyFieldNames) {
939 			try {
940 				ObjectUtils.setObjectProperty(bo, keyFieldName, null);
941 			}
942 			catch (Exception e) {
943 				LOG.error("Unable to clear primary key field: " + e.getMessage());
944 				throw new RuntimeException("Unable to clear primary key field: " + e.getMessage());
945 			}
946 		}
947 	}
948 
949 	
950 
951 
952 
953 
954 
955     protected void clearUnauthorizedNewFields(MaintenanceDocument document) {
956 		
957 		Person user = GlobalVariables.getUserSession().getPerson();
958 
959 		
960 		MaintenanceDocumentAuthorizer documentAuthorizer = (MaintenanceDocumentAuthorizer) getDocumentHelperService().getDocumentAuthorizer(document);
961 
962 		
963 		MaintenanceDocumentRestrictions maintenanceDocumentRestrictions = getBusinessObjectAuthorizationService().getMaintenanceDocumentRestrictions(document, user);
964 
965 		
966 		PersistableBusinessObject newBo = document.getNewMaintainableObject().getBusinessObject();
967 
968 		document.getNewMaintainableObject().clearBusinessObjectOfRestrictedValues(maintenanceDocumentRestrictions);
969 	}
970 
971 	
972 
973 
974 
975 
976 	@SuppressWarnings("unchecked")
977 	protected void doProcessingAfterPost( KualiForm form, HttpServletRequest request ) {
978 		MaintenanceDocument document = (MaintenanceDocument) ((KualiMaintenanceForm)form).getDocument();
979 		Maintainable maintainable = document.getNewMaintainableObject();
980 		PersistableBusinessObject bo = maintainable.getBusinessObject();
981 
982 		getBusinessObjectService().linkUserFields(bo);
983 
984 		maintainable.processAfterPost(document, request.getParameterMap() );
985 	}
986 
987 	protected void doProcessingAfterPost( KualiForm form, Map<String,String[]> parameters ) {
988 		MaintenanceDocument document = (MaintenanceDocument) ((KualiMaintenanceForm)form).getDocument();
989 		Maintainable maintainable = document.getNewMaintainableObject();
990 		PersistableBusinessObject bo = maintainable.getBusinessObject();
991 
992 		getBusinessObjectService().linkUserFields(bo);
993 
994 		maintainable.processAfterPost(document, parameters );
995 	}
996 
997 	protected void populateAuthorizationFields(KualiDocumentFormBase formBase){
998 		super.populateAuthorizationFields(formBase);
999 
1000 		KualiMaintenanceForm maintenanceForm = (KualiMaintenanceForm) formBase;
1001 		MaintenanceDocument maintenanceDocument = (MaintenanceDocument) maintenanceForm.getDocument();
1002 		MaintenanceDocumentAuthorizer maintenanceDocumentAuthorizer = (MaintenanceDocumentAuthorizer) getDocumentHelperService().getDocumentAuthorizer(maintenanceDocument);
1003 		Person user = GlobalVariables.getUserSession().getPerson();
1004 		maintenanceForm.setReadOnly(!formBase.getDocumentActions().containsKey(KRADConstants.KUALI_ACTION_CAN_EDIT));
1005 		MaintenanceDocumentRestrictions maintenanceDocumentAuthorizations = getBusinessObjectAuthorizationService().getMaintenanceDocumentRestrictions(maintenanceDocument, user);
1006 		maintenanceForm.setAuthorizations(maintenanceDocumentAuthorizations);
1007 	}
1008 
1009 	public LookupService getLookupService() {
1010 		if ( lookupService == null ) {
1011 			lookupService = KRADServiceLocatorWeb.getLookupService();
1012 		}
1013 		return this.lookupService;
1014 	}
1015 
1016 	public LookupResultsService getLookupResultsService() {
1017 		if ( lookupResultsService == null ) {
1018 			lookupResultsService = KNSServiceLocator.getLookupResultsService();
1019 		}
1020 		return this.lookupResultsService;
1021 	}
1022 
1023 }