Coverage Report - org.kuali.rice.kns.web.struts.action.KualiMaintenanceDocumentAction
 
Classes in this File Line Coverage Branch Coverage Complexity
KualiMaintenanceDocumentAction
0%
0/402
0%
0/192
5.065
 
 1  
 
 2  
 /*
 3  
  * Copyright 2005-2007 The Kuali Foundation
 4  
  * 
 5  
  * Licensed under the Educational Community License, Version 2.0 (the "License");
 6  
  * you may not use this file except in compliance with the License.
 7  
  * You may obtain a copy of the License at
 8  
  * 
 9  
  * http://www.opensource.org/licenses/ecl2.php
 10  
  * 
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 16  
  */
 17  
 package org.kuali.rice.kns.web.struts.action;
 18  
 
 19  
 import java.lang.reflect.Field;
 20  
 import java.lang.reflect.InvocationTargetException;
 21  
 import java.security.GeneralSecurityException;
 22  
 import java.util.ArrayList;
 23  
 import java.util.Collection;
 24  
 import java.util.Enumeration;
 25  
 import java.util.HashMap;
 26  
 import java.util.Iterator;
 27  
 import java.util.List;
 28  
 import java.util.Map;
 29  
 
 30  
 import javax.persistence.PersistenceException;
 31  
 import javax.servlet.http.HttpServletRequest;
 32  
 import javax.servlet.http.HttpServletResponse;
 33  
 
 34  
 import org.apache.commons.beanutils.PropertyUtils;
 35  
 import org.apache.commons.lang.StringUtils;
 36  
 import org.apache.ojb.broker.metadata.ClassNotPersistenceCapableException;
 37  
 import org.apache.struts.action.ActionForm;
 38  
 import org.apache.struts.action.ActionForward;
 39  
 import org.apache.struts.action.ActionMapping;
 40  
 import org.kuali.rice.core.jpa.metadata.EntityDescriptor;
 41  
 import org.kuali.rice.core.jpa.metadata.FieldDescriptor;
 42  
 import org.kuali.rice.core.jpa.metadata.MetadataManager;
 43  
 import org.kuali.rice.core.service.EncryptionService;
 44  
 import org.kuali.rice.core.util.OrmUtils;
 45  
 import org.kuali.rice.core.util.RiceConstants;
 46  
 import org.kuali.rice.kew.util.KEWConstants;
 47  
 import org.kuali.rice.kim.bo.Person;
 48  
 import org.kuali.rice.kns.bo.DocumentAttachment;
 49  
 import org.kuali.rice.kns.bo.PersistableAttachment;
 50  
 import org.kuali.rice.kns.bo.PersistableBusinessObject;
 51  
 import org.kuali.rice.kns.bo.PersistableBusinessObjectExtension;
 52  
 import org.kuali.rice.kns.datadictionary.DocumentEntry;
 53  
 import org.kuali.rice.kns.datadictionary.MaintainableCollectionDefinition;
 54  
 import org.kuali.rice.kns.document.MaintenanceDocument;
 55  
 import org.kuali.rice.kns.document.MaintenanceDocumentBase;
 56  
 import org.kuali.rice.kns.document.authorization.MaintenanceDocumentAuthorizer;
 57  
 import org.kuali.rice.kns.document.authorization.MaintenanceDocumentRestrictions;
 58  
 import org.kuali.rice.kns.exception.DocumentTypeAuthorizationException;
 59  
 import org.kuali.rice.kns.lookup.LookupResultsService;
 60  
 import org.kuali.rice.kns.maintenance.Maintainable;
 61  
 import org.kuali.rice.kns.rule.event.KualiAddLineEvent;
 62  
 import org.kuali.rice.kns.service.KNSServiceLocator;
 63  
 import org.kuali.rice.kns.service.LookupService;
 64  
 import org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService;
 65  
 import org.kuali.rice.kns.util.GlobalVariables;
 66  
 import org.kuali.rice.kns.util.KNSConstants;
 67  
 import org.kuali.rice.kns.util.KNSPropertyConstants;
 68  
 import org.kuali.rice.kns.util.MaintenanceUtils;
 69  
 import org.kuali.rice.kns.util.ObjectUtils;
 70  
 import org.kuali.rice.kns.util.RiceKeyConstants;
 71  
 import org.kuali.rice.kns.util.WebUtils;
 72  
 import org.kuali.rice.kns.web.format.Formatter;
 73  
 import org.kuali.rice.kns.web.struts.form.KualiDocumentFormBase;
 74  
 import org.kuali.rice.kns.web.struts.form.KualiForm;
 75  
 import org.kuali.rice.kns.web.struts.form.KualiMaintenanceForm;
 76  
 
 77  
 /**
 78  
  * This class handles actions for maintenance documents. These include creating new edit, and copying of maintenance records.
 79  
  */
 80  
 public class KualiMaintenanceDocumentAction extends KualiDocumentActionBase {
 81  0
     protected static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(KualiMaintenanceDocumentAction.class);
 82  
 
 83  0
     protected MaintenanceDocumentDictionaryService maintenanceDocumentDictionaryService = null;
 84  
     protected EncryptionService encryptionService;
 85  
     protected LookupService lookupService;
 86  
     protected LookupResultsService lookupResultsService;
 87  
 
 88  
         public KualiMaintenanceDocumentAction() {
 89  0
                 super();
 90  0
                 maintenanceDocumentDictionaryService = KNSServiceLocator.getMaintenanceDocumentDictionaryService();
 91  0
                 encryptionService = KNSServiceLocator.getEncryptionService();
 92  0
         }
 93  
 
 94  
         @Override
 95  
         public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {        
 96  0
                 request.setAttribute(KNSConstants.PARAM_MAINTENANCE_VIEW_MODE, KNSConstants.PARAM_MAINTENANCE_VIEW_MODE_MAINTENANCE);
 97  0
                 return super.execute(mapping, form, request, response);
 98  
         }
 99  
 
 100  
         /**
 101  
          * Calls setup Maintenance for new action.
 102  
          */
 103  
         public ActionForward start(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 104  0
                 request.setAttribute(KNSConstants.MAINTENANCE_ACTN, KNSConstants.MAINTENANCE_NEW_ACTION);
 105  0
                 return setupMaintenance(mapping, form, request, response, KNSConstants.MAINTENANCE_NEW_ACTION);
 106  
         }
 107  
 
 108  
         /**
 109  
          * Calls setupMaintenance for copy action.
 110  
          */
 111  
         public ActionForward copy(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 112  
                 // check for copy document number
 113  0
                 if (request.getParameter("document." + KNSPropertyConstants.DOCUMENT_NUMBER) == null) { // object copy
 114  0
                         return setupMaintenance(mapping, form, request, response, KNSConstants.MAINTENANCE_COPY_ACTION);
 115  
                 }
 116  
                 else { // document copy
 117  0
                         throw new UnsupportedOperationException("System does not support copying of maintenance documents.");
 118  
                 }
 119  
         }
 120  
 
 121  
         /**
 122  
          * Calls setupMaintenance for edit action.
 123  
          */
 124  
         public ActionForward edit(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 125  
         
 126  0
                 return setupMaintenance(mapping, form, request, response, KNSConstants.MAINTENANCE_EDIT_ACTION);
 127  
         }
 128  
 
 129  
         /**
 130  
          * KUALRice 3070 Calls setupMaintenance for delete action.
 131  
          */
 132  
         public ActionForward delete(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 133  0
                 if (isFormRepresentingLockObject((KualiDocumentFormBase)form)) {
 134  0
                          return super.delete(mapping, form, request, response);
 135  
                 }
 136  0
                 GlobalVariables.getMessageList().add(RiceKeyConstants.MESSAGE_DELETE);
 137  0
                 return setupMaintenance(mapping, form, request, response, KNSConstants.MAINTENANCE_DELETE_ACTION);
 138  
         }
 139  
         
 140  
         /**
 141  
          * Calls setupMaintenance for new object that have existing objects attributes.
 142  
          */
 143  
         public ActionForward newWithExisting(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 144  0
                 return setupMaintenance(mapping, form, request, response, KNSConstants.MAINTENANCE_NEWWITHEXISTING_ACTION);
 145  
         }
 146  
 
 147  
         /**
 148  
          * Gets a new document for a maintenance record. The maintainable is specified with the documentTypeName or business object
 149  
          * class request parameter and request parameters are parsed for key values for retrieving the business object. Forward to the
 150  
          * maintenance jsp which renders the page based on the maintainable's field specifications. Retrieves an existing business
 151  
          * object for edit and copy. Checks locking on edit.
 152  
          */
 153  
     protected ActionForward setupMaintenance(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response, String maintenanceAction) throws Exception {
 154  0
                 KualiMaintenanceForm maintenanceForm = (KualiMaintenanceForm) form;
 155  0
                 MaintenanceDocument document = null;
 156  
 
 157  
                 // create a new document object, if required (on NEW object, or other reasons)
 158  0
                 if (maintenanceForm.getDocument() == null) {
 159  0
                         if (StringUtils.isEmpty(maintenanceForm.getBusinessObjectClassName()) && StringUtils.isEmpty(maintenanceForm.getDocTypeName())) {
 160  0
                                 throw new IllegalArgumentException("Document type name or bo class not given!");
 161  
                         }
 162  
 
 163  0
                         String documentTypeName = maintenanceForm.getDocTypeName();
 164  
                         // get document type if not passed
 165  0
                         if (StringUtils.isEmpty(documentTypeName)) {
 166  0
                                 documentTypeName = maintenanceDocumentDictionaryService.getDocumentTypeName(Class.forName(maintenanceForm.getBusinessObjectClassName()));
 167  0
                                 maintenanceForm.setDocTypeName(documentTypeName);
 168  
                         }
 169  
 
 170  0
                         if (StringUtils.isEmpty(documentTypeName)) {
 171  0
                                 throw new RuntimeException("documentTypeName is empty; does this Business Object have a maintenance document definition? " + maintenanceForm.getBusinessObjectClassName());
 172  
                         }
 173  
 
 174  
                         // check doc type allows new or copy if that action was requested
 175  0
                         if (KNSConstants.MAINTENANCE_NEW_ACTION.equals(maintenanceAction) || KNSConstants.MAINTENANCE_COPY_ACTION.equals(maintenanceAction)) {
 176  0
                                 Class boClass = maintenanceDocumentDictionaryService.getBusinessObjectClass(documentTypeName);
 177  0
                                 boolean allowsNewOrCopy = getBusinessObjectAuthorizationService().canCreate(boClass, GlobalVariables.getUserSession().getPerson(), documentTypeName);
 178  0
                                 if (!allowsNewOrCopy) {
 179  0
                                         LOG.error("Document type " + documentTypeName + " does not allow new or copy actions.");
 180  0
                                         throw new DocumentTypeAuthorizationException(GlobalVariables.getUserSession().getPerson().getPrincipalId(), "newOrCopy", documentTypeName);
 181  
                                 }
 182  
                         }
 183  
 
 184  
                         // get new document from service
 185  0
                         document = (MaintenanceDocument) getDocumentService().getNewDocument(maintenanceForm.getDocTypeName());
 186  
                         // Check for an auto-incrementing PK and set it if needed
 187  
                         //            if (document.getNewMaintainableObject().getBoClass().isAnnotationPresent(Sequence.class)) {
 188  
                         //                            Sequence sequence = (Sequence) document.getNewMaintainableObject().getBoClass().getAnnotation(Sequence.class);
 189  
                         //                            Long pk = OrmUtils.getNextAutoIncValue(sequence);
 190  
                         //                            OrmUtils.populateAutoIncValue(document.getOldMaintainableObject().getBusinessObject(), pk);
 191  
                         //                            OrmUtils.populateAutoIncValue(document.getNewMaintainableObject().getBusinessObject(), pk);
 192  
                         //                            document.getOldMaintainableObject().getBusinessObject().setAutoIncrementSet(true);
 193  
                         //                            document.getNewMaintainableObject().getBusinessObject().setAutoIncrementSet(true);
 194  
                         //            }
 195  0
                         maintenanceForm.setDocument(document);
 196  0
                 }
 197  
                 else {
 198  0
                         document = (MaintenanceDocument) maintenanceForm.getDocument();
 199  
                 }
 200  
 
 201  
                 // retrieve business object from request parameters
 202  0
                 if (!(KNSConstants.MAINTENANCE_NEW_ACTION.equals(maintenanceAction)) && !(KNSConstants.MAINTENANCE_NEWWITHEXISTING_ACTION.equals(maintenanceAction))) {
 203  0
                         Map requestParameters = buildKeyMapFromRequest(document.getNewMaintainableObject(), request);
 204  0
             PersistableBusinessObject oldBusinessObject = null;
 205  
             try {
 206  0
                     oldBusinessObject = (PersistableBusinessObject) getLookupService().findObjectBySearch(Class.forName(maintenanceForm.getBusinessObjectClassName()), requestParameters);
 207  0
             } catch ( ClassNotPersistenceCapableException ex ) {
 208  0
                     if ( !document.getOldMaintainableObject().isExternalBusinessObject() ) {
 209  0
                             throw new RuntimeException( "BO Class: " + maintenanceForm.getBusinessObjectClassName() + " is not persistable and is not externalizable - configuration error" );
 210  
                     }
 211  
                     // otherwise, let fall through
 212  0
             }
 213  0
                         if (oldBusinessObject == null && !document.getOldMaintainableObject().isExternalBusinessObject()) {
 214  0
                 throw new RuntimeException("Cannot retrieve old record for maintenance document, incorrect parameters passed on maint url: " + requestParameters );
 215  
                         } 
 216  
 
 217  0
                         if(document.getOldMaintainableObject().isExternalBusinessObject()){
 218  0
                     if ( oldBusinessObject == null ) {
 219  
                             try {
 220  0
                                     oldBusinessObject = (PersistableBusinessObject)document.getOldMaintainableObject().getBoClass().newInstance();
 221  0
                             } catch ( Exception ex ) {
 222  0
                                     throw new RuntimeException( "External BO maintainable was null and unable to instantiate for old maintainable object.", ex );
 223  0
                             }
 224  
                     }
 225  0
                                 populateBOWithCopyKeyValues(request, oldBusinessObject, document.getOldMaintainableObject());
 226  0
                                 document.getOldMaintainableObject().prepareBusinessObject(oldBusinessObject);
 227  0
                     oldBusinessObject = document.getOldMaintainableObject().getBusinessObject();
 228  
                         }
 229  
 
 230  
                         // Temp solution for loading extension objects - need to find a better way
 231  0
                         if (OrmUtils.isJpaEnabled() && OrmUtils.isJpaAnnotated(oldBusinessObject.getClass()) && oldBusinessObject.getExtension() != null && OrmUtils.isJpaAnnotated(oldBusinessObject.getExtension().getClass())) {
 232  0
                                 if (oldBusinessObject.getExtension() != null) {
 233  0
                                         PersistableBusinessObjectExtension boe = oldBusinessObject.getExtension();
 234  0
                                         EntityDescriptor entity = MetadataManager.getEntityDescriptor(oldBusinessObject.getExtension().getClass());
 235  0
                                         org.kuali.rice.core.jpa.criteria.Criteria extensionCriteria = new org.kuali.rice.core.jpa.criteria.Criteria(boe.getClass().getName());
 236  0
                                         for (FieldDescriptor fieldDescriptor : entity.getPrimaryKeys()) {
 237  
                                                 try {
 238  0
                                                         Field field = oldBusinessObject.getClass().getDeclaredField(fieldDescriptor.getName());
 239  0
                                                         field.setAccessible(true);
 240  0
                                                         extensionCriteria.eq(fieldDescriptor.getName(), field.get(oldBusinessObject));
 241  0
                                                 } catch (Exception e) {
 242  0
                                                         LOG.error(e.getMessage(),e);
 243  0
                                                 }
 244  
                                         }                                
 245  
                                         try {
 246  0
                                                 boe = (PersistableBusinessObjectExtension) new org.kuali.rice.core.jpa.criteria.QueryByCriteria(getEntityManagerFactory().createEntityManager(), extensionCriteria).toQuery().getSingleResult();
 247  0
                                         } catch (PersistenceException e) {}
 248  0
                                         oldBusinessObject.setExtension(boe);
 249  
                                 }
 250  
                         }
 251  
 
 252  0
                         PersistableBusinessObject newBusinessObject = (PersistableBusinessObject) ObjectUtils.deepCopy(oldBusinessObject);
 253  
 
 254  
                         // set business object instance for editing
 255  0
                         document.getOldMaintainableObject().setBusinessObject(oldBusinessObject);
 256  0
                         document.getOldMaintainableObject().setBoClass(Class.forName(maintenanceForm.getBusinessObjectClassName()));
 257  0
                         document.getNewMaintainableObject().setBusinessObject(newBusinessObject);
 258  0
                         document.getNewMaintainableObject().setBoClass(Class.forName(maintenanceForm.getBusinessObjectClassName()));
 259  
 
 260  
                         // on a COPY, clear any fields that this user isnt authorized for, and also
 261  
                         // clear the primary key fields
 262  0
                         if (KNSConstants.MAINTENANCE_COPY_ACTION.equals(maintenanceAction)) {
 263  0
                                 if (!document.isFieldsClearedOnCopy()) {
 264  
                                         //for issue KULRice 3072
 265  0
                                         Class boClass = maintenanceDocumentDictionaryService.getBusinessObjectClass(maintenanceForm.getDocTypeName());
 266  0
                                         if(!maintenanceDocumentDictionaryService.getPreserveLockingKeysOnCopy(boClass))
 267  0
                                                 clearPrimaryKeyFields(document);
 268  
 
 269  0
                                         clearUnauthorizedNewFields(document);
 270  
 
 271  0
                                         Maintainable maintainable = document.getNewMaintainableObject();
 272  
 
 273  0
                                         maintainable.processAfterCopy( document, request.getParameterMap() );
 274  
 
 275  
                                         // mark so that this clearing doesnt happen again
 276  0
                                         document.setFieldsClearedOnCopy(true);
 277  
 
 278  
                                         // mark so that blank required fields will be populated with default values
 279  0
                                         maintainable.setGenerateBlankRequiredValues(maintenanceForm.getDocTypeName());
 280  0
                                 }
 281  
                         }
 282  0
                         else if (KNSConstants.MAINTENANCE_EDIT_ACTION.equals(maintenanceAction)) {                                                
 283  0
                                 boolean allowsEdit = getBusinessObjectAuthorizationService().canMaintain(oldBusinessObject, GlobalVariables.getUserSession().getPerson(), document.getDocumentHeader().getWorkflowDocument().getDocumentType());  
 284  0
                                 if (!allowsEdit) {
 285  0
                                         LOG.error("Document type " + document.getDocumentHeader().getWorkflowDocument().getDocumentType() + " does not allow edit actions.");
 286  0
                                         throw  new DocumentTypeAuthorizationException(GlobalVariables.getUserSession().getPerson().getPrincipalId(), "edit", document.getDocumentHeader().getWorkflowDocument().getDocumentType());
 287  
                                 }
 288  0
                                 document.getNewMaintainableObject().processAfterEdit( document, request.getParameterMap() );
 289  0
                         }
 290  
                         //3070
 291  0
                         else if (KNSConstants.MAINTENANCE_DELETE_ACTION.equals(maintenanceAction)) {                        
 292  0
                                 boolean allowsDelete = getBusinessObjectAuthorizationService().canMaintain(oldBusinessObject, GlobalVariables.getUserSession().getPerson(), document.getDocumentHeader().getWorkflowDocument().getDocumentType());  
 293  0
                                 if (!allowsDelete) {
 294  0
                                         LOG.error("Document type " + document.getDocumentHeader().getWorkflowDocument().getDocumentType() + " does not allow delete actions.");
 295  0
                                         throw  new DocumentTypeAuthorizationException(GlobalVariables.getUserSession().getPerson().getPrincipalId(), "delete", document.getDocumentHeader().getWorkflowDocument().getDocumentType());
 296  
                                 }        
 297  
                                 //document.getNewMaintainableObject().processAfterEdit( document, request.getParameterMap() );
 298  
                         }
 299  
                         // Check for an auto-incrementing PK and set it if needed
 300  
                         //            if (document.getNewMaintainableObject().getBoClass().isAnnotationPresent(Sequence.class)) {
 301  
                         //                            Sequence sequence = (Sequence) document.getNewMaintainableObject().getBoClass().getAnnotation(Sequence.class);
 302  
                         //                            Long pk = OrmUtils.getNextAutoIncValue(sequence);
 303  
                         //                            OrmUtils.populateAutoIncValue(document.getNewMaintainableObject().getBusinessObject(), pk);
 304  
                         //                            document.getNewMaintainableObject().getBusinessObject().setAutoIncrementSet(true);
 305  
                         //            }
 306  
                 }
 307  
                 // if new with existing we need to populate we need to populate with passed in parameters
 308  0
                 if (KNSConstants.MAINTENANCE_NEWWITHEXISTING_ACTION.equals(maintenanceAction)) {
 309  
                         // TODO: this code should be abstracted out into a helper
 310  
                         // also is it a problem that we're not calling setGenerateDefaultValues? it blanked out the below values when I did
 311  
                         // maybe we need a new generateDefaultValues that doesn't overwrite?
 312  0
                         PersistableBusinessObject newBO = document.getNewMaintainableObject().getBusinessObject();
 313  0
                         Map<String, String> parameters = buildKeyMapFromRequest(document.getNewMaintainableObject(), request);
 314  0
                         copyParametersToBO(parameters, newBO);
 315  0
                         newBO.refresh();
 316  0
                         document.getNewMaintainableObject().setupNewFromExisting( document, request.getParameterMap() );
 317  
                 }
 318  
 
 319  
                 // for new maintainble need to pick up default values
 320  0
                 if (KNSConstants.MAINTENANCE_NEW_ACTION.equals(maintenanceAction)) {
 321  0
                         document.getNewMaintainableObject().setGenerateDefaultValues(maintenanceForm.getDocTypeName());
 322  0
                         document.getNewMaintainableObject().processAfterNew( document, request.getParameterMap() );
 323  
 
 324  
                         // If a maintenance lock exists, warn the user.
 325  0
                         MaintenanceUtils.checkForLockingDocument(document.getNewMaintainableObject(), false);
 326  
                 }
 327  
 
 328  
                 // set maintenance action state
 329  0
                 document.getNewMaintainableObject().setMaintenanceAction(maintenanceAction);
 330  0
                 maintenanceForm.setMaintenanceAction(maintenanceAction);
 331  
 
 332  
                 // attach any extra JS from the data dictionary
 333  0
                 if (LOG.isDebugEnabled()) {
 334  0
                         LOG.debug("maintenanceForm.getAdditionalScriptFiles(): " + maintenanceForm.getAdditionalScriptFiles());
 335  
                 }
 336  0
                 if (maintenanceForm.getAdditionalScriptFiles().isEmpty()) {
 337  0
                         DocumentEntry docEntry = getDataDictionaryService().getDataDictionary().getDocumentEntry(document.getDocumentHeader().getWorkflowDocument().getDocumentType());
 338  0
                         maintenanceForm.getAdditionalScriptFiles().addAll(docEntry.getWebScriptFiles());
 339  
                 }
 340  
 
 341  
                 // Retrieve notes topic display flag from data dictionary and add to document
 342  
                 //      
 343  0
                 DocumentEntry entry = maintenanceDocumentDictionaryService.getMaintenanceDocumentEntry(document.getDocumentHeader().getWorkflowDocument().getDocumentType());
 344  0
                 document.setDisplayTopicFieldInNotes(entry.getDisplayTopicFieldInNotes());
 345  
 
 346  0
                 return mapping.findForward(RiceConstants.MAPPING_BASIC);
 347  
         }
 348  
 
 349  
     protected void populateBOWithCopyKeyValues(HttpServletRequest request, PersistableBusinessObject oldBusinessObject, Maintainable oldMaintainableObject) throws Exception{
 350  0
                 List keyFieldNamesToCopy = new ArrayList();
 351  
                 Map<String, String> parametersToCopy;
 352  0
                 if (!StringUtils.isBlank(request.getParameter(KNSConstants.COPY_KEYS))) {
 353  0
                         String[] copyKeys = request.getParameter(KNSConstants.COPY_KEYS).split(KNSConstants.FIELD_CONVERSIONS_SEPARATOR);
 354  0
                         for (String copyKey: copyKeys) {
 355  0
                                 keyFieldNamesToCopy.add(copyKey);
 356  
                         }
 357  
                 }
 358  0
                 parametersToCopy = getRequestParameters(keyFieldNamesToCopy, oldMaintainableObject, request);
 359  0
                 if(parametersToCopy!=null && parametersToCopy.size()>0){
 360  0
                         copyParametersToBO(parametersToCopy, oldBusinessObject);
 361  
                 }
 362  0
         }
 363  
 
 364  
     protected void copyParametersToBO(Map<String, String> parameters, PersistableBusinessObject newBO) throws Exception{
 365  0
                 for (String parmName : parameters.keySet()) {
 366  0
                         String propertyValue = parameters.get(parmName);
 367  
 
 368  0
                         if (StringUtils.isNotBlank(propertyValue)) {
 369  0
                                 String propertyName = parmName;
 370  
                                 // set value of property in bo
 371  0
                                 if (PropertyUtils.isWriteable(newBO, propertyName)) {
 372  0
                                         Class type = ObjectUtils.easyGetPropertyType(newBO, propertyName);
 373  0
                                         if (type != null && Formatter.getFormatter(type) != null) {
 374  0
                                                 Formatter formatter = Formatter.getFormatter(type);
 375  0
                                                 Object obj = formatter.convertFromPresentationFormat(propertyValue);
 376  0
                                                 ObjectUtils.setObjectProperty(newBO, propertyName, obj.getClass(), obj);
 377  0
                                         }
 378  
                                         else {
 379  0
                                                 ObjectUtils.setObjectProperty(newBO, propertyName, String.class, propertyValue);
 380  
                                         }
 381  
                                 }
 382  
                         }
 383  0
                 }
 384  0
         }
 385  
 
 386  
         /**
 387  
          * Downloads the attachment to the user's browser
 388  
          *
 389  
          * @param mapping
 390  
          * @param form
 391  
          * @param request
 392  
          * @param response
 393  
          * @return ActionForward
 394  
          * @throws Exception
 395  
          */
 396  
         public ActionForward downloadAttachment(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 397  0
                 KualiDocumentFormBase documentForm = (KualiDocumentFormBase) form;
 398  0
                 MaintenanceDocumentBase document = (MaintenanceDocumentBase) documentForm.getDocument();
 399  0
                 document.refreshReferenceObject("attachment");
 400  0
                 DocumentAttachment attachment = document.getAttachment();
 401  0
                 if(attachment != null) {
 402  0
                         streamToResponse(attachment.getAttachmentContent(), attachment.getFileName(), attachment.getContentType(), response); 
 403  
                 }
 404  0
                 return null;
 405  
         }
 406  
 
 407  
 
 408  
         /**
 409  
          * 
 410  
          * This method used to replace the attachment
 411  
          * @param mapping
 412  
          * @param form
 413  
          * @param request
 414  
          * @param response
 415  
          * @return
 416  
          * @throws Exception
 417  
          */
 418  
         public ActionForward replaceAttachment(ActionMapping mapping, ActionForm form, HttpServletRequest request,
 419  
                         HttpServletResponse response) throws Exception {
 420  0
                 KualiDocumentFormBase documentForm = (KualiDocumentFormBase) form;
 421  0
                 MaintenanceDocumentBase document = (MaintenanceDocumentBase) documentForm.getDocument();
 422  0
                 document.refreshReferenceObject("attachment");
 423  0
                 getBusinessObjectService().delete(document.getAttachment());
 424  0
                 return mapping.findForward(RiceConstants.MAPPING_BASIC);
 425  
         }
 426  
 
 427  
         /**
 428  
          * route the document using the document service
 429  
          * 
 430  
          * @param mapping
 431  
          * @param form
 432  
          * @param request
 433  
          * @param response
 434  
          * @return ActionForward
 435  
          * @throws Exception
 436  
          */
 437  
         @Override
 438  
         public ActionForward route(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 439  0
                 KualiDocumentFormBase documentForm = (KualiDocumentFormBase) form;
 440  0
                 MaintenanceDocumentBase document = (MaintenanceDocumentBase) documentForm.getDocument();
 441  
 
 442  0
                 ActionForward forward = super.route(mapping, form, request, response);
 443  0
                 if(document.getNewMaintainableObject().getBusinessObject() instanceof PersistableAttachment) {
 444  0
                         PersistableAttachment bo = (PersistableAttachment) getBusinessObjectService().retrieve(document.getNewMaintainableObject().getBusinessObject());
 445  0
                         request.setAttribute("fileName", bo.getFileName());
 446  
                 }
 447  
 
 448  0
                 return forward;
 449  
         }
 450  
 
 451  
         /**
 452  
          * Handles creating and loading of documents.
 453  
          */
 454  
         @Override
 455  
         public ActionForward docHandler(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 456  0
                 super.docHandler(mapping, form, request, response);
 457  0
                 KualiMaintenanceForm kualiMaintenanceForm = (KualiMaintenanceForm) form;
 458  
 
 459  0
                 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) {
 460  0
                         if (kualiMaintenanceForm.getDocument() instanceof MaintenanceDocument) {
 461  0
                                 kualiMaintenanceForm.setReadOnly(true);
 462  0
                                 kualiMaintenanceForm.setMaintenanceAction(((MaintenanceDocument) kualiMaintenanceForm.getDocument()).getNewMaintainableObject().getMaintenanceAction());
 463  
 
 464  
                                 //Retrieving the FileName from BO table
 465  0
                                 Maintainable tmpMaintainable = ((MaintenanceDocument) kualiMaintenanceForm.getDocument()).getNewMaintainableObject();
 466  0
                                 if(tmpMaintainable.getBusinessObject() instanceof PersistableAttachment) {
 467  0
                                         PersistableAttachment bo = (PersistableAttachment) getBusinessObjectService().retrieve(tmpMaintainable.getBusinessObject());
 468  0
                                         if(bo != null)
 469  0
                                                 request.setAttribute("fileName", bo.getFileName());
 470  
                                 }
 471  0
                         }
 472  
                         else {
 473  0
                                 LOG.error("Illegal State: document is not a maintenance document");
 474  0
                                 throw new IllegalStateException("Document is not a maintenance document");
 475  
                         }
 476  
                 }
 477  0
                 else if (KEWConstants.INITIATE_COMMAND.equals(kualiMaintenanceForm.getCommand())) {
 478  0
                         kualiMaintenanceForm.setReadOnly(false);
 479  0
                         return setupMaintenance(mapping, form, request, response, KNSConstants.MAINTENANCE_NEW_ACTION);
 480  
                 }
 481  
                 else {
 482  0
                         LOG.error("We should never have gotten to here");
 483  0
                         throw new IllegalStateException("docHandler called with invalid parameters");
 484  
                 }
 485  0
                 return mapping.findForward(RiceConstants.MAPPING_BASIC);
 486  
         }
 487  
 
 488  
         /**
 489  
          * Called on return from a lookup.
 490  
          */
 491  
         @Override
 492  
         public ActionForward refresh(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 493  0
                 KualiMaintenanceForm maintenanceForm = (KualiMaintenanceForm) form;
 494  
 
 495  0
                 WebUtils.reuseErrorMapFromPreviousRequest(maintenanceForm);
 496  0
                 maintenanceForm.setDerivedValuesOnForm(request);
 497  
 
 498  0
                 refreshAdHocRoutingWorkgroupLookups(request, maintenanceForm);
 499  0
                 MaintenanceDocument document = (MaintenanceDocument) maintenanceForm.getDocument();
 500  
 
 501  
                 // call refresh on new maintainable
 502  0
                 Map<String, String> requestParams = new HashMap<String, String>();
 503  0
                 for (Enumeration i = request.getParameterNames(); i.hasMoreElements();) {
 504  0
                         String requestKey = (String) i.nextElement();
 505  0
                         String requestValue = request.getParameter(requestKey);
 506  0
                         requestParams.put(requestKey, requestValue);
 507  0
                 }
 508  
 
 509  
                 // Add multiple values from Lookup
 510  0
                 Collection<PersistableBusinessObject> rawValues = null;
 511  0
                 if (StringUtils.equals(KNSConstants.MULTIPLE_VALUE, maintenanceForm.getRefreshCaller())) {
 512  0
                         String lookupResultsSequenceNumber = maintenanceForm.getLookupResultsSequenceNumber();
 513  0
                         if (StringUtils.isNotBlank(lookupResultsSequenceNumber)) {
 514  
                                 // actually returning from a multiple value lookup
 515  0
                                 String lookupResultsBOClassName = maintenanceForm.getLookupResultsBOClassName();
 516  0
                                 Class lookupResultsBOClass = Class.forName(lookupResultsBOClassName);
 517  
 
 518  0
                                 rawValues = getLookupResultsService().retrieveSelectedResultBOs(lookupResultsSequenceNumber, lookupResultsBOClass, GlobalVariables.getUserSession().getPerson().getPrincipalId());
 519  
                         }
 520  
                 }
 521  
 
 522  0
                 if (rawValues != null) { // KULCOA-1073 - caused by this block running unnecessarily?
 523  
                         // we need to run the business rules on all the newly added items to the collection
 524  
                         // KULCOA-1000, KULCOA-1004 removed business rule validation on multiple value return
 525  
                         // (this was running before the objects were added anyway)
 526  
                         // getKualiRuleService().applyRules(new SaveDocumentEvent(document));
 527  0
                         String collectionName = maintenanceForm.getLookedUpCollectionName();
 528  
                         //TODO: Cathy remember to delete this block of comments after I've tested.            
 529  
                         //            PersistableBusinessObject bo = document.getNewMaintainableObject().getBusinessObject();
 530  
                         //            Collection maintCollection = this.extractCollection(bo, collectionName);
 531  
                         //            String docTypeName = ((MaintenanceDocument) maintenanceForm.getDocument()).getDocumentHeader().getWorkflowDocument().getDocumentType();
 532  
                         //            Class collectionClass = extractCollectionClass(docTypeName, collectionName);
 533  
                         //
 534  
                         //            List<MaintainableSectionDefinition> sections = maintenanceDocumentDictionaryService.getMaintainableSections(docTypeName);
 535  
                         //            Map<String, String> template = MaintenanceUtils.generateMultipleValueLookupBOTemplate(sections, collectionName);
 536  
                         //            for (PersistableBusinessObject nextBo : rawValues) {
 537  
                         //                PersistableBusinessObject templatedBo = (PersistableBusinessObject) ObjectUtils.createHybridBusinessObject(collectionClass, nextBo, template);
 538  
                         //                templatedBo.setNewCollectionRecord(true);
 539  
                         //                maintCollection.add(templatedBo);
 540  
                         //            }
 541  0
                         document.getNewMaintainableObject().addMultipleValueLookupResults(document, collectionName, rawValues, false, document.getNewMaintainableObject().getBusinessObject());
 542  0
                         if (LOG.isInfoEnabled()) {
 543  0
                                 LOG.info("********************doing editing 3 in refersh()***********************.");
 544  
                         }
 545  0
                         boolean isEdit = KNSConstants.MAINTENANCE_EDIT_ACTION.equals(maintenanceForm.getMaintenanceAction());
 546  0
                         boolean isCopy = KNSConstants.MAINTENANCE_COPY_ACTION.equals(maintenanceForm.getMaintenanceAction());
 547  
 
 548  0
                         if (isEdit || isCopy) {
 549  0
                                 document.getOldMaintainableObject().addMultipleValueLookupResults(document, collectionName, rawValues, true, document.getOldMaintainableObject().getBusinessObject());
 550  0
                                 document.getOldMaintainableObject().refresh(maintenanceForm.getRefreshCaller(), requestParams, document);
 551  
                         }
 552  
                 }
 553  
 
 554  0
                 document.getNewMaintainableObject().refresh(maintenanceForm.getRefreshCaller(), requestParams, document);
 555  
 
 556  
                 //pass out customAction from methodToCall parameter. Call processAfterPost
 557  0
                 String fullParameter = (String) request.getAttribute(KNSConstants.METHOD_TO_CALL_ATTRIBUTE);
 558  0
                 if(StringUtils.contains(fullParameter, KNSConstants.CUSTOM_ACTION)){
 559  0
                         String customAction = StringUtils.substringBetween(fullParameter, KNSConstants.METHOD_TO_CALL_PARM1_LEFT_DEL, KNSConstants.METHOD_TO_CALL_PARM1_RIGHT_DEL);
 560  0
                         String[] actionValue = new String[1];
 561  0
                         actionValue[0]= StringUtils.substringAfter(customAction, ".");
 562  0
                         Map<String,String[]> paramMap = request.getParameterMap();
 563  0
                         paramMap.put(KNSConstants.CUSTOM_ACTION, actionValue);
 564  0
                         doProcessingAfterPost( (KualiMaintenanceForm) form, paramMap );
 565  
                 }
 566  
 
 567  0
                 return mapping.findForward(RiceConstants.MAPPING_BASIC);
 568  
         }
 569  
 
 570  
         /**
 571  
          * Gets keys for the maintainable business object from the persistence metadata explorer. Checks for existence of key property
 572  
          * names as request parameters, if found adds them to the returned hash map.
 573  
          */
 574  
     protected Map buildKeyMapFromRequest(Maintainable maintainable, HttpServletRequest request) {
 575  0
                 List keyFieldNames = null;
 576  
                 // are override keys listed in the request? If so, then those need to be our keys,
 577  
                 // not the primary keye fields for the BO
 578  0
                 if (!StringUtils.isBlank(request.getParameter(KNSConstants.OVERRIDE_KEYS))) {
 579  0
                         String[] overrideKeys = request.getParameter(KNSConstants.OVERRIDE_KEYS).split(KNSConstants.FIELD_CONVERSIONS_SEPARATOR);
 580  0
                         keyFieldNames = new ArrayList();
 581  0
                         for (String overrideKey : overrideKeys) {
 582  0
                                 keyFieldNames.add(overrideKey);
 583  
                         }
 584  0
                 }
 585  
                 else {
 586  0
                         keyFieldNames = getBusinessObjectMetaDataService().listPrimaryKeyFieldNames(maintainable.getBusinessObject().getClass());
 587  
                 }
 588  0
                 return getRequestParameters(keyFieldNames, maintainable, request);
 589  
         }
 590  
 
 591  
     protected Map<String, String> getRequestParameters(List keyFieldNames, Maintainable maintainable, HttpServletRequest request){
 592  
 
 593  0
                 Map<String, String> requestParameters = new HashMap<String, String>();
 594  
 
 595  
 
 596  0
                 for (Iterator iter = keyFieldNames.iterator(); iter.hasNext();) {
 597  0
                         String keyPropertyName = (String) iter.next();
 598  
 
 599  0
                         if (request.getParameter(keyPropertyName) != null) {
 600  0
                                 String keyValue = request.getParameter(keyPropertyName);
 601  
 
 602  
                                 // Check if this element was encrypted, if it was decrypt it
 603  0
                 if (getBusinessObjectAuthorizationService().attributeValueNeedsToBeEncryptedOnFormsAndLinks(maintainable.getBoClass(), keyPropertyName)) {
 604  
                                         try {
 605  0
                             keyValue = StringUtils.removeEnd(keyValue, EncryptionService.ENCRYPTION_POST_PREFIX);
 606  0
                                                 keyValue = encryptionService.decrypt(keyValue);
 607  
                                         }
 608  0
                                         catch (GeneralSecurityException e) {
 609  0
                                                 throw new RuntimeException(e);
 610  0
                                         }
 611  
                                 }
 612  
 
 613  
 
 614  0
                                 requestParameters.put(keyPropertyName, keyValue);
 615  
                         }
 616  0
                 }
 617  
 
 618  0
                 return requestParameters;
 619  
 
 620  
         }
 621  
 
 622  
         /**
 623  
          * Convert a Request into a Map<String,String>. Technically, Request parameters do not neatly translate into a Map of Strings,
 624  
          * because a given parameter may legally appear more than once (so a Map of String[] would be more accurate.) This method should
 625  
          * be safe for business objects, but may not be reliable for more general uses.
 626  
          */
 627  
         String extractCollectionName(HttpServletRequest request, String methodToCall) {
 628  
                 // collection name and underlying object type from request parameter
 629  0
                 String parameterName = (String) request.getAttribute(KNSConstants.METHOD_TO_CALL_ATTRIBUTE);
 630  0
                 String collectionName = null;
 631  0
                 if (StringUtils.isNotBlank(parameterName)) {
 632  0
                         collectionName = StringUtils.substringBetween(parameterName, methodToCall + ".", ".(");
 633  
                 }
 634  0
                 return collectionName;
 635  
         }
 636  
 
 637  
         Collection extractCollection(PersistableBusinessObject bo, String collectionName) {
 638  
                 // retrieve the collection from the business object
 639  0
                 Collection maintCollection = (Collection) ObjectUtils.getPropertyValue(bo, collectionName);
 640  0
                 return maintCollection;
 641  
         }
 642  
 
 643  
         Class extractCollectionClass(String docTypeName, String collectionName) {
 644  0
                 return maintenanceDocumentDictionaryService.getCollectionBusinessObjectClass(docTypeName, collectionName);
 645  
         }
 646  
 
 647  
         /**
 648  
          * Adds a line to a collection being maintained in a many section.
 649  
          */
 650  
         public ActionForward addLine(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 651  0
                 KualiMaintenanceForm maintenanceForm = (KualiMaintenanceForm) form;
 652  0
                 MaintenanceDocument document = (MaintenanceDocument) maintenanceForm.getDocument();
 653  0
                 Maintainable oldMaintainable = document.getOldMaintainableObject();
 654  0
                 Maintainable newMaintainable = document.getNewMaintainableObject();
 655  
 
 656  0
                 String collectionName = extractCollectionName(request, KNSConstants.ADD_LINE_METHOD);
 657  0
                 if (collectionName == null) {
 658  0
                         LOG.error("Unable to get find collection name and class in request.");
 659  0
                         throw new RuntimeException("Unable to get find collection name and class in request.");
 660  
                 }
 661  
 
 662  
                 // if dealing with sub collection it will have a "["
 663  0
                 if ((StringUtils.lastIndexOf(collectionName, "]") + 1) == collectionName.length()) {
 664  0
                         collectionName = StringUtils.substringBeforeLast(collectionName, "[");
 665  
                 }
 666  
 
 667  0
                 PersistableBusinessObject bo = newMaintainable.getBusinessObject();
 668  0
                 Collection maintCollection = extractCollection(bo, collectionName);
 669  0
                 Class collectionClass = extractCollectionClass(((MaintenanceDocument) maintenanceForm.getDocument()).getDocumentHeader().getWorkflowDocument().getDocumentType(), collectionName);
 670  
 
 671  
                 // TODO: sort of collection, new instance should be first
 672  
 
 673  
                 // get the BO from the new collection line holder
 674  0
                 PersistableBusinessObject addBO = newMaintainable.getNewCollectionLine(collectionName);
 675  0
                 if (LOG.isDebugEnabled()) {
 676  0
                         LOG.debug("obtained addBO from newCollectionLine: " + addBO);
 677  
                 }
 678  
 
 679  
                 // link up the user fields, if any
 680  0
                 getBusinessObjectService().linkUserFields(addBO);
 681  
 
 682  
                 //KULRICE-4264 - a hook to change the state of the business object, which is the "new line" of a collection, before it is validated
 683  0
                 newMaintainable.processBeforeAddLine(collectionName, collectionClass, addBO);
 684  
                 
 685  
                 // apply rules to the addBO
 686  0
                 boolean rulePassed = false;
 687  0
                 if (LOG.isDebugEnabled()) {
 688  0
                         LOG.debug("about to call AddLineEvent applyRules: document=" + document + "\ncollectionName=" + collectionName + "\nBO=" + addBO);
 689  
                 }
 690  0
                 rulePassed = getKualiRuleService().applyRules(new KualiAddLineEvent(document, collectionName, addBO));
 691  
 
 692  
                 // if the rule evaluation passed, let's add it
 693  0
                 if (rulePassed) {
 694  0
                         if (LOG.isInfoEnabled()) {
 695  0
                                 LOG.info("********************doing editing 4 in addline()***********************.");
 696  
                         }
 697  
                         // if edit or copy action, just add empty instance to old maintainable
 698  0
                         boolean isEdit = KNSConstants.MAINTENANCE_EDIT_ACTION.equals(maintenanceForm.getMaintenanceAction());
 699  0
                         boolean isCopy = KNSConstants.MAINTENANCE_COPY_ACTION.equals(maintenanceForm.getMaintenanceAction());
 700  
 
 701  
 
 702  0
                         if (isEdit || isCopy) {
 703  0
                                 PersistableBusinessObject oldBo = oldMaintainable.getBusinessObject();
 704  0
                                 Collection oldMaintCollection = (Collection) ObjectUtils.getPropertyValue(oldBo, collectionName);
 705  
 
 706  0
                                 if (oldMaintCollection == null) {
 707  0
                                         oldMaintCollection = new ArrayList();
 708  
                                 }
 709  0
                                 if (PersistableBusinessObject.class.isAssignableFrom(collectionClass)) {
 710  0
                                         PersistableBusinessObject placeholder = (PersistableBusinessObject) collectionClass.newInstance();
 711  
                                         // KULRNE-4538: must set it as a new collection record, because the maintainable will set the BO that gets added
 712  
                                         // to the new maintainable as a new collection record
 713  
 
 714  
                                         // if not set, then the subcollections of the newly added object will appear as read only
 715  
                                         // see FieldUtils.getContainerRows on how the delete button is rendered
 716  0
                                         placeholder.setNewCollectionRecord(true);
 717  0
                                         ((List) oldMaintCollection).add(placeholder);
 718  0
                                 }
 719  
                                 else {
 720  0
                                         LOG.warn("Should be a instance of PersistableBusinessObject");
 721  0
                                         ((List) oldMaintCollection).add(collectionClass.newInstance());
 722  
                                 }
 723  
                                 // update collection in maintenance business object
 724  0
                                 ObjectUtils.setObjectProperty(oldBo, collectionName, List.class, oldMaintCollection);
 725  
                         }
 726  
 
 727  0
                         newMaintainable.addNewLineToCollection(collectionName);
 728  0
                         int subCollectionIndex = 0;
 729  0
                         for (Object aSubCollection : maintCollection) {
 730  0
                                 subCollectionIndex += getSubCollectionIndex(aSubCollection, maintenanceForm.getDocTypeName());
 731  
                         }
 732  
                         //TODO: Should we keep this logic and continue using currentTabIndex as the key in the tabStates HashMap ?
 733  
                         //            
 734  
                         //            String parameter = (String) request.getAttribute(Constants.METHOD_TO_CALL_ATTRIBUTE);
 735  
                         //            String indexStr = StringUtils.substringBetween(parameter, Constants.METHOD_TO_CALL_PARM13_LEFT_DEL, Constants.METHOD_TO_CALL_PARM13_RIGHT_DEL);
 736  
                         //            // + 1 is for the fact that the first element of a collection is on the next tab
 737  
                         //            int index = Integer.parseInt(indexStr) + subCollectionIndex + 1;
 738  
                         //            Map<String, String> tabStates = maintenanceForm.getTabStates();
 739  
                         //            Map<String, String> copyOfTabStates = new HashMap<String, String>();
 740  
                         //
 741  
                         //            int incrementor = 0;
 742  
                         //            for (String tabState : tabStates.keySet()) {
 743  
                         //                    String originalValue = maintenanceForm.getTabState(Integer.toString(incrementor));
 744  
                         //                copyOfTabStates.put(Integer.toString(incrementor), originalValue);
 745  
                         //                incrementor++;
 746  
                         //            }
 747  
                         //
 748  
                         //            int i = index;
 749  
                         //                if (tabStates.containsKey(Integer.toString(i-1))) {
 750  
                         //                        tabStates.remove(Integer.toString(i-1));
 751  
                         //                }
 752  
                         //            while (i < copyOfTabStates.size() + 1) {
 753  
                         //                String originalValue = copyOfTabStates.get(Integer.toString(i-1));
 754  
                         //                if (tabStates.containsKey(Integer.toString(i))) {
 755  
                         //                    tabStates.remove(Integer.toString(i));
 756  
                         //                }
 757  
                         //                tabStates.put(Integer.toString(i), originalValue);
 758  
                         //                i++;
 759  
                         //            }
 760  
 
 761  
 
 762  
                         // End of whether we should continue to keep this logic and use currentTabIndex as the key            
 763  
                 }
 764  0
                 doProcessingAfterPost( (KualiMaintenanceForm) form, request );
 765  
 
 766  0
                 return mapping.findForward(RiceConstants.MAPPING_BASIC);
 767  
         }
 768  
 
 769  
     protected int getSubCollectionIndex(Object object, String documentTypeName) {
 770  0
                 int index = 1;
 771  0
                 MaintainableCollectionDefinition theCollectionDefinition = null;
 772  0
                 for (MaintainableCollectionDefinition maintainableCollectionDefinition : maintenanceDocumentDictionaryService.getMaintainableCollections(documentTypeName)) {
 773  0
                         if (maintainableCollectionDefinition.getBusinessObjectClass().equals(object.getClass())) {
 774  
                                 // we've found the collection we were looking for, so let's find all of its subcollections
 775  0
                                 theCollectionDefinition = maintainableCollectionDefinition;
 776  0
                                 break;
 777  
                         }
 778  
                 }
 779  0
                 if (theCollectionDefinition != null) {
 780  0
                         for (MaintainableCollectionDefinition subCollDef : theCollectionDefinition.getMaintainableCollections()) {
 781  0
                                 String name = subCollDef.getName();
 782  0
                                 String capitalFirst = name.substring(0, 1).toUpperCase();
 783  0
                                 String methodName = "get" + capitalFirst + name.substring(1);
 784  0
                                 List subCollectionList = new ArrayList();
 785  
                                 try {
 786  0
                                         subCollectionList = (List) object.getClass().getMethod(methodName).invoke(object);
 787  
                                 }
 788  0
                                 catch (InvocationTargetException ite) {
 789  
                                         // this shouldn't happen
 790  
                                 }
 791  0
                                 catch (IllegalAccessException iae) {
 792  
                                         // this shouldn't happen
 793  
                                 }
 794  0
                                 catch (NoSuchMethodException nme) {
 795  
                                         // this shouldn't happen
 796  0
                                 }
 797  0
                                 index += subCollectionList.size();
 798  0
                         }
 799  
                 }
 800  0
                 return index;
 801  
         }
 802  
 
 803  
         /**
 804  
          * Deletes a collection line that is pending by this document. The collection name and the index to delete is embedded into the
 805  
          * delete button name. These parameters are extracted, the collection pulled out of the parent business object, and finally the
 806  
          * collection record at the specified index is removed for the new maintainable, and the old if we are dealing with an edit.
 807  
          */
 808  
         public ActionForward deleteLine(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 809  0
                 KualiMaintenanceForm maintenanceForm = (KualiMaintenanceForm) form;
 810  0
                 MaintenanceDocument document = (MaintenanceDocument) maintenanceForm.getDocument();
 811  0
                 Maintainable oldMaintainable = document.getOldMaintainableObject();
 812  0
                 Maintainable newMaintainable = document.getNewMaintainableObject();
 813  
 
 814  0
                 String collectionName = extractCollectionName(request, KNSConstants.DELETE_LINE_METHOD);
 815  0
                 if (collectionName == null) {
 816  0
                         LOG.error("Unable to get find collection name in request.");
 817  0
                         throw new RuntimeException("Unable to get find collection class in request.");
 818  
                 }
 819  
 
 820  0
                 PersistableBusinessObject bo = newMaintainable.getBusinessObject();
 821  0
                 Collection maintCollection = extractCollection(bo, collectionName);
 822  0
                 if (collectionName == null) {
 823  0
                         LOG.error("Collection is null in parent business object.");
 824  0
                         throw new RuntimeException("Collection is null in parent business object.");
 825  
                 }
 826  
 
 827  0
                 int deleteRecordIndex = getLineToDelete(request);
 828  0
                 if (deleteRecordIndex < 0 || deleteRecordIndex > maintCollection.size() - 1) {
 829  0
                         if (collectionName == null) {
 830  0
                                 LOG.error("Invalid index for deletion of collection record: " + deleteRecordIndex);
 831  0
                                 throw new RuntimeException("Invalid index for deletion of collection record: " + deleteRecordIndex);
 832  
                         }
 833  
                 }
 834  
 
 835  0
                 ((List) maintCollection).remove(deleteRecordIndex);
 836  
 
 837  
                 // if it's either an edit or a copy, need to remove the collection from the old maintainable as well
 838  0
                 if (KNSConstants.MAINTENANCE_EDIT_ACTION.equals(maintenanceForm.getMaintenanceAction()) ||
 839  
                                 KNSConstants.MAINTENANCE_COPY_ACTION.equals(maintenanceForm.getMaintenanceAction())) {
 840  0
                         bo = oldMaintainable.getBusinessObject();
 841  0
                         maintCollection = extractCollection(bo, collectionName);
 842  
 
 843  0
                         if (collectionName == null) {
 844  0
                                 LOG.error("Collection is null in parent business object.");
 845  0
                                 throw new RuntimeException("Collection is null in parent business object.");
 846  
                         }
 847  
 
 848  0
                         ((List) maintCollection).remove(deleteRecordIndex);
 849  
                 }
 850  
 
 851  
                 // remove the tab state information of the tab that the deleted element originally occupied, so that it will keep tab states
 852  
                 // consistent
 853  
                 //        String parameter = (String) request.getAttribute(Constants.METHOD_TO_CALL_ATTRIBUTE);
 854  
                 //        String indexStr = StringUtils.substringBetween(parameter, Constants.METHOD_TO_CALL_PARM13_LEFT_DEL, Constants.METHOD_TO_CALL_PARM13_RIGHT_DEL);
 855  
                 //        int index = Integer.parseInt(indexStr);
 856  
                 //        maintenanceForm.removeTabState(index);
 857  
 
 858  
 
 859  
                 //      TODO: Should we keep this logic and continue using currentTabIndex as the key in the tabStates HashMap ?        
 860  
                 //        
 861  
                 //        String parameter = (String) request.getAttribute(Constants.METHOD_TO_CALL_ATTRIBUTE);
 862  
                 //        String indexStr = StringUtils.substringBetween(parameter, Constants.METHOD_TO_CALL_PARM13_LEFT_DEL, Constants.METHOD_TO_CALL_PARM13_RIGHT_DEL);
 863  
                 //        // + 1 is for the fact that the first element of a collection is on the next tab
 864  
                 //        int index = Integer.parseInt(indexStr) +  1;
 865  
                 //        Map<String, String> tabStates = maintenanceForm.getTabStates();
 866  
                 //        Map<String, String> copyOfTabStates = new HashMap<String, String>();
 867  
                 //
 868  
                 //        int incrementor = 0;
 869  
                 //        for (String tabState : tabStates.keySet()) {
 870  
                 //                String originalValue = maintenanceForm.getTabState(Integer.toString(incrementor));
 871  
                 //            copyOfTabStates.put(Integer.toString(incrementor), originalValue);
 872  
                 //            incrementor++;
 873  
                 //        }
 874  
                 //
 875  
                 //        int i = index;
 876  
                 //
 877  
                 //        while (i < copyOfTabStates.size() ) {
 878  
                 //            String originalValue = copyOfTabStates.get(Integer.toString(i));
 879  
                 //            if (tabStates.containsKey(Integer.toString(i-1))) {
 880  
                 //                tabStates.remove(Integer.toString(i-1));
 881  
                 //            }
 882  
                 //            tabStates.put(Integer.toString(i-1), originalValue);
 883  
                 //            i++;
 884  
                 //        }
 885  
                 //
 886  
                 //        
 887  
                 //End of whether we should continue to keep this logic and use currentTabIndex as the key            
 888  
 
 889  0
                 doProcessingAfterPost( (KualiMaintenanceForm) form, request );
 890  
 
 891  0
                 return mapping.findForward(RiceConstants.MAPPING_BASIC);
 892  
         }
 893  
 
 894  
         /**
 895  
          * Turns on (or off) the inactive record display for a maintenance collection.
 896  
          */
 897  
         public ActionForward toggleInactiveRecordDisplay(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 898  0
                 KualiMaintenanceForm maintenanceForm = (KualiMaintenanceForm) form;
 899  0
                 MaintenanceDocument document = (MaintenanceDocument) maintenanceForm.getDocument();
 900  0
                 Maintainable oldMaintainable = document.getOldMaintainableObject();
 901  0
                 Maintainable newMaintainable = document.getNewMaintainableObject();
 902  
 
 903  0
                 String collectionName = extractCollectionName(request, KNSConstants.TOGGLE_INACTIVE_METHOD);
 904  0
                 if (collectionName == null) {
 905  0
                         LOG.error("Unable to get find collection name in request.");
 906  0
                         throw new RuntimeException("Unable to get find collection class in request.");
 907  
                 }  
 908  
 
 909  0
                 String parameterName = (String) request.getAttribute(KNSConstants.METHOD_TO_CALL_ATTRIBUTE);
 910  0
                 boolean showInactive = Boolean.parseBoolean(StringUtils.substringBetween(parameterName, KNSConstants.METHOD_TO_CALL_BOPARM_LEFT_DEL, "."));
 911  
 
 912  0
                 oldMaintainable.setShowInactiveRecords(collectionName, showInactive);
 913  0
                 newMaintainable.setShowInactiveRecords(collectionName, showInactive);
 914  
 
 915  0
                 return mapping.findForward(RiceConstants.MAPPING_BASIC);
 916  
         }
 917  
 
 918  
 
 919  
 
 920  
         /**
 921  
          * This method clears the value of the primary key fields on a Business Object.
 922  
          * 
 923  
          * @param document - document to clear the pk fields on
 924  
          */
 925  
     protected void clearPrimaryKeyFields(MaintenanceDocument document) {
 926  
                 // get business object being maintained and its keys
 927  0
                 PersistableBusinessObject bo = document.getNewMaintainableObject().getBusinessObject();
 928  0
                 List<String> keyFieldNames = getBusinessObjectMetaDataService().listPrimaryKeyFieldNames(bo.getClass());
 929  
 
 930  0
                 for (String keyFieldName : keyFieldNames) {
 931  
                         try {
 932  0
                                 ObjectUtils.setObjectProperty(bo, keyFieldName, null);
 933  
                         }
 934  0
                         catch (Exception e) {
 935  0
                                 LOG.error("Unable to clear primary key field: " + e.getMessage());
 936  0
                                 throw new RuntimeException("Unable to clear primary key field: " + e.getMessage());
 937  0
                         }
 938  
                 }
 939  0
         }
 940  
 
 941  
         /**
 942  
          * This method is used as part of the Copy functionality, to clear any field values that the user making the copy does not have
 943  
          * permissions to modify. This will prevent authorization errors on a copy.
 944  
          * 
 945  
          * @param document - document to be adjusted
 946  
          */
 947  
     protected void clearUnauthorizedNewFields(MaintenanceDocument document) {
 948  
                 // get a reference to the current user
 949  0
                 Person user = GlobalVariables.getUserSession().getPerson();
 950  
 
 951  
                 // get the correct documentAuthorizer for this document
 952  0
                 MaintenanceDocumentAuthorizer documentAuthorizer = (MaintenanceDocumentAuthorizer) getDocumentHelperService().getDocumentAuthorizer(document);
 953  
 
 954  
                 // get a new instance of MaintenanceDocumentAuthorizations for this context
 955  0
                 MaintenanceDocumentRestrictions maintenanceDocumentRestrictions = getBusinessObjectAuthorizationService().getMaintenanceDocumentRestrictions(document, user);
 956  
 
 957  
                 // get a reference to the newBo
 958  0
                 PersistableBusinessObject newBo = document.getNewMaintainableObject().getBusinessObject();
 959  
 
 960  0
                 document.getNewMaintainableObject().clearBusinessObjectOfRestrictedValues(maintenanceDocumentRestrictions);
 961  0
         }
 962  
 
 963  
         /**
 964  
          * This method does all special processing on a document that should happen on each HTTP post (ie, save, route, approve, etc).
 965  
          * 
 966  
          * @param form
 967  
          */
 968  
         @SuppressWarnings("unchecked")
 969  
         protected void doProcessingAfterPost( KualiForm form, HttpServletRequest request ) {
 970  0
                 MaintenanceDocument document = (MaintenanceDocument) ((KualiMaintenanceForm)form).getDocument();
 971  0
                 Maintainable maintainable = document.getNewMaintainableObject();
 972  0
                 PersistableBusinessObject bo = maintainable.getBusinessObject();
 973  
 
 974  0
                 getBusinessObjectService().linkUserFields(bo);
 975  
 
 976  0
                 maintainable.processAfterPost(document, request.getParameterMap() );
 977  0
         }
 978  
 
 979  
         protected void doProcessingAfterPost( KualiForm form, Map<String,String[]> parameters ) {
 980  0
                 MaintenanceDocument document = (MaintenanceDocument) ((KualiMaintenanceForm)form).getDocument();
 981  0
                 Maintainable maintainable = document.getNewMaintainableObject();
 982  0
                 PersistableBusinessObject bo = maintainable.getBusinessObject();
 983  
 
 984  0
                 getBusinessObjectService().linkUserFields(bo);
 985  
 
 986  0
                 maintainable.processAfterPost(document, parameters );
 987  0
         }
 988  
 
 989  
         protected void populateAuthorizationFields(KualiDocumentFormBase formBase){
 990  0
                 super.populateAuthorizationFields(formBase);
 991  
 
 992  0
                 KualiMaintenanceForm maintenanceForm = (KualiMaintenanceForm) formBase;
 993  0
                 MaintenanceDocument maintenanceDocument = (MaintenanceDocument) maintenanceForm.getDocument();
 994  0
                 MaintenanceDocumentAuthorizer maintenanceDocumentAuthorizer = (MaintenanceDocumentAuthorizer) getDocumentHelperService().getDocumentAuthorizer(maintenanceDocument);
 995  0
                 Person user = GlobalVariables.getUserSession().getPerson();
 996  0
                 maintenanceForm.setReadOnly(!formBase.getDocumentActions().containsKey(KNSConstants.KUALI_ACTION_CAN_EDIT));
 997  0
                 MaintenanceDocumentRestrictions maintenanceDocumentAuthorizations = getBusinessObjectAuthorizationService().getMaintenanceDocumentRestrictions(maintenanceDocument, user);
 998  0
                 maintenanceForm.setAuthorizations(maintenanceDocumentAuthorizations);
 999  0
         }
 1000  
 
 1001  
         public LookupService getLookupService() {
 1002  0
                 if ( lookupService == null ) {
 1003  0
                         lookupService = KNSServiceLocator.getLookupService();
 1004  
                 }
 1005  0
                 return this.lookupService;
 1006  
         }
 1007  
 
 1008  
         public LookupResultsService getLookupResultsService() {
 1009  0
                 if ( lookupResultsService == null ) {
 1010  0
                         lookupResultsService = KNSServiceLocator.getLookupResultsService();
 1011  
                 }
 1012  0
                 return this.lookupResultsService;
 1013  
         }
 1014  
 
 1015  
 }