Coverage Report - org.kuali.rice.kns.service.impl.MaintenanceDocumentDictionaryServiceImpl
 
Classes in this File Line Coverage Branch Coverage Complexity
MaintenanceDocumentDictionaryServiceImpl
0%
0/328
0%
0/204
4.238
 
 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.service.impl;
 17  
 
 18  
 import java.util.ArrayList;
 19  
 import java.util.Collection;
 20  
 import java.util.Iterator;
 21  
 import java.util.List;
 22  
 
 23  
 import org.apache.commons.lang.StringUtils;
 24  
 import org.kuali.rice.kew.dto.DocumentTypeDTO;
 25  
 import org.kuali.rice.kew.exception.WorkflowException;
 26  
 import org.kuali.rice.kns.bo.PersistableBusinessObject;
 27  
 import org.kuali.rice.kns.datadictionary.DataDictionary;
 28  
 import org.kuali.rice.kns.datadictionary.MaintainableCollectionDefinition;
 29  
 import org.kuali.rice.kns.datadictionary.MaintainableFieldDefinition;
 30  
 import org.kuali.rice.kns.datadictionary.MaintainableItemDefinition;
 31  
 import org.kuali.rice.kns.datadictionary.MaintainableSectionDefinition;
 32  
 import org.kuali.rice.kns.datadictionary.MaintenanceDocumentEntry;
 33  
 import org.kuali.rice.kns.document.MaintenanceDocument;
 34  
 import org.kuali.rice.kns.lookup.valueFinder.ValueFinder;
 35  
 import org.kuali.rice.kns.maintenance.Maintainable;
 36  
 import org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase;
 37  
 import org.kuali.rice.kns.service.DataDictionaryService;
 38  
 import org.kuali.rice.kns.service.KNSServiceLocator;
 39  
 import org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService;
 40  
 import org.kuali.rice.kns.util.GlobalVariables;
 41  
 import org.kuali.rice.kns.util.ObjectUtils;
 42  
 import org.kuali.rice.kns.util.RiceKeyConstants;
 43  
 
 44  
 /**
 45  
  * This class is the service implementation for the MaintenanceDocumentDictionary structure. Defines the API for the interacting
 46  
  * with Document-related entries in the data dictionary. This is the default implementation, that is delivered with Kuali.
 47  
  */
 48  0
 public class MaintenanceDocumentDictionaryServiceImpl implements MaintenanceDocumentDictionaryService {
 49  0
     protected static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(MaintenanceDocumentDictionaryServiceImpl.class);
 50  
 
 51  
     private DataDictionaryService dataDictionaryService;
 52  
 
 53  
     /**
 54  
      * This method gets the workflow document type for the given documentTypeName
 55  
      * 
 56  
      * @param documentTypeName
 57  
      * @return
 58  
      */
 59  
     protected DocumentTypeDTO getDocumentType(String documentTypeName) {
 60  
         try {
 61  0
             return KNSServiceLocator.getWorkflowInfoService().getDocType(documentTypeName);
 62  0
         } catch (WorkflowException e) {
 63  0
             throw new RuntimeException("Caught exception attempting to get document type for doc type name '" + documentTypeName + "'", e);
 64  
         }
 65  
     }
 66  
 
 67  
     /**
 68  
      * @see org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService#getMaintenanceLabel(java.lang.String)
 69  
      */
 70  
     public String getMaintenanceLabel(String docTypeName) {
 71  0
         String label = null;
 72  
 
 73  0
         DocumentTypeDTO docType = getDocumentType(docTypeName);
 74  0
         if (docType != null) {
 75  0
             label = docType.getDocTypeLabel();
 76  
         }
 77  
 
 78  0
         return label;
 79  
     }
 80  
 
 81  
     /**
 82  
      * @see org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService#getMaintenanceDescription(java.lang.String)
 83  
      */
 84  
     public String getMaintenanceDescription(String docTypeName) {
 85  0
         String description = null;
 86  
 
 87  0
         DocumentTypeDTO docType = getDocumentType(docTypeName);
 88  0
         if (docType != null) {
 89  0
             description = docType.getDocTypeDescription();
 90  
         }
 91  
 
 92  0
         return description;
 93  
     }
 94  
 
 95  
     /**
 96  
      * @see org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService#getMaintainableClass(java.lang.String)
 97  
      */
 98  
     public Class getMaintainableClass(String docTypeName) {
 99  0
         Class maintainableClass = null;
 100  
 
 101  0
         MaintenanceDocumentEntry entry = getMaintenanceDocumentEntry(docTypeName);
 102  0
         if (entry != null) {
 103  0
             LOG.debug("suppling a generic Rule to insure basic validation");
 104  0
             maintainableClass = entry.getMaintainableClass();
 105  
         }
 106  
 
 107  0
         return maintainableClass;
 108  
     }
 109  
 
 110  
     /**
 111  
      * @see org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService#getBusinessObjectClass(java.lang.String)
 112  
      */
 113  
     public Class getBusinessObjectClass(String docTypeName) {
 114  0
         Class businessObjectClass = null;
 115  
 
 116  0
         MaintenanceDocumentEntry entry = getMaintenanceDocumentEntry(docTypeName);
 117  0
         if (entry != null) {
 118  0
             businessObjectClass = entry.getBusinessObjectClass();
 119  
         }
 120  
 
 121  0
         return businessObjectClass;
 122  
     }
 123  
 
 124  
     /**
 125  
      * @see org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService#getDocumentTypeName(java.lang.Class)
 126  
      */
 127  
     public String getDocumentTypeName(Class businessObjectClass) {
 128  0
         String documentTypeName = null;
 129  
 
 130  0
         MaintenanceDocumentEntry entry = getMaintenanceDocumentEntry(businessObjectClass);
 131  0
         if (entry != null) {
 132  0
             documentTypeName = entry.getDocumentTypeName();
 133  
         }
 134  
 
 135  0
         return documentTypeName;
 136  
     }
 137  
 
 138  
     /**
 139  
      * @see org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService#getMaintainableSections(java.lang.String)
 140  
      */
 141  
     public List getMaintainableSections(String docTypeName) {
 142  0
         List sections = null;
 143  
 
 144  0
         MaintenanceDocumentEntry entry = getMaintenanceDocumentEntry(docTypeName);
 145  0
         if (entry != null) {
 146  0
             sections = entry.getMaintainableSections();
 147  
         }
 148  
 
 149  0
         return sections;
 150  
     }
 151  
 
 152  
     /**
 153  
      * @see org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService#getBusinessRulesClass(MaintenanceDocument)
 154  
      */
 155  
     public Class getBusinessRulesClass(MaintenanceDocument document) {
 156  0
         Maintainable maintainable = document.getOldMaintainableObject();
 157  0
         if (maintainable == null) {
 158  0
             throw new IllegalArgumentException("unable to determine documentType for maintenanceDocument with no oldMaintainableObject");
 159  
         }
 160  
 
 161  0
         Class businessRulesClass = null;
 162  
 
 163  0
         MaintenanceDocumentEntry entry = getMaintenanceDocumentEntry(maintainable.getBoClass());
 164  0
         if (entry != null) {
 165  0
             businessRulesClass = entry.getBusinessRulesClass();
 166  
         }
 167  
 
 168  0
         if (businessRulesClass == null) {
 169  0
             return MaintenanceDocumentRuleBase.class; // default to a generic rule that will enforce Required fields
 170  
         }
 171  
 
 172  0
         LOG.info("return class: " + businessRulesClass.getName());
 173  
 
 174  0
         return businessRulesClass;
 175  
     }
 176  
 
 177  
     /**
 178  
      * @see org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService#getDefaultExistenceChecks(java.lang.Class)
 179  
      */
 180  
     public Collection getDefaultExistenceChecks(Class businessObjectClass) {
 181  0
         return getDefaultExistenceChecks(getDocumentTypeName(businessObjectClass));
 182  
     }
 183  
 
 184  
     /**
 185  
      * @see org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService#getDefaultExistenceChecks(java.lang.String)
 186  
      */
 187  
     public Collection getDefaultExistenceChecks(String docTypeName) {
 188  
 
 189  0
         Collection defaultExistenceChecks = null;
 190  
 
 191  0
         MaintenanceDocumentEntry entry = getMaintenanceDocumentEntry(docTypeName);
 192  0
         if (entry != null) {
 193  0
             defaultExistenceChecks = entry.getDefaultExistenceChecks();
 194  
         }
 195  
 
 196  0
         return defaultExistenceChecks;
 197  
     }
 198  
 
 199  
     /**
 200  
      * @see org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService#getApplyApcRules(java.lang.Class)
 201  
      */
 202  
     public Collection getApplyApcRules(Class businessObjectClass) {
 203  0
         return getApplyApcRules(getDocumentTypeName(businessObjectClass));
 204  
     }
 205  
 
 206  
     /**
 207  
      * @see org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService#getApplyApcRules(java.lang.String)
 208  
      */
 209  
     public Collection getApplyApcRules(String docTypeName) {
 210  
 
 211  0
         Collection apcRules = null;
 212  
 
 213  0
         MaintenanceDocumentEntry entry = getMaintenanceDocumentEntry(docTypeName);
 214  0
         if (entry != null) {
 215  0
             apcRules = entry.getApcRules();
 216  
         }
 217  
 
 218  0
         return apcRules;
 219  
     }
 220  
 
 221  
     /**
 222  
      * @see org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService#getLockingKeys(java.lang.String)
 223  
      */
 224  
     public List getLockingKeys(String docTypeName) {
 225  0
         List lockingKeys = null;
 226  
 
 227  0
         MaintenanceDocumentEntry entry = getMaintenanceDocumentEntry(docTypeName);
 228  0
         if (entry != null) {
 229  0
             lockingKeys = entry.getLockingKeyFieldNames();
 230  
         }
 231  
 
 232  0
         return lockingKeys;
 233  
     }
 234  
 
 235  
     /**
 236  
      * @param dataDictionaryService
 237  
      */
 238  
     public void setDataDictionaryService(DataDictionaryService dataDictionaryService) {
 239  0
         this.dataDictionaryService = dataDictionaryService;
 240  0
     }
 241  
 
 242  
     /**
 243  
      * @return
 244  
      */
 245  
     public DataDictionary getDataDictionary() {
 246  0
         return this.dataDictionaryService.getDataDictionary();
 247  
     }
 248  
 
 249  
     /**
 250  
      * @param docTypeName
 251  
      * @return
 252  
      */
 253  
     public MaintenanceDocumentEntry getMaintenanceDocumentEntry(String docTypeName) {
 254  0
         if (StringUtils.isBlank(docTypeName)) {
 255  0
             throw new IllegalArgumentException("invalid (blank) docTypeName");
 256  
         }
 257  
 
 258  0
         MaintenanceDocumentEntry entry = (MaintenanceDocumentEntry)getDataDictionary().getDocumentEntry(docTypeName);
 259  0
         return entry;
 260  
     }
 261  
 
 262  
     private MaintenanceDocumentEntry getMaintenanceDocumentEntry(Class businessObjectClass) {
 263  0
         if (businessObjectClass == null) {
 264  0
             throw new IllegalArgumentException("invalid (blank) businessObjectClass");
 265  
         }
 266  
 
 267  0
         MaintenanceDocumentEntry entry = getDataDictionary().getMaintenanceDocumentEntryForBusinessObjectClass(businessObjectClass);
 268  0
         return entry;
 269  
     }
 270  
 
 271  
     /**
 272  
      * @see org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService#getFieldDefaultValue(java.lang.Class, java.lang.String)
 273  
      */
 274  
     public String getFieldDefaultValue(Class boClass, String fieldName) {
 275  
 
 276  
         // input parameter validation
 277  0
         if (boClass == null) {
 278  0
             throw new IllegalArgumentException("The boClass parameter value specified was " + "null.  A valid class representing the boClass must " + "be specified.");
 279  
         }
 280  
 
 281  
         // call the twin
 282  0
         return getFieldDefaultValue(getDocumentTypeName(boClass), fieldName);
 283  
     }
 284  
 
 285  
     /**
 286  
      * @see org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService#getFieldDefaultValue(java.lang.String, java.lang.String)
 287  
      */
 288  
     public String getFieldDefaultValue(String docTypeName, String fieldName) {
 289  
 
 290  
         // input parameter validation
 291  0
         if (StringUtils.isBlank(docTypeName)) {
 292  0
             throw new IllegalArgumentException("The docTypeName parameter value specified was  " + "blank, whitespace, or null.  A valid string representing the docTypeName must " + "be specified.");
 293  
         }
 294  0
         if (StringUtils.isBlank(fieldName)) {
 295  0
             throw new IllegalArgumentException("The fieldName parameter value specified was  " + "blank, whitespace, or null.  A valid string representing the fieldName must " + "be specified.");
 296  
         }
 297  
 
 298  
         // walk through the sections
 299  0
         List sections = getMaintainableSections(docTypeName);
 300  0
         for (Iterator sectionIterator = sections.iterator(); sectionIterator.hasNext();) {
 301  0
             MaintainableSectionDefinition section = (MaintainableSectionDefinition) sectionIterator.next();
 302  
 
 303  
             // walk through the fields
 304  0
             Collection fields = section.getMaintainableItems();
 305  0
             String defaultValue = getFieldDefaultValue(fields, fieldName);
 306  
             // need to keep trying sections until a match is found
 307  0
             if (defaultValue != null) {
 308  0
                 return defaultValue;
 309  
             }
 310  0
         }
 311  0
         return null;
 312  
     }
 313  
 
 314  
     private String getFieldDefaultValue(Collection maintainableFields, String fieldName) {
 315  0
         for (Iterator iterator = maintainableFields.iterator(); iterator.hasNext();) {
 316  0
             MaintainableItemDefinition item = (MaintainableItemDefinition) iterator.next();
 317  
             // only check fields...skip subcollections
 318  0
             if (item instanceof MaintainableFieldDefinition) {
 319  
 
 320  0
                 MaintainableFieldDefinition field = (MaintainableFieldDefinition) item;
 321  
 
 322  
                 // if the field name matches
 323  0
                 if (field.getName().endsWith(fieldName)) {
 324  
 
 325  
                     // preferentially take the raw default value
 326  0
                     if (StringUtils.isNotBlank(field.getDefaultValue())) {
 327  0
                         return field.getDefaultValue();
 328  
                     }
 329  
 
 330  
                     // take the valuefinder
 331  0
                     else if (field.getDefaultValueFinderClass() != null) {
 332  
 
 333  
                         // attempt to get an instance of the defaultValueFinderClass
 334  0
                         ValueFinder valueFinder = null;
 335  
                         try {
 336  0
                             valueFinder = (ValueFinder) field.getDefaultValueFinderClass().newInstance();
 337  
                         }
 338  0
                         catch (Exception e) {
 339  0
                             LOG.info("Exception obtaining valueFinder for collection field default value", e);
 340  0
                             valueFinder = null;
 341  0
                         }
 342  
 
 343  
                         // get the value
 344  0
                         if (valueFinder != null) {
 345  0
                             return valueFinder.getValue();
 346  
                         }
 347  0
                     }
 348  
                     // if we found the field, but no default anything, then we're done
 349  
                     else {
 350  0
                         return null;
 351  
                     }
 352  
                 }
 353  
             }
 354  0
         }
 355  0
         return null;
 356  
     }
 357  
 
 358  
     /**
 359  
      * @see org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService#getCollectionFieldDefaultValue(java.lang.String,
 360  
      *      java.lang.String, java.lang.String)
 361  
      */
 362  
     public String getCollectionFieldDefaultValue(String docTypeName, String collectionName, String fieldName) {
 363  
         // input parameter validation
 364  0
         if (StringUtils.isBlank(docTypeName)) {
 365  0
             throw new IllegalArgumentException("The docTypeName parameter value specified was blank, whitespace, or null.  A valid string representing the docTypeName must be specified.");
 366  
         }
 367  0
         if (StringUtils.isBlank(fieldName)) {
 368  0
             throw new IllegalArgumentException("The fieldName parameter value specified was blank, whitespace, or null.  A valid string representing the fieldName must be specified.");
 369  
         }
 370  0
         if (StringUtils.isBlank(collectionName)) {
 371  0
             throw new IllegalArgumentException("The collectionName parameter value specified was null.  A valid string representing the collectionName must be specified.");
 372  
         }
 373  
 
 374  0
         MaintainableCollectionDefinition coll = getMaintainableCollection(docTypeName, collectionName);
 375  0
         if (coll != null) {
 376  0
             Collection collectionFields = coll.getMaintainableFields();
 377  0
             return getFieldDefaultValue(collectionFields, fieldName);
 378  
         }
 379  0
         return null;
 380  
     }
 381  
 
 382  
     /**
 383  
      * @see org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService#getAllowsCopy(MaintenanceDocument)
 384  
      */
 385  
     public Boolean getAllowsCopy(MaintenanceDocument document) {
 386  0
         Boolean allowsCopy = Boolean.FALSE;
 387  0
         if (document != null && document.getNewMaintainableObject() != null) {
 388  0
             MaintenanceDocumentEntry entry = getMaintenanceDocumentEntry(document.getNewMaintainableObject().getBoClass());
 389  0
             if (entry != null) {
 390  0
                 allowsCopy = Boolean.valueOf(entry.getAllowsCopy());
 391  
             }
 392  
         }
 393  
 
 394  0
         return allowsCopy;
 395  
     }
 396  
 
 397  
     /**
 398  
      * @see org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService#getAllowsNewOrCopy(java.lang.String)
 399  
      */
 400  
     public Boolean getAllowsNewOrCopy(String docTypeName) {
 401  0
         Boolean allowsNewOrCopy = Boolean.FALSE;
 402  
 
 403  0
         if (docTypeName != null) {
 404  0
             MaintenanceDocumentEntry entry = getMaintenanceDocumentEntry(docTypeName);
 405  0
             if (entry != null) {
 406  0
                 allowsNewOrCopy = Boolean.valueOf(entry.getAllowsNewOrCopy());
 407  
             }
 408  
         }
 409  
 
 410  0
         return allowsNewOrCopy;
 411  
     }
 412  
 
 413  
     public MaintainableItemDefinition getMaintainableItem(String docTypeName, String itemName) {
 414  
         // input parameter validation
 415  0
         if (StringUtils.isBlank(docTypeName)) {
 416  0
             throw new IllegalArgumentException("The docTypeName parameter value specified was  " + "blank, whitespace, or null.  A valid string representing the docTypeName must " + "be specified.");
 417  
         }
 418  0
         if (StringUtils.isBlank(itemName)) {
 419  0
             throw new IllegalArgumentException("The itemName parameter value specified was  " + "blank, whitespace, or null.  A valid string representing the itemName must " + "be specified.");
 420  
         }
 421  
 
 422  
         // split name for subcollections
 423  0
         String[] subItems = {};
 424  0
         subItems = StringUtils.split(itemName, ".");
 425  
 
 426  
 
 427  
         // walk through the sections
 428  0
         List sections = getMaintainableSections(docTypeName);
 429  0
         for (Iterator sectionIterator = sections.iterator(); sectionIterator.hasNext();) {
 430  0
             MaintainableSectionDefinition section = (MaintainableSectionDefinition) sectionIterator.next();
 431  
 
 432  
             // walk through the fields
 433  0
             Collection fields = section.getMaintainableItems();
 434  0
             for (Iterator fieldIterator = fields.iterator(); fieldIterator.hasNext();) {
 435  0
                 MaintainableItemDefinition item = (MaintainableItemDefinition) fieldIterator.next();
 436  
 
 437  0
                 if (item.getName().equals(itemName)) {
 438  0
                     return item;
 439  
                 }
 440  
                 // if collection check to see if it has sub collections
 441  
                 // for now this only allows 1 level (i.e. a.b) it should be expanded at some point
 442  0
                 if (item instanceof MaintainableCollectionDefinition) {
 443  0
                     MaintainableCollectionDefinition col = (MaintainableCollectionDefinition) item;
 444  0
                     if ((subItems.length > 1) && (StringUtils.equals(col.getName(), subItems[0]))) {
 445  0
                         for (Iterator<MaintainableCollectionDefinition> colIterator = col.getMaintainableCollections().iterator(); colIterator.hasNext();) {
 446  0
                             MaintainableCollectionDefinition subCol = (MaintainableCollectionDefinition) colIterator.next();
 447  0
                             if (subCol.getName().equals(subItems[1])) {
 448  0
                                 return subCol;
 449  
                             }
 450  0
                         }
 451  
                     }
 452  
                 }
 453  0
             }
 454  0
         }
 455  0
         return null;
 456  
     }
 457  
 
 458  
     public MaintainableFieldDefinition getMaintainableField(String docTypeName, String fieldName) {
 459  0
         MaintainableItemDefinition item = getMaintainableItem(docTypeName, fieldName);
 460  0
         if (item != null && item instanceof MaintainableFieldDefinition) {
 461  0
             return (MaintainableFieldDefinition) item;
 462  
         }
 463  0
         return null;
 464  
     }
 465  
 
 466  
     public MaintainableCollectionDefinition getMaintainableCollection(String docTypeName, String collectionName) {
 467  
         // strip brackets as they are not needed to get to collection class
 468  
         // Like the other subcollections changes this currently only supports one sub level
 469  0
         if (StringUtils.contains(collectionName, "[")) {
 470  0
             collectionName = StringUtils.substringBefore(collectionName, "[") + StringUtils.substringAfter(collectionName, "]");
 471  
         }
 472  0
         MaintainableItemDefinition item = getMaintainableItem(docTypeName, collectionName);
 473  0
         if (item != null && item instanceof MaintainableCollectionDefinition) {
 474  0
             return (MaintainableCollectionDefinition) item;
 475  
         }
 476  0
         return null;
 477  
     }
 478  
 
 479  
     public Class getCollectionBusinessObjectClass(String docTypeName, String collectionName) {
 480  0
         MaintainableCollectionDefinition coll = getMaintainableCollection(docTypeName, collectionName);
 481  0
         if (coll != null) {
 482  0
             return coll.getBusinessObjectClass();
 483  
         }
 484  0
         return null;
 485  
     }
 486  
 
 487  
     public List<MaintainableCollectionDefinition> getMaintainableCollections(String docTypeName) {
 488  0
         ArrayList<MaintainableCollectionDefinition> collections = new ArrayList<MaintainableCollectionDefinition>();
 489  
 
 490  
         // walk through the sections
 491  0
         List sections = getMaintainableSections(docTypeName);
 492  0
         for (Iterator sectionIterator = sections.iterator(); sectionIterator.hasNext();) {
 493  0
             MaintainableSectionDefinition section = (MaintainableSectionDefinition) sectionIterator.next();
 494  
 
 495  
             // walk through the fields
 496  0
             Collection fields = section.getMaintainableItems();
 497  0
             for (Iterator fieldIterator = fields.iterator(); fieldIterator.hasNext();) {
 498  0
                 MaintainableItemDefinition item = (MaintainableItemDefinition) fieldIterator.next();
 499  
 
 500  0
                 if (item instanceof MaintainableCollectionDefinition) {
 501  0
                     collections.add((MaintainableCollectionDefinition) item);
 502  
                     // collections.addAll( getMaintainableCollections( (MaintainableCollectionDefinition)item ) );
 503  
                 }
 504  0
             }
 505  0
         }
 506  
 
 507  0
         return collections;
 508  
     }
 509  
 
 510  
     public List<MaintainableCollectionDefinition> getMaintainableCollections(MaintainableCollectionDefinition parentCollection) {
 511  0
         ArrayList<MaintainableCollectionDefinition> collections = new ArrayList<MaintainableCollectionDefinition>();
 512  
 
 513  
         // walk through the sections
 514  0
         Collection<MaintainableCollectionDefinition> colls = parentCollection.getMaintainableCollections();
 515  0
         for (MaintainableCollectionDefinition coll : colls) {
 516  0
             collections.add(coll);
 517  0
             collections.addAll(getMaintainableCollections(coll));
 518  
         }
 519  
 
 520  0
         return collections;
 521  
     }
 522  
 
 523  
     /**
 524  
      * @see org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService#validateMaintenanceRequiredFields(org.kuali.rice.kns.document.MaintenanceDocument)
 525  
      */
 526  
     public void validateMaintenanceRequiredFields(MaintenanceDocument document) {
 527  0
         Maintainable newMaintainableObject = document.getNewMaintainableObject();
 528  0
         if (newMaintainableObject == null) {
 529  0
             LOG.error("New maintainable is null");
 530  0
             throw new RuntimeException("New maintainable is null");
 531  
         }
 532  
 
 533  0
         List<MaintainableSectionDefinition> maintainableSectionDefinitions = getMaintainableSections(getDocumentTypeName(newMaintainableObject.getBoClass()));
 534  0
         for (MaintainableSectionDefinition maintainableSectionDefinition : maintainableSectionDefinitions) {
 535  0
             for (MaintainableItemDefinition maintainableItemDefinition : maintainableSectionDefinition.getMaintainableItems()) {
 536  
                 // validate fields
 537  0
                 if (maintainableItemDefinition instanceof MaintainableFieldDefinition) {
 538  0
                     validateMaintainableFieldRequiredFields((MaintainableFieldDefinition) maintainableItemDefinition, newMaintainableObject.getBusinessObject(), maintainableItemDefinition.getName());
 539  
                 }
 540  
                 // validate collections
 541  0
                 else if (maintainableItemDefinition instanceof MaintainableCollectionDefinition) {
 542  0
                     validateMaintainableCollectionsRequiredFields(newMaintainableObject.getBusinessObject(), (MaintainableCollectionDefinition) maintainableItemDefinition);
 543  
                 }
 544  
             }
 545  
         }
 546  0
     }
 547  
 
 548  
     /**
 549  
      * generates error message if a field is marked as required but is not filled in
 550  
      * 
 551  
      * @param maintainableFieldDefinition
 552  
      * @param businessObject
 553  
      * @param fieldName
 554  
      */
 555  
     private void validateMaintainableFieldRequiredFields(MaintainableFieldDefinition maintainableFieldDefinition, PersistableBusinessObject businessObject, String fieldName) {
 556  
 
 557  0
         if (StringUtils.isBlank(fieldName)) {
 558  0
             throw new IllegalArgumentException("invalid fieldName parameter.");
 559  
         }
 560  
         // if required check we have a value for this field
 561  0
         if (maintainableFieldDefinition.isRequired() && !maintainableFieldDefinition.isUnconditionallyReadOnly() ) {
 562  
             try {
 563  0
                 Object obj = ObjectUtils.getNestedValue(businessObject, fieldName);
 564  
 
 565  0
                 if (obj == null || StringUtils.isBlank(obj.toString())) {
 566  0
                     String attributeLabel = dataDictionaryService.getAttributeLabel(businessObject.getClass(), fieldName);
 567  0
                     String shortLabel = dataDictionaryService.getAttributeShortLabel(businessObject.getClass(), fieldName);
 568  0
                     GlobalVariables.getMessageMap().putError(fieldName, RiceKeyConstants.ERROR_REQUIRED, attributeLabel + " (" + shortLabel + ")" );
 569  0
                 } else if ( fieldName.endsWith(".principalName") ) {
 570  
                     // special handling to catch when the principalName is not really a valid user
 571  
                     // pull the Person object and test the entity ID.  If that's null, then this
 572  
                     // is just a shell user instance and does not represent a true user
 573  
                     // the main principalId property on the main object would be null at this point
 574  
                     // but it is also unconditionally read only and not tested - checking that would
 575  
                     // require checking the relationships and be more complex than we want to get here
 576  0
                     String personProperty = ObjectUtils.getNestedAttributePrefix(fieldName); 
 577  0
                     if ( StringUtils.isNotBlank(personProperty) ) {
 578  0
                         if ( StringUtils.isBlank( (String)ObjectUtils.getNestedValue(businessObject, personProperty+".entityId") ) ) {
 579  0
                             String attributeLabel = dataDictionaryService.getAttributeLabel(businessObject.getClass(), fieldName);
 580  0
                             GlobalVariables.getMessageMap().putError(fieldName, RiceKeyConstants.ERROR_EXISTENCE, attributeLabel );
 581  
                         }
 582  
                     }
 583  
                 }
 584  0
             } catch( Exception ex ) {
 585  0
                 LOG.error( "unable to read property during doc required field checks", ex );
 586  0
             }
 587  
         }
 588  0
     }
 589  
 
 590  
     
 591  
     private MaintainableCollectionDefinition getCollectionDefinition( String docTypeName, String collectionName ) {
 592  0
         String currentCollection = collectionName;
 593  0
         String nestedCollections = "";
 594  0
             if (StringUtils.contains(collectionName, "[")) {
 595  
                     // strip off any array indexes
 596  0
             currentCollection = StringUtils.substringBefore( collectionName, "[" );
 597  0
             nestedCollections = StringUtils.substringAfter( collectionName, "." );
 598  
             }
 599  
             
 600  
         // loop over all sections to find this collection
 601  0
         List<MaintainableSectionDefinition> maintainableSectionDefinitions = getMaintainableSections( docTypeName );
 602  0
         for (MaintainableSectionDefinition maintainableSectionDefinition : maintainableSectionDefinitions) {
 603  0
             for (MaintainableItemDefinition maintainableItemDefinition : maintainableSectionDefinition.getMaintainableItems()) {
 604  0
                 if (maintainableItemDefinition instanceof MaintainableCollectionDefinition && maintainableItemDefinition.getName().equals( currentCollection ) ) {
 605  0
                     if ( StringUtils.isBlank( nestedCollections ) ) {
 606  0
                         return (MaintainableCollectionDefinition) maintainableItemDefinition;
 607  
                     } 
 608  
                     
 609  0
                     return getCollectionDefinition( (MaintainableCollectionDefinition)maintainableItemDefinition, nestedCollections );
 610  
                 }
 611  
             }
 612  
         }
 613  
         
 614  0
         return null;
 615  
     }
 616  
 
 617  
     private MaintainableCollectionDefinition getCollectionDefinition( MaintainableCollectionDefinition collectionDef, String collectionName ) {
 618  0
         String currentCollection = collectionName;
 619  0
         String nestedCollections = "";
 620  0
             if (StringUtils.contains(collectionName, "[")) {
 621  
                     // strip off any array indexes
 622  0
             currentCollection = StringUtils.substringBefore( collectionName, "[" );
 623  0
             nestedCollections = StringUtils.substringAfter( collectionName, "." );
 624  
             }
 625  
         
 626  
         // loop over all nested collections
 627  0
         for (MaintainableCollectionDefinition maintainableCollectionDefinition : collectionDef.getMaintainableCollections()) {
 628  0
             if ( maintainableCollectionDefinition.getName().equals( currentCollection ) ) {
 629  0
                 if ( StringUtils.isBlank( nestedCollections ) ) {
 630  0
                     return maintainableCollectionDefinition;
 631  
                 } 
 632  0
                 return getCollectionDefinition( maintainableCollectionDefinition, nestedCollections );
 633  
             }
 634  
         }
 635  
         
 636  0
         return null;
 637  
     }
 638  
     
 639  
     public void validateMaintainableCollectionsAddLineRequiredFields(MaintenanceDocument document, PersistableBusinessObject businessObject, String collectionName ) {
 640  0
         MaintainableCollectionDefinition def = getCollectionDefinition( getDocumentTypeName(businessObject.getClass()), collectionName );
 641  0
         if ( def != null ) {
 642  0
             validateMaintainableCollectionsAddLineRequiredFields( document, businessObject, collectionName, def, 0);
 643  
         }
 644  0
     }
 645  
     /**
 646  
      * calls code to generate error messages if maintainableFields within any collections or sub-collections are marked as required
 647  
      * 
 648  
      * @param document
 649  
      * @param businessObject
 650  
      * @param collectionName
 651  
      * @param maintainableCollectionDefinition
 652  
      * @param depth
 653  
      */
 654  
     private void validateMaintainableCollectionsAddLineRequiredFields(MaintenanceDocument document, PersistableBusinessObject businessObject, String collectionName, MaintainableCollectionDefinition maintainableCollectionDefinition, int depth) {
 655  0
         if ( depth == 0 ) {
 656  0
             GlobalVariables.getMessageMap().addToErrorPath("add");
 657  
         }
 658  
         // validate required fields on fields withing collection definition
 659  0
         PersistableBusinessObject element = document.getNewMaintainableObject().getNewCollectionLine( collectionName );
 660  0
         GlobalVariables.getMessageMap().addToErrorPath(collectionName);
 661  0
         for (MaintainableFieldDefinition maintainableFieldDefinition : maintainableCollectionDefinition.getMaintainableFields()) {
 662  0
             final String fieldName = maintainableFieldDefinition.getName();
 663  0
             validateMaintainableFieldRequiredFields(maintainableFieldDefinition, element, fieldName);
 664  
             
 665  0
         }
 666  
 
 667  0
         GlobalVariables.getMessageMap().removeFromErrorPath(collectionName);
 668  0
         if ( depth == 0 ) {
 669  0
             GlobalVariables.getMessageMap().removeFromErrorPath("add");
 670  
         }
 671  0
     }
 672  
 
 673  
     /**
 674  
      * calls code to generate error messages if maintainableFields within any collections or sub-collections are marked as required
 675  
      * 
 676  
      * @param businessObject
 677  
      * @param maintainableCollectionDefinition
 678  
      */
 679  
     private void validateMaintainableCollectionsRequiredFields(PersistableBusinessObject businessObject, MaintainableCollectionDefinition maintainableCollectionDefinition) {
 680  0
         final String collectionName = maintainableCollectionDefinition.getName();
 681  
 
 682  
         // validate required fields on fields withing collection definition
 683  0
         Collection<PersistableBusinessObject> collection = (Collection) ObjectUtils.getPropertyValue(businessObject, collectionName);
 684  0
         if (collection != null && !collection.isEmpty()) {
 685  0
             for (MaintainableFieldDefinition maintainableFieldDefinition : maintainableCollectionDefinition.getMaintainableFields()) {
 686  0
                 int pos = 0;
 687  0
                 final String fieldName = maintainableFieldDefinition.getName();
 688  0
                 for (PersistableBusinessObject element : collection) {
 689  0
                     String parentName = collectionName + "[" + (pos++) + "]";
 690  0
                     GlobalVariables.getMessageMap().addToErrorPath(parentName);
 691  0
                     validateMaintainableFieldRequiredFields(maintainableFieldDefinition, element, fieldName);
 692  0
                     GlobalVariables.getMessageMap().removeFromErrorPath(parentName);
 693  0
                 }
 694  0
             }
 695  
 
 696  
             // recursivley validate required fields on subcollections
 697  0
             GlobalVariables.getMessageMap().addToErrorPath(collectionName);
 698  0
             for (MaintainableCollectionDefinition nestedMaintainableCollectionDefinition : maintainableCollectionDefinition.getMaintainableCollections()) {
 699  0
                 for (PersistableBusinessObject element : collection) {
 700  0
                     validateMaintainableCollectionsRequiredFields(element, nestedMaintainableCollectionDefinition);
 701  
                 }
 702  
             }
 703  0
             GlobalVariables.getMessageMap().removeFromErrorPath(collectionName);
 704  
         }
 705  0
     }
 706  
     
 707  
     /**
 708  
      * default implementation checks for duplicats based on keys of objects only
 709  
      * 
 710  
      * @see org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService#validateMaintainableCollectionsForDuplicateEntries(org.kuali.rice.kns.document.MaintenanceDocument)
 711  
      */
 712  
     public void validateMaintainableCollectionsForDuplicateEntries(MaintenanceDocument document) {
 713  0
         Maintainable newMaintainableObject = document.getNewMaintainableObject();
 714  0
         if (newMaintainableObject == null) {
 715  0
             LOG.error("New maintainable is null");
 716  0
             throw new RuntimeException("New maintainable is null");
 717  
         }
 718  
 
 719  0
         List<MaintainableSectionDefinition> maintainableSectionDefinitions = getMaintainableSections(getDocumentTypeName(newMaintainableObject.getBoClass()));
 720  0
         for (MaintainableSectionDefinition maintainableSectionDefinition : maintainableSectionDefinitions) {
 721  0
             for (MaintainableItemDefinition maintainableItemDefinition : maintainableSectionDefinition.getMaintainableItems()) {
 722  
                 // validate collections
 723  0
                 if (maintainableItemDefinition instanceof MaintainableCollectionDefinition) {
 724  0
                     validateMaintainableCollectionsForDuplicateEntries(newMaintainableObject.getBusinessObject(), (MaintainableCollectionDefinition) maintainableItemDefinition);
 725  
                 }
 726  
             }
 727  
         }
 728  0
     }
 729  
 
 730  
     /**
 731  
      * recursivly checks collections for duplicate entries based on key valuse
 732  
      * 
 733  
      * @param businessObject
 734  
      * @param maintainableCollectionDefinition
 735  
      */
 736  
     private void validateMaintainableCollectionsForDuplicateEntries(PersistableBusinessObject businessObject, MaintainableCollectionDefinition maintainableCollectionDefinition) {
 737  0
         final String collectionName = maintainableCollectionDefinition.getName();
 738  
 
 739  0
         if (maintainableCollectionDefinition.dissallowDuplicateKey()) {
 740  0
             final Class maintainableBusinessObjectClass = businessObject.getClass();
 741  
             // validate that no duplicates based on keys exist
 742  0
             Collection<PersistableBusinessObject> collection = (Collection) ObjectUtils.getPropertyValue(businessObject, collectionName);
 743  0
             if (collection != null && !collection.isEmpty()) {
 744  0
                 final String propertyName = maintainableCollectionDefinition.getAttributeToHighlightOnDuplicateKey();
 745  
                 // get collection label for dd
 746  0
                 final String label = dataDictionaryService.getCollectionLabel(maintainableBusinessObjectClass, collectionName);
 747  0
                 final String shortLabel = dataDictionaryService.getCollectionShortLabel(maintainableBusinessObjectClass, collectionName);
 748  0
                 int pos = 0;
 749  0
                 for (PersistableBusinessObject element : collection) {
 750  0
                     String pathToElement = collectionName + "[" + (pos++) + "]";
 751  0
                     if (ObjectUtils.countObjectsWithIdentitcalKey(collection, element) > 1) {
 752  0
                         GlobalVariables.getMessageMap().addToErrorPath(pathToElement);
 753  0
                         GlobalVariables.getMessageMap().putError(propertyName, RiceKeyConstants.ERROR_DUPLICATE_ELEMENT, new String[] { label, shortLabel });
 754  0
                         GlobalVariables.getMessageMap().removeFromErrorPath(pathToElement);
 755  
                     }
 756  0
                 }
 757  
 
 758  
                 // recursivley check for duplicate entries on subcollections
 759  0
                 GlobalVariables.getMessageMap().addToErrorPath(collectionName);
 760  0
                 for (MaintainableCollectionDefinition nestedMaintainableCollectionDefinition : maintainableCollectionDefinition.getMaintainableCollections()) {
 761  0
                     for (PersistableBusinessObject element : collection) {
 762  0
                         validateMaintainableCollectionsForDuplicateEntries(element, nestedMaintainableCollectionDefinition);
 763  
                     }
 764  
                 }
 765  0
                 GlobalVariables.getMessageMap().removeFromErrorPath(collectionName);
 766  
 
 767  
             }
 768  
         }
 769  0
     }
 770  
        
 771  
         /**
 772  
          * for issue KULRice 3072
 773  
          * 
 774  
          * @see org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService#getgetPreserveLockingKeysOnCopy(java.lang.Class)
 775  
          */
 776  
         public boolean getPreserveLockingKeysOnCopy(Class businessObjectClass) {
 777  
 
 778  0
                 boolean preserveLockingKeysOnCopy = false;
 779  
 
 780  0
                 MaintenanceDocumentEntry docEntry = getMaintenanceDocumentEntry(businessObjectClass);
 781  
                 
 782  0
                 if (docEntry != null) {
 783  0
                         preserveLockingKeysOnCopy = docEntry.getPreserveLockingKeysOnCopy();
 784  
                 }
 785  
                 
 786  0
                 return preserveLockingKeysOnCopy;
 787  
         }
 788  
 
 789  
         /**
 790  
          * for isue KULRice 3070
 791  
          * 
 792  
          * @see org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService#getAllowsRecordDeletion(java.lang.Class)
 793  
          */
 794  
         public Boolean getAllowsRecordDeletion(Class businessObjectClass) {
 795  
                 
 796  0
                 Boolean allowsRecordDeletion = Boolean.FALSE;
 797  
 
 798  0
                 MaintenanceDocumentEntry docEntry = getMaintenanceDocumentEntry(businessObjectClass);
 799  
                 
 800  0
                 if (docEntry != null) {
 801  0
                         allowsRecordDeletion = Boolean.valueOf(docEntry.getAllowsRecordDeletion());
 802  
                 }
 803  
                 
 804  0
                 return allowsRecordDeletion;
 805  
         }
 806  
 
 807  
         /**
 808  
          *  for issue KULRice3070, see if need delete button
 809  
          * 
 810  
          * @see org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService#getAllowsRecordDeletion(org.kuali.rice.kns.document.MaintenanceDocument)
 811  
          */
 812  
         public Boolean getAllowsRecordDeletion(MaintenanceDocument document) {
 813  0
         return document != null ? this.getAllowsRecordDeletion(document.getNewMaintainableObject().getBoClass()) : Boolean.FALSE;
 814  
         }
 815  
 
 816  
         /**
 817  
          * @see org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService#translateCodes(java.lang.Class)
 818  
          */
 819  
         public Boolean translateCodes(Class businessObjectClass) {
 820  0
                 boolean translateCodes = false;
 821  
 
 822  0
                 MaintenanceDocumentEntry docEntry = getMaintenanceDocumentEntry(businessObjectClass);
 823  
 
 824  0
                 if (docEntry != null) {
 825  0
                         translateCodes = docEntry.isTranslateCodes();
 826  
                 }
 827  
 
 828  0
                 return translateCodes;
 829  
         }
 830  
 
 831  
 }