001/**
002 * Copyright 2005-2016 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 */
016package org.kuali.rice.kns.web.struts.form;
017
018import org.apache.commons.beanutils.PropertyUtils;
019import org.apache.commons.lang.StringUtils;
020import org.apache.struts.upload.FormFile;
021import org.kuali.rice.core.api.config.ConfigurationException;
022import org.kuali.rice.core.api.util.RiceKeyConstants;
023import org.kuali.rice.core.web.format.FormatException;
024import org.kuali.rice.core.web.format.Formatter;
025import org.kuali.rice.kew.api.WorkflowDocument;
026import org.kuali.rice.kim.api.services.KimApiServiceLocator;
027import org.kuali.rice.kns.document.MaintenanceDocument;
028import org.kuali.rice.kns.document.MaintenanceDocumentBase;
029import org.kuali.rice.kns.document.authorization.MaintenanceDocumentRestrictions;
030import org.kuali.rice.kns.maintenance.Maintainable;
031import org.kuali.rice.kns.service.KNSServiceLocator;
032import org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService;
033import org.kuali.rice.kns.util.FieldUtils;
034import org.kuali.rice.krad.bo.BusinessObject;
035import org.kuali.rice.krad.bo.PersistableAttachment;
036import org.kuali.rice.krad.bo.PersistableBusinessObject;
037import org.kuali.rice.krad.datadictionary.exception.UnknownDocumentTypeException;
038import org.kuali.rice.krad.document.Document;
039import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
040import org.kuali.rice.krad.util.GlobalVariables;
041import org.kuali.rice.krad.util.KRADConstants;
042import org.kuali.rice.krad.util.ObjectUtils;
043
044import javax.servlet.http.HttpServletRequest;
045import java.lang.reflect.Constructor;
046import java.lang.reflect.InvocationTargetException;
047import java.util.Enumeration;
048import java.util.HashMap;
049import java.util.Iterator;
050import java.util.List;
051import java.util.Map;
052import java.util.regex.Matcher;
053import java.util.regex.Pattern;
054
055/**
056 * This class is the base action form for all maintenance documents.
057 * 
058 * 
059 */
060public 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