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