Coverage Report - org.kuali.rice.kns.web.ui.SectionBridge
 
Classes in this File Line Coverage Branch Coverage Complexity
SectionBridge
0%
0/366
0%
0/256
6.773
 
 1  
 /*
 2  
  * Copyright 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.web.ui;
 17  
 
 18  
 import java.util.ArrayList;
 19  
 import java.util.Collection;
 20  
 import java.util.HashMap;
 21  
 import java.util.HashSet;
 22  
 import java.util.Iterator;
 23  
 import java.util.List;
 24  
 import java.util.Map;
 25  
 import java.util.Set;
 26  
 
 27  
 import org.apache.commons.beanutils.PropertyUtils;
 28  
 import org.apache.commons.lang.StringUtils;
 29  
 import org.kuali.rice.kns.authorization.FieldRestriction;
 30  
 import org.kuali.rice.kns.bo.BusinessObject;
 31  
 import org.kuali.rice.kns.bo.Inactivateable;
 32  
 import org.kuali.rice.kns.bo.PersistableBusinessObject;
 33  
 import org.kuali.rice.kns.datadictionary.CollectionDefinitionI;
 34  
 import org.kuali.rice.kns.datadictionary.FieldDefinition;
 35  
 import org.kuali.rice.kns.datadictionary.FieldDefinitionI;
 36  
 import org.kuali.rice.kns.datadictionary.InquiryCollectionDefinition;
 37  
 import org.kuali.rice.kns.datadictionary.InquirySectionDefinition;
 38  
 import org.kuali.rice.kns.datadictionary.InquirySubSectionHeaderDefinition;
 39  
 import org.kuali.rice.kns.datadictionary.MaintainableCollectionDefinition;
 40  
 import org.kuali.rice.kns.datadictionary.MaintainableFieldDefinition;
 41  
 import org.kuali.rice.kns.datadictionary.MaintainableItemDefinition;
 42  
 import org.kuali.rice.kns.datadictionary.MaintainableSectionDefinition;
 43  
 import org.kuali.rice.kns.datadictionary.MaintainableSubSectionHeaderDefinition;
 44  
 import org.kuali.rice.kns.datadictionary.SubSectionHeaderDefinitionI;
 45  
 import org.kuali.rice.kns.datadictionary.mask.MaskFormatter;
 46  
 import org.kuali.rice.kns.exception.ClassNotPersistableException;
 47  
 import org.kuali.rice.kns.inquiry.Inquirable;
 48  
 import org.kuali.rice.kns.inquiry.InquiryRestrictions;
 49  
 import org.kuali.rice.kns.lookup.LookupUtils;
 50  
 import org.kuali.rice.kns.maintenance.Maintainable;
 51  
 import org.kuali.rice.kns.service.BusinessObjectAuthorizationService;
 52  
 import org.kuali.rice.kns.service.DataDictionaryService;
 53  
 import org.kuali.rice.kns.service.KNSServiceLocator;
 54  
 import org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService;
 55  
 import org.kuali.rice.kns.util.FieldUtils;
 56  
 import org.kuali.rice.kns.util.KNSConstants;
 57  
 import org.kuali.rice.kns.util.MaintenanceUtils;
 58  
 import org.kuali.rice.kns.util.ObjectUtils;
 59  
 
 60  0
 public class SectionBridge {
 61  0
     private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(SectionBridge.class);
 62  
     private static BusinessObjectAuthorizationService businessObjectAuthorizationService;
 63  
     private static BusinessObjectAuthorizationService getBusinessObjectAuthorizationService() {
 64  0
             if (businessObjectAuthorizationService == null) {
 65  0
                     businessObjectAuthorizationService = KNSServiceLocator.getBusinessObjectAuthorizationService();
 66  
             }
 67  0
             return businessObjectAuthorizationService;
 68  
     }
 69  
     private static DataDictionaryService dataDictionaryService;
 70  
     private static DataDictionaryService getDataDictionaryService() {
 71  0
             if (dataDictionaryService == null) {
 72  0
                     dataDictionaryService = KNSServiceLocator.getDataDictionaryService();
 73  
             }
 74  0
             return dataDictionaryService;
 75  
     }
 76  
     private static MaintenanceDocumentDictionaryService maintenanceDocumentDictionaryService;
 77  
 
 78  
     /**
 79  
      * This method creates a Section for display on an Inquiry Screen.
 80  
      * 
 81  
      * @param sd The DD definition from which to construct the Section.
 82  
      * @param o The BusinessObject from which to populate the Section values.
 83  
      * @return A populated Section.
 84  
      */
 85  
     public static final Section toSection(Inquirable inquirable, InquirySectionDefinition sd, BusinessObject o, InquiryRestrictions auths) {
 86  0
         Section section = new Section();
 87  0
         section.setSectionId( sd.getId() );
 88  0
         section.setSectionTitle(sd.getTitle());
 89  0
         section.setRows(new ArrayList());
 90  0
         section.setDefaultOpen(sd.isDefaultOpen());
 91  
         
 92  0
         if (sd.getNumberOfColumns() != null) {
 93  0
             section.setNumberOfColumns(sd.getNumberOfColumns());
 94  
         }
 95  
         else {
 96  0
             section.setNumberOfColumns(KNSConstants.DEFAULT_NUM_OF_COLUMNS);
 97  
         }
 98  
 
 99  0
         List<Field> sectionFields = new ArrayList();
 100  0
         for (FieldDefinition fieldDefinition : sd.getInquiryFields()) {
 101  0
             List row = new ArrayList();
 102  
 
 103  0
             Field f = null;
 104  0
             if (fieldDefinition instanceof InquiryCollectionDefinition) {
 105  0
                 InquiryCollectionDefinition inquiryCollectionDefinition = (InquiryCollectionDefinition) fieldDefinition;
 106  
 
 107  0
                 List<Row> sectionRows = new ArrayList();
 108  0
                 sectionRows = getContainerRows(section, inquiryCollectionDefinition, o, null, null, new ArrayList(), new HashSet<String>(), new StringBuffer(section.getErrorKey()), inquiryCollectionDefinition.getNumberOfColumns(), inquirable);
 109  0
                 section.setRows(sectionRows);
 110  0
             }
 111  0
             else if (fieldDefinition instanceof InquirySubSectionHeaderDefinition) {
 112  0
                 f = createMaintainableSubSectionHeader((InquirySubSectionHeaderDefinition) fieldDefinition);
 113  
             }
 114  
             else {
 115  0
                 f = FieldBridge.toField(fieldDefinition, o, section);
 116  
             }
 117  
 
 118  0
             if (null != f) {
 119  0
                 sectionFields.add(f);
 120  
             }
 121  
 
 122  0
         }
 123  
 
 124  0
         if (!sectionFields.isEmpty()) {
 125  0
             section.setRows(FieldUtils.wrapFields(sectionFields, section.getNumberOfColumns()));
 126  
         }
 127  
 
 128  0
         applyInquirySectionAuthorizations(section, auths);
 129  
         
 130  0
         section.setRows(reArrangeRows(section.getRows(), section.getNumberOfColumns()));
 131  
         
 132  0
         return section;
 133  
     }
 134  
     
 135  
    
 136  
     private static final void applyInquirySectionAuthorizations(Section section, InquiryRestrictions inquiryRestrictions) {
 137  0
             applyInquiryRowsAuthorizations(section.getRows(), inquiryRestrictions);
 138  0
     }
 139  
     
 140  
     private static final void applyInquiryRowsAuthorizations(List<Row> rows, InquiryRestrictions inquiryRestrictions) {
 141  0
             for (Row row : rows) {
 142  0
                     List<Field> rowFields = row.getFields();
 143  0
                     for (Field field : rowFields) {
 144  0
                             applyInquiryFieldAuthorizations(field, inquiryRestrictions);
 145  
                     }
 146  0
             }
 147  0
     }
 148  
     
 149  
     protected static final void applyInquiryFieldAuthorizations(Field field, InquiryRestrictions inquiryRestrictions) {
 150  0
             if (Field.CONTAINER.equals(field.getFieldType())) {
 151  0
                     applyInquiryRowsAuthorizations(field.getContainerRows(), inquiryRestrictions);
 152  0
                     field.setContainerRows(reArrangeRows(field.getContainerRows(), field.getNumberOfColumnsForCollection()));
 153  
             }
 154  0
             else if (!Field.IMAGE_SUBMIT.equals(field.getFieldType())) {
 155  0
                     FieldRestriction fieldRestriction = inquiryRestrictions.getFieldRestriction(field.getPropertyName());
 156  0
                     if (fieldRestriction.isHidden()) {
 157  0
                             field.setFieldType(Field.HIDDEN);
 158  0
                             field.setPropertyValue(null);
 159  
                     }
 160  0
                     else if (fieldRestriction.isMasked()) {
 161  0
                     field.setSecure(true);
 162  0
                     MaskFormatter maskFormatter = fieldRestriction.getMaskFormatter();
 163  0
                     String displayMaskValue = maskFormatter.maskValue(field.getPropertyValue());
 164  0
                     field.setDisplayMaskValue(displayMaskValue);
 165  
                     // since it's an inquiry, let's wipe out the encrypted field value since we don't need to post it back
 166  0
                     field.setEncryptedValue("");
 167  
                     }
 168  
                }
 169  0
     }
 170  
     
 171  
     //This method is used to remove hidden fields (To fix JIRA KFSMI-2449)
 172  
     private static final List<Row> reArrangeRows(List<Row> rows, int numberOfColumns){
 173  0
             List<Row> rearrangedRows = new ArrayList<Row>();
 174  
             
 175  0
             for (Row row : rows) {
 176  0
                     List<Field> fields = new ArrayList<Field>();
 177  0
                     List<Field> rowFields = row.getFields();
 178  0
                     for (Field field : rowFields) {
 179  0
                             if(!Field.HIDDEN.equals(field.getFieldType()) && !Field.BLANK_SPACE.equals(field.getFieldType())){
 180  0
                                     fields.add(field);
 181  
                             }
 182  
                     }
 183  0
                     List<Row> rewrappedFieldRows = FieldUtils.wrapFields(fields, numberOfColumns);
 184  0
                     if (row.isHidden()) {
 185  0
                             for (Row rewrappedRow : rewrappedFieldRows) {
 186  0
                                     rewrappedRow.setHidden(true);
 187  
                             }
 188  
                     }
 189  0
                     rearrangedRows.addAll(rewrappedFieldRows);
 190  0
             }
 191  
             
 192  0
             return rearrangedRows;
 193  
     }
 194  
 
 195  
     
 196  
     /**
 197  
      * This method creates a Section for a MaintenanceDocument.
 198  
      * 
 199  
      * @param sd The DD definition of the Section.
 200  
      * @param o The BusinessObject from which the Section will be populated.
 201  
      * @param maintainable
 202  
      * @param maintenanceAction The action (new, newwithexisting, copy, edit, etc) requested from the UI.
 203  
      * @param autoFillDefaultValues Should default values be auto-filled?
 204  
      * @param autoFillBlankRequiredValues Should required values left blank on the UI be auto-filled?
 205  
      * @param displayedFieldNames What fields are displayed on the UI?
 206  
      * @return A populated Section.
 207  
      * @throws InstantiationException
 208  
      * @throws IllegalAccessException
 209  
      */
 210  
     public static final Section toSection(MaintainableSectionDefinition sd, BusinessObject o, Maintainable maintainable, Maintainable oldMaintainable, String maintenanceAction,  List<String> displayedFieldNames, Set<String> conditionallyRequiredMaintenanceFields) throws InstantiationException, IllegalAccessException {
 211  0
             Section section = new Section();
 212  
 
 213  0
         section.setSectionId( sd.getId() );
 214  0
         section.setSectionTitle(sd.getTitle());
 215  0
         section.setSectionClass(o.getClass());
 216  0
         section.setHidden( sd.isHidden() );
 217  0
         section.setDefaultOpen(sd.isDefaultOpen());
 218  0
         section.setHelpUrl(sd.getHelpUrl());
 219  
 
 220  
         // iterate through section maint items and contruct Field UI objects
 221  0
         Collection<MaintainableItemDefinition> maintItems = sd.getMaintainableItems();
 222  0
         List<Row> sectionRows = new ArrayList<Row>();
 223  0
         List<Field> sectionFields = new ArrayList<Field>();
 224  
 
 225  0
         for (MaintainableItemDefinition maintItem : maintItems) {
 226  0
             Field field = FieldBridge.toField(maintItem, sd, o, maintainable, section, displayedFieldNames, conditionallyRequiredMaintenanceFields);
 227  0
             boolean skipAdd = false;
 228  
 
 229  
             // if CollectionDefiniton, then have a many section
 230  0
             if (maintItem instanceof MaintainableCollectionDefinition) {
 231  0
                 MaintainableCollectionDefinition definition = (MaintainableCollectionDefinition) maintItem;
 232  0
                 section.getContainedCollectionNames().add(maintItem.getName());
 233  
 
 234  0
                 StringBuffer containerRowErrorKey = new StringBuffer();
 235  0
                 sectionRows = getContainerRows(section, definition, o, maintainable, oldMaintainable, displayedFieldNames, conditionallyRequiredMaintenanceFields, containerRowErrorKey, KNSConstants.DEFAULT_NUM_OF_COLUMNS, null);
 236  0
             } else if (maintItem instanceof MaintainableSubSectionHeaderDefinition) {
 237  0
                 MaintainableSubSectionHeaderDefinition definition = (MaintainableSubSectionHeaderDefinition) maintItem;
 238  0
                 field = createMaintainableSubSectionHeader(definition);
 239  
             }
 240  
 
 241  0
             if (!skipAdd) {
 242  0
                 sectionFields.add(field);
 243  
             }
 244  0
         }
 245  
 
 246  
         // populate field values from business object
 247  
         //if (o != null && !autoFillDefaultValues) {
 248  0
         if (o != null) {
 249  0
             sectionFields = FieldUtils.populateFieldsFromBusinessObject(sectionFields, o);
 250  
 
 251  
             /* if maintenance action is copy, clear out secure fields */
 252  0
             if (KNSConstants.MAINTENANCE_COPY_ACTION.equals(maintenanceAction)) {
 253  0
                 for (Iterator iterator = sectionFields.iterator(); iterator.hasNext();) {
 254  0
                     Field element = (Field) iterator.next();
 255  0
                     if (element.isSecure()) {
 256  0
                         element.setPropertyValue("");
 257  
                     }
 258  0
                 }
 259  
             }
 260  
         }
 261  
 
 262  0
         sectionRows.addAll(FieldUtils.wrapFields(sectionFields));
 263  0
         section.setRows(sectionRows);
 264  
 
 265  0
         return section;
 266  
 
 267  
     }
 268  
     
 269  
     
 270  
     /**
 271  
      * @see #getContainerRows(Section, CollectionDefinitionI, BusinessObject, Maintainable, List<String>, StringBuffer, String,
 272  
      *      boolean, int)
 273  
      */
 274  
     public static final List<Row> getContainerRows(Section s, CollectionDefinitionI collectionDefinition, BusinessObject o, Maintainable m, Maintainable oldMaintainable, List<String> displayedFieldNames, Set<String> conditionallyRequiredMaintenanceFields, StringBuffer containerRowErrorKey, int numberOfColumns, Inquirable inquirable) {
 275  0
         return getContainerRows(s, collectionDefinition, o, m, oldMaintainable, displayedFieldNames, conditionallyRequiredMaintenanceFields, containerRowErrorKey, "", false, numberOfColumns, inquirable);
 276  
     }
 277  
 
 278  
     /**
 279  
      * Builds a list of Rows with Fields of type containers for a many section.
 280  
      * 
 281  
      * @param s The Section containing the Collection/Container.
 282  
      * @param collectionDefinition The DD definition of the Collection.
 283  
      * @param o The BusinessObject from which the Container/Collection will be populated.
 284  
      * @param m The Maintainable for the BO (needed by some methods called on FieldBridge, FieldUtils etc.)
 285  
      * @param displayedFieldNames
 286  
      * @param containerRowErrorKey The error key for the Container/Collection.
 287  
      * @param parents
 288  
      * @param hideAdd Should the add line be added to the Container/Collection?
 289  
      * @param numberOfColumns In how many columns in the UI will the fields in the Container/Collection be shown?
 290  
      * @return
 291  
      */
 292  
      public static final List<Row> getContainerRows(Section s, CollectionDefinitionI collectionDefinition, BusinessObject o, Maintainable m, Maintainable oldMaintainable, List<String> displayedFieldNames, Set<String> conditionallyRequiredMaintenanceFields, StringBuffer containerRowErrorKey, String parents, boolean hideAdd, int numberOfColumns, Inquirable inquirable) {
 293  0
         List<Row> containerRows = new ArrayList<Row>();
 294  0
         List<Field> collFields = new ArrayList<Field>();
 295  
         
 296  0
         String collectionName = collectionDefinition.getName();
 297  
         
 298  
         // add the toggle inactive record display button for the collection
 299  0
         if (m != null && Inactivateable.class.isAssignableFrom(collectionDefinition.getBusinessObjectClass()) && StringUtils.isBlank(parents)) {
 300  0
             addShowInactiveButtonField(s, collectionName, !m.getShowInactiveRecords(collectionName));
 301  
         }
 302  0
         if (inquirable != null && Inactivateable.class.isAssignableFrom(collectionDefinition.getBusinessObjectClass()) && StringUtils.isBlank(parents)) {
 303  0
             addShowInactiveButtonField(s, collectionName, !inquirable.getShowInactiveRecords(collectionName));
 304  
         }
 305  
         
 306  
         // first need to populate the containerRows with the "new" form if available
 307  0
         if (!hideAdd) {
 308  0
             List<Field> newFormFields = new ArrayList<Field>();
 309  0
             if (collectionDefinition.getIncludeAddLine()) {
 310  
 
 311  
 
 312  0
                 newFormFields = FieldBridge.getNewFormFields(collectionDefinition, o, m, displayedFieldNames, conditionallyRequiredMaintenanceFields, containerRowErrorKey, parents, hideAdd, numberOfColumns);
 313  
 
 314  
 
 315  0
             } else if(collectionDefinition instanceof MaintainableCollectionDefinition) {
 316  0
                 MaintainableCollectionDefinition mcd = (MaintainableCollectionDefinition)collectionDefinition;
 317  0
                 if(FieldUtils.isCollectionMultipleLookupEnabled(mcd)) {
 318  
                     //do just the top line for collection if add is not allowed
 319  0
                   newFormFields = FieldBridge.constructContainerField(collectionDefinition, parents, o, hideAdd, numberOfColumns, mcd.getName(), new ArrayList<Field>());
 320  
                 }
 321  
             }
 322  0
             if (null != newFormFields) {
 323  0
                 containerRows.add(new Row(newFormFields));
 324  
             }
 325  
         }
 326  
         
 327  0
         Collection<? extends CollectionDefinitionI> collections = collectionDefinition.getCollections();
 328  0
          for (CollectionDefinitionI collection : collections) {
 329  0
              int subCollectionNumberOfColumn = numberOfColumns;
 330  0
              if (collectionDefinition instanceof InquiryCollectionDefinition) {
 331  0
                  InquiryCollectionDefinition icd = (InquiryCollectionDefinition) collection;
 332  0
                  if (icd.getNumberOfColumns() != null) {
 333  0
                      subCollectionNumberOfColumn = icd.getNumberOfColumns();
 334  
                  }
 335  
              }
 336  
              // no colNum for add rows
 337  0
              containerRows.addAll(getContainerRows(s, collection, o, m, oldMaintainable, displayedFieldNames, conditionallyRequiredMaintenanceFields, containerRowErrorKey, parents + collectionDefinition.getName() + ".", true, subCollectionNumberOfColumn, inquirable));
 338  0
          }
 339  
 
 340  
         // then we need to loop through the existing collection and add those fields
 341  0
         Collection<? extends FieldDefinitionI> collectionFields = collectionDefinition.getFields();
 342  
         // get label for collection
 343  0
         String collectionLabel = getDataDictionaryService().getCollectionLabel(o.getClass(), collectionDefinition.getName());
 344  
         
 345  
         // retrieve the summary label either from the override or from the DD
 346  0
         String collectionElementLabel = collectionDefinition.getSummaryTitle();
 347  0
         if (StringUtils.isEmpty(collectionElementLabel)) {
 348  0
             collectionElementLabel = getDataDictionaryService().getCollectionElementLabel(o.getClass().getName(), collectionDefinition.getName(), collectionDefinition.getBusinessObjectClass());
 349  
         }
 350  
 
 351  0
         boolean translateCodes = getMaintenanceDocumentDictionaryService().translateCodes(o.getClass());
 352  
 
 353  0
         if (o != null) {
 354  0
             if (PropertyUtils.isWriteable(o, collectionDefinition.getName()) && ObjectUtils.getPropertyValue(o, collectionDefinition.getName()) != null) {
 355  0
                 Object obj = ObjectUtils.getPropertyValue(o, collectionName);
 356  
                 
 357  0
                 Object oldObj = null;
 358  0
                 if (oldMaintainable != null && oldMaintainable.getBusinessObject() != null) {
 359  0
                     oldObj = ObjectUtils.getPropertyValue(oldMaintainable.getBusinessObject(), collectionName);
 360  
                 }
 361  
 
 362  0
                 if (obj instanceof List) {
 363  0
                     Map summaryFields = new HashMap();
 364  0
                     boolean hidableRowsPresent = false;
 365  0
                     for (int i = 0; i < ((List) obj).size(); i++) {
 366  0
                         BusinessObject lineBusinessObject = (BusinessObject) ((List) obj).get(i);
 367  
                         
 368  0
                         if (lineBusinessObject instanceof PersistableBusinessObject) {
 369  0
                                 ((PersistableBusinessObject) lineBusinessObject).refreshNonUpdateableReferences();
 370  
                         }
 371  
                         
 372  
                         /*
 373  
                          * Handle display of inactive records. The old maintainable is used to compare the old side (if it exists). If the row should not be displayed, it is set as
 374  
                          * hidden and will be handled in the maintenance rowDisplay.tag.   
 375  
                          */  
 376  0
                         boolean setRowHidden = false;
 377  0
                         BusinessObject oldLineBusinessObject = null;
 378  0
                         if (oldObj != null && ((List) oldObj).size() > i) {
 379  0
                             oldLineBusinessObject = (BusinessObject) ((List) oldObj).get(i);
 380  
                         }
 381  
                         
 382  0
                         if (lineBusinessObject instanceof Inactivateable && !((Inactivateable) lineBusinessObject).isActive()) {
 383  0
                             if (m != null) {
 384  
                                 // rendering a maint doc
 385  0
                                 if (!hidableRowsPresent) {
 386  0
                                     hidableRowsPresent = isRowHideableForMaintenanceDocument(lineBusinessObject, oldLineBusinessObject);
 387  
                                     }
 388  0
                                 setRowHidden = isRowHiddenForMaintenanceDocument(lineBusinessObject, oldLineBusinessObject, m, collectionName);
 389  
                                     }
 390  0
                             if (inquirable != null) {
 391  
                                 // rendering an inquiry screen
 392  0
                                 if (!hidableRowsPresent) {
 393  0
                                     hidableRowsPresent = isRowHideableForInquiry(lineBusinessObject);
 394  
                                 }
 395  0
                                 setRowHidden = isRowHiddenForInquiry(lineBusinessObject, inquirable, collectionName);
 396  
                             }
 397  
                         }
 398  
 
 399  0
                         collFields = new ArrayList<Field>();
 400  0
                         List<String> duplicateIdentificationFieldNames = new ArrayList<String>(); 
 401  
                         //We only need to do this if the collection definition is a maintainable collection definition, 
 402  
                         //don't need it for inquiry collection definition.
 403  0
                         if (collectionDefinition instanceof MaintainableCollectionDefinition) {
 404  0
                             Collection<MaintainableFieldDefinition> duplicateFieldDefs = ((MaintainableCollectionDefinition)collectionDefinition).getDuplicateIdentificationFields();
 405  0
                             for (MaintainableFieldDefinition eachFieldDef : duplicateFieldDefs) {
 406  0
                                 duplicateIdentificationFieldNames.add(eachFieldDef.getName());
 407  
                             }
 408  
                         }
 409  
 
 410  0
                         for (FieldDefinitionI collectionField : collectionFields) {
 411  
 
 412  
                             // construct Field UI object from definition
 413  0
                             Field collField = FieldUtils.getPropertyField(collectionDefinition.getBusinessObjectClass(), collectionField.getName(), false);
 414  
 
 415  0
                             if (translateCodes) {
 416  0
                                 FieldUtils.setAdditionalDisplayPropertyForCodes(lineBusinessObject.getClass(), collField.getPropertyName(), collField);
 417  
                             }
 418  
 
 419  0
                             FieldBridge.setupField(collField, collectionField, conditionallyRequiredMaintenanceFields);
 420  0
                             setPrimaryKeyFieldsReadOnly(collectionDefinition.getBusinessObjectClass(), collField);
 421  
 
 422  
                             //If the duplicateIdentificationFields were specified in the maint. doc. DD, we'll need
 423  
                             //to set the fields to be read only as well, in addition to the primary key fields.
 424  0
                             if (duplicateIdentificationFieldNames.size() > 0) {
 425  0
                                 setDuplicateIdentificationFieldsReadOnly(collField, duplicateIdentificationFieldNames);
 426  
                             }
 427  
 
 428  0
                             FieldUtils.setInquiryURL(collField, lineBusinessObject, collectionField.getName());
 429  
                             // save the simple property name
 430  0
                             String name = collField.getPropertyName();
 431  
 
 432  
                             // prefix name for multi line (indexed)
 433  0
                             collField.setPropertyName(collectionDefinition.getName() + "[" + (new Integer(i)).toString() + "]." + collField.getPropertyName());
 434  
 
 435  
                             // commenting out codes for sub-collections show/hide for now
 436  
                             // subCollField.setContainerName(collectionDefinition.getName() + "["+i+"]" +"." +
 437  
                             // subCollectionDefinition.getName() + "[" + j + "]");
 438  
 
 439  0
                             if (collectionField instanceof MaintainableFieldDefinition) {
 440  0
                                 MaintenanceUtils.setFieldQuickfinder(lineBusinessObject, collectionDefinition.getName(), false, i, name, collField, displayedFieldNames, m, (MaintainableFieldDefinition) collectionField);
 441  0
                                 MaintenanceUtils.setFieldDirectInquiry(lineBusinessObject, name, (MaintainableFieldDefinition) collectionField, collField, displayedFieldNames);
 442  
                             } else {
 443  0
                                 LookupUtils.setFieldQuickfinder(lineBusinessObject, collectionDefinition.getName(), false, i, name, collField, displayedFieldNames, m);
 444  0
                                 LookupUtils.setFieldDirectInquiry(lineBusinessObject, name, collField);
 445  
                             }
 446  
 
 447  0
                             String propertyValue = ObjectUtils.getFormattedPropertyValueUsingDataDictionary(lineBusinessObject, collectionField.getName());
 448  0
                             collField.setPropertyValue(propertyValue);
 449  
 
 450  0
                             if (StringUtils.isNotBlank(collField.getAlternateDisplayPropertyName())) {
 451  0
                                 String alternateDisplayPropertyValue = ObjectUtils.getFormattedPropertyValueUsingDataDictionary(lineBusinessObject,
 452  
                                         collField.getAlternateDisplayPropertyName());
 453  0
                                 collField.setAlternateDisplayPropertyValue(alternateDisplayPropertyValue);
 454  
                             }
 455  
 
 456  0
                             if (StringUtils.isNotBlank(collField.getAdditionalDisplayPropertyName())) {
 457  0
                                 String additionalDisplayPropertyValue = ObjectUtils.getFormattedPropertyValueUsingDataDictionary(lineBusinessObject,
 458  
                                         collField.getAdditionalDisplayPropertyName());
 459  0
                                 collField.setAdditionalDisplayPropertyValue(additionalDisplayPropertyValue);
 460  
                             }
 461  
 
 462  
                             //update user fields with universal id and/or name
 463  0
                             updateUserFields(collField, lineBusinessObject);
 464  
 
 465  
                             // the the field as read only (if appropriate)
 466  0
                             if (collectionField.isReadOnlyAfterAdd()) {
 467  0
                                 collField.setReadOnly(true);
 468  
                             }
 469  
 
 470  
                             // check if this is a summary field
 471  0
                             if (collectionDefinition.hasSummaryField(collectionField.getName())) {
 472  0
                                 summaryFields.put(collectionField.getName(), collField);
 473  
                             }
 474  
 
 475  0
                             collFields.add(collField);
 476  0
                         }
 477  
 
 478  
                         Field containerField;
 479  0
                         containerField = FieldUtils.constructContainerField(KNSConstants.EDIT_PREFIX + "[" + (new Integer(i)).toString() + "]", collectionLabel + " " + (i + 1), collFields, numberOfColumns);
 480  
                         // why is this only on collections and not subcollections any significance or just oversight?
 481  0
                         containerField.setContainerName(collectionDefinition.getName() + "[" + (new Integer(i)).toString() + "].");
 482  
 
 483  
                         /* If the collection line is pending (meaning added by this document) the isNewCollectionRecord will be set to true. In this
 484  
                            case we give an option to delete the line. The parameters for the delete action method are embedded into the button name. */
 485  0
                         if (lineBusinessObject instanceof PersistableBusinessObject && 
 486  
                                         (((PersistableBusinessObject) lineBusinessObject).isNewCollectionRecord() 
 487  
                                                         || collectionDefinition.isAlwaysAllowCollectionDeletion())) {
 488  0
                             containerField.getContainerRows().add(new Row(getDeleteRowButtonField(parents + collectionDefinition.getName(), (new Integer(i)).toString())));
 489  
                         }
 490  
 
 491  0
                         if (StringUtils.isNotEmpty(collectionElementLabel)) {
 492  
                             //We don't want to associate any indexes to the containerElementName anymore so that
 493  
                             //when the element is deleted, the currentTabIndex won't be associated with the
 494  
                             //wrong tab for the remaining tab.
 495  
                             //containerField.setContainerElementName(collectionElementLabel + " " + (i + 1));
 496  0
                             containerField.setContainerElementName(collectionElementLabel);
 497  
                             // reorder summaryFields to make sure they are in the order specified in the summary section
 498  0
                             List orderedSummaryFields = getSummaryFields(summaryFields, collectionDefinition);
 499  0
                             containerField.setContainerDisplayFields(orderedSummaryFields);
 500  
                         }
 501  
                         
 502  0
                         Row containerRow = new Row(containerField);
 503  0
                         if (setRowHidden) {
 504  0
                             containerRow.setHidden(true);
 505  
                         }
 506  0
                         containerRows.add(containerRow);
 507  
                         
 508  
                         
 509  
 
 510  0
                         Collection<? extends CollectionDefinitionI> subCollections = collectionDefinition.getCollections();
 511  0
                         List<Field> subCollFields = new ArrayList<Field>();
 512  
 
 513  0
                         summaryFields = new HashMap();
 514  
                         // iterate over the subCollections directly on this collection
 515  0
                         for (CollectionDefinitionI subCollection : subCollections) {
 516  0
                             Collection<? extends FieldDefinitionI> subCollectionFields = subCollection.getFields();
 517  0
                             int subCollectionNumberOfColumns = numberOfColumns;
 518  
 
 519  0
                             if (!s.getContainedCollectionNames().contains(collectionDefinition.getName() + "." + subCollection.getName())) {
 520  0
                                 s.getContainedCollectionNames().add(collectionDefinition.getName() + "." + subCollection.getName());
 521  
                             }
 522  
 
 523  0
                             if (subCollection instanceof InquiryCollectionDefinition) {
 524  0
                                 InquiryCollectionDefinition icd = (InquiryCollectionDefinition) subCollection;
 525  0
                                 if (icd.getNumberOfColumns() != null) {
 526  0
                                     subCollectionNumberOfColumns = icd.getNumberOfColumns();
 527  
                                 }
 528  
                             }
 529  
                             // get label for collection
 530  0
                             String subCollectionLabel = getDataDictionaryService().getCollectionLabel(o.getClass(), subCollection.getName());
 531  
 
 532  
                             // retrieve the summary label either from the override or from the DD
 533  0
                             String subCollectionElementLabel = subCollection.getSummaryTitle();
 534  0
                             if (StringUtils.isEmpty(subCollectionElementLabel)) {
 535  0
                                 subCollectionElementLabel = getDataDictionaryService().getCollectionElementLabel(o.getClass().getName(), subCollection.getName(), subCollection.getBusinessObjectClass());
 536  
                             }
 537  
                             // make sure it's really a collection (i.e. list)
 538  
 
 539  0
                             String subCollectionName = subCollection.getName();
 540  0
                             Object subObj = ObjectUtils.getPropertyValue(lineBusinessObject, subCollectionName);
 541  
 
 542  0
                             Object oldSubObj = null;
 543  0
                             if (oldLineBusinessObject != null) {
 544  0
                                 oldSubObj = ObjectUtils.getPropertyValue(oldLineBusinessObject, subCollectionName);
 545  
                             }
 546  
 
 547  0
                             if (subObj instanceof List) {
 548  
                                 /* recursively call this method to get the add row and exisiting members of the subCollections subcollections containerRows.addAll(getContainerRows(subCollectionDefinition,
 549  
                                    displayedFieldNames,containerRowErrorKey, parents+collectionDefinition.getName()+"["+i+"]"+".","[0]",false, subCollectionNumberOfColumn)); */
 550  0
                                 containerField.getContainerRows().addAll(getContainerRows(s, subCollection, o, m, oldMaintainable, displayedFieldNames, conditionallyRequiredMaintenanceFields, containerRowErrorKey, parents + collectionDefinition.getName() + "[" + i + "]" + ".", false, subCollectionNumberOfColumns, inquirable));
 551  
 
 552  
                                 // iterate over the fields
 553  0
                                 for (int j = 0; j < ((List) subObj).size(); j++) {
 554  0
                                     BusinessObject lineSubBusinessObject = (BusinessObject) ((List) subObj).get(j);
 555  
 
 556  0
                                     if (lineSubBusinessObject instanceof PersistableBusinessObject) {
 557  0
                                         ((PersistableBusinessObject) lineSubBusinessObject).refreshNonUpdateableReferences();
 558  
                                     }
 559  
 
 560  
                                     // determine if sub collection line is inactive and should be hidden
 561  0
                                     boolean setSubRowHidden = false;
 562  0
                                     if (lineSubBusinessObject instanceof Inactivateable && !((Inactivateable) lineSubBusinessObject).isActive()) {
 563  0
                                         if (oldSubObj != null) {
 564  
                                             // get corresponding elements in both the new list and the old list
 565  0
                                             BusinessObject oldLineSubBusinessObject = (BusinessObject) ((List) oldSubObj).get(j);
 566  0
                                             if (m != null) {
 567  0
                                                 if (!hidableRowsPresent) {
 568  0
                                                     hidableRowsPresent = isRowHideableForMaintenanceDocument(lineSubBusinessObject, oldLineSubBusinessObject);
 569  
                                                 }
 570  0
                                                 setSubRowHidden = isRowHiddenForMaintenanceDocument(lineSubBusinessObject, oldLineSubBusinessObject, m, collectionName);
 571  
                                             }
 572  
                                         }
 573  0
                                         if (inquirable != null) {
 574  0
                                             if (!hidableRowsPresent) {
 575  0
                                                 hidableRowsPresent = isRowHideableForInquiry(lineSubBusinessObject);
 576  
                                             }
 577  0
                                             setSubRowHidden = isRowHiddenForInquiry(lineSubBusinessObject, inquirable, collectionName);
 578  
                                         }
 579  
                                     }
 580  
 
 581  
 
 582  0
                                     subCollFields = new ArrayList<Field>();
 583  
                                     // construct field objects based on fields
 584  0
                                     for (FieldDefinitionI subCollectionField : subCollectionFields) {
 585  
 
 586  
                                         // construct Field UI object from definition
 587  0
                                         Field subCollField = FieldUtils.getPropertyField(subCollection.getBusinessObjectClass(), subCollectionField.getName(), false);
 588  
 
 589  0
                                         String subCollectionFullName = collectionDefinition.getName() + "[" + i + "]" + "." + subCollection.getName();
 590  
 
 591  0
                                         if (translateCodes) {
 592  0
                                             FieldUtils.setAdditionalDisplayPropertyForCodes(lineSubBusinessObject.getClass(), subCollField.getPropertyName(), subCollField);
 593  
                                         }
 594  
 
 595  0
                                         FieldBridge.setupField(subCollField, subCollectionField, conditionallyRequiredMaintenanceFields);
 596  0
                                         setPrimaryKeyFieldsReadOnly(subCollection.getBusinessObjectClass(), subCollField);
 597  
 
 598  
                                         // save the simple property name
 599  0
                                         String name = subCollField.getPropertyName();
 600  
 
 601  
                                         // prefix name for multi line (indexed)
 602  0
                                         subCollField.setPropertyName(subCollectionFullName + "[" + j + "]." + subCollField.getPropertyName());
 603  
 
 604  
                                         // commenting out codes for sub-collections show/hide for now
 605  0
                                         if (subCollectionField instanceof MaintainableFieldDefinition) {
 606  0
                                             MaintenanceUtils.setFieldQuickfinder(lineSubBusinessObject, subCollectionFullName, false, j, name, subCollField, displayedFieldNames, m, (MaintainableFieldDefinition) subCollectionField);
 607  0
                                             MaintenanceUtils.setFieldDirectInquiry(lineSubBusinessObject, subCollectionFullName, false, j, name, subCollField, displayedFieldNames, m, (MaintainableFieldDefinition) subCollectionField);
 608  
                                         } else {
 609  0
                                             LookupUtils.setFieldQuickfinder(lineSubBusinessObject, subCollectionFullName, false, j, name, subCollField, displayedFieldNames);
 610  0
                                             LookupUtils.setFieldDirectInquiry(lineBusinessObject, name, subCollField);
 611  
                                         }
 612  
 
 613  0
                                         String propertyValue = ObjectUtils.getFormattedPropertyValueUsingDataDictionary(lineSubBusinessObject, subCollectionField.getName());
 614  0
                                         subCollField.setPropertyValue(propertyValue);
 615  
 
 616  0
                                         if (StringUtils.isNotBlank(subCollField.getAlternateDisplayPropertyName())) {
 617  0
                                             String alternateDisplayPropertyValue = ObjectUtils.getFormattedPropertyValueUsingDataDictionary(lineSubBusinessObject,
 618  
                                                     subCollField.getAlternateDisplayPropertyName());
 619  0
                                             subCollField.setAlternateDisplayPropertyValue(alternateDisplayPropertyValue);
 620  
                                         }
 621  
 
 622  0
                                         if (StringUtils.isNotBlank(subCollField.getAdditionalDisplayPropertyName())) {
 623  0
                                             String additionalDisplayPropertyValue = ObjectUtils.getFormattedPropertyValueUsingDataDictionary(lineSubBusinessObject,
 624  
                                                     subCollField.getAdditionalDisplayPropertyName());
 625  0
                                             subCollField.setAdditionalDisplayPropertyValue(additionalDisplayPropertyValue);
 626  
                                         }
 627  
 
 628  
                                         // check if this is a summary field
 629  0
                                         if (subCollection.hasSummaryField(subCollectionField.getName())) {
 630  0
                                             summaryFields.put(subCollectionField.getName(), subCollField);
 631  
                                         }
 632  
 
 633  0
                                         if (subCollectionField.isReadOnlyAfterAdd()) {
 634  0
                                             subCollField.setReadOnly(true);
 635  
                                         }
 636  
 
 637  0
                                         subCollFields.add(subCollField);
 638  0
                                     }
 639  
 
 640  0
                                     Field subContainerField = FieldUtils.constructContainerField(KNSConstants.EDIT_PREFIX + "[" + (new Integer(j)).toString() + "]", subCollectionLabel, subCollFields);
 641  0
                                     if (lineSubBusinessObject instanceof PersistableBusinessObject && (((PersistableBusinessObject) lineSubBusinessObject).isNewCollectionRecord() || subCollection.isAlwaysAllowCollectionDeletion())) {
 642  0
                                         subContainerField.getContainerRows().add(new Row(getDeleteRowButtonField(parents + collectionDefinition.getName() + "[" + i + "]" + "." + subCollectionName, (new Integer(j)).toString())));
 643  
                                     }
 644  
 
 645  
                                     // summary line code
 646  0
                                     if (StringUtils.isNotEmpty(subCollectionElementLabel)) {
 647  
                                         //We don't want to associate any indexes to the containerElementName anymore so that
 648  
                                         //when the element is deleted, the currentTabIndex won't be associated with the
 649  
                                         //wrong tab for the remaining tab.
 650  
                                         //subContainerField.setContainerElementName(subCollectionElementLabel + " " + (j + 1));
 651  0
                                         subContainerField.setContainerElementName(collectionElementLabel + "-" + subCollectionElementLabel);
 652  
                                     }
 653  0
                                     subContainerField.setContainerName(collectionDefinition.getName() + "." + subCollectionName);
 654  0
                                     if (!summaryFields.isEmpty()) {
 655  
                                         // reorder summaryFields to make sure they are in the order specified in the summary section
 656  0
                                         List orderedSummaryFields = getSummaryFields(summaryFields, subCollection);
 657  0
                                         subContainerField.setContainerDisplayFields(orderedSummaryFields);
 658  
                                     }
 659  
 
 660  0
                                     Row subContainerRow = new Row(subContainerField);
 661  0
                                     if (setRowHidden || setSubRowHidden) {
 662  0
                                         subContainerRow.setHidden(true);
 663  
                                     }
 664  0
                                     containerField.getContainerRows().add(subContainerRow);
 665  
                                 }
 666  
                             }
 667  0
                         }
 668  
                     }
 669  0
                     if ( !hidableRowsPresent ) {
 670  0
                         s.setExtraButtonSource( "" );
 671  
                     }
 672  
                 }
 673  
             }
 674  
         }
 675  
         
 676  0
         return containerRows;
 677  
     }
 678  
 
 679  
     /**
 680  
       * Updates fields of type kualiuser sets the universal user id and/or name if required. 
 681  
       * 
 682  
       * @param field
 683  
       * @param businessObject
 684  
       */
 685  
      private static final void updateUserFields(Field field, BusinessObject businessObject){
 686  
          // for user fields, attempt to pull the principal ID and person's name from the source object
 687  0
          if ( field.getFieldType().equals(Field.KUALIUSER) ) {
 688  
              // this is supplemental, so catch and log any errors
 689  
              try {
 690  0
                  if ( StringUtils.isNotBlank(field.getUniversalIdAttributeName()) ) {
 691  0
                      Object principalId = ObjectUtils.getNestedValue(businessObject, field.getUniversalIdAttributeName());
 692  0
                      if ( principalId != null ) {
 693  0
                          field.setUniversalIdValue(principalId.toString());
 694  
                      }
 695  
                  }
 696  0
                  if ( StringUtils.isNotBlank(field.getPersonNameAttributeName()) ) {
 697  0
                      Object personName = ObjectUtils.getNestedValue(businessObject, field.getPersonNameAttributeName());
 698  0
                      if ( personName != null ) {
 699  0
                          field.setPersonNameValue( personName.toString() );
 700  
                      }
 701  
                  }
 702  0
              } catch ( Exception ex ) {
 703  0
                  LOG.warn( "Unable to get principal ID or person name property in SectionBridge.", ex );
 704  0
              }
 705  
          }
 706  0
      }
 707  
      
 708  
     /**
 709  
      * Helper method to build up a Field containing a delete button mapped up to remove the collection record identified by the
 710  
      * given collection name and index.
 711  
      * 
 712  
      * @param collectionName - name of the collection
 713  
      * @param rowIndex - index of the record to associate delete button
 714  
      * @return Field - of type IMAGE_SUBMIT
 715  
      */
 716  
     private static final Field getDeleteRowButtonField(String collectionName, String rowIndex) {
 717  0
         Field deleteButtonField = new Field();
 718  
 
 719  0
         String deleteButtonName = KNSConstants.DISPATCH_REQUEST_PARAMETER + "." + KNSConstants.DELETE_LINE_METHOD + "." + collectionName + "." + KNSConstants.METHOD_TO_CALL_BOPARM_LEFT_DEL + ".line" + rowIndex;
 720  0
         deleteButtonField.setPropertyName(deleteButtonName);
 721  0
         deleteButtonField.setFieldType(Field.IMAGE_SUBMIT);
 722  0
         deleteButtonField.setPropertyValue("images/tinybutton-delete1.gif");
 723  
 
 724  0
         return deleteButtonField;
 725  
     }
 726  
     
 727  
     /**
 728  
      * Helper method to build up the show inactive button source and place in the section.
 729  
      * 
 730  
      * @param section - section that will display the button
 731  
      * @param collectionName - name of the collection to toggle setting
 732  
      * @param showInactive - boolean indicating whether inactive rows should be displayed
 733  
      * @return Field - of type IMAGE_SUBMIT
 734  
      */
 735  
     private static final void addShowInactiveButtonField(Section section, String collectionName, boolean showInactive) {
 736  0
             String methodName = KNSConstants.DISPATCH_REQUEST_PARAMETER + "." + KNSConstants.TOGGLE_INACTIVE_METHOD + "." + collectionName.replace( '.', '_' );
 737  0
         methodName += "." + KNSConstants.METHOD_TO_CALL_BOPARM_LEFT_DEL + showInactive + ".anchorshowInactive." + collectionName + KNSConstants.METHOD_TO_CALL_BOPARM_RIGHT_DEL;
 738  
            
 739  0
         String imageSource = showInactive ? "tinybutton-showinact.gif" : "tinybutton-hideinact.gif";
 740  
 
 741  0
         String showInactiveButton = "property=" + methodName + ";src=" + imageSource + ";alt=show(hide) inactive" + ";title=show(hide) inactive";
 742  
 
 743  0
         section.setExtraButtonSource(showInactiveButton);
 744  0
     }
 745  
     
 746  
     /**
 747  
      * Retrieves the primary key property names for the given class. If the field's property is one of those keys, makes the field
 748  
      * read-only. This is called for collection lines. Since deletion is not allowed for existing lines, the pk fields must be
 749  
      * read-only, otherwise a user could change the pk value which would be equivalent to deleting the line and adding a new line.
 750  
      */
 751  
     private static final void setPrimaryKeyFieldsReadOnly(Class businessObjectClass, Field field) {
 752  
             try{
 753  
                     //TODO: Revisit this. Changing since getPrimaryKeys and listPrimaryKeyFieldNames are apparently same.
 754  
                     //May be we might want to replace listPrimaryKeyFieldNames with getPrimaryKeys... Not sure.
 755  0
                     List primaryKeyPropertyNames = 
 756  
                             KNSServiceLocator.getBusinessObjectMetaDataService().listPrimaryKeyFieldNames(businessObjectClass);
 757  0
                 if (primaryKeyPropertyNames.contains(field.getPropertyName())) {
 758  0
                     field.setReadOnly(true);
 759  
                 }
 760  0
             } catch(ClassNotPersistableException ex){
 761  
                     //Not all classes will be persistable in a collection. For e.g. externalizable business objects.
 762  0
                     LOG.info("Not persistable businessObjectClass: "+businessObjectClass+", field: "+field);
 763  0
             }
 764  0
     }
 765  
     
 766  
     private static void setDuplicateIdentificationFieldsReadOnly(Field field, List<String>duplicateIdentificationFieldNames) {
 767  0
         if (duplicateIdentificationFieldNames.contains(field.getPropertyName())) {
 768  0
             field.setReadOnly(true);
 769  
         }
 770  0
     }
 771  
 
 772  
     /**
 773  
      * This method returns an ordered list of fields.
 774  
      * 
 775  
      * @param collSummaryFields
 776  
      * @param collectionDefinition
 777  
      * @return
 778  
      */
 779  
     private static final List<Field> getSummaryFields(Map collSummaryFields, CollectionDefinitionI collectionDefinition) {
 780  0
         List<Field> orderedSummaryFields = new ArrayList<Field>();
 781  0
         for (FieldDefinitionI summaryField : collectionDefinition.getSummaryFields()) {
 782  0
             String name = summaryField.getName();
 783  0
             boolean found = false;
 784  0
             Field addField = (Field) collSummaryFields.get(name);
 785  0
             if (!(addField == null)) {
 786  0
                 orderedSummaryFields.add(addField);
 787  0
                 found = true;
 788  
             }
 789  
 
 790  0
             if (!found) {
 791  
                 // should we throw a real error here?
 792  0
                 LOG.error("summaryField " + summaryField + " not present in the list");
 793  
             }
 794  
 
 795  0
         }
 796  0
         return orderedSummaryFields;
 797  
     }
 798  
 
 799  
     /**
 800  
      * This is a helper method to create a sub section header
 801  
      * 
 802  
      * @param definition the MaintainableSubSectionHeaderDefinition that we'll use to create the sub section header
 803  
      * @return the Field, which is the sub section header
 804  
      */
 805  
     private static final Field createMaintainableSubSectionHeader(SubSectionHeaderDefinitionI definition) {
 806  0
         Field separatorField = new Field();
 807  0
         separatorField.setFieldLabel(definition.getName());
 808  0
         separatorField.setFieldType(Field.SUB_SECTION_SEPARATOR);
 809  0
         separatorField.setReadOnly(true);
 810  
 
 811  0
         return separatorField;
 812  
     }
 813  
     
 814  
     /**
 815  
      * Determines whether a business object is hidable on a maintenance document.  Hidable means that if the user chose to hide the inactive
 816  
      * elements in the collection in which the passed in BOs reside, then the BOs would be hidden
 817  
      * 
 818  
      * @param lineBusinessObject the BO in the new maintainable, should be of type {@link PersistableBusinessObject} and {@link Inquirable}
 819  
      * @param oldLineBusinessObject the corresponding BO in the old maintainable, should be of type {@link PersistableBusinessObject} and 
 820  
      * {@link Inquirable}
 821  
      * @return whether the BOs are eligible to be hidden if the user decides to hide them
 822  
      */
 823  
     protected static boolean isRowHideableForMaintenanceDocument(BusinessObject lineBusinessObject, BusinessObject oldLineBusinessObject) {
 824  0
         if (oldLineBusinessObject != null) {
 825  0
             if (((PersistableBusinessObject) lineBusinessObject).isNewCollectionRecord()) {
 826  
                 // new records are never hidden, regardless of active status
 827  0
                 return false;
 828  
 }
 829  0
             if (!((Inactivateable) lineBusinessObject).isActive() && !((Inactivateable) oldLineBusinessObject).isActive()) {
 830  
                 // records with an old and new collection elements of NOT active are eligible to be hidden
 831  0
                 return true;
 832  
             }
 833  
         }
 834  0
         return false;
 835  
     }
 836  
     /**
 837  
      * Determines whether a business object is hidden on a maintenance document.
 838  
      * 
 839  
      * @param lineBusinessObject the BO in the new maintainable, should be of type {@link PersistableBusinessObject}
 840  
      * @param oldLineBusinessObject the corresponding BO in the old maintainable
 841  
      * @param newMaintainable the new maintainable from the maintenace document
 842  
      * @param collectionName the name of the collection from which these BOs come
 843  
      * @return
 844  
      */
 845  
     protected static boolean isRowHiddenForMaintenanceDocument(BusinessObject lineBusinessObject, BusinessObject oldLineBusinessObject,
 846  
             Maintainable newMaintainable, String collectionName) {
 847  0
         return isRowHideableForMaintenanceDocument(lineBusinessObject, oldLineBusinessObject) && !newMaintainable.getShowInactiveRecords(collectionName);
 848  
     }
 849  
     
 850  
     /**
 851  
      * Determines whether a business object is hidable on an inquiry screen.  Hidable means that if the user chose to hide the inactive
 852  
      * elements in the collection in which the passed in BO resides, then the BO would be hidden
 853  
      * 
 854  
      * @param lineBusinessObject the collection element BO, should be of type {@link PersistableBusinessObject} and {@link Inquirable}
 855  
      * @return whether the BO is eligible to be hidden if the user decides to hide them
 856  
      */
 857  
     protected static boolean isRowHideableForInquiry(BusinessObject lineBusinessObject) {
 858  0
         return !((Inactivateable) lineBusinessObject).isActive();
 859  
     }
 860  
     
 861  
     /**
 862  
      * Determines whether a business object is hidden on an inquiry screen.
 863  
      * 
 864  
      * @param lineBusinessObject the BO in the collection, should be of type {@link PersistableBusinessObject} and {@link Inquirable}
 865  
      * @param inquirable the inquirable
 866  
      * @param collectionName the name of the collection from which the BO comes
 867  
      * @return true if the business object is to be hidden; false otherwise
 868  
      */
 869  
     protected static boolean isRowHiddenForInquiry(BusinessObject lineBusinessObject, Inquirable inquirable, String collectionName) {
 870  0
         return isRowHideableForInquiry(lineBusinessObject) && !inquirable.getShowInactiveRecords(collectionName);
 871  
     }
 872  
     
 873  
         public static MaintenanceDocumentDictionaryService getMaintenanceDocumentDictionaryService() {
 874  0
             if (maintenanceDocumentDictionaryService == null) {
 875  0
                     maintenanceDocumentDictionaryService = KNSServiceLocator.getMaintenanceDocumentDictionaryService();
 876  
             }
 877  0
                 return maintenanceDocumentDictionaryService; 
 878  
         }
 879  
 }
 880