Coverage Report - org.kuali.rice.kns.maintenance.KualiMaintainableImpl
 
Classes in this File Line Coverage Branch Coverage Complexity
KualiMaintainableImpl
0%
0/760
0%
0/402
3.574
 
 1  
 /*
 2  
  * Copyright 2005-2007 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.maintenance;
 17  
 
 18  
 import java.beans.PropertyDescriptor;
 19  
 import java.io.Serializable;
 20  
 import java.lang.reflect.InvocationTargetException;
 21  
 import java.security.GeneralSecurityException;
 22  
 import java.util.ArrayList;
 23  
 import java.util.Arrays;
 24  
 import java.util.Collection;
 25  
 import java.util.HashMap;
 26  
 import java.util.HashSet;
 27  
 import java.util.Iterator;
 28  
 import java.util.List;
 29  
 import java.util.Map;
 30  
 import java.util.Set;
 31  
 
 32  
 import org.apache.commons.beanutils.PropertyUtils;
 33  
 import org.apache.commons.lang.StringUtils;
 34  
 import org.apache.ojb.broker.metadata.ClassNotPersistenceCapableException;
 35  
 import org.kuali.rice.core.api.encryption.EncryptionService;
 36  
 import org.kuali.rice.core.api.services.CoreApiServiceLocator;
 37  
 import org.kuali.rice.core.web.format.FormatException;
 38  
 import org.kuali.rice.kim.bo.Person;
 39  
 import org.kuali.rice.kns.authorization.FieldRestriction;
 40  
 import org.kuali.rice.kns.bo.BusinessObject;
 41  
 import org.kuali.rice.kns.bo.BusinessObjectRelationship;
 42  
 import org.kuali.rice.kns.bo.DocumentHeader;
 43  
 import org.kuali.rice.kns.bo.PersistableBusinessObject;
 44  
 import org.kuali.rice.kns.datadictionary.AttributeSecurity;
 45  
 import org.kuali.rice.kns.datadictionary.MaintainableCollectionDefinition;
 46  
 import org.kuali.rice.kns.datadictionary.MaintainableFieldDefinition;
 47  
 import org.kuali.rice.kns.datadictionary.MaintainableItemDefinition;
 48  
 import org.kuali.rice.kns.datadictionary.MaintainableSectionDefinition;
 49  
 import org.kuali.rice.kns.datadictionary.exception.UnknownBusinessClassAttributeException;
 50  
 import org.kuali.rice.kns.document.MaintenanceDocument;
 51  
 import org.kuali.rice.kns.document.MaintenanceLock;
 52  
 import org.kuali.rice.kns.document.authorization.MaintenanceDocumentPresentationController;
 53  
 import org.kuali.rice.kns.document.authorization.MaintenanceDocumentRestrictions;
 54  
 import org.kuali.rice.kns.exception.DocumentTypeAuthorizationException;
 55  
 import org.kuali.rice.kns.exception.PessimisticLockingException;
 56  
 import org.kuali.rice.kns.lookup.LookupUtils;
 57  
 import org.kuali.rice.kns.lookup.valuefinder.ValueFinder;
 58  
 import org.kuali.rice.kns.service.BusinessObjectAuthorizationService;
 59  
 import org.kuali.rice.kns.service.BusinessObjectDictionaryService;
 60  
 import org.kuali.rice.kns.service.BusinessObjectMetaDataService;
 61  
 import org.kuali.rice.kns.service.BusinessObjectService;
 62  
 import org.kuali.rice.kns.service.DataDictionaryService;
 63  
 import org.kuali.rice.kns.service.DocumentHelperService;
 64  
 import org.kuali.rice.kns.service.KNSServiceLocator;
 65  
 import org.kuali.rice.kns.service.KNSServiceLocatorWeb;
 66  
 import org.kuali.rice.kns.service.LookupService;
 67  
 import org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService;
 68  
 import org.kuali.rice.kns.service.MaintenanceDocumentService;
 69  
 import org.kuali.rice.kns.service.ModuleService;
 70  
 import org.kuali.rice.kns.service.PersistenceStructureService;
 71  
 import org.kuali.rice.kns.uif.container.CollectionGroup;
 72  
 import org.kuali.rice.kns.uif.container.View;
 73  
 import org.kuali.rice.kns.uif.service.impl.ViewHelperServiceImpl;
 74  
 import org.kuali.rice.kns.uif.util.ObjectPropertyUtils;
 75  
 import org.kuali.rice.kns.util.FieldUtils;
 76  
 import org.kuali.rice.kns.util.GlobalVariables;
 77  
 import org.kuali.rice.kns.util.InactiveRecordsHidingUtils;
 78  
 import org.kuali.rice.kns.util.KNSConstants;
 79  
 import org.kuali.rice.kns.util.KNSPropertyConstants;
 80  
 import org.kuali.rice.kns.util.MaintenanceUtils;
 81  
 import org.kuali.rice.kns.util.MessageMap;
 82  
 import org.kuali.rice.kns.util.ObjectUtils;
 83  
 import org.kuali.rice.kns.util.WebUtils;
 84  
 import org.kuali.rice.kns.web.spring.form.MaintenanceForm;
 85  
 import org.kuali.rice.kns.web.ui.Section;
 86  
 import org.kuali.rice.kns.web.ui.SectionBridge;
 87  
 
 88  
 /**
 89  
  * Base Maintainable class to hold things common to all maintainables.
 90  
  */
 91  
 public class KualiMaintainableImpl extends ViewHelperServiceImpl implements Maintainable {
 92  
         private static final long serialVersionUID = 4814145799502207182L;
 93  
 
 94  0
         private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(KualiMaintainableImpl.class);
 95  
 
 96  
         protected String documentNumber;
 97  
         protected Object dataObject;
 98  
         protected PersistableBusinessObject businessObject;
 99  
         protected Class boClass;
 100  
         protected String maintenanceAction;
 101  
 
 102  0
         protected Map<String, PersistableBusinessObject> newCollectionLines = new HashMap<String, PersistableBusinessObject>();
 103  0
         protected Map<String, Boolean> inactiveRecordDisplay = new HashMap<String, Boolean>();
 104  
 
 105  
         protected String docTypeName;
 106  
 
 107  
         protected transient PersistenceStructureService persistenceStructureService;
 108  
         protected transient MaintenanceDocumentDictionaryService maintenanceDocumentDictionaryService;
 109  
         protected transient BusinessObjectService businessObjectService;
 110  
         protected transient BusinessObjectDictionaryService businessObjectDictionaryService;
 111  
         protected transient EncryptionService encryptionService;
 112  
         protected transient org.kuali.rice.kim.service.PersonService personService;
 113  
         protected transient BusinessObjectMetaDataService businessObjectMetaDataService;
 114  
         protected transient BusinessObjectAuthorizationService businessObjectAuthorizationService;
 115  
         protected transient MaintenanceDocumentService maintenanceDocumentService;
 116  
         protected transient DocumentHelperService documentHelperService;
 117  
         protected transient LookupService lookupService;
 118  
 
 119  
         /**
 120  
          * Default empty constructor
 121  
          */
 122  0
         public KualiMaintainableImpl() {
 123  0
         }
 124  
 
 125  
         /**
 126  
          * Constructor which initializes the business object to be maintained.
 127  
          * 
 128  
          * @param businessObject
 129  
          */
 130  
         public KualiMaintainableImpl(PersistableBusinessObject businessObject) {
 131  0
                 this();
 132  0
                 this.businessObject = businessObject;
 133  0
                 this.dataObject = businessObject;
 134  0
         }
 135  
 
 136  
         /**
 137  
          * This methods will do the setting of some attributes that might be
 138  
          * necessary if we're creating a new business object using on an existing
 139  
          * business object. For example, create a division Vendor based on an
 140  
          * existing parent Vendor. (Please see VendorMaintainableImpl.java)
 141  
          */
 142  
         public void setupNewFromExisting(MaintenanceDocument document, Map<String, String[]> parameters) {
 143  
 
 144  0
         }
 145  
 
 146  
         public void processAfterPost(MaintenanceDocument document, Map<String, String[]> parameters) {
 147  
 
 148  0
         }
 149  
 
 150  
         /**
 151  
          * This is a hook to allow the document to override the generic document
 152  
          * title.
 153  
          * 
 154  
          * @return String document title
 155  
          */
 156  
         public String getDocumentTitle(MaintenanceDocument document) {
 157  
                 // default implementation is to allow MaintenanceDocumentBase to
 158  
                 // generate the doc title
 159  0
                 return "";
 160  
         }
 161  
 
 162  
         /**
 163  
          * Note: as currently implemented, every key field for a given
 164  
          * BusinessObject subclass must have a visible getter.
 165  
          * 
 166  
          * @return String containing the business object class and key value pairs
 167  
          *         of the current instance that can be used as a unique locking
 168  
          *         representation.
 169  
          */
 170  
         public List<MaintenanceLock> generateMaintenanceLocks() {
 171  
 
 172  
                 // NOTE: KualiGlobalMaintainableImpl overrides this method and forces
 173  
                 // all globals to override that, so they each do their own thing
 174  
 
 175  0
                 List<MaintenanceLock> maintenanceLocks = new ArrayList<MaintenanceLock>();
 176  0
                 StringBuffer lockRepresentation = new StringBuffer(boClass.getName());
 177  0
                 lockRepresentation.append(KNSConstants.Maintenance.AFTER_CLASS_DELIM);
 178  
 
 179  0
                 Object bo = getDataObject();
 180  0
                 List keyFieldNames = getMaintenanceDocumentDictionaryService().getLockingKeys(getDocumentTypeName());
 181  
 
 182  0
                 for (Iterator i = keyFieldNames.iterator(); i.hasNext();) {
 183  0
                         String fieldName = (String) i.next();
 184  0
                         Object fieldValue = ObjectUtils.getPropertyValue(bo, fieldName);
 185  0
                         if (fieldValue == null) {
 186  0
                                 fieldValue = "";
 187  
                         }
 188  
 
 189  
                         // check if field is a secure
 190  0
                         if (getBusinessObjectAuthorizationService().attributeValueNeedsToBeEncryptedOnFormsAndLinks(boClass,
 191  
                                         fieldName)) {
 192  
                                 try {
 193  0
                                         fieldValue = getEncryptionService().encrypt(fieldValue);
 194  
                                 }
 195  0
                                 catch (GeneralSecurityException e) {
 196  0
                                         LOG.error("Unable to encrypt secure field for locking representation " + e.getMessage());
 197  0
                                         throw new RuntimeException("Unable to encrypt secure field for locking representation "
 198  
                                                         + e.getMessage());
 199  0
                                 }
 200  
                         }
 201  
 
 202  0
                         lockRepresentation.append(fieldName);
 203  0
                         lockRepresentation.append(KNSConstants.Maintenance.AFTER_FIELDNAME_DELIM);
 204  0
                         lockRepresentation.append(String.valueOf(fieldValue));
 205  0
                         if (i.hasNext()) {
 206  0
                                 lockRepresentation.append(KNSConstants.Maintenance.AFTER_VALUE_DELIM);
 207  
                         }
 208  0
                 }
 209  
 
 210  0
                 MaintenanceLock maintenanceLock = new MaintenanceLock();
 211  0
                 maintenanceLock.setDocumentNumber(documentNumber);
 212  0
                 maintenanceLock.setLockingRepresentation(lockRepresentation.toString());
 213  0
                 maintenanceLocks.add(maintenanceLock);
 214  0
                 return maintenanceLocks;
 215  
         }
 216  
 
 217  
         /**
 218  
          * @see org.kuali.rice.kns.maintenance.Maintainable#populateBusinessObject(java.util.Map,
 219  
          *      org.kuali.rice.kns.document.MaintenanceDocument, String)
 220  
          */
 221  
         @SuppressWarnings("unchecked")
 222  
         public Map populateBusinessObject(Map<String, String> fieldValues, MaintenanceDocument maintenanceDocument,
 223  
                         String methodToCall) {
 224  0
                 fieldValues = decryptEncryptedData(fieldValues, maintenanceDocument, methodToCall);
 225  0
                 Map newFieldValues = null;
 226  0
                 newFieldValues = getPersonService().resolvePrincipalNamesToPrincipalIds(getBusinessObject(), fieldValues);
 227  
 
 228  0
                 Map cachedValues = FieldUtils.populateBusinessObjectFromMap(getBusinessObject(), newFieldValues);
 229  0
                 performForceUpperCase(newFieldValues);
 230  
 
 231  0
                 return cachedValues;
 232  
         }
 233  
 
 234  
         /**
 235  
          * Special hidden parameters are set on the maintenance jsp starting with a
 236  
          * prefix that tells us which fields have been encrypted. This field finds
 237  
          * the those parameters in the map, whose value gives us the property name
 238  
          * that has an encrypted value. We then need to decrypt the value in the Map
 239  
          * before the business object is populated.
 240  
          * 
 241  
          * @param fieldValues
 242  
          *            - possibly with encrypted values
 243  
          * @return Map fieldValues - with no encrypted values
 244  
          */
 245  
         protected Map<String, String> decryptEncryptedData(Map<String, String> fieldValues,
 246  
                         MaintenanceDocument maintenanceDocument, String methodToCall) {
 247  
                 try {
 248  0
                         MaintenanceDocumentRestrictions auths = KNSServiceLocatorWeb.getBusinessObjectAuthorizationService()
 249  
                                         .getMaintenanceDocumentRestrictions(maintenanceDocument,
 250  
                                                         GlobalVariables.getUserSession().getPerson());
 251  0
                         for (Iterator<String> iter = fieldValues.keySet().iterator(); iter.hasNext();) {
 252  0
                                 String fieldName = iter.next();
 253  0
                                 String fieldValue = (String) fieldValues.get(fieldName);
 254  
 
 255  0
                                 if (fieldValue != null && !"".equals(fieldValue)
 256  
                                                 && fieldValue.endsWith(EncryptionService.ENCRYPTION_POST_PREFIX)) {
 257  0
                                         if (shouldFieldBeEncrypted(maintenanceDocument, fieldName, auths, methodToCall)) {
 258  0
                                                 String encryptedValue = fieldValue;
 259  
 
 260  
                                                 // take off the postfix
 261  0
                                                 encryptedValue = StringUtils.stripEnd(encryptedValue, EncryptionService.ENCRYPTION_POST_PREFIX);
 262  0
                                                 String decryptedValue = getEncryptionService().decrypt(encryptedValue);
 263  
 
 264  0
                                                 fieldValues.put(fieldName, decryptedValue);
 265  0
                                         }
 266  
                                         else
 267  0
                                                 throw new RuntimeException("The field value for field name " + fieldName
 268  
                                                                 + " should not be encrypted.");
 269  
                                 }
 270  0
                                 else if (fieldValue != null && !"".equals(fieldValue)
 271  
                                                 && shouldFieldBeEncrypted(maintenanceDocument, fieldName, auths, methodToCall))
 272  0
                                         throw new RuntimeException("The field value for field name " + fieldName + " should be encrypted.");
 273  0
                         }
 274  
                 }
 275  0
                 catch (GeneralSecurityException e) {
 276  0
                         throw new RuntimeException("Unable to decrypt secure data: " + e.getMessage());
 277  0
                 }
 278  
 
 279  0
                 return fieldValues;
 280  
         }
 281  
 
 282  
         /**
 283  
          * Determines whether the field in a request should be encrypted. This base
 284  
          * implementation does not work for properties of collection elements.
 285  
          * 
 286  
          * This base implementation will only return true if the maintenance
 287  
          * document is being refreshed after a lookup (i.e. methodToCall is
 288  
          * "refresh") and the data dictionary-based attribute security definition
 289  
          * has any restriction defined, whether the user would be authorized to view
 290  
          * the field. This assumes that only fields returned from a lookup should be
 291  
          * encrypted in a request. If the user otherwise has no permissions to
 292  
          * view/edit the field, then a request parameter will not be sent back to
 293  
          * the server for population.
 294  
          * 
 295  
          * @param maintenanceDocument
 296  
          * @param fieldName
 297  
          * @param auths
 298  
          * @param methodToCall
 299  
          * @return
 300  
          */
 301  
         protected boolean shouldFieldBeEncrypted(MaintenanceDocument maintenanceDocument, String fieldName,
 302  
                         MaintenanceDocumentRestrictions auths, String methodToCall) {
 303  0
                 if ("refresh".equals(methodToCall) && fieldName != null) {
 304  0
                         fieldName = fieldName.replaceAll("\\[[0-9]*+\\]", "");
 305  0
                         fieldName = fieldName.replaceAll("^add\\.", "");
 306  0
                         Map<String, AttributeSecurity> fieldNameToAttributeSecurityMap = MaintenanceUtils
 307  
                                         .retrievePropertyPathToAttributeSecurityMappings(getDocumentTypeName());
 308  0
                         AttributeSecurity attributeSecurity = fieldNameToAttributeSecurityMap.get(fieldName);
 309  0
                         return attributeSecurity != null && attributeSecurity.hasRestrictionThatRemovesValueFromUI();
 310  
                 }
 311  
                 else {
 312  0
                         return false;
 313  
                 }
 314  
         }
 315  
 
 316  
         /**
 317  
          * Calls method to get all the core sections for the business object defined
 318  
          * in the data dictionary. Then determines if the bo has custom attributes,
 319  
          * if so builds a custom attribute section and adds to the section list.
 320  
          * 
 321  
          * @return List of org.kuali.ui.Section objects
 322  
          */
 323  
         public List getSections(MaintenanceDocument document, Maintainable oldMaintainable) {
 324  0
                 List<Section> sections = new ArrayList<Section>();
 325  0
                 sections.addAll(getCoreSections(document, oldMaintainable));
 326  
 
 327  0
                 return sections;
 328  
         }
 329  
 
 330  
         /**
 331  
          * Gets list of maintenance sections built from the data dictionary. If the
 332  
          * section contains maintenance fields, construct Row/Field UI objects and
 333  
          * place under Section UI. If section contains a maintenance collection,
 334  
          * call method to build a Section UI which contains rows of Container
 335  
          * Fields.
 336  
          * 
 337  
          * @return List of org.kuali.ui.Section objects
 338  
          */
 339  
         public List<Section> getCoreSections(MaintenanceDocument document, Maintainable oldMaintainable) {
 340  0
                 List<Section> sections = new ArrayList<Section>();
 341  0
                 MaintenanceDocumentRestrictions maintenanceRestrictions = KNSServiceLocatorWeb
 342  
                                 .getBusinessObjectAuthorizationService().getMaintenanceDocumentRestrictions(document,
 343  
                                                 GlobalVariables.getUserSession().getPerson());
 344  
 
 345  0
                 MaintenanceDocumentPresentationController maintenanceDocumentPresentationController = (MaintenanceDocumentPresentationController) getDocumentHelperService()
 346  
                                 .getDocumentPresentationController(document);
 347  0
                 Set<String> conditionallyRequiredFields = maintenanceDocumentPresentationController
 348  
                                 .getConditionallyRequiredPropertyNames(document);
 349  
 
 350  0
                 List<MaintainableSectionDefinition> sectionDefinitions = getMaintenanceDocumentDictionaryService()
 351  
                                 .getMaintainableSections(docTypeName);
 352  
                 try {
 353  
                         // iterate through section definitions and create Section UI object
 354  0
                         for (Iterator iter = sectionDefinitions.iterator(); iter.hasNext();) {
 355  0
                                 MaintainableSectionDefinition maintSectionDef = (MaintainableSectionDefinition) iter.next();
 356  
 
 357  0
                                 List<String> displayedFieldNames = new ArrayList<String>();
 358  0
                                 if (!maintenanceRestrictions.isHiddenSectionId(maintSectionDef.getId())) {
 359  
 
 360  0
                                         for (Iterator iter2 = maintSectionDef.getMaintainableItems().iterator(); iter2.hasNext();) {
 361  0
                                                 MaintainableItemDefinition item = (MaintainableItemDefinition) iter2.next();
 362  0
                                                 if (item instanceof MaintainableFieldDefinition) {
 363  0
                                                         displayedFieldNames.add(((MaintainableFieldDefinition) item).getName());
 364  
                                                 }
 365  0
                                         }
 366  
 
 367  0
                                         Section section = SectionBridge.toSection(maintSectionDef, getBusinessObject(), this,
 368  
                                                         oldMaintainable, getMaintenanceAction(), displayedFieldNames, conditionallyRequiredFields);
 369  0
                                         if (maintenanceRestrictions.isReadOnlySectionId(maintSectionDef.getId())) {
 370  0
                                                 section.setReadOnly(true);
 371  
                                         }
 372  
 
 373  
                                         // add to section list
 374  0
                                         sections.add(section);
 375  
                                 }
 376  
 
 377  0
                         }
 378  
 
 379  
                 }
 380  0
                 catch (InstantiationException e) {
 381  0
                         LOG.error("Unable to create instance of object class" + e.getMessage());
 382  0
                         throw new RuntimeException("Unable to create instance of object class" + e.getMessage());
 383  
                 }
 384  0
                 catch (IllegalAccessException e) {
 385  0
                         LOG.error("Unable to create instance of object class" + e.getMessage());
 386  0
                         throw new RuntimeException("Unable to create instance of object class" + e.getMessage());
 387  0
                 }
 388  
 
 389  0
                 return sections;
 390  
         }
 391  
 
 392  
         /**
 393  
          * 
 394  
          * @see org.kuali.rice.kns.maintenance.Maintainable#saveBusinessObject()
 395  
          */
 396  
         public void saveBusinessObject() {
 397  0
                 getBusinessObjectService().linkAndSave(businessObject);
 398  0
         }
 399  
 
 400  
         /**
 401  
          * Retrieves title for maintenance document from data dictionary
 402  
          */
 403  
         public String getMaintainableTitle() {
 404  0
                 return getMaintenanceDocumentDictionaryService().getMaintenanceLabel(getDocumentTypeName());
 405  
         }
 406  
 
 407  
         /**
 408  
          * Retrieves the status of the boNotesEnabled
 409  
          */
 410  
         public boolean isBoNotesEnabled() {
 411  0
                 return getBusinessObjectDictionaryService().areNotesSupported(this.boClass);
 412  
         }
 413  
 
 414  
         /**
 415  
          * @see org.kuali.rice.kns.maintenance.Maintainable#refresh(java.lang.String,
 416  
          *      java.util.Map) Impls will be needed if custom action is needed on
 417  
          *      refresh.
 418  
          */
 419  
         public void refresh(String refreshCaller, Map fieldValues, MaintenanceDocument document) {
 420  0
                 String referencesToRefresh = (String) fieldValues.get(KNSConstants.REFERENCES_TO_REFRESH);
 421  0
                 refreshReferences(referencesToRefresh);
 422  0
         }
 423  
 
 424  
         protected void refreshReferences(String referencesToRefresh) {
 425  0
                 PersistenceStructureService persistenceStructureService = getPersistenceStructureService();
 426  0
                 if (StringUtils.isNotBlank(referencesToRefresh)) {
 427  0
                         String[] references = StringUtils.split(referencesToRefresh, KNSConstants.REFERENCES_TO_REFRESH_SEPARATOR);
 428  0
                         for (String reference : references) {
 429  0
                                 if (StringUtils.isNotBlank(reference)) {
 430  0
                                         if (reference.startsWith(KNSConstants.ADD_PREFIX + ".")) {
 431  
                                                 // add one for the period
 432  0
                                                 reference = reference.substring(KNSConstants.ADD_PREFIX.length() + 1);
 433  
 
 434  0
                                                 String boToRefreshName = StringUtils.substringBeforeLast(reference, ".");
 435  0
                                                 String propertyToRefresh = StringUtils.substringAfterLast(reference, ".");
 436  0
                                                 if (StringUtils.isNotBlank(propertyToRefresh)) {
 437  0
                                                         PersistableBusinessObject addlineBO = getNewCollectionLine(boToRefreshName);
 438  0
                                                         Class addlineBOClass = addlineBO.getClass();
 439  0
                                                         if (LOG.isDebugEnabled()) {
 440  0
                                                                 LOG.debug("Refresh this \"new\"/add object for the collections:  " + reference);
 441  
                                                         }
 442  0
                                                         if (persistenceStructureService.hasReference(addlineBOClass, propertyToRefresh)
 443  
                                                                         || persistenceStructureService.hasCollection(addlineBOClass, propertyToRefresh)) {
 444  0
                                                                 addlineBO.refreshReferenceObject(propertyToRefresh);
 445  
                                                         }
 446  
                                                         else {
 447  0
                                                                 if (getDataDictionaryService().hasRelationship(addlineBOClass.getName(),
 448  
                                                                                 propertyToRefresh)) {
 449  
                                                                         // a DD mapping, try to go straight to the
 450  
                                                                         // object and refresh it there
 451  0
                                                                         Object possibleBO = ObjectUtils.getPropertyValue(addlineBO, propertyToRefresh);
 452  0
                                                                         if (possibleBO != null && possibleBO instanceof PersistableBusinessObject) {
 453  0
                                                                                 ((PersistableBusinessObject) possibleBO).refresh();
 454  
                                                                         }
 455  
                                                                 }
 456  
                                                         }
 457  0
                                                 }
 458  
                                                 else {
 459  0
                                                         LOG.error("Error: unable to refresh this \"new\"/add object for the collections:  "
 460  
                                                                         + reference);
 461  
                                                 }
 462  0
                                         }
 463  0
                                         else if (ObjectUtils.isNestedAttribute(reference)) {
 464  0
                                                 Object nestedObject = ObjectUtils.getNestedValue(getBusinessObject(),
 465  
                                                                 ObjectUtils.getNestedAttributePrefix(reference));
 466  0
                                                 if (nestedObject instanceof Collection) {
 467  
                                                         // do nothing, probably because it's not really a
 468  
                                                         // collection reference but a relationship defined
 469  
                                                         // in the DD for a collections lookup
 470  
                                                         // this part will need to be rewritten when the DD
 471  
                                                         // supports true collection references
 472  
                                                 }
 473  0
                                                 else if (nestedObject instanceof PersistableBusinessObject) {
 474  0
                                                         String propertyToRefresh = ObjectUtils.getNestedAttributePrimitive(reference);
 475  0
                                                         if (persistenceStructureService.hasReference(nestedObject.getClass(), propertyToRefresh)
 476  
                                                                         || persistenceStructureService.hasCollection(nestedObject.getClass(),
 477  
                                                                                         propertyToRefresh)) {
 478  0
                                                                 if (LOG.isDebugEnabled()) {
 479  0
                                                                         LOG.debug("Refeshing " + ObjectUtils.getNestedAttributePrefix(reference) + " "
 480  
                                                                                         + ObjectUtils.getNestedAttributePrimitive(reference));
 481  
                                                                 }
 482  0
                                                                 ((PersistableBusinessObject) nestedObject).refreshReferenceObject(propertyToRefresh);
 483  
                                                         }
 484  
                                                         else {
 485  
                                                                 // a DD mapping, try to go straight to the
 486  
                                                                 // object and refresh it there
 487  0
                                                                 Object possibleBO = ObjectUtils.getPropertyValue(nestedObject, propertyToRefresh);
 488  0
                                                                 if (possibleBO != null && possibleBO instanceof PersistableBusinessObject) {
 489  0
                                                                         if (getDataDictionaryService().hasRelationship(possibleBO.getClass().getName(),
 490  
                                                                                         propertyToRefresh)) {
 491  0
                                                                                 ((PersistableBusinessObject) possibleBO).refresh();
 492  
                                                                         }
 493  
                                                                 }
 494  
                                                         }
 495  0
                                                 }
 496  
                                                 else {
 497  0
                                                         LOG.warn("Expected that a referenceToRefresh ("
 498  
                                                                         + reference
 499  
                                                                         + ")  would be a PersistableBusinessObject or Collection, but instead, it was of class "
 500  
                                                                         + nestedObject.getClass().getName());
 501  
                                                 }
 502  0
                                         }
 503  
                                         else {
 504  0
                                                 if (LOG.isDebugEnabled()) {
 505  0
                                                         LOG.debug("Refreshing " + reference);
 506  
                                                 }
 507  0
                                                 if (persistenceStructureService.hasReference(boClass, reference)
 508  
                                                                 || persistenceStructureService.hasCollection(boClass, reference)) {
 509  0
                                                         getBusinessObject().refreshReferenceObject(reference);
 510  
                                                 }
 511  
                                                 else {
 512  0
                                                         if (getDataDictionaryService().hasRelationship(getBusinessObject().getClass().getName(),
 513  
                                                                         reference)) {
 514  
                                                                 // a DD mapping, try to go straight to the
 515  
                                                                 // object and refresh it there
 516  0
                                                                 Object possibleRelationship = ObjectUtils.getPropertyValue(getBusinessObject(),
 517  
                                                                                 reference);
 518  0
                                                                 if (possibleRelationship != null) {
 519  0
                                                                         if (possibleRelationship instanceof PersistableBusinessObject) {
 520  0
                                                                                 ((PersistableBusinessObject) possibleRelationship).refresh();
 521  
                                                                         }
 522  0
                                                                         else if (possibleRelationship instanceof Collection) {
 523  
                                                                                 // do nothing, probably because it's not
 524  
                                                                                 // really a collection reference but a
 525  
                                                                                 // relationship defined in the DD for a
 526  
                                                                                 // collections lookup
 527  
                                                                                 // this part will need to be rewritten
 528  
                                                                                 // when the DD supports true collection
 529  
                                                                                 // references
 530  
                                                                         }
 531  
                                                                         else {
 532  0
                                                                                 LOG.warn("Expected that a referenceToRefresh ("
 533  
                                                                                                 + reference
 534  
                                                                                                 + ")  would be a PersistableBusinessObject or Collection, but instead, it was of class "
 535  
                                                                                                 + possibleRelationship.getClass().getName());
 536  
                                                                         }
 537  
                                                                 }
 538  
                                                         }
 539  
                                                 }
 540  
                                         }
 541  
                                 }
 542  
                         }
 543  
                 }
 544  0
         }
 545  
 
 546  
         public void addMultipleValueLookupResults(MaintenanceDocument document, String collectionName,
 547  
                         Collection<PersistableBusinessObject> rawValues, boolean needsBlank, PersistableBusinessObject bo) {
 548  0
                 Collection maintCollection = (Collection) ObjectUtils.getPropertyValue(bo, collectionName);
 549  0
                 String docTypeName = document.getDocumentHeader().getWorkflowDocument().getDocumentType();
 550  
 
 551  0
                 List<String> duplicateIdentifierFieldsFromDataDictionary = getDuplicateIdentifierFieldsFromDataDictionary(
 552  
                                 docTypeName, collectionName);
 553  
 
 554  0
                 List<String> existingIdentifierList = getMultiValueIdentifierList(maintCollection,
 555  
                                 duplicateIdentifierFieldsFromDataDictionary);
 556  
 
 557  0
                 Class collectionClass = getMaintenanceDocumentDictionaryService().getCollectionBusinessObjectClass(docTypeName,
 558  
                                 collectionName);
 559  
 
 560  0
                 List<MaintainableSectionDefinition> sections = getMaintenanceDocumentDictionaryService()
 561  
                                 .getMaintainableSections(docTypeName);
 562  0
                 Map<String, String> template = MaintenanceUtils.generateMultipleValueLookupBOTemplate(sections, collectionName);
 563  
                 try {
 564  0
                         for (PersistableBusinessObject nextBo : rawValues) {
 565  
                                 PersistableBusinessObject templatedBo;
 566  0
                                 if (needsBlank) {
 567  0
                                         templatedBo = (PersistableBusinessObject) collectionClass.newInstance();
 568  
                                 }
 569  
                                 else {
 570  
                                         // templatedBo = (PersistableBusinessObject)
 571  
                                         // ObjectUtils.createHybridBusinessObject(collectionClass,
 572  
                                         // nextBo, template);
 573  
                                         try {
 574  0
                                                 ModuleService moduleService = KNSServiceLocatorWeb.getKualiModuleService()
 575  
                                                                 .getResponsibleModuleService(collectionClass);
 576  0
                                                 if (moduleService != null && moduleService.isExternalizable(collectionClass))
 577  0
                                                         templatedBo = (PersistableBusinessObject) moduleService
 578  
                                                                         .createNewObjectFromExternalizableClass(collectionClass);
 579  
                                                 else
 580  0
                                                         templatedBo = (PersistableBusinessObject) collectionClass.newInstance();
 581  
                                         }
 582  0
                                         catch (Exception e) {
 583  0
                                                 throw new RuntimeException("Cannot instantiate " + collectionClass.getName(), e);
 584  0
                                         }
 585  
                                         // first set the default values specified in the DD
 586  0
                                         setNewCollectionLineDefaultValues(collectionName, templatedBo);
 587  
                                         // then set the values from the multiple value lookup result
 588  0
                                         ObjectUtils.createHybridBusinessObject(templatedBo, nextBo, template);
 589  
 
 590  0
                                         prepareBusinessObjectForAdditionFromMultipleValueLookup(collectionName, templatedBo);
 591  
                                 }
 592  0
                                 templatedBo.setNewCollectionRecord(true);
 593  
 
 594  0
                                 if (!hasBusinessObjectExisted(templatedBo, existingIdentifierList,
 595  
                                                 duplicateIdentifierFieldsFromDataDictionary)) {
 596  0
                                         maintCollection.add(templatedBo);
 597  
 
 598  
                                 }
 599  0
                         }
 600  
                 }
 601  0
                 catch (Exception e) {
 602  0
                         LOG.error("Unable to add multiple value lookup results " + e.getMessage());
 603  0
                         throw new RuntimeException("Unable to add multiple value lookup results " + e.getMessage());
 604  0
                 }
 605  0
         }
 606  
 
 607  
         /**
 608  
          * This method is to retrieve a List of fields which are specified in the
 609  
          * maintenance document data dictionary as the
 610  
          * duplicateIdentificationFields. This List is used to determine whether the
 611  
          * new entry being added to the collection is a duplicate entry and if so,
 612  
          * we should not add the new entry to the existing collection
 613  
          * 
 614  
          * @param docTypeName
 615  
          * @param collectionName
 616  
          */
 617  
         public List<String> getDuplicateIdentifierFieldsFromDataDictionary(String docTypeName, String collectionName) {
 618  0
                 List<String> duplicateIdentifierFieldNames = new ArrayList<String>();
 619  0
                 MaintainableCollectionDefinition collDef = getMaintenanceDocumentDictionaryService().getMaintainableCollection(
 620  
                                 docTypeName, collectionName);
 621  0
                 Collection<MaintainableFieldDefinition> fieldDef = collDef.getDuplicateIdentificationFields();
 622  0
                 for (MaintainableFieldDefinition eachFieldDef : fieldDef) {
 623  0
                         duplicateIdentifierFieldNames.add(eachFieldDef.getName());
 624  
                 }
 625  0
                 return duplicateIdentifierFieldNames;
 626  
         }
 627  
 
 628  
         public List<String> getMultiValueIdentifierList(Collection maintCollection, List<String> duplicateIdentifierFields) {
 629  0
                 List<String> identifierList = new ArrayList<String>();
 630  0
                 for (PersistableBusinessObject bo : (Collection<PersistableBusinessObject>) maintCollection) {
 631  0
                         String uniqueIdentifier = new String();
 632  0
                         for (String identifierField : duplicateIdentifierFields) {
 633  0
                                 uniqueIdentifier = uniqueIdentifier + identifierField + "-"
 634  
                                                 + ObjectUtils.getPropertyValue(bo, identifierField);
 635  
                         }
 636  0
                         if (StringUtils.isNotEmpty(uniqueIdentifier)) {
 637  0
                                 identifierList.add(uniqueIdentifier);
 638  
                         }
 639  0
                 }
 640  0
                 return identifierList;
 641  
         }
 642  
 
 643  
         public boolean hasBusinessObjectExisted(BusinessObject bo, List<String> existingIdentifierList,
 644  
                         List<String> duplicateIdentifierFields) {
 645  0
                 String uniqueIdentifier = new String();
 646  0
                 for (String identifierField : duplicateIdentifierFields) {
 647  0
                         uniqueIdentifier = uniqueIdentifier + identifierField + "-"
 648  
                                         + ObjectUtils.getPropertyValue(bo, identifierField);
 649  
                 }
 650  0
                 if (existingIdentifierList.contains(uniqueIdentifier)) {
 651  0
                         return true;
 652  
                 }
 653  
                 else {
 654  0
                         return false;
 655  
                 }
 656  
         }
 657  
 
 658  
         public void prepareBusinessObjectForAdditionFromMultipleValueLookup(String collectionName, BusinessObject bo) {
 659  
                 // default implementation does nothing
 660  0
         }
 661  
 
 662  
         /**
 663  
          * 
 664  
          * @see org.kuali.rice.kns.maintenance.Maintainable#prepareForSave()
 665  
          */
 666  
         public void prepareForSave() {
 667  
 
 668  0
         }
 669  
 
 670  
         /**
 671  
          * 
 672  
          * @see org.kuali.rice.kns.maintenance.Maintainable#processAfterRetrieve()
 673  
          */
 674  
         public void processAfterRetrieve() {
 675  0
         }
 676  
 
 677  
         /**
 678  
          * Set the new collection records back to true so they can be deleted (copy
 679  
          * should act like new)
 680  
          * 
 681  
          * @see org.kuali.rice.kns.maintenance.KualiMaintainableImpl#processAfterCopy()
 682  
          */
 683  
         public void processAfterCopy(MaintenanceDocument document, Map<String, String[]> parameters) {
 684  
                 try {
 685  0
                         ObjectUtils.setObjectPropertyDeep(businessObject, KNSPropertyConstants.NEW_COLLECTION_RECORD,
 686  
                                         boolean.class, true, 2);
 687  
                 }
 688  0
                 catch (Exception e) {
 689  0
                         LOG.error("unable to set newCollectionRecord property: " + e.getMessage(), e);
 690  0
                         throw new RuntimeException("unable to set newCollectionRecord property: " + e.getMessage(), e);
 691  0
                 }
 692  0
         }
 693  
 
 694  
         /**
 695  
          * @see org.kuali.rice.kns.maintenance.Maintainable#processAfterEdit()
 696  
          */
 697  
         public void processAfterEdit(MaintenanceDocument document, Map<String, String[]> parameters) {
 698  0
         }
 699  
 
 700  
         /**
 701  
          * @see org.kuali.rice.kns.maintenance.Maintainable#processAfterNew()
 702  
          */
 703  
         public void processAfterNew(MaintenanceDocument document, Map<String, String[]> parameters) {
 704  0
         }
 705  
 
 706  
         /**
 707  
          * Retrieves the document type name from the data dictionary based on
 708  
          * business object class
 709  
          */
 710  
         protected String getDocumentTypeName() {
 711  0
                 return getMaintenanceDocumentDictionaryService().getDocumentTypeName(boClass);
 712  
         }
 713  
 
 714  
         @Override
 715  
     public Object getDataObject() {
 716  0
         return dataObject;
 717  
     }
 718  
 
 719  
     @Override
 720  
     public void setDataObject(Object object) {
 721  0
         this.dataObject = object;
 722  
         
 723  0
         if(object instanceof PersistableBusinessObject) {
 724  0
             this.businessObject = (PersistableBusinessObject)object;
 725  
         }
 726  0
     }
 727  
 
 728  
     /**
 729  
      * @return Returns the instance of the business object being maintained.
 730  
      */
 731  
     public PersistableBusinessObject getBusinessObject() {
 732  0
         return businessObject;
 733  
     }
 734  
 
 735  
     /**
 736  
      * @param businessObject
 737  
      *            Sets the instance of a business object that will be
 738  
      *            maintained.
 739  
      */
 740  
     public void setBusinessObject(PersistableBusinessObject businessObject) {
 741  0
         this.businessObject = businessObject;
 742  0
         this.dataObject = businessObject;
 743  0
     }
 744  
 
 745  
         /**
 746  
          * @return Returns the boClass.
 747  
          */
 748  
         public Class getBoClass() {
 749  0
                 return boClass;
 750  
         }
 751  
 
 752  
         /**
 753  
          * @param boClass
 754  
          *            The boClass to set.
 755  
          */
 756  
         public void setBoClass(Class boClass) {
 757  0
                 this.boClass = boClass;
 758  0
                 this.docTypeName = getDocumentTypeName();
 759  0
         }
 760  
 
 761  
         /**
 762  
          * @return Returns the maintenanceAction.
 763  
          */
 764  
         public String getMaintenanceAction() {
 765  0
                 return maintenanceAction;
 766  
         }
 767  
 
 768  
         /**
 769  
          * @param maintenanceAction
 770  
          *            The maintenanceAction to set.
 771  
          */
 772  
         public void setMaintenanceAction(String maintenanceAction) {
 773  0
                 this.maintenanceAction = maintenanceAction;
 774  0
         }
 775  
 
 776  
         /**
 777  
          * 
 778  
          * @see org.kuali.rice.kns.maintenance.Maintainable#setGenerateDefaultValues()
 779  
          */
 780  
         public void setGenerateDefaultValues(String docTypeName) {
 781  0
                 List<MaintainableSectionDefinition> sectionDefinitions = getMaintenanceDocumentDictionaryService()
 782  
                                 .getMaintainableSections(docTypeName);
 783  0
                 Map defaultValues = new HashMap();
 784  
 
 785  
                 try {
 786  
                         // iterate through section definitions
 787  0
                         for (Iterator iter = sectionDefinitions.iterator(); iter.hasNext();) {
 788  
 
 789  0
                                 MaintainableSectionDefinition maintSectionDef = (MaintainableSectionDefinition) iter.next();
 790  0
                                 Collection maintItems = maintSectionDef.getMaintainableItems();
 791  0
                                 for (Iterator iterator = maintItems.iterator(); iterator.hasNext();) {
 792  0
                                         MaintainableItemDefinition item = (MaintainableItemDefinition) iterator.next();
 793  
 
 794  0
                                         if (item instanceof MaintainableFieldDefinition) {
 795  0
                                                 MaintainableFieldDefinition maintainableFieldDefinition = (MaintainableFieldDefinition) item;
 796  
 
 797  0
                                                 String defaultValue = maintainableFieldDefinition.getDefaultValue();
 798  0
                                                 if (defaultValue != null) {
 799  0
                                                         if (defaultValue.equals("true")) {
 800  0
                                                                 defaultValue = "Yes";
 801  
                                                         }
 802  0
                                                         else if (defaultValue.equals("false")) {
 803  0
                                                                 defaultValue = "No";
 804  
                                                         }
 805  
                                                 }
 806  
 
 807  0
                                                 Class defaultValueFinderClass = maintainableFieldDefinition.getDefaultValueFinderClass();
 808  0
                                                 if (defaultValueFinderClass != null) {
 809  0
                                                         defaultValue = ((ValueFinder) defaultValueFinderClass.newInstance()).getValue();
 810  
 
 811  
                                                 }
 812  0
                                                 if (defaultValue != null) {
 813  0
                                                         defaultValues.put(item.getName(), defaultValue);
 814  
                                                 }
 815  
                                         }
 816  0
                                 }
 817  0
                         }
 818  0
                         Map cachedValues = FieldUtils.populateBusinessObjectFromMap(getBusinessObject(), defaultValues);
 819  
                 }
 820  0
                 catch (Exception e) {
 821  0
                         LOG.error("Unable to set default value " + e.getMessage(), e);
 822  0
                         throw new RuntimeException("Unable to set default value" + e.getMessage(), e);
 823  0
                 }
 824  
 
 825  0
         }
 826  
 
 827  
         /**
 828  
          * 
 829  
          * @see org.kuali.rice.kns.maintenance.Maintainable#setGenerateBlankRequiredValues()
 830  
          */
 831  
         public void setGenerateBlankRequiredValues(String docTypeName) {
 832  
                 try {
 833  0
                         List<MaintainableSectionDefinition> sectionDefinitions = getMaintenanceDocumentDictionaryService()
 834  
                                         .getMaintainableSections(docTypeName);
 835  0
                         Map<String, String> defaultValues = new HashMap<String, String>();
 836  
 
 837  0
                         for (MaintainableSectionDefinition maintSectionDef : sectionDefinitions) {
 838  0
                                 for (MaintainableItemDefinition item : maintSectionDef.getMaintainableItems()) {
 839  0
                                         if (item instanceof MaintainableFieldDefinition) {
 840  0
                                                 MaintainableFieldDefinition maintainableFieldDefinition = (MaintainableFieldDefinition) item;
 841  0
                                                 if (maintainableFieldDefinition.isRequired()
 842  
                                                                 && maintainableFieldDefinition.isUnconditionallyReadOnly()) {
 843  0
                                                         Object currPropVal = ObjectUtils.getPropertyValue(this.getBusinessObject(), item.getName());
 844  0
                                                         if (currPropVal == null
 845  
                                                                         || (currPropVal instanceof String && StringUtils.isBlank((String) currPropVal))) {
 846  0
                                                                 Class<? extends ValueFinder> defaultValueFinderClass = maintainableFieldDefinition
 847  
                                                                                 .getDefaultValueFinderClass();
 848  0
                                                                 if (defaultValueFinderClass != null) {
 849  0
                                                                         String defaultValue = defaultValueFinderClass.newInstance().getValue();
 850  0
                                                                         if (defaultValue != null) {
 851  0
                                                                                 defaultValues.put(item.getName(), defaultValue);
 852  
                                                                         }
 853  
                                                                 }
 854  
                                                         }
 855  
                                                 }
 856  0
                                         }
 857  
                                 }
 858  
                         }
 859  0
                         FieldUtils.populateBusinessObjectFromMap(getBusinessObject(), defaultValues);
 860  
                 }
 861  0
                 catch (Exception e) {
 862  0
                         LOG.error("Unable to set blank required value " + e.getMessage(), e);
 863  0
                         throw new RuntimeException("Unable to set blank required value" + e.getMessage(), e);
 864  0
                 }
 865  0
         }
 866  
 
 867  
         /**
 868  
          * Sets the documentNumber attribute value.
 869  
          * 
 870  
          * @param documentNumber
 871  
          *            The documentNumber to set.
 872  
          */
 873  
         public final void setDocumentNumber(String documentNumber) {
 874  0
                 this.documentNumber = documentNumber;
 875  0
         }
 876  
 
 877  
         @Deprecated
 878  
         public void processAfterAddLine(String colName, Class colClass) {
 879  0
         }
 880  
 
 881  
         /**
 882  
          * @see org.kuali.rice.kns.maintenance.Maintainable#processBeforeAddLine(java.lang.String,
 883  
          *      java.lang.Class, org.kuali.rice.kns.bo.BusinessObject)
 884  
          */
 885  
         public void processBeforeAddLine(String colName, Class colClass, BusinessObject addBO) {
 886  0
         }
 887  
 
 888  
         /**
 889  
          * @see org.kuali.rice.kns.maintenance.Maintainable#getShowInactiveRecords(java.lang.String)
 890  
          */
 891  
         public boolean getShowInactiveRecords(String collectionName) {
 892  0
                 return InactiveRecordsHidingUtils.getShowInactiveRecords(inactiveRecordDisplay, collectionName);
 893  
         }
 894  
 
 895  
         /**
 896  
          * @see org.kuali.rice.kns.maintenance.Maintainable#setShowInactiveRecords(java.lang.String,
 897  
          *      boolean)
 898  
          */
 899  
         public void setShowInactiveRecords(String collectionName, boolean showInactive) {
 900  0
                 InactiveRecordsHidingUtils.setShowInactiveRecords(inactiveRecordDisplay, collectionName, showInactive);
 901  0
         }
 902  
 
 903  
         /**
 904  
          * @return the inactiveRecordDisplay
 905  
          */
 906  
         public Map<String, Boolean> getInactiveRecordDisplay() {
 907  0
                 return inactiveRecordDisplay;
 908  
         }
 909  
 
 910  
         public void addNewLineToCollection(String collectionName) {
 911  
 
 912  0
                 if (LOG.isDebugEnabled()) {
 913  0
                         LOG.debug("addNewLineToCollection( " + collectionName + " )");
 914  
                 }
 915  
                 // get the new line from the map
 916  0
                 PersistableBusinessObject addLine = newCollectionLines.get(collectionName);
 917  0
                 if (addLine != null) {
 918  
                         // mark the isNewCollectionRecord so the option to delete this line
 919  
                         // will be presented
 920  0
                         addLine.setNewCollectionRecord(true);
 921  
 
 922  
                         // if we add back add button on sub collection of an "add line" we
 923  
                         // may need extra logic here
 924  
 
 925  
                         // get the collection from the business object
 926  0
                         Collection maintCollection = (Collection) ObjectUtils.getPropertyValue(getBusinessObject(), collectionName);
 927  
                         // add the line to the collection
 928  0
                         maintCollection.add(addLine);
 929  
                         // refresh parent object since attributes could of changed prior to
 930  
                         // user clicking add
 931  
 
 932  0
                         String referencesToRefresh = LookupUtils
 933  
                                         .convertReferencesToSelectCollectionToString(getAllRefreshableReferences(getBusinessObject()
 934  
                                                         .getClass()));
 935  0
                         if (LOG.isInfoEnabled()) {
 936  0
                                 LOG.info("References to refresh for adding line to collection " + collectionName + ": "
 937  
                                                 + referencesToRefresh);
 938  
                         }
 939  0
                         refreshReferences(referencesToRefresh);
 940  
                 }
 941  
 
 942  0
                 initNewCollectionLine(collectionName);
 943  
 
 944  0
         }
 945  
 
 946  
         public PersistableBusinessObject getNewCollectionLine(String collectionName) {
 947  0
                 if (LOG.isDebugEnabled()) {
 948  
                         // LOG.debug( this + ") getNewCollectionLine( " + collectionName +
 949  
                         // ")", new Exception( "tracing exception") );
 950  0
                         LOG.debug("newCollectionLines: " + newCollectionLines);
 951  
                 }
 952  0
                 PersistableBusinessObject addLine = newCollectionLines.get(collectionName);
 953  0
                 if (addLine == null) {
 954  0
                         addLine = initNewCollectionLine(collectionName);
 955  
                 }
 956  0
                 return addLine;
 957  
         }
 958  
 
 959  
         public PersistableBusinessObject initNewCollectionLine(String collectionName) {
 960  0
                 if (LOG.isDebugEnabled()) {
 961  0
                         LOG.debug("initNewCollectionLine( " + collectionName + " )");
 962  
                 }
 963  
                 // try to get the object from the map
 964  
                 // BusinessObject addLine = newCollectionLines.get( collectionName );
 965  
                 // if ( addLine == null ) {
 966  
                 // if not there, instantiate a new one
 967  
                 PersistableBusinessObject addLine;
 968  
                 try {
 969  0
                         addLine = (PersistableBusinessObject) getMaintenanceDocumentDictionaryService()
 970  
                                         .getCollectionBusinessObjectClass(docTypeName, collectionName).newInstance();
 971  
                 }
 972  0
                 catch (Exception ex) {
 973  0
                         LOG.error("unable to instantiate new collection line", ex);
 974  0
                         throw new RuntimeException("unable to instantiate new collection line", ex);
 975  0
                 }
 976  
                 // and add it to the map
 977  0
                 newCollectionLines.put(collectionName, addLine);
 978  
                 // }
 979  
                 // set its values to the defaults
 980  0
                 setNewCollectionLineDefaultValues(collectionName, addLine);
 981  0
                 return addLine;
 982  
         }
 983  
 
 984  
         /**
 985  
          * 
 986  
          * @see org.kuali.rice.kns.maintenance.Maintainable#populateNewCollectionLines(java.util.Map)
 987  
          */
 988  
         public Map<String, String> populateNewCollectionLines(Map<String, String> fieldValues,
 989  
                         MaintenanceDocument maintenanceDocument, String methodToCall) {
 990  0
                 if (LOG.isDebugEnabled()) {
 991  0
                         LOG.debug("populateNewCollectionLines: " + fieldValues);
 992  
                 }
 993  0
                 fieldValues = decryptEncryptedData(fieldValues, maintenanceDocument, methodToCall);
 994  
 
 995  0
                 Map<String, String> cachedValues = new HashMap<String, String>();
 996  
 
 997  
                 // loop over all collections with an enabled add line
 998  0
                 List<MaintainableCollectionDefinition> collections = getMaintenanceDocumentDictionaryService()
 999  
                                 .getMaintainableCollections(docTypeName);
 1000  
 
 1001  0
                 for (MaintainableCollectionDefinition coll : collections) {
 1002  
                         // get the collection name
 1003  0
                         String collName = coll.getName();
 1004  0
                         if (LOG.isDebugEnabled()) {
 1005  0
                                 LOG.debug("checking for collection: " + collName);
 1006  
                         }
 1007  
                         // build a map for that collection
 1008  0
                         Map<String, String> collectionValues = new HashMap<String, String>();
 1009  0
                         Map<String, String> subCollectionValues = new HashMap<String, String>();
 1010  
                         // loop over the collection, extracting entries with a matching
 1011  
                         // prefix
 1012  0
                         for (Map.Entry<String, String> entry : fieldValues.entrySet()) {
 1013  0
                                 String key = entry.getKey();
 1014  0
                                 if (key.startsWith(collName)) {
 1015  0
                                         String subStrKey = key.substring(collName.length() + 1);
 1016  
                                         // check for subcoll w/ '[', set collName to propername and
 1017  
                                         // put in correct name for collection values (i.e. strip
 1018  
                                         // '*[x].')
 1019  0
                                         if (key.contains("[")) {
 1020  
 
 1021  
                                                 // collName = StringUtils.substringBeforeLast(key,"[");
 1022  
 
 1023  
                                                 // need the whole thing if subcollection
 1024  0
                                                 subCollectionValues.put(key, entry.getValue());
 1025  
                                         }
 1026  
                                         else {
 1027  0
                                                 collectionValues.put(subStrKey, entry.getValue());
 1028  
                                         }
 1029  
                                 }
 1030  0
                         }
 1031  
                         // send those values to the business object
 1032  0
                         if (LOG.isDebugEnabled()) {
 1033  0
                                 LOG.debug("values for collection: " + collectionValues);
 1034  
                         }
 1035  0
                         cachedValues.putAll(FieldUtils.populateBusinessObjectFromMap(getNewCollectionLine(collName),
 1036  
                                         collectionValues, KNSConstants.MAINTENANCE_ADD_PREFIX + collName + "."));
 1037  0
                         performFieldForceUpperCase(getNewCollectionLine(collName), collectionValues);
 1038  
 
 1039  0
                         cachedValues.putAll(populateNewSubCollectionLines(coll, subCollectionValues));
 1040  0
                 }
 1041  
 
 1042  
                 // cachedValues.putAll( FieldUtils.populateBusinessObjectFromMap( ))
 1043  0
                 return cachedValues;
 1044  
         }
 1045  
 
 1046  
         /*
 1047  
          * Yes, I think this could be merged with the above code - I'm leaving it
 1048  
          * separate until I figure out of there are any issues which would reqire
 1049  
          * that it be separated.
 1050  
          */
 1051  
         protected Map populateNewSubCollectionLines(MaintainableCollectionDefinition parentCollection, Map fieldValues) {
 1052  0
                 if (LOG.isDebugEnabled()) {
 1053  0
                         LOG.debug("populateNewSubCollectionLines: " + fieldValues);
 1054  
                 }
 1055  0
                 Map cachedValues = new HashMap();
 1056  
 
 1057  0
                 for (MaintainableCollectionDefinition coll : parentCollection.getMaintainableCollections()) {
 1058  
                         // get the collection name
 1059  0
                         String collName = coll.getName();
 1060  
 
 1061  0
                         if (LOG.isDebugEnabled()) {
 1062  0
                                 LOG.debug("checking for sub collection: " + collName);
 1063  
                         }
 1064  0
                         Map<String, String> parents = new HashMap<String, String>();
 1065  
                         // get parents from list
 1066  0
                         for (Object entry : fieldValues.entrySet()) {
 1067  0
                                 String key = (String) ((Map.Entry) entry).getKey();
 1068  0
                                 if (key.contains(collName)) {
 1069  0
                                         parents.put(StringUtils.substringBefore(key, "."), "");
 1070  
                                 }
 1071  0
                         }
 1072  
 
 1073  0
                         for (String parent : parents.keySet()) {
 1074  
                                 // build a map for that collection
 1075  0
                                 Map<String, Object> collectionValues = new HashMap<String, Object>();
 1076  
                                 // loop over the collection, extracting entries with a matching
 1077  
                                 // prefix
 1078  0
                                 for (Object entry : fieldValues.entrySet()) {
 1079  0
                                         String key = (String) ((Map.Entry) entry).getKey();
 1080  0
                                         if (key.contains(parent)) {
 1081  0
                                                 String substr = StringUtils.substringAfterLast(key, ".");
 1082  0
                                                 collectionValues.put(substr, ((Map.Entry) entry).getValue());
 1083  
                                         }
 1084  0
                                 }
 1085  
                                 // send those values to the business object
 1086  0
                                 if (LOG.isDebugEnabled()) {
 1087  0
                                         LOG.debug("values for sub collection: " + collectionValues);
 1088  
                                 }
 1089  0
                                 GlobalVariables.getMessageMap().addToErrorPath(
 1090  
                                                 KNSConstants.MAINTENANCE_ADD_PREFIX + parent + "." + collName);
 1091  0
                                 cachedValues.putAll(FieldUtils.populateBusinessObjectFromMap(getNewCollectionLine(parent + "."
 1092  
                                                 + collName), collectionValues, KNSConstants.MAINTENANCE_ADD_PREFIX + parent + "." + collName
 1093  
                                                 + "."));
 1094  0
                                 performFieldForceUpperCase(getNewCollectionLine(parent + "." + collName), collectionValues);
 1095  0
                                 GlobalVariables.getMessageMap().removeFromErrorPath(
 1096  
                                                 KNSConstants.MAINTENANCE_ADD_PREFIX + parent + "." + collName);
 1097  0
                         }
 1098  
 
 1099  0
                         cachedValues.putAll(populateNewSubCollectionLines(coll, fieldValues));
 1100  0
                 }
 1101  
 
 1102  0
                 return cachedValues;
 1103  
         }
 1104  
 
 1105  
         public Collection<String> getAffectedReferencesFromLookup(BusinessObject baseBO, String attributeName,
 1106  
                         String collectionPrefix) {
 1107  0
                 PersistenceStructureService pss = getPersistenceStructureService();
 1108  0
                 String nestedBOPrefix = "";
 1109  0
                 if (ObjectUtils.isNestedAttribute(attributeName)) {
 1110  
                         // if we're performing a lookup on a nested attribute, we need to
 1111  
                         // use the nested BO all the way down the chain
 1112  0
                         nestedBOPrefix = ObjectUtils.getNestedAttributePrefix(attributeName);
 1113  
 
 1114  
                         // renormalize the base BO so that the attribute name is not nested
 1115  
                         // anymore
 1116  0
                         Class reference = ObjectUtils.getPropertyType(baseBO, nestedBOPrefix, pss);
 1117  0
                         if (!(PersistableBusinessObject.class.isAssignableFrom(reference))) {
 1118  0
                                 return new ArrayList<String>();
 1119  
                         }
 1120  
 
 1121  
                         try {
 1122  0
                                 baseBO = (PersistableBusinessObject) reference.newInstance();
 1123  
                         }
 1124  0
                         catch (InstantiationException e) {
 1125  0
                                 LOG.error(e);
 1126  
                         }
 1127  0
                         catch (IllegalAccessException e) {
 1128  0
                                 LOG.error(e);
 1129  0
                         }
 1130  0
                         attributeName = ObjectUtils.getNestedAttributePrimitive(attributeName);
 1131  
                 }
 1132  
 
 1133  0
                 if (baseBO == null) {
 1134  0
                         return new ArrayList<String>();
 1135  
                 }
 1136  
 
 1137  0
                 Map<String, Class> referenceNameToClassFromPSS = LookupUtils.getPrimitiveReference(baseBO, attributeName);
 1138  0
                 if (referenceNameToClassFromPSS.size() > 1) {
 1139  0
                         LOG.error("LookupUtils.getPrimitiveReference return results should only have at most one element");
 1140  
                 }
 1141  
 
 1142  0
                 BusinessObjectMetaDataService businessObjectMetaDataService = getBusinessObjectMetaDataService();
 1143  0
                 BusinessObjectRelationship relationship = businessObjectMetaDataService.getBusinessObjectRelationship(baseBO,
 1144  
                                 attributeName);
 1145  0
                 if (relationship == null) {
 1146  0
                         return new ArrayList<String>();
 1147  
                 }
 1148  
 
 1149  0
                 Map<String, String> fkToPkMappings = relationship.getParentToChildReferences();
 1150  
 
 1151  0
                 Collection<String> affectedReferences = generateAllAffectedReferences(baseBO.getClass(), fkToPkMappings,
 1152  
                                 nestedBOPrefix, collectionPrefix);
 1153  0
                 if (LOG.isDebugEnabled()) {
 1154  0
                         LOG.debug("References affected by a lookup on BO attribute \"" + collectionPrefix + nestedBOPrefix + "."
 1155  
                                         + attributeName + ": " + affectedReferences);
 1156  
                 }
 1157  
 
 1158  0
                 return affectedReferences;
 1159  
         }
 1160  
 
 1161  
         protected boolean isRelationshipRefreshable(Class boClass, String relationshipName) {
 1162  0
                 if (getPersistenceStructureService().isPersistable(boClass)) {
 1163  0
                         if (getPersistenceStructureService().hasCollection(boClass, relationshipName)) {
 1164  0
                                 return !getPersistenceStructureService().isCollectionUpdatable(boClass, relationshipName);
 1165  
                         }
 1166  0
                         else if (getPersistenceStructureService().hasReference(boClass, relationshipName)) {
 1167  0
                                 return !getPersistenceStructureService().isReferenceUpdatable(boClass, relationshipName);
 1168  
                         }
 1169  
                         // else, assume that the relationship is defined in the DD
 1170  
                 }
 1171  
 
 1172  0
                 return true;
 1173  
         }
 1174  
 
 1175  
         protected Collection<String> generateAllAffectedReferences(Class boClass, Map<String, String> fkToPkMappings,
 1176  
                         String nestedBOPrefix, String collectionPrefix) {
 1177  0
                 Set<String> allAffectedReferences = new HashSet<String>();
 1178  0
                 DataDictionaryService dataDictionaryService = getDataDictionaryService();
 1179  0
                 PersistenceStructureService pss = getPersistenceStructureService();
 1180  
 
 1181  0
                 collectionPrefix = StringUtils.isBlank(collectionPrefix) ? "" : collectionPrefix;
 1182  
 
 1183  
                 // retrieve the attributes that are affected by a lookup on
 1184  
                 // attributeName.
 1185  0
                 Collection<String> attributeReferenceFKAttributes = fkToPkMappings.keySet();
 1186  
 
 1187  
                 // a lookup on an attribute may cause other attributes to be updated
 1188  
                 // (e.g. account code lookup would also affect chart code)
 1189  
                 // build a list of all affected FK values via mapKeyFields above, and
 1190  
                 // for each FK, see if there are any non-updatable references with that
 1191  
                 // FK
 1192  
 
 1193  
                 // deal with regular simple references (<reference-descriptor>s in OJB)
 1194  0
                 for (String fkAttribute : attributeReferenceFKAttributes) {
 1195  0
                         for (String affectedReference : pss.getReferencesForForeignKey(boClass, fkAttribute).keySet()) {
 1196  0
                                 if (isRelationshipRefreshable(boClass, affectedReference)) {
 1197  0
                                         if (StringUtils.isBlank(nestedBOPrefix)) {
 1198  0
                                                 allAffectedReferences.add(collectionPrefix + affectedReference);
 1199  
                                         }
 1200  
                                         else {
 1201  0
                                                 allAffectedReferences.add(collectionPrefix + nestedBOPrefix + "." + affectedReference);
 1202  
                                         }
 1203  
                                 }
 1204  
                         }
 1205  
                 }
 1206  
 
 1207  
                 // now with collection references (<collection-descriptor>s in OJB)
 1208  0
                 for (String collectionName : pss.listCollectionObjectTypes(boClass).keySet()) {
 1209  0
                         if (isRelationshipRefreshable(boClass, collectionName)) {
 1210  0
                                 Map<String, String> keyMappingsForCollection = pss.getInverseForeignKeysForCollection(boClass,
 1211  
                                                 collectionName);
 1212  0
                                 for (String collectionForeignKey : keyMappingsForCollection.keySet()) {
 1213  0
                                         if (attributeReferenceFKAttributes.contains(collectionForeignKey)) {
 1214  0
                                                 if (StringUtils.isBlank(nestedBOPrefix)) {
 1215  0
                                                         allAffectedReferences.add(collectionPrefix + collectionName);
 1216  
                                                 }
 1217  
                                                 else {
 1218  0
                                                         allAffectedReferences.add(collectionPrefix + nestedBOPrefix + "." + collectionName);
 1219  
                                                 }
 1220  
                                         }
 1221  
                                 }
 1222  0
                         }
 1223  
                 }
 1224  
 
 1225  
                 // now use the DD to compute more affected references
 1226  0
                 List<String> ddDefinedRelationships = dataDictionaryService.getRelationshipNames(boClass.getName());
 1227  0
                 for (String ddRelationship : ddDefinedRelationships) {
 1228  
                         // note that this map is PK (key/target) => FK (value/source)
 1229  0
                         Map<String, String> referencePKtoFKmappings = dataDictionaryService.getRelationshipAttributeMap(
 1230  
                                         boClass.getName(), ddRelationship);
 1231  0
                         for (String sourceAttribute : referencePKtoFKmappings.values()) {
 1232  
                                 // the sourceAttribute is the FK pointing to the target
 1233  
                                 // attribute (PK)
 1234  0
                                 if (attributeReferenceFKAttributes.contains(sourceAttribute)) {
 1235  0
                                         for (String affectedReference : dataDictionaryService.getRelationshipEntriesForSourceAttribute(
 1236  
                                                         boClass.getName(), sourceAttribute)) {
 1237  0
                                                 if (isRelationshipRefreshable(boClass, ddRelationship)) {
 1238  0
                                                         if (StringUtils.isBlank(nestedBOPrefix)) {
 1239  0
                                                                 allAffectedReferences.add(affectedReference);
 1240  
                                                         }
 1241  
                                                         else {
 1242  0
                                                                 allAffectedReferences.add(nestedBOPrefix + "." + affectedReference);
 1243  
                                                         }
 1244  
                                                 }
 1245  
                                         }
 1246  
                                 }
 1247  
                         }
 1248  0
                 }
 1249  0
                 return allAffectedReferences;
 1250  
         }
 1251  
 
 1252  
         protected Collection<String> getAllRefreshableReferences(Class boClass) {
 1253  0
                 HashSet<String> references = new HashSet<String>();
 1254  0
                 for (String referenceName : getPersistenceStructureService().listReferenceObjectFields(boClass).keySet()) {
 1255  0
                         if (isRelationshipRefreshable(boClass, referenceName)) {
 1256  0
                                 references.add(referenceName);
 1257  
                         }
 1258  
                 }
 1259  0
                 for (String collectionName : getPersistenceStructureService().listCollectionObjectTypes(boClass).keySet()) {
 1260  0
                         if (isRelationshipRefreshable(boClass, collectionName)) {
 1261  0
                                 references.add(collectionName);
 1262  
                         }
 1263  
                 }
 1264  0
                 for (String relationshipName : getDataDictionaryService().getRelationshipNames(boClass.getName())) {
 1265  0
                         if (isRelationshipRefreshable(boClass, relationshipName)) {
 1266  0
                                 references.add(relationshipName);
 1267  
                         }
 1268  
                 }
 1269  0
                 return references;
 1270  
         }
 1271  
 
 1272  
         protected void setNewCollectionLineDefaultValues(String collectionName, PersistableBusinessObject addLine) {
 1273  0
                 PropertyDescriptor[] descriptors = PropertyUtils.getPropertyDescriptors(addLine);
 1274  0
                 for (int i = 0; i < descriptors.length; ++i) {
 1275  0
                         PropertyDescriptor propertyDescriptor = descriptors[i];
 1276  
 
 1277  0
                         String fieldName = propertyDescriptor.getName();
 1278  0
                         Class propertyType = propertyDescriptor.getPropertyType();
 1279  0
                         String value = getMaintenanceDocumentDictionaryService().getCollectionFieldDefaultValue(docTypeName,
 1280  
                                         collectionName, fieldName);
 1281  
 
 1282  0
                         if (value != null) {
 1283  
                                 try {
 1284  0
                                         ObjectUtils.setObjectProperty(addLine, fieldName, propertyType, value);
 1285  
                                 }
 1286  0
                                 catch (Exception ex) {
 1287  0
                                         LOG.error("Unable to set default property of collection object: " + "\nobject: " + addLine
 1288  
                                                         + "\nfieldName=" + fieldName + "\npropertyType=" + propertyType + "\nvalue=" + value, ex);
 1289  0
                                 }
 1290  
                         }
 1291  
 
 1292  
                 }
 1293  0
         }
 1294  
 
 1295  
         public void doRouteStatusChange(DocumentHeader documentHeader) {
 1296  0
         }
 1297  
 
 1298  
         public List<Long> getWorkflowEngineDocumentIdsToLock() {
 1299  0
                 return null;
 1300  
         }
 1301  
 
 1302  
         /**
 1303  
          * @see org.kuali.rice.kns.maintenance.Maintainable#clearBusinessObjectOfRestrictedValues(org.kuali.rice.kns.document.authorization.MaintenanceDocumentRestrictions)
 1304  
          */
 1305  
         public void clearBusinessObjectOfRestrictedValues(MaintenanceDocumentRestrictions maintenanceDocumentRestrictions) {
 1306  0
                 List<MaintainableSectionDefinition> sections = getMaintenanceDocumentDictionaryService()
 1307  
                                 .getMaintainableSections(docTypeName);
 1308  0
                 for (MaintainableSectionDefinition sectionDefinition : sections) {
 1309  0
                         for (MaintainableItemDefinition itemDefinition : sectionDefinition.getMaintainableItems()) {
 1310  0
                                 if (itemDefinition instanceof MaintainableFieldDefinition) {
 1311  0
                                         clearFieldRestrictedValues("", businessObject, (MaintainableFieldDefinition) itemDefinition,
 1312  
                                                         maintenanceDocumentRestrictions);
 1313  
                                 }
 1314  0
                                 else if (itemDefinition instanceof MaintainableCollectionDefinition) {
 1315  0
                                         clearCollectionRestrictedValues("", businessObject,
 1316  
                                                         (MaintainableCollectionDefinition) itemDefinition, maintenanceDocumentRestrictions);
 1317  
                                 }
 1318  
                         }
 1319  
                 }
 1320  0
         }
 1321  
 
 1322  
         protected void clearCollectionRestrictedValues(String fieldNamePrefix, BusinessObject businessObject,
 1323  
                         MaintainableCollectionDefinition collectionDefinition,
 1324  
                         MaintenanceDocumentRestrictions maintenanceDocumentRestrictions) {
 1325  0
                 String collectionName = fieldNamePrefix + collectionDefinition.getName();
 1326  0
                 Collection<BusinessObject> collection = (Collection<BusinessObject>) ObjectUtils.getPropertyValue(
 1327  
                                 businessObject, collectionDefinition.getName());
 1328  
 
 1329  0
                 if (collection != null) {
 1330  0
                         int i = 0;
 1331  
                         // even though it's technically a Collection, we're going to index
 1332  
                         // it like a list
 1333  0
                         for (BusinessObject collectionItem : collection) {
 1334  0
                                 String collectionItemNamePrefix = collectionName + "[" + i + "].";
 1335  0
                                 for (MaintainableCollectionDefinition subCollectionDefinition : collectionDefinition
 1336  
                                                 .getMaintainableCollections()) {
 1337  0
                                         clearCollectionRestrictedValues(collectionItemNamePrefix, collectionItem, subCollectionDefinition,
 1338  
                                                         maintenanceDocumentRestrictions);
 1339  
                                 }
 1340  0
                                 for (MaintainableFieldDefinition fieldDefinition : collectionDefinition.getMaintainableFields()) {
 1341  0
                                         clearFieldRestrictedValues(collectionItemNamePrefix, collectionItem, fieldDefinition,
 1342  
                                                         maintenanceDocumentRestrictions);
 1343  
                                 }
 1344  0
                                 i++;
 1345  0
                         }
 1346  
                 }
 1347  0
         }
 1348  
 
 1349  
         protected void clearFieldRestrictedValues(String fieldNamePrefix, BusinessObject businessObject,
 1350  
                         MaintainableFieldDefinition fieldDefinition, MaintenanceDocumentRestrictions maintenanceDocumentRestrictions) {
 1351  0
                 String fieldName = fieldNamePrefix + fieldDefinition.getName();
 1352  
 
 1353  0
                 FieldRestriction fieldRestriction = maintenanceDocumentRestrictions.getFieldRestriction(fieldName);
 1354  0
                 if (fieldRestriction.isRestricted()) {
 1355  0
                         String defaultValue = null;
 1356  0
                         if (StringUtils.isNotBlank(fieldDefinition.getDefaultValue())) {
 1357  0
                                 defaultValue = fieldDefinition.getDefaultValue();
 1358  
                         }
 1359  0
                         else if (fieldDefinition.getDefaultValueFinderClass() != null) {
 1360  
                                 try {
 1361  0
                                         defaultValue = ((ValueFinder) fieldDefinition.getDefaultValueFinderClass().newInstance())
 1362  
                                                         .getValue();
 1363  
                                 }
 1364  0
                                 catch (Exception e) {
 1365  0
                                         defaultValue = null;
 1366  0
                                         LOG.error("Error trying to instantiate ValueFinder or to determine ValueFinder for doc type: "
 1367  
                                                         + docTypeName + " field name " + fieldDefinition.getName() + " with field prefix: "
 1368  
                                                         + fieldNamePrefix, e);
 1369  0
                                 }
 1370  
                         }
 1371  
                         try {
 1372  0
                                 ObjectUtils.setObjectProperty(businessObject, fieldDefinition.getName(), defaultValue);
 1373  
                         }
 1374  0
                         catch (Exception e) {
 1375  
                                 // throw an exception, because we don't want users to be able to
 1376  
                                 // see the restricted value
 1377  0
                                 LOG.error("Unable to clear maintenance document values for field name: " + fieldName
 1378  
                                                 + " default value: " + defaultValue, e);
 1379  0
                                 throw new RuntimeException("Unable to clear maintenance document values for field name: " + fieldName,
 1380  
                                                 e);
 1381  0
                         }
 1382  
                 }
 1383  0
         }
 1384  
 
 1385  
         protected void performForceUpperCase(Map fieldValues) {
 1386  0
                 List<MaintainableSectionDefinition> sections = getMaintenanceDocumentDictionaryService()
 1387  
                                 .getMaintainableSections(docTypeName);
 1388  0
                 for (MaintainableSectionDefinition sectionDefinition : sections) {
 1389  0
                         for (MaintainableItemDefinition itemDefinition : sectionDefinition.getMaintainableItems()) {
 1390  0
                                 if (itemDefinition instanceof MaintainableFieldDefinition) {
 1391  0
                                         performFieldForceUpperCase("", businessObject, (MaintainableFieldDefinition) itemDefinition,
 1392  
                                                         fieldValues);
 1393  
                                 }
 1394  0
                                 else if (itemDefinition instanceof MaintainableCollectionDefinition) {
 1395  0
                                         performCollectionForceUpperCase("", businessObject,
 1396  
                                                         (MaintainableCollectionDefinition) itemDefinition, fieldValues);
 1397  
 
 1398  
                                 }
 1399  
                         }
 1400  
                 }
 1401  0
         }
 1402  
 
 1403  
         protected void performFieldForceUpperCase(String fieldNamePrefix, BusinessObject bo,
 1404  
                         MaintainableFieldDefinition fieldDefinition, Map fieldValues) {
 1405  0
                 MessageMap errorMap = GlobalVariables.getMessageMap();
 1406  0
                 String fieldName = fieldDefinition.getName();
 1407  0
                 String mapKey = fieldNamePrefix + fieldName;
 1408  0
                 if (fieldValues != null && fieldValues.get(mapKey) != null) {
 1409  0
                         if (PropertyUtils.isWriteable(bo, fieldName) && ObjectUtils.getNestedValue(bo, fieldName) != null) {
 1410  
 
 1411  
                                 try {
 1412  0
                                         Class type = ObjectUtils.easyGetPropertyType(bo, fieldName);
 1413  
                                         // convert to upperCase based on data dictionary
 1414  0
                                         Class businessObjectClass = bo.getClass();
 1415  0
                                         boolean upperCase = false;
 1416  
                                         try {
 1417  0
                                                 upperCase = getDataDictionaryService().getAttributeForceUppercase(businessObjectClass,
 1418  
                                                                 fieldName);
 1419  
                                         }
 1420  0
                                         catch (UnknownBusinessClassAttributeException t) {
 1421  0
                                                 boolean catchme = true;
 1422  
                                                 // throw t;
 1423  0
                                         }
 1424  
 
 1425  0
                                         Object fieldValue = ObjectUtils.getNestedValue(bo, fieldName);
 1426  
 
 1427  0
                                         if (upperCase && fieldValue instanceof String) {
 1428  0
                                                 fieldValue = ((String) fieldValue).toUpperCase();
 1429  
                                         }
 1430  0
                                         ObjectUtils.setObjectProperty(bo, fieldName, type, fieldValue);
 1431  
                                 }
 1432  0
                                 catch (FormatException e) {
 1433  0
                                         errorMap.putError(fieldName, e.getErrorKey(), e.getErrorArgs());
 1434  
                                 }
 1435  0
                                 catch (IllegalAccessException e) {
 1436  0
                                         LOG.error("unable to populate business object" + e.getMessage());
 1437  0
                                         throw new RuntimeException(e.getMessage(), e);
 1438  
                                 }
 1439  0
                                 catch (InvocationTargetException e) {
 1440  0
                                         LOG.error("unable to populate business object" + e.getMessage());
 1441  0
                                         throw new RuntimeException(e.getMessage(), e);
 1442  
                                 }
 1443  0
                                 catch (NoSuchMethodException e) {
 1444  0
                                         LOG.error("unable to populate business object" + e.getMessage());
 1445  0
                                         throw new RuntimeException(e.getMessage(), e);
 1446  0
                                 }
 1447  
                         }
 1448  
                 }
 1449  0
         }
 1450  
 
 1451  
         protected void performCollectionForceUpperCase(String fieldNamePrefix, BusinessObject bo,
 1452  
                         MaintainableCollectionDefinition collectionDefinition, Map fieldValues) {
 1453  0
                 String collectionName = fieldNamePrefix + collectionDefinition.getName();
 1454  0
                 Collection<BusinessObject> collection = (Collection<BusinessObject>) ObjectUtils.getPropertyValue(bo,
 1455  
                                 collectionDefinition.getName());
 1456  0
                 if (collection != null) {
 1457  0
                         int i = 0;
 1458  
                         // even though it's technically a Collection, we're going to index
 1459  
                         // it like a list
 1460  0
                         for (BusinessObject collectionItem : collection) {
 1461  0
                                 String collectionItemNamePrefix = collectionName + "[" + i + "].";
 1462  
                                 // String collectionItemNamePrefix = "";
 1463  0
                                 for (MaintainableFieldDefinition fieldDefinition : collectionDefinition.getMaintainableFields()) {
 1464  0
                                         performFieldForceUpperCase(collectionItemNamePrefix, collectionItem, fieldDefinition, fieldValues);
 1465  
                                 }
 1466  0
                                 for (MaintainableCollectionDefinition subCollectionDefinition : collectionDefinition
 1467  
                                                 .getMaintainableCollections()) {
 1468  0
                                         performCollectionForceUpperCase(collectionItemNamePrefix, collectionItem, subCollectionDefinition,
 1469  
                                                         fieldValues);
 1470  
                                 }
 1471  0
                                 i++;
 1472  0
                         }
 1473  
                 }
 1474  0
         }
 1475  
 
 1476  
         protected void performFieldForceUpperCase(BusinessObject bo, Map fieldValues) {
 1477  0
                 MessageMap errorMap = GlobalVariables.getMessageMap();
 1478  
 
 1479  
                 try {
 1480  0
                         for (Iterator iter = fieldValues.keySet().iterator(); iter.hasNext();) {
 1481  0
                                 String propertyName = (String) iter.next();
 1482  
 
 1483  0
                                 if (PropertyUtils.isWriteable(bo, propertyName) && fieldValues.get(propertyName) != null) {
 1484  
                                         // if the field propertyName is a valid property on the bo
 1485  
                                         // class
 1486  0
                                         Class type = ObjectUtils.easyGetPropertyType(bo, propertyName);
 1487  
                                         try {
 1488  
                                                 // Keep the convert to upperCase logic here. It will be
 1489  
                                                 // used in populateNewCollectionLines,
 1490  
                                                 // populateNewSubCollectionLines
 1491  
                                                 // convert to upperCase based on data dictionary
 1492  0
                                                 Class businessObjectClass = bo.getClass();
 1493  0
                                                 boolean upperCase = false;
 1494  
                                                 try {
 1495  0
                                                         upperCase = getDataDictionaryService().getAttributeForceUppercase(businessObjectClass,
 1496  
                                                                         propertyName);
 1497  
                                                 }
 1498  0
                                                 catch (UnknownBusinessClassAttributeException t) {
 1499  0
                                                         boolean catchme = true;
 1500  
                                                         // throw t;
 1501  0
                                                 }
 1502  
 
 1503  0
                                                 Object fieldValue = fieldValues.get(propertyName);
 1504  
 
 1505  0
                                                 if (upperCase && fieldValue instanceof String) {
 1506  0
                                                         fieldValue = ((String) fieldValue).toUpperCase();
 1507  
                                                 }
 1508  0
                                                 ObjectUtils.setObjectProperty(bo, propertyName, type, fieldValue);
 1509  
                                         }
 1510  0
                                         catch (FormatException e) {
 1511  0
                                                 errorMap.putError(propertyName, e.getErrorKey(), e.getErrorArgs());
 1512  0
                                         }
 1513  
                                 }
 1514  0
                         }
 1515  
                 }
 1516  0
                 catch (IllegalAccessException e) {
 1517  0
                         LOG.error("unable to populate business object" + e.getMessage());
 1518  0
                         throw new RuntimeException(e.getMessage(), e);
 1519  
                 }
 1520  0
                 catch (InvocationTargetException e) {
 1521  0
                         LOG.error("unable to populate business object" + e.getMessage());
 1522  0
                         throw new RuntimeException(e.getMessage(), e);
 1523  
                 }
 1524  0
                 catch (NoSuchMethodException e) {
 1525  0
                         LOG.error("unable to populate business object" + e.getMessage());
 1526  0
                         throw new RuntimeException(e.getMessage(), e);
 1527  0
                 }
 1528  
 
 1529  0
         }
 1530  
 
 1531  
         /**
 1532  
          * By default a maintainable is not external
 1533  
          * 
 1534  
          * @see org.kuali.rice.kns.maintenance.Maintainable#isExternalBusinessObject()
 1535  
          */
 1536  
         public boolean isExternalBusinessObject() {
 1537  0
                 return false;
 1538  
         }
 1539  
 
 1540  
         /**
 1541  
          * @see org.kuali.rice.kns.maintenance.Maintainable#getExternalBusinessObject()
 1542  
          */
 1543  
         public void prepareBusinessObject(BusinessObject businessObject) {
 1544  
                 // Do nothing by default
 1545  0
         }
 1546  
 
 1547  
         /**
 1548  
          * @see org.kuali.rice.kns.maintenance.Maintainable#getLockingDocumentId()
 1549  
          */
 1550  
         public String getLockingDocumentId() {
 1551  0
                 return getMaintenanceDocumentService().getLockingDocumentId(this, documentNumber);
 1552  
         }
 1553  
 
 1554  
         /**
 1555  
          * This default implementation simply returns false to indicate that custom
 1556  
          * lock descriptors are not supported by KualiMaintainableImpl. If custom
 1557  
          * lock descriptors are needed, the appropriate subclasses should override
 1558  
          * this method.
 1559  
          * 
 1560  
          * @see org.kuali.rice.kns.maintenance.Maintainable#useCustomLockDescriptors()
 1561  
          */
 1562  
         public boolean useCustomLockDescriptors() {
 1563  0
                 return false;
 1564  
         }
 1565  
 
 1566  
         /**
 1567  
          * This default implementation just throws a PessimisticLockingException.
 1568  
          * Subclasses of KualiMaintainableImpl that need support for custom lock
 1569  
          * descriptors should override this method.
 1570  
          * 
 1571  
          * @see org.kuali.rice.kns.maintenance.Maintainable#getCustomLockDescriptor(org.kuali.rice.kim.bo.Person)
 1572  
          */
 1573  
         public String getCustomLockDescriptor(Person user) {
 1574  0
                 throw new PessimisticLockingException(
 1575  
                                 "The Maintainable for document "
 1576  
                                                 + documentNumber
 1577  
                                                 + " is using pessimistic locking with custom lock descriptors, but the Maintainable has not overriden the getCustomLockDescriptor method");
 1578  
         }
 1579  
 
 1580  
         // 3070
 1581  
         public void deleteBusinessObject() {
 1582  0
                 if (businessObject == null)
 1583  0
                         return;
 1584  
 
 1585  0
                 KNSServiceLocator.getBusinessObjectService().delete(businessObject);
 1586  0
                 businessObject = null;
 1587  0
         }
 1588  
 
 1589  
         public boolean isOldBusinessObjectInDocument() {
 1590  0
                 boolean isOldBusinessObjectInExistence = false;
 1591  0
                 if (getBusinessObject() == null) {
 1592  0
                         isOldBusinessObjectInExistence = false;
 1593  
                 }
 1594  
                 else {
 1595  0
                         if (KNSServiceLocator.getPersistenceStructureService().isPersistable(getBusinessObject().getClass())) {
 1596  0
                                 isOldBusinessObjectInExistence = KNSServiceLocator.getPersistenceStructureService()
 1597  
                                                 .hasPrimaryKeyFieldValues(getBusinessObject());
 1598  
                         }
 1599  
                 }
 1600  0
                 return isOldBusinessObjectInExistence;
 1601  
 
 1602  
         }
 1603  
 
 1604  
         /**
 1605  
          * @see org.kuali.rice.kns.maintenance.Maintainable#setupMaintenanceObject(org.kuali.rice.kns.document.MaintenanceDocument,
 1606  
          *      java.lang.String, java.util.Map)
 1607  
          */
 1608  
         public void setupMaintenanceObject(MaintenanceDocument document, String maintenanceAction,
 1609  
                         Map<String, String[]> requestParameters) {
 1610  0
                 setMaintenanceAction(maintenanceAction);
 1611  0
                 document.getOldMaintainableObject().setMaintenanceAction(maintenanceAction);
 1612  
 
 1613  
                 // if action is edit or copy first need to retrieve the old record
 1614  0
                 if (!KNSConstants.MAINTENANCE_NEW_ACTION.equals(maintenanceAction)
 1615  
                                 && !KNSConstants.MAINTENANCE_NEWWITHEXISTING_ACTION.equals(maintenanceAction)) {
 1616  0
                         Object oldBusinessObject = retrieveObjectForMaintenance(document, requestParameters);
 1617  
 
 1618  
                         // TODO should we be using ObjectUtils? also, this needs dictionary
 1619  
                         // enhancement to indicate fields to/not to copy
 1620  0
                         Object newBusinessObject = ObjectUtils.deepCopy((Serializable) oldBusinessObject);
 1621  
 
 1622  
                         // process further object preparations for copy action
 1623  0
                         if (KNSConstants.MAINTENANCE_COPY_ACTION.equals(maintenanceAction)) {
 1624  0
                                 processMaintenanceObjectForCopy(document, newBusinessObject, requestParameters);
 1625  
                         }
 1626  
                         else {
 1627  0
                                 checkMaintenanceActionAuthorization(document, oldBusinessObject, requestParameters);
 1628  
                         }
 1629  
 
 1630  
                         // set object instance for editing
 1631  0
                         document.getOldMaintainableObject().setDataObject(oldBusinessObject);
 1632  0
                         document.getNewMaintainableObject().setDataObject(newBusinessObject);
 1633  
                 }
 1634  
 
 1635  
                 // if new with existing we need to populate with passed in parameters
 1636  0
                 if (KNSConstants.MAINTENANCE_NEWWITHEXISTING_ACTION.equals(maintenanceAction)) {
 1637  0
                         Object newBO = document.getNewMaintainableObject().getDataObject();
 1638  0
                         Map<String, String> parameters = buildKeyMapFromRequest(requestParameters);
 1639  0
                         ObjectPropertyUtils.copyPropertiesToObject(parameters, newBO);
 1640  0
                         if(newBO instanceof PersistableBusinessObject) {
 1641  0
                             ((PersistableBusinessObject)newBO).refresh();
 1642  
                         }
 1643  
 
 1644  0
                         setupNewFromExisting(document, requestParameters);
 1645  0
                 }
 1646  0
                 else if (KNSConstants.MAINTENANCE_NEW_ACTION.equals(maintenanceAction)) {
 1647  0
                         processAfterNew(document, requestParameters);
 1648  
                 }
 1649  0
         }
 1650  
 
 1651  
         /**
 1652  
          * For the edit and delete maintenance actions checks with the
 1653  
          * <code>BusinessObjectAuthorizationService</code> to check whether the
 1654  
          * action is allowed for the record data. In action is allowed invokes the
 1655  
          * custom processing hook on the <code>Maintainble</code>.
 1656  
          * 
 1657  
          * @param document
 1658  
          *            - document instance for the maintenance object
 1659  
          * @param oldBusinessObject
 1660  
          *            - the old maintenance record
 1661  
          * @param requestParameters
 1662  
          *            - map of parameters from the request
 1663  
          */
 1664  
         protected void checkMaintenanceActionAuthorization(MaintenanceDocument document, Object oldBusinessObject,
 1665  
                         Map<String, String[]> requestParameters) {
 1666  0
                 if (KNSConstants.MAINTENANCE_EDIT_ACTION.equals(maintenanceAction)) {
 1667  0
                         boolean allowsEdit = getBusinessObjectAuthorizationService().canMaintain(
 1668  
                                         oldBusinessObject, GlobalVariables.getUserSession().getPerson(),
 1669  
                                         document.getDocumentHeader().getWorkflowDocument().getDocumentType());
 1670  0
                         if (!allowsEdit) {
 1671  0
                                 LOG.error("Document type " + document.getDocumentHeader().getWorkflowDocument().getDocumentType()
 1672  
                                                 + " does not allow edit actions.");
 1673  0
                                 throw new DocumentTypeAuthorizationException(GlobalVariables.getUserSession().getPerson()
 1674  
                                                 .getPrincipalId(), "edit", document.getDocumentHeader().getWorkflowDocument().getDocumentType());
 1675  
                         }
 1676  
 
 1677  
                         // invoke custom processing method
 1678  0
                         processAfterEdit(document, requestParameters);
 1679  0
                 }
 1680  
                 // 3070
 1681  0
                 else if (KNSConstants.MAINTENANCE_DELETE_ACTION.equals(maintenanceAction)) {
 1682  0
                         boolean allowsDelete = getBusinessObjectAuthorizationService().canMaintain(
 1683  
                                         (BusinessObject) oldBusinessObject, GlobalVariables.getUserSession().getPerson(),
 1684  
                                         document.getDocumentHeader().getWorkflowDocument().getDocumentType());
 1685  0
                         if (!allowsDelete) {
 1686  0
                                 LOG.error("Document type " + document.getDocumentHeader().getWorkflowDocument().getDocumentType()
 1687  
                                                 + " does not allow delete actions.");
 1688  0
                                 throw new DocumentTypeAuthorizationException(GlobalVariables.getUserSession().getPerson()
 1689  
                                                 .getPrincipalId(), "delete", document.getDocumentHeader().getWorkflowDocument()
 1690  
                                                 .getDocumentType());
 1691  
                         }
 1692  
                 }
 1693  0
         }
 1694  
 
 1695  
         /**
 1696  
          * For the edit or copy actions retrieves the record that is to be
 1697  
          * maintained
 1698  
          * 
 1699  
          * <p>
 1700  
          * Based on the persistence metadata for the maintenance object class
 1701  
          * retrieves the primary key values from the given request parameters map
 1702  
          * (if the class is persistable). With those key values attempts to find the
 1703  
          * record using the <code>LookupService</code>.
 1704  
          * </p>
 1705  
          * 
 1706  
          * @param document
 1707  
          *            - document instance for the maintenance object
 1708  
          * @param requestParameters
 1709  
          *            - Map of parameters from the request
 1710  
          * @return Object the retrieved old object
 1711  
          */
 1712  
         protected Object retrieveObjectForMaintenance(MaintenanceDocument document, Map<String, String[]> requestParameters) {
 1713  
             // TODO the logic in this method is very odd, but I don't know how clients
 1714  
             // are extending this impl.  It seems like clients made non persistent objects
 1715  
             // extend PBO in order to not break the framework which requires PBO everywhere,
 1716  
             // KRAD is fixing that.
 1717  
             //
 1718  
             // Would like to see this method get passed keys already parsed from request,
 1719  
             // it seems odd to have entire http request map passed this deep
 1720  
 
 1721  0
                 Map<String, String> keyMap = buildKeyMapFromRequest(requestParameters);
 1722  
                 
 1723  0
                 Object oldBusinessObject = retrieveObjectForEditOrCopy(document, keyMap);
 1724  
                 
 1725  0
                 if (oldBusinessObject == null && !document.getOldMaintainableObject().isExternalBusinessObject()) {
 1726  0
                         throw new RuntimeException(
 1727  
                                         "Cannot retrieve old record for maintenance document, incorrect parameters passed on maint url: "
 1728  
                                                         + requestParameters);
 1729  
                 }
 1730  
 
 1731  0
                 if (document.getOldMaintainableObject().isExternalBusinessObject()) {
 1732  0
                         if (oldBusinessObject == null) {
 1733  
                                 try {
 1734  0
                                         oldBusinessObject = document.getOldMaintainableObject().getBoClass()
 1735  
                                                         .newInstance();
 1736  
                                 }
 1737  0
                                 catch (Exception ex) {
 1738  0
                                         throw new RuntimeException(
 1739  
                                                         "External BO maintainable was null and unable to instantiate for old maintainable object.",
 1740  
                                                         ex);
 1741  0
                                 }
 1742  
                         }
 1743  
 
 1744  0
                         populateMaintenanceObjectWithCopyKeyValues(WebUtils.translateRequestParameterMap(requestParameters),
 1745  
                                         oldBusinessObject, document.getOldMaintainableObject());
 1746  0
                         document.getOldMaintainableObject().prepareBusinessObject((PersistableBusinessObject)oldBusinessObject);
 1747  0
                         oldBusinessObject = document.getOldMaintainableObject().getDataObject();
 1748  
                 }
 1749  
 
 1750  0
                 return oldBusinessObject;
 1751  
         }
 1752  
         
 1753  
 
 1754  
         /**
 1755  
          * @see org.kuali.rice.kns.maintenance.Maintainable#retrieveObjectForEditOrCopy(java.util.Map)
 1756  
          */
 1757  
         @Override
 1758  
     public Object retrieveObjectForEditOrCopy(MaintenanceDocument document, Map<String, String> dataObjectKeys) {
 1759  0
             Object dataObject = null;
 1760  
             
 1761  
             try {
 1762  0
             dataObject = getLookupService().findObjectBySearch(getBoClass(), dataObjectKeys);
 1763  
         }
 1764  0
         catch (ClassNotPersistenceCapableException ex) {
 1765  0
             if (!document.getOldMaintainableObject().isExternalBusinessObject()) {
 1766  0
                 throw new RuntimeException("BO Class: " + getBoClass()
 1767  
                         + " is not persistable and is not externalizable - configuration error");
 1768  
             }
 1769  
             // otherwise, let fall through
 1770  0
         }
 1771  
         
 1772  0
         return dataObject;
 1773  
     }
 1774  
 
 1775  
     /**
 1776  
          * For the copy action clears out primary key values for the old record and
 1777  
          * does authorization checks on the remaining fields. Also invokes the
 1778  
          * custom processing method on the <code>Maintainble</code>
 1779  
          * 
 1780  
          * @param document
 1781  
          *            - document instance for the maintenance object
 1782  
          * @param maintenanceObject
 1783  
          *            - the object instance being maintained
 1784  
          * @param requestParameters
 1785  
          *            - map of parameters from the request
 1786  
          */
 1787  
         protected void processMaintenanceObjectForCopy(MaintenanceDocument document, Object maintenanceObject,
 1788  
                         Map<String, String[]> requestParameters) {
 1789  0
                 if (!document.isFieldsClearedOnCopy()) {
 1790  0
                         if (!maintenanceDocumentDictionaryService.getPreserveLockingKeysOnCopy(getBoClass())) {
 1791  0
                                 clearPrimaryKeyFields(maintenanceObject);
 1792  
                         }
 1793  
 
 1794  0
                         clearUnauthorizedNewFields(document);
 1795  
 
 1796  0
                         Maintainable maintainable = document.getNewMaintainableObject();
 1797  0
                         maintainable.processAfterCopy(document, requestParameters);
 1798  
 
 1799  
                         // mark so that this clearing does not happen again
 1800  0
                         document.setFieldsClearedOnCopy(true);
 1801  
                 }
 1802  0
         }
 1803  
 
 1804  
         /**
 1805  
          * Clears the value of the primary key fields on the maintenance object
 1806  
          * 
 1807  
          * @param document
 1808  
          *            - document to clear the pk fields on
 1809  
          */
 1810  
         protected void clearPrimaryKeyFields(Object maintenanceObject) {
 1811  0
                 List<String> keyFieldNames = getBusinessObjectMetaDataService().listPrimaryKeyFieldNames(getBoClass());
 1812  0
                 for (String keyFieldName : keyFieldNames) {
 1813  0
                         ObjectPropertyUtils.setPropertyValue(maintenanceObject, keyFieldName, null);
 1814  
                 }
 1815  0
         }
 1816  
 
 1817  
         /**
 1818  
          * Used as part of the Copy functionality, to clear any field values that
 1819  
          * the user making the copy does not have permissions to modify. This will
 1820  
          * prevent authorization errors on a copy.
 1821  
          * 
 1822  
          * @param document
 1823  
          *            - document to be adjusted
 1824  
          */
 1825  
         protected void clearUnauthorizedNewFields(MaintenanceDocument document) {
 1826  
                 // get a reference to the current user
 1827  0
                 Person user = GlobalVariables.getUserSession().getPerson();
 1828  
 
 1829  
                 // get a new instance of MaintenanceDocumentAuthorizations for context
 1830  0
                 MaintenanceDocumentRestrictions maintenanceDocumentRestrictions = getBusinessObjectAuthorizationService()
 1831  
                                 .getMaintenanceDocumentRestrictions(document, user);
 1832  
 
 1833  0
                 clearBusinessObjectOfRestrictedValues(maintenanceDocumentRestrictions);
 1834  0
         }
 1835  
 
 1836  
         /**
 1837  
          * Based on the maintenance object class retrieves the key field names from
 1838  
          * the <code>BusinessObjectMetaDataService</code> (or alternatively from the
 1839  
          * request parameters), then retrieves any matching key value pairs from the
 1840  
          * request parameters
 1841  
          * 
 1842  
          * @param requestParameters
 1843  
          *            - map of parameters from the request
 1844  
          * @return Map<String, String> key value pairs
 1845  
          */
 1846  
         protected Map<String, String> buildKeyMapFromRequest(Map<String, String[]> requestParameters) {
 1847  0
                 List<String> keyFieldNames = null;
 1848  
 
 1849  
                 // translate request parameters
 1850  0
                 Map<String, String> parameters = WebUtils.translateRequestParameterMap(requestParameters);
 1851  
 
 1852  
                 // are override keys listed in the request? If so, then those need to be
 1853  
                 // our keys, not the primary key fields for the BO
 1854  0
                 if (!StringUtils.isBlank(parameters.get(KNSConstants.OVERRIDE_KEYS))) {
 1855  0
                         String[] overrideKeys = parameters.get(KNSConstants.OVERRIDE_KEYS).split(
 1856  
                                         KNSConstants.FIELD_CONVERSIONS_SEPARATOR);
 1857  0
                         keyFieldNames = Arrays.asList(overrideKeys);
 1858  0
                 }
 1859  
                 else {
 1860  0
                         keyFieldNames = getBusinessObjectMetaDataService().listPrimaryKeyFieldNames(getBoClass());
 1861  
                 }
 1862  
 
 1863  0
                 return WebUtils.getParametersFromRequest(keyFieldNames, getBoClass(), parameters);
 1864  
         }
 1865  
 
 1866  
         /**
 1867  
          * Looks for a special request parameters giving the names of the keys that
 1868  
          * should be retrieved from the request parameters and copied to the
 1869  
          * maintenance object
 1870  
          * 
 1871  
          * @param parameters
 1872  
          *            - map of parameters from the request
 1873  
          * @param oldBusinessObject
 1874  
          *            - the old maintenance object
 1875  
          * @param oldMaintainableObject
 1876  
          *            - the old maintainble object (used to get object class for
 1877  
          *            security checks)
 1878  
          */
 1879  
         protected void populateMaintenanceObjectWithCopyKeyValues(Map<String, String> parameters, Object oldBusinessObject,
 1880  
                         Maintainable oldMaintainableObject) {
 1881  0
                 List<String> keyFieldNamesToCopy = null;
 1882  0
                 Map<String, String> parametersToCopy = null;
 1883  
 
 1884  0
                 if (!StringUtils.isBlank(parameters.get(KNSConstants.COPY_KEYS))) {
 1885  0
                         String[] copyKeys = parameters.get(KNSConstants.COPY_KEYS).split(KNSConstants.FIELD_CONVERSIONS_SEPARATOR);
 1886  0
                         keyFieldNamesToCopy = Arrays.asList(copyKeys);
 1887  0
                         parametersToCopy = WebUtils.getParametersFromRequest(keyFieldNamesToCopy,
 1888  
                                         oldMaintainableObject.getBoClass(), parameters);
 1889  
                 }
 1890  
 
 1891  0
                 if (parametersToCopy != null) {
 1892  
                         // TODO: make sure we are doing formatting here eventually
 1893  0
                         ObjectPropertyUtils.copyPropertiesToObject(parametersToCopy, oldBusinessObject);
 1894  
                 }
 1895  0
         }
 1896  
 
 1897  
         /**
 1898  
          * In the case of edit maintenance adds a new blank line to the old side
 1899  
          * 
 1900  
          * TODO: should this write some sort of missing message on the old side
 1901  
          * instead?
 1902  
          * 
 1903  
          * @see org.kuali.rice.kns.uif.service.impl.ViewHelperServiceImpl#processAfterAddLine(org.kuali.rice.kns.uif.container.View,
 1904  
          *      org.kuali.rice.kns.uif.container.CollectionGroup, java.lang.Object,
 1905  
          *      java.lang.Object)
 1906  
          */
 1907  
         @Override
 1908  
         protected void processAfterAddLine(View view, CollectionGroup collectionGroup, Object model, Object addLine) {
 1909  0
                 super.processAfterAddLine(view, collectionGroup, model, addLine);
 1910  
 
 1911  0
                 if (KNSConstants.MAINTENANCE_EDIT_ACTION.equals(maintenanceAction)) {
 1912  0
                         MaintenanceForm maintenanceForm = (MaintenanceForm) model;
 1913  0
                         MaintenanceDocument document = maintenanceForm.getDocument();
 1914  
 
 1915  
                         // get the old object's collection
 1916  0
                         Collection<Object> oldCollection = ObjectPropertyUtils.getPropertyValue(document.getOldMaintainableObject()
 1917  
                                         .getBusinessObject(), collectionGroup.getPropertyName());
 1918  
                         try {
 1919  0
                                 Object blankLine = getBoClass().newInstance();
 1920  0
                                 oldCollection.add(blankLine);
 1921  
                         }
 1922  0
                         catch (Exception e) {
 1923  0
                                 throw new RuntimeException("Unable to create new line instance for old maintenance object", e);
 1924  0
                         }
 1925  
                 }
 1926  0
         }
 1927  
 
 1928  
         protected PersistenceStructureService getPersistenceStructureService() {
 1929  0
                 if (persistenceStructureService == null) {
 1930  0
                         persistenceStructureService = KNSServiceLocator.getPersistenceStructureService();
 1931  
                 }
 1932  0
                 return persistenceStructureService;
 1933  
         }
 1934  
 
 1935  
         protected MaintenanceDocumentDictionaryService getMaintenanceDocumentDictionaryService() {
 1936  0
                 if (maintenanceDocumentDictionaryService == null) {
 1937  0
                         maintenanceDocumentDictionaryService = KNSServiceLocatorWeb.getMaintenanceDocumentDictionaryService();
 1938  
                 }
 1939  0
                 return maintenanceDocumentDictionaryService;
 1940  
         }
 1941  
 
 1942  
         protected BusinessObjectService getBusinessObjectService() {
 1943  0
                 if (businessObjectService == null) {
 1944  0
                         businessObjectService = KNSServiceLocator.getBusinessObjectService();
 1945  
                 }
 1946  0
                 return businessObjectService;
 1947  
         }
 1948  
 
 1949  
         protected BusinessObjectDictionaryService getBusinessObjectDictionaryService() {
 1950  0
                 if (businessObjectDictionaryService == null) {
 1951  0
                         businessObjectDictionaryService = KNSServiceLocatorWeb.getBusinessObjectDictionaryService();
 1952  
                 }
 1953  0
                 return businessObjectDictionaryService;
 1954  
         }
 1955  
 
 1956  
         protected EncryptionService getEncryptionService() {
 1957  0
                 if (encryptionService == null) {
 1958  0
                         encryptionService = CoreApiServiceLocator.getEncryptionService();
 1959  
                 }
 1960  0
                 return encryptionService;
 1961  
         }
 1962  
 
 1963  
         protected org.kuali.rice.kim.service.PersonService getPersonService() {
 1964  0
                 if (personService == null) {
 1965  0
                         personService = org.kuali.rice.kim.service.KIMServiceLocator.getPersonService();
 1966  
                 }
 1967  0
                 return personService;
 1968  
         }
 1969  
 
 1970  
         protected BusinessObjectMetaDataService getBusinessObjectMetaDataService() {
 1971  0
                 if (businessObjectMetaDataService == null) {
 1972  0
                         businessObjectMetaDataService = KNSServiceLocatorWeb.getBusinessObjectMetaDataService();
 1973  
                 }
 1974  0
                 return businessObjectMetaDataService;
 1975  
         }
 1976  
 
 1977  
         protected BusinessObjectAuthorizationService getBusinessObjectAuthorizationService() {
 1978  0
                 if (businessObjectAuthorizationService == null) {
 1979  0
                         businessObjectAuthorizationService = KNSServiceLocatorWeb.getBusinessObjectAuthorizationService();
 1980  
                 }
 1981  0
                 return businessObjectAuthorizationService;
 1982  
         }
 1983  
 
 1984  
         protected MaintenanceDocumentService getMaintenanceDocumentService() {
 1985  0
                 if (maintenanceDocumentService == null) {
 1986  0
                         maintenanceDocumentService = KNSServiceLocatorWeb.getMaintenanceDocumentService();
 1987  
                 }
 1988  0
                 return maintenanceDocumentService;
 1989  
         }
 1990  
 
 1991  
         protected DocumentHelperService getDocumentHelperService() {
 1992  0
                 if (documentHelperService == null) {
 1993  0
                         documentHelperService = KNSServiceLocatorWeb.getDocumentHelperService();
 1994  
                 }
 1995  0
                 return documentHelperService;
 1996  
         }
 1997  
 
 1998  
         public void setPersistenceStructureService(PersistenceStructureService persistenceStructureService) {
 1999  0
                 this.persistenceStructureService = persistenceStructureService;
 2000  0
         }
 2001  
 
 2002  
         public void setMaintenanceDocumentDictionaryService(
 2003  
                         MaintenanceDocumentDictionaryService maintenanceDocumentDictionaryService) {
 2004  0
                 this.maintenanceDocumentDictionaryService = maintenanceDocumentDictionaryService;
 2005  0
         }
 2006  
 
 2007  
         public void setBusinessObjectService(BusinessObjectService businessObjectService) {
 2008  0
                 this.businessObjectService = businessObjectService;
 2009  0
         }
 2010  
 
 2011  
         public void setBusinessObjectDictionaryService(BusinessObjectDictionaryService businessObjectDictionaryService) {
 2012  0
                 this.businessObjectDictionaryService = businessObjectDictionaryService;
 2013  0
         }
 2014  
 
 2015  
         public void setEncryptionService(EncryptionService encryptionService) {
 2016  0
                 this.encryptionService = encryptionService;
 2017  0
         }
 2018  
 
 2019  
         public void setPersonService(org.kuali.rice.kim.service.PersonService personService) {
 2020  0
                 this.personService = personService;
 2021  0
         }
 2022  
 
 2023  
         public void setBusinessObjectMetaDataService(BusinessObjectMetaDataService businessObjectMetaDataService) {
 2024  0
                 this.businessObjectMetaDataService = businessObjectMetaDataService;
 2025  0
         }
 2026  
 
 2027  
         public void setBusinessObjectAuthorizationService(
 2028  
                         BusinessObjectAuthorizationService businessObjectAuthorizationService) {
 2029  0
                 this.businessObjectAuthorizationService = businessObjectAuthorizationService;
 2030  0
         }
 2031  
 
 2032  
         public void setMaintenanceDocumentService(MaintenanceDocumentService maintenanceDocumentService) {
 2033  0
                 this.maintenanceDocumentService = maintenanceDocumentService;
 2034  0
         }
 2035  
 
 2036  
         public void setDocumentHelperService(DocumentHelperService documentHelperService) {
 2037  0
                 this.documentHelperService = documentHelperService;
 2038  0
         }
 2039  
 
 2040  
         protected LookupService getLookupService() {
 2041  0
                 if (lookupService == null) {
 2042  0
                         lookupService = KNSServiceLocatorWeb.getLookupService();
 2043  
                 }
 2044  0
                 return this.lookupService;
 2045  
         }
 2046  
 
 2047  
         public void setLookupService(LookupService lookupService) {
 2048  0
                 this.lookupService = lookupService;
 2049  0
         }
 2050  
 
 2051  
 }