View Javadoc
1   /**
2    * Copyright 2005-2016 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.kns.web.struts.form;
17  
18  import org.apache.commons.beanutils.PropertyUtils;
19  import org.apache.commons.lang.StringUtils;
20  import org.apache.struts.upload.FormFile;
21  import org.kuali.rice.core.api.config.ConfigurationException;
22  import org.kuali.rice.core.api.util.RiceKeyConstants;
23  import org.kuali.rice.core.web.format.FormatException;
24  import org.kuali.rice.core.web.format.Formatter;
25  import org.kuali.rice.kew.api.WorkflowDocument;
26  import org.kuali.rice.kim.api.services.KimApiServiceLocator;
27  import org.kuali.rice.kns.document.MaintenanceDocument;
28  import org.kuali.rice.kns.document.MaintenanceDocumentBase;
29  import org.kuali.rice.kns.document.authorization.MaintenanceDocumentRestrictions;
30  import org.kuali.rice.kns.maintenance.Maintainable;
31  import org.kuali.rice.kns.service.KNSServiceLocator;
32  import org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService;
33  import org.kuali.rice.kns.util.FieldUtils;
34  import org.kuali.rice.krad.bo.BusinessObject;
35  import org.kuali.rice.krad.bo.PersistableAttachment;
36  import org.kuali.rice.krad.bo.PersistableBusinessObject;
37  import org.kuali.rice.krad.datadictionary.exception.UnknownDocumentTypeException;
38  import org.kuali.rice.krad.document.Document;
39  import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
40  import org.kuali.rice.krad.util.GlobalVariables;
41  import org.kuali.rice.krad.util.KRADConstants;
42  import org.kuali.rice.krad.util.ObjectUtils;
43  
44  import javax.servlet.http.HttpServletRequest;
45  import java.lang.reflect.Constructor;
46  import java.lang.reflect.InvocationTargetException;
47  import java.util.Enumeration;
48  import java.util.HashMap;
49  import java.util.Iterator;
50  import java.util.List;
51  import java.util.Map;
52  import java.util.regex.Matcher;
53  import java.util.regex.Pattern;
54  
55  /**
56   * This class is the base action form for all maintenance documents.
57   * 
58   * 
59   */
60  public class KualiMaintenanceForm extends KualiDocumentFormBase {
61      protected static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(KualiMaintenanceForm.class);
62  
63      protected static final long serialVersionUID = 1L;
64  
65      protected String businessObjectClassName;
66      protected String description;
67      protected boolean readOnly;
68      protected Map<String, String> oldMaintainableValues;
69      protected Map<String, String> newMaintainableValues;
70      protected String maintenanceAction;
71      private static final Pattern ELEMENT_IN_COLLECTION = Pattern.compile("(.*)(\\[)([0-9]*)(\\])(.*)");
72  
73  
74  	/**
75       * @see KualiDocumentFormBase#addRequiredNonEditableProperties()
76       */
77      @Override
78      public void addRequiredNonEditableProperties(){
79      	super.addRequiredNonEditableProperties();
80      	registerRequiredNonEditableProperty(KRADConstants.BUSINESS_OBJECT_CLASS_ATTRIBUTE);
81      	registerRequiredNonEditableProperty(KRADConstants.LOOKUP_RESULTS_BO_CLASS_NAME);
82      	registerRequiredNonEditableProperty(KRADConstants.LOOKED_UP_COLLECTION_NAME);
83      	registerRequiredNonEditableProperty(KRADConstants.LOOKUP_RESULTS_SEQUENCE_NUMBER);
84      	registerRequiredNonEditableProperty(KRADConstants.FIELD_NAME_TO_FOCUS_ON_AFTER_SUBMIT);
85      }
86  
87      /**
88       * Used to indicate which result set we're using when refreshing/returning from a multi-value lookup
89       */
90      protected String lookupResultsSequenceNumber;
91      /**
92       * The type of result returned by the multi-value lookup
93       * 
94       * TODO: to be persisted in the lookup results service instead?
95       */
96      protected String lookupResultsBOClassName;
97      
98      /**
99       * The name of the collection looked up (by a multiple value lookup)
100      */
101     protected String lookedUpCollectionName;
102     
103     protected MaintenanceDocumentRestrictions authorizations;
104     
105     /**
106      * Override the default method to add the if statement which can't be called until after parameters from a multipart request
107      * have been made accessible, but which must be called before the parameter values are used to instantiate and populate business
108      * objects.
109      * 
110      * @param requestParameters
111      */
112     @Override
113     public void postprocessRequestParameters(Map requestParameters) {
114         super.postprocessRequestParameters(requestParameters);
115 
116         String docTypeName = null;
117         String[] docTypeNames = (String[]) requestParameters.get(KRADConstants.DOCUMENT_TYPE_NAME);
118         if ((docTypeNames != null) && (docTypeNames.length > 0)) {
119             docTypeName = docTypeNames[0];
120         }
121 
122         if (StringUtils.isNotBlank(docTypeName)) {          
123         	if(this.getDocument() == null){
124             setDocTypeName(docTypeName);
125             Class documentClass = KRADServiceLocatorWeb.getDataDictionaryService().getDocumentClassByTypeName(docTypeName);
126             if (documentClass == null) {
127                 throw new UnknownDocumentTypeException("unable to get class for unknown documentTypeName '" + docTypeName + "'");
128             }
129             if (!MaintenanceDocumentBase.class.isAssignableFrom(documentClass)) {
130                 throw new ConfigurationException("Document class '" + documentClass + "' is not assignable to '" + MaintenanceDocumentBase.class + "'");
131             }
132             Document document = null;
133             try {
134                 Class[] defaultConstructor = new Class[]{String.class};
135                 Constructor cons = documentClass.getConstructor(defaultConstructor);
136                 if (ObjectUtils.isNull(cons)) {
137                     throw new ConfigurationException("Could not find constructor with document type name parameter needed for Maintenance Document Base class");
138                 }
139                 document = (Document) cons.newInstance(docTypeName);
140             } catch (SecurityException e) {
141                 throw new RuntimeException("Error instantiating Maintenance Document", e);
142             } catch (NoSuchMethodException e) {
143                 throw new RuntimeException("Error instantiating Maintenance Document: No constructor with String parameter found", e);
144             } catch (IllegalAccessException e) {
145                 throw new RuntimeException("Error instantiating Maintenance Document", e);
146             } catch (InstantiationException e) {
147                 throw new RuntimeException("Error instantiating Maintenance Document", e);
148             } catch (IllegalArgumentException e) {
149                 throw new RuntimeException("Error instantiating Maintenance Document", e);
150             } catch (InvocationTargetException e) {
151                 throw new RuntimeException("Error instantiating Maintenance Document", e);
152             }
153             if (document == null) {
154                 throw new RuntimeException("Unable to instantiate document with type name '" + docTypeName + "' and document class '" + documentClass + "'");
155             }
156             setDocument(document);
157           } 
158        }
159         
160         MaintenanceDocumentBase maintenanceDocument = (MaintenanceDocumentBase) getDocument();
161 
162         //Handling the Multi-Part Attachment
163         for ( Object obj : requestParameters.entrySet() ) {
164             String parameter = (String)((Map.Entry)obj).getKey(); 
165             if (parameter.toUpperCase().startsWith(KRADConstants.MAINTENANCE_NEW_MAINTAINABLE.toUpperCase())) {
166                 String propertyName = parameter.substring(KRADConstants.MAINTENANCE_NEW_MAINTAINABLE.length());
167                 Object propertyValue = requestParameters.get(parameter);
168                 
169                 if(propertyValue != null && propertyValue instanceof FormFile) {
170                     populateAttachmentFile(maintenanceDocument, propertyName, (FormFile) propertyValue);
171                     if (propertyName.startsWith(KRADConstants.MAINTENANCE_ADD_PREFIX)) {
172                         String parsedPropertyName = propertyName.substring(
173                                 KRADConstants.MAINTENANCE_ADD_PREFIX.length());
174                         String collectionName = parseAddCollectionName(parseAddCollectionName(parsedPropertyName));
175                         maintenanceDocument.setAttachmentCollectionName(collectionName);
176                         maintenanceDocument.setAttachmentListPropertyName(propertyName.substring(KRADConstants.MAINTENANCE_ADD_PREFIX.length()).substring(collectionName.length() + 1));
177                     } else {
178                         //if property not part of collection
179                         Matcher matcher = ELEMENT_IN_COLLECTION.matcher(propertyName);
180                         if (!matcher.matches()) {
181                             maintenanceDocument.setAttachmentPropertyName(propertyName);
182                         }
183                     }
184                 }
185             }
186         }
187     }
188 
189     private void populateAttachmentFile(MaintenanceDocumentBase maintenanceDocument, String propertyName, FormFile propertyValue) {
190          if(StringUtils.isNotEmpty(((FormFile)propertyValue).getFileName())) {
191  	 	 	 PersistableBusinessObject boClass;
192              String boPropertyName;
193 
194              Matcher matcher = ELEMENT_IN_COLLECTION.matcher(propertyName);
195              if (propertyName.startsWith(KRADConstants.MAINTENANCE_ADD_PREFIX)) {
196                  String prefix = matcher.matches() ? "" : KRADConstants.MAINTENANCE_ADD_PREFIX;
197                  String collectionName = parseAddCollectionName(propertyName.substring(prefix.length()));
198                  boClass = maintenanceDocument.getNewMaintainableObject().getNewCollectionLine(collectionName);
199                  boPropertyName = propertyName.substring(prefix.length()).substring(collectionName.length() + 1);
200 
201                  setAttachmentProperty(boClass, boPropertyName, propertyValue);
202              } else {
203                  boClass = maintenanceDocument.getNewMaintainableObject().getBusinessObject();
204                  boPropertyName = propertyName;
205                  if(StringUtils.isNotEmpty(((FormFile)propertyValue).getFileName())
206                          && !matcher.matches()) {
207                      maintenanceDocument.setFileAttachment((FormFile) propertyValue);
208                  }
209                  setAttachmentProperty(boClass, boPropertyName, propertyValue);
210              }
211          }
212     }
213 
214     private void setAttachmentProperty(PersistableBusinessObject boClass, String propertyName, Object propertyValue) {
215         try {
216             PropertyUtils.setProperty(boClass, propertyName, propertyValue);
217         } catch (InvocationTargetException e) {
218             throw new RuntimeException("no setter for property '" + boClass.getClass().getName() + "." + propertyName + "'", e);
219         } catch (NoSuchMethodException e) {
220             throw new RuntimeException("no setter for property '" + boClass.getClass().getName() + "." + propertyName + "'", e);
221         } catch (IllegalAccessException e) {
222             throw new RuntimeException("problem accessing property '" + boClass.getClass().getName() + "." + propertyName + "'", e);
223         }
224     }
225 
226     /**
227      * Hook into populate so we can set the maintenance documents and feed the field values to its maintainables.
228      */
229     @Override
230     public void populate(HttpServletRequest request) {
231         super.populate(request);
232 
233 
234         // document type name is null on start, otherwise should be here
235         if (StringUtils.isNotBlank(getDocTypeName())) {
236             Map<String, String> localOldMaintainableValues = new HashMap<String, String>();
237             Map<String, String> localNewMaintainableValues = new HashMap<String, String>();
238             Map<String,String> localNewCollectionValues = new HashMap<String,String>();
239             for (Enumeration i = request.getParameterNames(); i.hasMoreElements();) {
240                 String parameter = (String) i.nextElement();
241                 if (parameter.toUpperCase().startsWith(KRADConstants.MAINTENANCE_OLD_MAINTAINABLE.toUpperCase())) {
242                 	if (shouldPropertyBePopulatedInForm(parameter, request)) {
243                         String propertyName = parameter.substring(KRADConstants.MAINTENANCE_OLD_MAINTAINABLE.length());
244                         localOldMaintainableValues.put(propertyName, request.getParameter(parameter));
245                     }
246                 }
247                 if (parameter.toUpperCase().startsWith(KRADConstants.MAINTENANCE_NEW_MAINTAINABLE.toUpperCase())) {
248                 	if (shouldPropertyBePopulatedInForm(parameter, request)) {
249                         String propertyName = parameter.substring(KRADConstants.MAINTENANCE_NEW_MAINTAINABLE.length());
250                         localNewMaintainableValues.put(propertyName, request.getParameter(parameter));
251                     }
252                 }
253             }
254             
255             // now, get all add lines and store them to a separate map
256             // for use in a separate call to the maintainable
257             for ( Map.Entry<String, String> entry : localNewMaintainableValues.entrySet() ) {
258                 String key = entry.getKey(); 
259                 if ( key.startsWith( KRADConstants.MAINTENANCE_ADD_PREFIX ) ) {
260                     localNewCollectionValues.put( key.substring( KRADConstants.MAINTENANCE_ADD_PREFIX.length() ),
261                             entry.getValue() );
262                 }
263             }
264             if ( LOG.isDebugEnabled() ) {
265                 LOG.debug( "checked for add line parameters - got: " + localNewCollectionValues );
266             }
267             
268             this.newMaintainableValues = localNewMaintainableValues;
269             this.oldMaintainableValues = localOldMaintainableValues;
270 
271             MaintenanceDocumentBase maintenanceDocument = (MaintenanceDocumentBase) getDocument();
272 
273             GlobalVariables.getMessageMap().addToErrorPath("document.oldMaintainableObject");
274             maintenanceDocument.getOldMaintainableObject().populateBusinessObject(localOldMaintainableValues, maintenanceDocument, getMethodToCall());
275             GlobalVariables.getMessageMap().removeFromErrorPath("document.oldMaintainableObject");
276 
277             GlobalVariables.getMessageMap().addToErrorPath("document.newMaintainableObject");
278             // update the main object
279             Map cachedValues = 
280             	maintenanceDocument.getNewMaintainableObject().populateBusinessObject(localNewMaintainableValues, maintenanceDocument, getMethodToCall());
281             
282             if(maintenanceDocument.getFileAttachment() != null) {
283                 populateAttachmentPropertyForBO(maintenanceDocument);
284             }
285             
286             // update add lines
287             localNewCollectionValues = KimApiServiceLocator.getPersonService().resolvePrincipalNamesToPrincipalIds((BusinessObject)maintenanceDocument.getNewMaintainableObject().getBusinessObject(), localNewCollectionValues);
288             cachedValues.putAll( maintenanceDocument.getNewMaintainableObject().populateNewCollectionLines( localNewCollectionValues, maintenanceDocument, getMethodToCall() ) );
289             GlobalVariables.getMessageMap().removeFromErrorPath("document.newMaintainableObject");
290 
291             if (cachedValues.size() > 0) {
292                 GlobalVariables.getMessageMap().putError(KRADConstants.DOCUMENT_ERRORS, RiceKeyConstants.ERROR_DOCUMENT_MAINTENANCE_FORMATTING_ERROR);
293                 for (Iterator iter = cachedValues.keySet().iterator(); iter.hasNext();) {
294                     String propertyName = (String) iter.next();
295                     String value = (String) cachedValues.get(propertyName);
296                     cacheUnconvertedValue(KRADConstants.MAINTENANCE_NEW_MAINTAINABLE + propertyName, value);
297                 }
298             }
299         }
300     }
301 
302     protected void populateAttachmentPropertyForBO(MaintenanceDocumentBase maintenanceDocument) {
303         try {
304             Object dataObject = maintenanceDocument.getNewMaintainableObject().getDataObject();
305             if (dataObject instanceof PersistableAttachment) {
306                 Class type = ObjectUtils.easyGetPropertyType(maintenanceDocument.getNewMaintainableObject().getDataObject(), maintenanceDocument.getAttachmentPropertyName());
307                 ObjectUtils.setObjectProperty(maintenanceDocument.getNewMaintainableObject().getBusinessObject(), maintenanceDocument.getAttachmentPropertyName(), type, maintenanceDocument.getFileAttachment());
308             }
309         } catch (FormatException e) {
310             throw new RuntimeException("Exception occurred while setting attachment property on NewMaintainable bo", e);
311         } catch (IllegalAccessException e) {
312             throw new RuntimeException("Exception occurred while setting attachment property on NewMaintainable bo", e);
313         } catch (NoSuchMethodException e) {
314             throw new RuntimeException("Exception occurred while setting attachment property on NewMaintainable bo", e);
315         } catch (InvocationTargetException e) {
316             throw new RuntimeException("Exception occurred while setting attachment property on NewMaintainable bo", e);
317         }
318     }
319     
320     /**
321      * Merges rows of old and new for each section (tab) of the ui. Also, renames fields to prevent naming conflicts and does
322      * setting of read only fields.
323      * 
324      * @return Returns the maintenanceSections.
325      */
326     public List getSections() {
327         if (getDocument() == null) {
328             throw new RuntimeException("Document not set in maintenance form.");
329         }
330         if (((MaintenanceDocumentBase) getDocument()).getNewMaintainableObject() == null) {
331             throw new RuntimeException("New maintainable not set in document.");
332         }
333         if ((KRADConstants.MAINTENANCE_EDIT_ACTION.equals(this.getMaintenanceAction())
334         		|| KRADConstants.MAINTENANCE_COPY_ACTION.equals(this.getMaintenanceAction())
335         		|| KRADConstants.MAINTENANCE_DELETE_ACTION.equals(this.getMaintenanceAction()))
336         		&& ((MaintenanceDocumentBase) getDocument()).getOldMaintainableObject() == null) {
337             throw new RuntimeException("Old maintainable not set in document.");
338         }
339 
340         // if the authorization stuff hasnt been applied yet, then apply it
341         //if (authorizations == null) {
342         //    applyAuthorizations();
343         //}
344 
345         
346         // get business object being maintained and its keys
347         List keyFieldNames = KNSServiceLocator.getBusinessObjectMetaDataService().listPrimaryKeyFieldNames(((MaintenanceDocumentBase) getDocument()).getNewMaintainableObject().getBusinessObject().getClass());
348 
349         // sections for maintenance document
350         Maintainable oldMaintainable = ((MaintenanceDocumentBase) getDocument()).getOldMaintainableObject();
351         oldMaintainable.setMaintenanceAction(getMaintenanceAction());
352         List oldMaintSections = oldMaintainable.getSections((MaintenanceDocument) getDocument(), null);
353         
354         Maintainable newMaintainable = ((MaintenanceDocumentBase) getDocument()).getNewMaintainableObject();
355         newMaintainable.setMaintenanceAction(getMaintenanceAction());
356         List newMaintSections = newMaintainable.getSections((MaintenanceDocument) getDocument(), oldMaintainable);
357         WorkflowDocument workflowDocument = this.getDocument().getDocumentHeader().getWorkflowDocument();
358         String documentStatus =  workflowDocument.getStatus().getCode();
359         String documentInitiatorPrincipalId = workflowDocument.getInitiatorPrincipalId();
360         
361 
362         // mesh sections for proper jsp display
363         List meshedSections = FieldUtils
364                 .meshSections(oldMaintSections, newMaintSections, keyFieldNames, getMaintenanceAction(), isReadOnly(),
365                         authorizations, documentStatus, documentInitiatorPrincipalId);
366 
367         return meshedSections;
368     }    
369 
370     /**
371      * @return Returns the maintenanceAction.
372      */
373     public String getMaintenanceAction() {
374         return maintenanceAction;
375     }
376 
377     /**
378      * @return Returns the businessObjectClassName.
379      */
380     public String getBusinessObjectClassName() {
381         return businessObjectClassName;
382     }
383 
384     /**
385      * @param businessObjectClassName The businessObjectClassName to set.
386      */
387     public void setBusinessObjectClassName(String businessObjectClassName) {
388         this.businessObjectClassName = businessObjectClassName;
389     }
390 
391     /**
392      * @return Returns the description.
393      */
394     public String getDescription() {
395         return description;
396     }
397 
398     /**
399      * @param description The description to set.
400      */
401     public void setDescription(String description) {
402         this.description = description;
403     }
404 
405     /**
406      * @return Returns the isReadOnly.
407      */
408     public boolean isReadOnly() {
409         return readOnly;
410     }
411 
412     /**
413      * @param readOnly The isReadOnly to set.
414      */
415     public void setReadOnly(boolean readOnly) {
416         this.readOnly = readOnly;
417     }
418 
419     /**
420      * @return Returns the newMaintainableValues.
421      */
422     public Map getNewMaintainableValues() {
423         return newMaintainableValues;
424     }
425 
426     /**
427      * @return Returns the oldMaintainableValues.
428      */
429     public Map getOldMaintainableValues() {
430         return oldMaintainableValues;
431     }
432 
433     /**
434      * @param maintenanceAction The maintenanceAction to set.
435      */
436     public void setMaintenanceAction(String maintenanceAction) {
437         this.maintenanceAction = maintenanceAction;
438     }
439 
440     /**
441      * Gets the authorizations attribute.
442      * 
443      * @return Returns the authorizations.
444      */
445     public MaintenanceDocumentRestrictions getAuthorizations() {
446         return authorizations;
447     }
448 
449     /**
450      * Sets the authorizations attribute value.
451      * 
452      * @param authorizations The authorizations to set.
453      */
454     public void setAuthorizations(MaintenanceDocumentRestrictions authorizations) {
455         this.authorizations = authorizations;
456     }
457 
458     /**
459      * Sets the newMaintainableValues attribute value.
460      * 
461      * @param newMaintainableValues The newMaintainableValues to set.
462      */
463     public void setNewMaintainableValues(Map newMaintainableValues) {
464         this.newMaintainableValues = newMaintainableValues;
465     }
466 
467 
468     /**
469      * Sets the oldMaintainableValues attribute value.
470      * 
471      * @param oldMaintainableValues The oldMaintainableValues to set.
472      */
473     public void setOldMaintainableValues(Map oldMaintainableValues) {
474         this.oldMaintainableValues = oldMaintainableValues;
475     }
476 
477 
478     public String getLookupResultsSequenceNumber() {
479         return lookupResultsSequenceNumber;
480     }
481 
482 
483     public void setLookupResultsSequenceNumber(String lookupResultsSequenceNumber) {
484         this.lookupResultsSequenceNumber = lookupResultsSequenceNumber;
485     }
486 
487 
488     public String getLookupResultsBOClassName() {
489         return lookupResultsBOClassName;
490     }
491 
492 
493     public void setLookupResultsBOClassName(String lookupResultsBOClassName) {
494         this.lookupResultsBOClassName = lookupResultsBOClassName;
495     }
496 
497 
498     public String getLookedUpCollectionName() {
499         return lookedUpCollectionName;
500     }
501 
502 
503     public void setLookedUpCollectionName(String lookedUpCollectionName) {
504         this.lookedUpCollectionName = lookedUpCollectionName;
505     }
506 
507     public String getAdditionalSectionsFile() {
508         if ( businessObjectClassName != null ) {
509             try {
510                 MaintenanceDocumentDictionaryService maintenanceDocumentDictionaryService = KNSServiceLocator
511                         .getMaintenanceDocumentDictionaryService();
512                 String docTypeName = maintenanceDocumentDictionaryService.getDocumentTypeName(Class.forName(businessObjectClassName));
513                 return maintenanceDocumentDictionaryService.getMaintenanceDocumentEntry(businessObjectClassName).getAdditionalSectionsFile();
514             } catch ( ClassNotFoundException ex ) {
515                 LOG.error( "Unable to resolve business object class", ex);
516             }
517         }else{
518             MaintenanceDocumentDictionaryService maintenanceDocumentDictionaryService = KNSServiceLocator
519                     .getMaintenanceDocumentDictionaryService();
520             return maintenanceDocumentDictionaryService.getMaintenanceDocumentEntry(this.getDocTypeName()).getAdditionalSectionsFile();
521         }
522         return null;
523     }
524 
525 	/**
526 	 * This overridden method handles the case where maint doc properties do not reflect the true nature of the 
527 	 * 
528 	 * @see KualiForm#retrieveFormValueForLookupInquiryParameters(java.lang.String, java.lang.String)
529 	 */
530 	@Override
531 	public String retrieveFormValueForLookupInquiryParameters(String parameterName, String parameterValueLocation) {
532 		MaintenanceDocument maintDoc = (MaintenanceDocument) getDocument();
533 		if (parameterValueLocation.toLowerCase().startsWith(KRADConstants.MAINTENANCE_OLD_MAINTAINABLE.toLowerCase())) {
534 			String propertyName = parameterValueLocation.substring(KRADConstants.MAINTENANCE_OLD_MAINTAINABLE.length());
535 			if (maintDoc.getOldMaintainableObject() != null && maintDoc.getOldMaintainableObject().getBusinessObject() != null) {
536 				Object parameterValue = ObjectUtils.getPropertyValue(maintDoc.getOldMaintainableObject().getBusinessObject(), propertyName);
537 				if (parameterValue == null) {
538 					return null;
539 				}
540 				if (parameterValue instanceof String) {
541 					return (String) parameterValue;
542 				}
543 				Formatter formatter = Formatter.getFormatter(parameterValue.getClass());
544 				return (String) formatter.format(parameterValue); 
545 			}
546 		}
547 		if (parameterValueLocation.toLowerCase().startsWith(KRADConstants.MAINTENANCE_NEW_MAINTAINABLE.toLowerCase())) {
548 			// remove MAINT_NEW_MAINT from the pVL
549 			String propertyName = parameterValueLocation.substring(KRADConstants.MAINTENANCE_NEW_MAINTAINABLE.length());
550 			String addPrefix = KRADConstants.ADD_PREFIX.toLowerCase() + ".";
551 
552 			if (propertyName.toLowerCase().startsWith(addPrefix)) { // 
553 				propertyName = propertyName.substring(addPrefix.length()); // remove addPrefix from the propertyName
554 				String collectionName = parseAddCollectionName(propertyName);
555 				propertyName = propertyName.substring(collectionName.length()); // remove collectionName from pN
556 				if (propertyName.startsWith(".")) { propertyName = propertyName.substring(1); } // strip beginning "."
557 				PersistableBusinessObject newCollectionLine = 
558 					maintDoc.getNewMaintainableObject().getNewCollectionLine(collectionName);
559 				Object parameterValue = ObjectUtils.getPropertyValue(newCollectionLine, propertyName);
560 				if (parameterValue == null) {
561 					return null;
562 				}
563 				if (parameterValue instanceof String) {
564 					return (String) parameterValue;
565 				}
566 				Formatter formatter = Formatter.getFormatter(parameterValue.getClass());
567 				return (String) formatter.format(parameterValue);
568 			} else if (maintDoc.getNewMaintainableObject() != null && maintDoc.getNewMaintainableObject().getBusinessObject() != null) {
569 				Object parameterValue = ObjectUtils.getPropertyValue(maintDoc.getNewMaintainableObject().getBusinessObject(), propertyName);
570 				if (parameterValue == null) {
571 					return null;
572 				}
573 				if (parameterValue instanceof String) {
574 					return (String) parameterValue;
575 				}
576 				Formatter formatter = Formatter.getFormatter(parameterValue.getClass());
577 				return (String) formatter.format(parameterValue); 
578 			}
579 		}
580 		return super.retrieveFormValueForLookupInquiryParameters(parameterName, parameterValueLocation);
581 	}
582 
583 	/**
584 	 * This method returns the collection name (including nested collections) from a propertyName string
585 	 * 
586 	 * @param propertyName a parameterValueLocation w/ KRADConstants.MAINTENANCE_NEW_MAINTAINABLE +
587 	 * KRADConstants.ADD_PREFIX + "." stripped off the front
588 	 * @return the collectionName
589 	 */
590 	protected String parseAddCollectionName(String propertyName) {
591 		StringBuilder collectionNameBuilder = new StringBuilder();
592 
593 		boolean firstPathElement = true;
594         for (String pathElement : propertyName.split("\\.")) {
595             if (!StringUtils.isBlank(pathElement)) {
596                 if (firstPathElement) {
597                     firstPathElement = false;
598                 } else {
599                     collectionNameBuilder.append(".");
600                 }
601                 collectionNameBuilder.append(pathElement);
602                 if (!(pathElement.endsWith("]") && pathElement.contains("[")))
603                     break;
604             }
605         }
606 		String collectionName = collectionNameBuilder.toString();
607 		return collectionName;
608 	}
609 
610 
611 	/**
612 	 * This overridden method ...
613 	 * 
614 	 * @see KualiDocumentFormBase#shouldPropertyBePopulatedInForm(java.lang.String, javax.servlet.http.HttpServletRequest)
615 	 */
616 	@Override
617 	public boolean shouldPropertyBePopulatedInForm(
618 			String requestParameterName, HttpServletRequest request) {
619 		// the user clicked on a document initiation link
620 		//add delete check for 3070
621 		String methodToCallActionName = request.getParameter(KRADConstants.DISPATCH_REQUEST_PARAMETER);
622 		if (StringUtils.equals(methodToCallActionName, KRADConstants.MAINTENANCE_COPY_METHOD_TO_CALL) ||
623 				StringUtils.equals(methodToCallActionName, KRADConstants.MAINTENANCE_EDIT_METHOD_TO_CALL) ||
624 				StringUtils.equals(methodToCallActionName, KRADConstants.MAINTENANCE_NEW_METHOD_TO_CALL) ||
625 				StringUtils.equals(methodToCallActionName, KRADConstants.MAINTENANCE_NEWWITHEXISTING_ACTION) ||
626 				StringUtils.equals(methodToCallActionName, KRADConstants.MAINTENANCE_DELETE_METHOD_TO_CALL)) {
627 			return true;
628 		}
629 		if ( StringUtils.indexOf(methodToCallActionName, KRADConstants.TOGGLE_INACTIVE_METHOD ) == 0 ) {
630 			return true;
631 		}
632 		return super.shouldPropertyBePopulatedInForm(requestParameterName, request);
633 	}
634 
635 	/**
636 	 * This overridden method ...
637 	 * 
638 	 * @see KualiDocumentFormBase#shouldMethodToCallParameterBeUsed(java.lang.String, java.lang.String, javax.servlet.http.HttpServletRequest)
639 	 */
640 	@Override
641 	public boolean shouldMethodToCallParameterBeUsed(
642 			String methodToCallParameterName,
643 			String methodToCallParameterValue, HttpServletRequest request) {
644 		// the user clicked on a document initiation link
645 		if (StringUtils.equals(methodToCallParameterValue, KRADConstants.MAINTENANCE_COPY_METHOD_TO_CALL) ||
646 				StringUtils.equals(methodToCallParameterValue, KRADConstants.MAINTENANCE_EDIT_METHOD_TO_CALL) ||
647 				StringUtils.equals(methodToCallParameterValue, KRADConstants.MAINTENANCE_NEW_METHOD_TO_CALL) ||
648 				StringUtils.equals(methodToCallParameterValue, KRADConstants.MAINTENANCE_NEWWITHEXISTING_ACTION) ||
649 				StringUtils.equals(methodToCallParameterValue, KRADConstants.MAINTENANCE_DELETE_METHOD_TO_CALL)) {
650 			return true;
651 		}
652 		if ( StringUtils.indexOf(methodToCallParameterName, KRADConstants.DISPATCH_REQUEST_PARAMETER + "." + KRADConstants.TOGGLE_INACTIVE_METHOD ) == 0 ) {
653 			return true;
654 		}
655 		return super.shouldMethodToCallParameterBeUsed(methodToCallParameterName,
656 				methodToCallParameterValue, request);
657 	}
658 }
659 
660