001    /**
002     * Copyright 2005-2012 The Kuali Foundation
003     *
004     * Licensed under the Educational Community License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.opensource.org/licenses/ecl2.php
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    package org.kuali.rice.kns.web.struts.form;
017    
018    import org.apache.commons.beanutils.PropertyUtils;
019    import org.apache.commons.lang.StringUtils;
020    import org.apache.struts.upload.FormFile;
021    import org.kuali.rice.core.api.config.ConfigurationException;
022    import org.kuali.rice.core.api.util.RiceKeyConstants;
023    import org.kuali.rice.core.web.format.FormatException;
024    import org.kuali.rice.core.web.format.Formatter;
025    import org.kuali.rice.kew.api.WorkflowDocument;
026    import org.kuali.rice.kim.api.services.KimApiServiceLocator;
027    import org.kuali.rice.kns.document.MaintenanceDocument;
028    import org.kuali.rice.kns.document.MaintenanceDocumentBase;
029    import org.kuali.rice.kns.document.authorization.MaintenanceDocumentRestrictions;
030    import org.kuali.rice.kns.maintenance.Maintainable;
031    import org.kuali.rice.kns.service.KNSServiceLocator;
032    import org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService;
033    import org.kuali.rice.kns.util.FieldUtils;
034    import org.kuali.rice.krad.bo.BusinessObject;
035    import org.kuali.rice.krad.bo.PersistableAttachment;
036    import org.kuali.rice.krad.bo.PersistableBusinessObject;
037    import org.kuali.rice.krad.datadictionary.exception.UnknownDocumentTypeException;
038    import org.kuali.rice.krad.document.Document;
039    import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
040    import org.kuali.rice.krad.util.GlobalVariables;
041    import org.kuali.rice.krad.util.KRADConstants;
042    import org.kuali.rice.krad.util.ObjectUtils;
043    
044    import javax.servlet.http.HttpServletRequest;
045    import java.lang.reflect.Constructor;
046    import java.lang.reflect.InvocationTargetException;
047    import java.util.Enumeration;
048    import java.util.HashMap;
049    import java.util.Iterator;
050    import java.util.List;
051    import java.util.Map;
052    import java.util.regex.Matcher;
053    import java.util.regex.Pattern;
054    
055    /**
056     * This class is the base action form for all maintenance documents.
057     * 
058     * 
059     */
060    public class KualiMaintenanceForm extends KualiDocumentFormBase {
061        protected static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(KualiMaintenanceForm.class);
062    
063        protected static final long serialVersionUID = 1L;
064    
065        protected String businessObjectClassName;
066        protected String description;
067        protected boolean readOnly;
068        protected Map<String, String> oldMaintainableValues;
069        protected Map<String, String> newMaintainableValues;
070        protected String maintenanceAction;
071        private static final Pattern ELEMENT_IN_COLLECTION = Pattern.compile("(.*)(\\[)([0-9]*)(\\])(.*)");
072    
073    
074            /**
075         * @see KualiDocumentFormBase#addRequiredNonEditableProperties()
076         */
077        @Override
078        public void addRequiredNonEditableProperties(){
079            super.addRequiredNonEditableProperties();
080            registerRequiredNonEditableProperty(KRADConstants.BUSINESS_OBJECT_CLASS_ATTRIBUTE);
081            registerRequiredNonEditableProperty(KRADConstants.LOOKUP_RESULTS_BO_CLASS_NAME);
082            registerRequiredNonEditableProperty(KRADConstants.LOOKED_UP_COLLECTION_NAME);
083            registerRequiredNonEditableProperty(KRADConstants.LOOKUP_RESULTS_SEQUENCE_NUMBER);
084            registerRequiredNonEditableProperty(KRADConstants.FIELD_NAME_TO_FOCUS_ON_AFTER_SUBMIT);
085        }
086    
087        /**
088         * Used to indicate which result set we're using when refreshing/returning from a multi-value lookup
089         */
090        protected String lookupResultsSequenceNumber;
091        /**
092         * The type of result returned by the multi-value lookup
093         * 
094         * TODO: to be persisted in the lookup results service instead?
095         */
096        protected String lookupResultsBOClassName;
097        
098        /**
099         * 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