001/** 002 * Copyright 2005-2016 The Kuali Foundation 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.kuali.rice.kns.service.impl; 017 018import org.apache.commons.lang.StringUtils; 019import org.kuali.rice.core.api.util.RiceKeyConstants; 020import org.kuali.rice.kew.api.KewApiServiceLocator; 021import org.kuali.rice.kew.api.doctype.DocumentType; 022import org.kuali.rice.kns.datadictionary.MaintainableCollectionDefinition; 023import org.kuali.rice.kns.datadictionary.MaintainableFieldDefinition; 024import org.kuali.rice.kns.datadictionary.MaintainableItemDefinition; 025import org.kuali.rice.kns.datadictionary.MaintainableSectionDefinition; 026import org.kuali.rice.kns.datadictionary.MaintenanceDocumentEntry; 027import org.kuali.rice.kns.document.MaintenanceDocument; 028import org.kuali.rice.kns.maintenance.Maintainable; 029import org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase; 030import org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService; 031import org.kuali.rice.krad.bo.PersistableBusinessObject; 032import org.kuali.rice.krad.datadictionary.DataDictionary; 033import org.kuali.rice.krad.rules.rule.BusinessRule; 034import org.kuali.rice.krad.service.DataDictionaryService; 035import org.kuali.rice.krad.util.GlobalVariables; 036import org.kuali.rice.krad.util.ObjectUtils; 037import org.kuali.rice.krad.valuefinder.ValueFinder; 038 039import java.util.ArrayList; 040import java.util.Collection; 041import java.util.Iterator; 042import java.util.List; 043 044/** 045 * This class is the service implementation for the MaintenanceDocumentDictionary structure. Defines the API for the interacting 046 * with Document-related entries in the data dictionary. This is the default implementation, that is delivered with Kuali. 047 */ 048@Deprecated 049public class MaintenanceDocumentDictionaryServiceImpl implements MaintenanceDocumentDictionaryService { 050 protected static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(MaintenanceDocumentDictionaryServiceImpl.class); 051 052 private DataDictionaryService dataDictionaryService; 053 054 /** 055 * Gets the workflow document type for the given documentTypeName 056 * 057 * @param documentTypeName 058 * @return 059 */ 060 protected DocumentType getDocumentType(String documentTypeName) { 061 return KewApiServiceLocator.getDocumentTypeService().getDocumentTypeByName(documentTypeName); 062 } 063 064 /** 065 * @see org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService#getMaintenanceLabel(java.lang.String) 066 */ 067 public String getMaintenanceLabel(String docTypeName) { 068 String label = null; 069 070 DocumentType docType = getDocumentType(docTypeName); 071 if (docType != null) { 072 label = docType.getLabel(); 073 } 074 075 return label; 076 } 077 078 /** 079 * @see org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService#getMaintenanceDescription(java.lang.String) 080 */ 081 public String getMaintenanceDescription(String docTypeName) { 082 String description = null; 083 084 DocumentType docType = getDocumentType(docTypeName); 085 if (docType != null) { 086 description = docType.getDescription(); 087 } 088 089 return description; 090 } 091 092 /** 093 * @see org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService#getMaintainableClass(java.lang.String) 094 */ 095 @Deprecated 096 public Class getMaintainableClass(String docTypeName) { 097 Class maintainableClass = null; 098 099 MaintenanceDocumentEntry entry = getMaintenanceDocumentEntry(docTypeName); 100 if (entry != null) { 101 LOG.debug("suppling a generic Rule to insure basic validation"); 102 maintainableClass = entry.getMaintainableClass(); 103 } 104 105 return maintainableClass; 106 } 107 108 /** 109 * @see org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService#getDataObjectClass(java.lang.String) 110 */ 111 public Class getDataObjectClass(String docTypeName) { 112 Class dataObjectClass = null; 113 114 MaintenanceDocumentEntry entry = getMaintenanceDocumentEntry(docTypeName); 115 if (entry != null) { 116 dataObjectClass = entry.getDataObjectClass(); 117 } 118 119 return dataObjectClass; 120 } 121 122 /** 123 * @see org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService#getDocumentTypeName(java.lang.Class) 124 */ 125 public String getDocumentTypeName(Class businessObjectClass) { 126 String documentTypeName = null; 127 128 MaintenanceDocumentEntry entry = getMaintenanceDocumentEntry(businessObjectClass); 129 if (entry != null) { 130 documentTypeName = entry.getDocumentTypeName(); 131 } 132 133 return documentTypeName; 134 } 135 136 /** 137 * @see org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService#getMaintainableSections(java.lang.String) 138 */ 139 @Deprecated 140 public List getMaintainableSections(String docTypeName) { 141 List sections = null; 142 143 MaintenanceDocumentEntry entry = getMaintenanceDocumentEntry(docTypeName); 144 if (entry != null) { 145 sections = entry.getMaintainableSections(); 146 } 147 148 return sections; 149 } 150 151 152 /** 153 * @see org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService#getDefaultExistenceChecks(java.lang.Class) 154 */ 155 public Collection getDefaultExistenceChecks(Class businessObjectClass) { 156 return getDefaultExistenceChecks(getDocumentTypeName(businessObjectClass)); 157 } 158 159 /** 160 * @see org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService#getDefaultExistenceChecks(java.lang.String) 161 */ 162 public Collection getDefaultExistenceChecks(String docTypeName) { 163 164 Collection defaultExistenceChecks = null; 165 166 MaintenanceDocumentEntry entry = getMaintenanceDocumentEntry(docTypeName); 167 if (entry != null) { 168 defaultExistenceChecks = entry.getDefaultExistenceChecks(); 169 } 170 171 return defaultExistenceChecks; 172 } 173 174 /** 175 * @see org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService#getLockingKeys(java.lang.String) 176 */ 177 public List getLockingKeys(String docTypeName) { 178 List lockingKeys = null; 179 180 MaintenanceDocumentEntry entry = getMaintenanceDocumentEntry(docTypeName); 181 if (entry != null) { 182 lockingKeys = entry.getLockingKeyFieldNames(); 183 } 184 185 return lockingKeys; 186 } 187 188 /** 189 * @param dataDictionaryService 190 */ 191 public void setDataDictionaryService(DataDictionaryService dataDictionaryService) { 192 this.dataDictionaryService = dataDictionaryService; 193 } 194 195 /** 196 * @return 197 */ 198 public DataDictionary getDataDictionary() { 199 return this.dataDictionaryService.getDataDictionary(); 200 } 201 202 /** 203 * @param docTypeName 204 * @return 205 */ 206 public MaintenanceDocumentEntry getMaintenanceDocumentEntry(String docTypeName) { 207 if (StringUtils.isBlank(docTypeName)) { 208 throw new IllegalArgumentException("invalid (blank) docTypeName"); 209 } 210 211 MaintenanceDocumentEntry entry = (MaintenanceDocumentEntry)getDataDictionary().getDocumentEntry(docTypeName); 212 return entry; 213 } 214 215 private MaintenanceDocumentEntry getMaintenanceDocumentEntry(Class businessObjectClass) { 216 if (businessObjectClass == null) { 217 throw new IllegalArgumentException("invalid (blank) dataObjectClass"); 218 } 219 220 MaintenanceDocumentEntry entry = (MaintenanceDocumentEntry) getDataDictionary().getMaintenanceDocumentEntryForBusinessObjectClass(businessObjectClass); 221 return entry; 222 } 223 224 /** 225 * @see org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService#getFieldDefaultValue(java.lang.Class, java.lang.String) 226 */ 227 public String getFieldDefaultValue(Class boClass, String fieldName) { 228 229 // input parameter validation 230 if (boClass == null) { 231 throw new IllegalArgumentException("The boClass parameter value specified was " + "null. A valid class representing the boClass must " + "be specified."); 232 } 233 234 // call the twin 235 return getFieldDefaultValue(getDocumentTypeName(boClass), fieldName); 236 } 237 238 /** 239 * @see org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService#getFieldDefaultValue(java.lang.String, java.lang.String) 240 */ 241 public String getFieldDefaultValue(String docTypeName, String fieldName) { 242 243 // input parameter validation 244 if (StringUtils.isBlank(docTypeName)) { 245 throw new IllegalArgumentException("The docTypeName parameter value specified was " + "blank, whitespace, or null. A valid string representing the docTypeName must " + "be specified."); 246 } 247 if (StringUtils.isBlank(fieldName)) { 248 throw new IllegalArgumentException("The fieldName parameter value specified was " + "blank, whitespace, or null. A valid string representing the fieldName must " + "be specified."); 249 } 250 251 // walk through the sections 252 List sections = getMaintainableSections(docTypeName); 253 for (Iterator sectionIterator = sections.iterator(); sectionIterator.hasNext();) { 254 MaintainableSectionDefinition section = (MaintainableSectionDefinition) sectionIterator.next(); 255 256 // walk through the fields 257 Collection fields = section.getMaintainableItems(); 258 String defaultValue = getFieldDefaultValue(fields, fieldName); 259 // need to keep trying sections until a match is found 260 if (defaultValue != null) { 261 return defaultValue; 262 } 263 } 264 return null; 265 } 266 267 private String getFieldDefaultValue(Collection maintainableFields, String fieldName) { 268 for (Iterator iterator = maintainableFields.iterator(); iterator.hasNext();) { 269 MaintainableItemDefinition item = (MaintainableItemDefinition) iterator.next(); 270 // only check fields...skip subcollections 271 if (item instanceof MaintainableFieldDefinition) { 272 273 MaintainableFieldDefinition field = (MaintainableFieldDefinition) item; 274 275 // if the field name matches 276 if (field.getName().endsWith(fieldName)) { 277 278 // preferentially take the raw default value 279 if (StringUtils.isNotBlank(field.getDefaultValue())) { 280 return field.getDefaultValue(); 281 } 282 283 // take the valuefinder 284 else if (field.getDefaultValueFinderClass() != null) { 285 286 // attempt to get an instance of the defaultValueFinderClass 287 ValueFinder valueFinder = null; 288 try { 289 valueFinder = (ValueFinder) field.getDefaultValueFinderClass().newInstance(); 290 } 291 catch (Exception e) { 292 LOG.info("Exception obtaining valueFinder for collection field default value", e); 293 valueFinder = null; 294 } 295 296 // get the value 297 if (valueFinder != null) { 298 return valueFinder.getValue(); 299 } 300 } 301 // if we found the field, but no default anything, then we're done 302 else { 303 return null; 304 } 305 } 306 } 307 } 308 return null; 309 } 310 311 /** 312 * @see org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService#getCollectionFieldDefaultValue(java.lang.String, 313 * java.lang.String, java.lang.String) 314 */ 315 public String getCollectionFieldDefaultValue(String docTypeName, String collectionName, String fieldName) { 316 // input parameter validation 317 if (StringUtils.isBlank(docTypeName)) { 318 throw new IllegalArgumentException("The docTypeName parameter value specified was blank, whitespace, or null. A valid string representing the docTypeName must be specified."); 319 } 320 if (StringUtils.isBlank(fieldName)) { 321 throw new IllegalArgumentException("The fieldName parameter value specified was blank, whitespace, or null. A valid string representing the fieldName must be specified."); 322 } 323 if (StringUtils.isBlank(collectionName)) { 324 throw new IllegalArgumentException("The collectionName parameter value specified was null. A valid string representing the collectionName must be specified."); 325 } 326 327 MaintainableCollectionDefinition coll = getMaintainableCollection(docTypeName, collectionName); 328 if (coll != null) { 329 Collection collectionFields = coll.getMaintainableFields(); 330 return getFieldDefaultValue(collectionFields, fieldName); 331 } 332 return null; 333 } 334 335 /** 336 * @see org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService#getAllowsCopy(MaintenanceDocument) 337 */ 338 public Boolean getAllowsCopy(MaintenanceDocument document) { 339 Boolean allowsCopy = Boolean.FALSE; 340 if (document != null && document.getNewMaintainableObject() != null) { 341 MaintenanceDocumentEntry entry = getMaintenanceDocumentEntry(document.getNewMaintainableObject().getBoClass()); 342 if (entry != null) { 343 allowsCopy = Boolean.valueOf(entry.getAllowsCopy()); 344 } 345 } 346 347 return allowsCopy; 348 } 349 350 /** 351 * @see org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService#getAllowsNewOrCopy(java.lang.String) 352 */ 353 public Boolean getAllowsNewOrCopy(String docTypeName) { 354 Boolean allowsNewOrCopy = Boolean.FALSE; 355 356 if (docTypeName != null) { 357 MaintenanceDocumentEntry entry = getMaintenanceDocumentEntry(docTypeName); 358 if (entry != null) { 359 allowsNewOrCopy = Boolean.valueOf(entry.getAllowsNewOrCopy()); 360 } 361 } 362 363 return allowsNewOrCopy; 364 } 365 366 public MaintainableItemDefinition getMaintainableItem(String docTypeName, String itemName) { 367 // input parameter validation 368 if (StringUtils.isBlank(docTypeName)) { 369 throw new IllegalArgumentException("The docTypeName parameter value specified was " + "blank, whitespace, or null. A valid string representing the docTypeName must " + "be specified."); 370 } 371 if (StringUtils.isBlank(itemName)) { 372 throw new IllegalArgumentException("The itemName parameter value specified was " + "blank, whitespace, or null. A valid string representing the itemName must " + "be specified."); 373 } 374 375 // split name for subcollections 376 String[] subItems = {}; 377 subItems = StringUtils.split(itemName, "."); 378 379 380 // walk through the sections 381 List sections = getMaintainableSections(docTypeName); 382 for (Iterator sectionIterator = sections.iterator(); sectionIterator.hasNext();) { 383 MaintainableSectionDefinition section = (MaintainableSectionDefinition) sectionIterator.next(); 384 385 // walk through the fields 386 Collection fields = section.getMaintainableItems(); 387 for (Iterator fieldIterator = fields.iterator(); fieldIterator.hasNext();) { 388 MaintainableItemDefinition item = (MaintainableItemDefinition) fieldIterator.next(); 389 390 if (item.getName().equals(itemName)) { 391 return item; 392 } 393 // if collection check to see if it has sub collections 394 // for now this only allows 1 level (i.e. a.b) it should be expanded at some point 395 if (item instanceof MaintainableCollectionDefinition) { 396 MaintainableCollectionDefinition col = (MaintainableCollectionDefinition) item; 397 if ((subItems.length > 1) && (StringUtils.equals(col.getName(), subItems[0]))) { 398 for (Iterator<MaintainableCollectionDefinition> colIterator = col.getMaintainableCollections().iterator(); colIterator.hasNext();) { 399 MaintainableCollectionDefinition subCol = (MaintainableCollectionDefinition) colIterator.next(); 400 if (subCol.getName().equals(subItems[1])) { 401 return subCol; 402 } 403 } 404 } 405 } 406 } 407 } 408 return null; 409 } 410 411 public MaintainableFieldDefinition getMaintainableField(String docTypeName, String fieldName) { 412 MaintainableItemDefinition item = getMaintainableItem(docTypeName, fieldName); 413 if (item != null && item instanceof MaintainableFieldDefinition) { 414 return (MaintainableFieldDefinition) item; 415 } 416 return null; 417 } 418 419 public MaintainableCollectionDefinition getMaintainableCollection(String docTypeName, String collectionName) { 420 // strip brackets as they are not needed to get to collection class 421 // Like the other subcollections changes this currently only supports one sub level 422 if (StringUtils.contains(collectionName, "[")) { 423 collectionName = StringUtils.substringBefore(collectionName, "[") + StringUtils.substringAfter(collectionName, "]"); 424 } 425 MaintainableItemDefinition item = getMaintainableItem(docTypeName, collectionName); 426 if (item != null && item instanceof MaintainableCollectionDefinition) { 427 return (MaintainableCollectionDefinition) item; 428 } 429 return null; 430 } 431 432 public Class getCollectionBusinessObjectClass(String docTypeName, String collectionName) { 433 MaintainableCollectionDefinition coll = getMaintainableCollection(docTypeName, collectionName); 434 if (coll != null) { 435 return coll.getBusinessObjectClass(); 436 } 437 return null; 438 } 439 440 public List<MaintainableCollectionDefinition> getMaintainableCollections(String docTypeName) { 441 ArrayList<MaintainableCollectionDefinition> collections = new ArrayList<MaintainableCollectionDefinition>(); 442 443 // walk through the sections 444 List sections = getMaintainableSections(docTypeName); 445 for (Iterator sectionIterator = sections.iterator(); sectionIterator.hasNext();) { 446 MaintainableSectionDefinition section = (MaintainableSectionDefinition) sectionIterator.next(); 447 448 // walk through the fields 449 Collection fields = section.getMaintainableItems(); 450 for (Iterator fieldIterator = fields.iterator(); fieldIterator.hasNext();) { 451 MaintainableItemDefinition item = (MaintainableItemDefinition) fieldIterator.next(); 452 453 if (item instanceof MaintainableCollectionDefinition) { 454 collections.add((MaintainableCollectionDefinition) item); 455 // collections.addAll( getMaintainableCollections( (MaintainableCollectionDefinition)item ) ); 456 } 457 } 458 } 459 460 return collections; 461 } 462 463 public List<MaintainableCollectionDefinition> getMaintainableCollections(MaintainableCollectionDefinition parentCollection) { 464 ArrayList<MaintainableCollectionDefinition> collections = new ArrayList<MaintainableCollectionDefinition>(); 465 466 // walk through the sections 467 Collection<MaintainableCollectionDefinition> colls = parentCollection.getMaintainableCollections(); 468 for (MaintainableCollectionDefinition coll : colls) { 469 collections.add(coll); 470 collections.addAll(getMaintainableCollections(coll)); 471 } 472 473 return collections; 474 } 475 476 /** 477 * @see org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService#validateMaintenanceRequiredFields(org.kuali.rice.krad.maintenance.MaintenanceDocument) 478 */ 479 public void validateMaintenanceRequiredFields(MaintenanceDocument document) { 480 Maintainable newMaintainableObject = document.getNewMaintainableObject(); 481 if (newMaintainableObject == null) { 482 LOG.error("New maintainable is null"); 483 throw new RuntimeException("New maintainable is null"); 484 } 485 486 List<MaintainableSectionDefinition> maintainableSectionDefinitions = getMaintainableSections(getDocumentTypeName(newMaintainableObject.getBoClass())); 487 for (MaintainableSectionDefinition maintainableSectionDefinition : maintainableSectionDefinitions) { 488 for (MaintainableItemDefinition maintainableItemDefinition : maintainableSectionDefinition.getMaintainableItems()) { 489 // validate fields 490 if (maintainableItemDefinition instanceof MaintainableFieldDefinition) { 491 validateMaintainableFieldRequiredFields((MaintainableFieldDefinition) maintainableItemDefinition, newMaintainableObject.getBusinessObject(), maintainableItemDefinition.getName()); 492 } 493 // validate collections 494 else if (maintainableItemDefinition instanceof MaintainableCollectionDefinition) { 495 validateMaintainableCollectionsRequiredFields(newMaintainableObject.getBusinessObject(), (MaintainableCollectionDefinition) maintainableItemDefinition); 496 } 497 } 498 } 499 } 500 501 /** 502 * generates error message if a field is marked as required but is not filled in 503 * 504 * @param maintainableFieldDefinition 505 * @param businessObject 506 * @param fieldName 507 */ 508 private void validateMaintainableFieldRequiredFields(MaintainableFieldDefinition maintainableFieldDefinition, PersistableBusinessObject businessObject, String fieldName) { 509 510 if (StringUtils.isBlank(fieldName)) { 511 throw new IllegalArgumentException("invalid fieldName parameter."); 512 } 513 // if required check we have a value for this field 514 if (maintainableFieldDefinition.isRequired() && !maintainableFieldDefinition.isUnconditionallyReadOnly() ) { 515 try { 516 Object obj = ObjectUtils.getNestedValue(businessObject, fieldName); 517 518 if (obj == null || StringUtils.isBlank(obj.toString())) { 519 String attributeLabel = dataDictionaryService.getAttributeLabel(businessObject.getClass(), fieldName); 520 String shortLabel = dataDictionaryService.getAttributeShortLabel(businessObject.getClass(), fieldName); 521 GlobalVariables.getMessageMap().putError(fieldName, RiceKeyConstants.ERROR_REQUIRED, attributeLabel + " (" + shortLabel + ")" ); 522 } else if ( fieldName.endsWith(".principalName") ) { 523 // special handling to catch when the principalName is not really a valid user 524 // pull the Person object and test the entity ID. If that's null, then this 525 // is just a shell user instance and does not represent a true user 526 // the main principalId property on the main object would be null at this point 527 // but it is also unconditionally read only and not tested - checking that would 528 // require checking the relationships and be more complex than we want to get here 529 String personProperty = ObjectUtils.getNestedAttributePrefix(fieldName); 530 if ( StringUtils.isNotBlank(personProperty) ) { 531 if ( StringUtils.isBlank( (String)ObjectUtils.getNestedValue(businessObject, personProperty+".entityId") ) ) { 532 String attributeLabel = dataDictionaryService.getAttributeLabel(businessObject.getClass(), fieldName); 533 GlobalVariables.getMessageMap().putError(fieldName, RiceKeyConstants.ERROR_EXISTENCE, attributeLabel ); 534 } 535 } 536 } 537 } catch( Exception ex ) { 538 LOG.error( "unable to read property during doc required field checks", ex ); 539 } 540 } 541 } 542 543 544 private MaintainableCollectionDefinition getCollectionDefinition( String docTypeName, String collectionName ) { 545 String currentCollection = collectionName; 546 String nestedCollections = ""; 547 if (StringUtils.contains(collectionName, "[")) { 548 // strip off any array indexes 549 currentCollection = StringUtils.substringBefore( collectionName, "[" ); 550 nestedCollections = StringUtils.substringAfter( collectionName, "." ); 551 } 552 553 // loop over all sections to find this collection 554 List<MaintainableSectionDefinition> maintainableSectionDefinitions = getMaintainableSections( docTypeName ); 555 for (MaintainableSectionDefinition maintainableSectionDefinition : maintainableSectionDefinitions) { 556 for (MaintainableItemDefinition maintainableItemDefinition : maintainableSectionDefinition.getMaintainableItems()) { 557 if (maintainableItemDefinition instanceof MaintainableCollectionDefinition && maintainableItemDefinition.getName().equals( currentCollection ) ) { 558 if ( StringUtils.isBlank( nestedCollections ) ) { 559 return (MaintainableCollectionDefinition) maintainableItemDefinition; 560 } 561 562 return getCollectionDefinition( (MaintainableCollectionDefinition)maintainableItemDefinition, nestedCollections ); 563 } 564 } 565 } 566 567 return null; 568 } 569 570 private MaintainableCollectionDefinition getCollectionDefinition( MaintainableCollectionDefinition collectionDef, String collectionName ) { 571 String currentCollection = collectionName; 572 String nestedCollections = ""; 573 if (StringUtils.contains(collectionName, "[")) { 574 // strip off any array indexes 575 currentCollection = StringUtils.substringBefore( collectionName, "[" ); 576 nestedCollections = StringUtils.substringAfter( collectionName, "." ); 577 } 578 579 // loop over all nested collections 580 for (MaintainableCollectionDefinition maintainableCollectionDefinition : collectionDef.getMaintainableCollections()) { 581 if ( maintainableCollectionDefinition.getName().equals( currentCollection ) ) { 582 if ( StringUtils.isBlank( nestedCollections ) ) { 583 return maintainableCollectionDefinition; 584 } 585 return getCollectionDefinition( maintainableCollectionDefinition, nestedCollections ); 586 } 587 } 588 589 return null; 590 } 591 592 public void validateMaintainableCollectionsAddLineRequiredFields(MaintenanceDocument document, PersistableBusinessObject businessObject, String collectionName ) { 593 MaintainableCollectionDefinition def = getCollectionDefinition( getDocumentTypeName(businessObject.getClass()), collectionName ); 594 if ( def != null ) { 595 validateMaintainableCollectionsAddLineRequiredFields( document, businessObject, collectionName, def, 0); 596 } 597 } 598 /** 599 * calls code to generate error messages if maintainableFields within any collections or sub-collections are marked as required 600 * 601 * @param document 602 * @param businessObject 603 * @param collectionName 604 * @param maintainableCollectionDefinition 605 * @param depth 606 */ 607 private void validateMaintainableCollectionsAddLineRequiredFields(MaintenanceDocument document, PersistableBusinessObject businessObject, String collectionName, MaintainableCollectionDefinition maintainableCollectionDefinition, int depth) { 608 if ( depth == 0 ) { 609 GlobalVariables.getMessageMap().addToErrorPath("add"); 610 } 611 // validate required fields on fields withing collection definition 612 PersistableBusinessObject element = document.getNewMaintainableObject().getNewCollectionLine( collectionName ); 613 GlobalVariables.getMessageMap().addToErrorPath(collectionName); 614 for (MaintainableFieldDefinition maintainableFieldDefinition : maintainableCollectionDefinition.getMaintainableFields()) { 615 final String fieldName = maintainableFieldDefinition.getName(); 616 validateMaintainableFieldRequiredFields(maintainableFieldDefinition, element, fieldName); 617 618 } 619 620 GlobalVariables.getMessageMap().removeFromErrorPath(collectionName); 621 if ( depth == 0 ) { 622 GlobalVariables.getMessageMap().removeFromErrorPath("add"); 623 } 624 } 625 626 /** 627 * calls code to generate error messages if maintainableFields within any collections or sub-collections are marked as required 628 * 629 * @param businessObject 630 * @param maintainableCollectionDefinition 631 */ 632 private void validateMaintainableCollectionsRequiredFields(PersistableBusinessObject businessObject, MaintainableCollectionDefinition maintainableCollectionDefinition) { 633 final String collectionName = maintainableCollectionDefinition.getName(); 634 635 // validate required fields on fields withing collection definition 636 Collection<PersistableBusinessObject> collection = (Collection) ObjectUtils.getPropertyValue(businessObject, collectionName); 637 if (collection != null && !collection.isEmpty()) { 638 for (MaintainableFieldDefinition maintainableFieldDefinition : maintainableCollectionDefinition.getMaintainableFields()) { 639 int pos = 0; 640 final String fieldName = maintainableFieldDefinition.getName(); 641 for (PersistableBusinessObject element : collection) { 642 String parentName = collectionName + "[" + (pos++) + "]"; 643 GlobalVariables.getMessageMap().addToErrorPath(parentName); 644 validateMaintainableFieldRequiredFields(maintainableFieldDefinition, element, fieldName); 645 GlobalVariables.getMessageMap().removeFromErrorPath(parentName); 646 } 647 } 648 649 // recursivley validate required fields on subcollections 650 GlobalVariables.getMessageMap().addToErrorPath(collectionName); 651 for (MaintainableCollectionDefinition nestedMaintainableCollectionDefinition : maintainableCollectionDefinition.getMaintainableCollections()) { 652 for (PersistableBusinessObject element : collection) { 653 validateMaintainableCollectionsRequiredFields(element, nestedMaintainableCollectionDefinition); 654 } 655 } 656 GlobalVariables.getMessageMap().removeFromErrorPath(collectionName); 657 } 658 } 659 660 /** 661 * default implementation checks for duplicats based on keys of objects only 662 * 663 * @see org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService#validateMaintainableCollectionsForDuplicateEntries(org.kuali.rice.krad.maintenance.MaintenanceDocument) 664 */ 665 public void validateMaintainableCollectionsForDuplicateEntries(MaintenanceDocument document) { 666 Maintainable newMaintainableObject = document.getNewMaintainableObject(); 667 if (newMaintainableObject == null) { 668 LOG.error("New maintainable is null"); 669 throw new RuntimeException("New maintainable is null"); 670 } 671 672 List<MaintainableSectionDefinition> maintainableSectionDefinitions = getMaintainableSections(getDocumentTypeName(newMaintainableObject.getBoClass())); 673 for (MaintainableSectionDefinition maintainableSectionDefinition : maintainableSectionDefinitions) { 674 for (MaintainableItemDefinition maintainableItemDefinition : maintainableSectionDefinition.getMaintainableItems()) { 675 // validate collections 676 if (maintainableItemDefinition instanceof MaintainableCollectionDefinition) { 677 validateMaintainableCollectionsForDuplicateEntries(newMaintainableObject.getBusinessObject(), (MaintainableCollectionDefinition) maintainableItemDefinition); 678 } 679 } 680 } 681 } 682 683 /** 684 * recursivly checks collections for duplicate entries based on key valuse 685 * 686 * @param businessObject 687 * @param maintainableCollectionDefinition 688 */ 689 private void validateMaintainableCollectionsForDuplicateEntries(PersistableBusinessObject businessObject, MaintainableCollectionDefinition maintainableCollectionDefinition) { 690 final String collectionName = maintainableCollectionDefinition.getName(); 691 692 if (maintainableCollectionDefinition.dissallowDuplicateKey()) { 693 final Class maintainableBusinessObjectClass = businessObject.getClass(); 694 // validate that no duplicates based on keys exist 695 Collection<PersistableBusinessObject> collection = (Collection) ObjectUtils.getPropertyValue(businessObject, collectionName); 696 if (collection != null && !collection.isEmpty()) { 697 final String propertyName = maintainableCollectionDefinition.getAttributeToHighlightOnDuplicateKey(); 698 // get collection label for dd 699 final String label = dataDictionaryService.getCollectionLabel(maintainableBusinessObjectClass, collectionName); 700 final String shortLabel = dataDictionaryService.getCollectionShortLabel(maintainableBusinessObjectClass, collectionName); 701 int pos = 0; 702 for (PersistableBusinessObject element : collection) { 703 String pathToElement = collectionName + "[" + (pos++) + "]"; 704 if (ObjectUtils.countObjectsWithIdentitcalKey(collection, element) > 1) { 705 GlobalVariables.getMessageMap().addToErrorPath(pathToElement); 706 GlobalVariables.getMessageMap().putError(propertyName, RiceKeyConstants.ERROR_DUPLICATE_ELEMENT, new String[] { label, shortLabel }); 707 GlobalVariables.getMessageMap().removeFromErrorPath(pathToElement); 708 } 709 } 710 711 // recursivley check for duplicate entries on subcollections 712 GlobalVariables.getMessageMap().addToErrorPath(collectionName); 713 for (MaintainableCollectionDefinition nestedMaintainableCollectionDefinition : maintainableCollectionDefinition.getMaintainableCollections()) { 714 for (PersistableBusinessObject element : collection) { 715 validateMaintainableCollectionsForDuplicateEntries(element, nestedMaintainableCollectionDefinition); 716 } 717 } 718 GlobalVariables.getMessageMap().removeFromErrorPath(collectionName); 719 720 } 721 } 722 } 723 724 /** 725 * for issue KULRice 3072 726 * 727 * @see org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService#getgetPreserveLockingKeysOnCopy(java.lang.Class) 728 */ 729 public boolean getPreserveLockingKeysOnCopy(Class businessObjectClass) { 730 731 boolean preserveLockingKeysOnCopy = false; 732 733 MaintenanceDocumentEntry docEntry = getMaintenanceDocumentEntry(businessObjectClass); 734 735 if (docEntry != null) { 736 preserveLockingKeysOnCopy = docEntry.getPreserveLockingKeysOnCopy(); 737 } 738 739 return preserveLockingKeysOnCopy; 740 } 741 742 /** 743 * for isue KULRice 3070 744 * 745 * @see org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService#getAllowsRecordDeletion(java.lang.Class) 746 */ 747 public Boolean getAllowsRecordDeletion(Class businessObjectClass) { 748 749 Boolean allowsRecordDeletion = Boolean.FALSE; 750 751 MaintenanceDocumentEntry docEntry = getMaintenanceDocumentEntry(businessObjectClass); 752 753 if (docEntry != null) { 754 allowsRecordDeletion = Boolean.valueOf(docEntry.getAllowsRecordDeletion()); 755 } 756 757 return allowsRecordDeletion; 758 } 759 760 /** 761 * for issue KULRice3070, see if need delete button 762 * 763 * @see org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService#getAllowsRecordDeletion(org.kuali.rice.krad.maintenance.MaintenanceDocument) 764 */ 765 public Boolean getAllowsRecordDeletion(MaintenanceDocument document) { 766 return document != null ? this.getAllowsRecordDeletion(document.getNewMaintainableObject().getBoClass()) : Boolean.FALSE; 767 } 768 769 /** 770 * @see org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService#translateCodes(java.lang.Class) 771 */ 772 public Boolean translateCodes(Class businessObjectClass) { 773 boolean translateCodes = false; 774 775 MaintenanceDocumentEntry docEntry = getMaintenanceDocumentEntry(businessObjectClass); 776 777 if (docEntry != null) { 778 translateCodes = docEntry.isTranslateCodes(); 779 } 780 781 return translateCodes; 782 } 783 784}