1 /** 2 * Copyright 2005-2014 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.krad.service; 17 18 import org.kuali.rice.krad.bo.BusinessObject; 19 import org.kuali.rice.krad.datadictionary.DataDictionaryEntry; 20 import org.kuali.rice.krad.datadictionary.ReferenceDefinition; 21 import org.kuali.rice.krad.datadictionary.state.StateMapping; 22 import org.kuali.rice.krad.datadictionary.validation.AttributeValueReader; 23 import org.kuali.rice.krad.datadictionary.validation.result.DictionaryValidationResult; 24 import org.kuali.rice.krad.document.Document; 25 import org.kuali.rice.krad.document.TransactionalDocument; 26 27 import java.beans.PropertyDescriptor; 28 29 /** 30 * Defines the API for the validating against the data dictionary. 31 * 32 * @author Kuali Rice Team (rice.collab@kuali.org) 33 */ 34 public interface DictionaryValidationService { 35 36 /** 37 * Validates the contents of a document (i.e. attributes within a document) against the data dictionary. 38 * 39 * @param document - document to validate 40 */ 41 public void validateDocument(Document document); 42 43 /** 44 * Validates the contents of a document and recursively validates any of its updatable references 45 * 46 * @param document the document 47 * @param maxDepth the maximum numbers of levels to recurse 48 * @param validateRequired whether to validate whether a field is required and is currently blank 49 */ 50 public void validateDocumentAndUpdatableReferencesRecursively(Document document, int maxDepth, 51 boolean validateRequired); 52 53 /** 54 * Validates the contents of a document and recursively validates any of its updatable references 55 * 56 * @param document the document 57 * @param maxDepth the maximum numbers of levels to recurse 58 * @param validateRequired whether to validate whether a field is required and is currently blank 59 * @param chompLastLetterSFromCollectionName if true, the error path for any collections encountered will have the 60 * last "s" removed from the collection name if it ends 61 * with the letter "s". If false, this method acts like {@link #validateDocumentAndUpdatableReferencesRecursively(Document, 62 * int, boolean)} 63 */ 64 public void validateDocumentAndUpdatableReferencesRecursively(Document document, int maxDepth, 65 boolean validateRequired, boolean chompLastLetterSFromCollectionName); 66 67 /** 68 * Validates the specified attribute of the given document against the data dictionary. 69 * 70 * @param document 71 * @param attributeName 72 * @param errorPrefix 73 */ 74 public void validateDocumentAttribute(Document document, String attributeName, String errorPrefix); 75 76 /** 77 * Validates an object using its class name as the entry name to look up its metadata in the dictionary. 78 * 79 * @param object - an object to validate 80 * @return the dictionary validation result object associated with this validation 81 */ 82 public DictionaryValidationResult validate(Object object); 83 84 /** 85 * Validate an object with the passed in dictionary entryName and the specific attribute to be evaluated 86 * 87 * @param object - an object to validate 88 * @param entryName - the dictionary entry name to look up the metadata associated with this object 89 * @param attributeName - the name of the attribute (field) on the object that should be validated 90 * @param doOptionalProcessing true if the validation should do optional validation (e.g. to check if empty values 91 * are required or not), false otherwise 92 * @return the dictionary validation result object associated with this validation 93 * @since 1.1 94 */ 95 public DictionaryValidationResult validate(Object object, String entryName, String attributeName, 96 boolean doOptionalProcessing); 97 98 /** 99 * Same as {@link DictionaryValidationService#validate(Object, String, String, boolean)} except 100 * that it provides an explicit data dictionary entry to use for the purpose of validation. 101 * 102 * @param object - an object to validate 103 * @param entryName - the dictionary entry name to use in association with error look ups 104 * @param entry - the dictionary entry to use for validation 105 * @param doOptionalProcessing true if the validation should do optional validation (e.g. to 106 * check if empty values are required or not), false otherwise 107 * @return the dictionary validation result object associated with this validation 108 * @since 1.1 109 */ 110 public DictionaryValidationResult validate(Object object, String entryName, DataDictionaryEntry entry, 111 boolean doOptionalProcessing); 112 113 /** 114 * Validates the object agains the next state (or current state if there is no next state). 115 * 116 * <p>When no stateMapping exists on the DataDictionaryEntry that applies for this object, validation is considered 117 * stateless and all constraints are processed regardless of their states attribute.</p> 118 * 119 * @param object 120 * @return the dictionary validation result object associated with this validation 121 * @since 2.2 122 */ 123 public DictionaryValidationResult validateAgainstNextState(Object object); 124 125 /** 126 * Validates the object against the state specified. 127 * 128 * <p>Important note: Alternatively the state can be changed on the 129 * object itself and another validation method can be used instead of this one (in practice, you'd revert the 130 * state on the object if validation returns errors).</p> 131 * 132 * @param object 133 * @param validationState 134 * @return the dictionary validation result object associated with this validation 135 * @since 2.2 136 */ 137 public DictionaryValidationResult validateAgainstState(Object object, String validationState); 138 139 /** 140 * Same as other validate methods, except allows you to provide the attributeValueReader directly for evaluation 141 * 142 * @param valueReader - an object to validate 143 * @param doOptionalProcessing true if the validation should do optional validation (e.g. to check if empty values 144 * are required or not), false otherwise 145 * @return the dictionary validation result object associated with this validation 146 * @since 1.1 147 */ 148 public DictionaryValidationResult validate(AttributeValueReader valueReader, boolean doOptionalProcessing, 149 String validationState, StateMapping stateMapping); 150 151 /** 152 * Encapsulates {@link #validateBusinessObject(BusinessObject)} and returns boolean so one 153 * doesn't need to check the ErrorMap.Validates the business object primitive attributes against 154 * the data dictionary. Adds errors to the map as they are encountered.<br/> 155 * <br/> 156 * Makes no error path adjustments 157 * 158 * @param businessObject - business object to validate 159 * @return boolean validOrNot 160 */ 161 public boolean isBusinessObjectValid(BusinessObject businessObject); 162 163 /** 164 * Encapsulates {@link #validateBusinessObject(BusinessObject)} and returns boolean so one 165 * doesn't need to check the ErrorMap.Validates the business object primitive attributes against 166 * the data dictionary. Adds errors to the map as they are encountered.<br/> 167 * <br/> 168 * Makes no error path adjustments 169 * 170 * @param businessObject - business object to validate 171 * @param prefix - error prefix 172 * @return boolean valid or not 173 */ 174 public boolean isBusinessObjectValid(BusinessObject businessObject, String prefix); 175 176 /** 177 * Validates the business object primitive attributes against the data dictionary. Adds errors to the map as they 178 * are 179 * encountered. 180 * 181 * @param businessObject - business object to validate 182 * @deprecated since 1.1 - use validate(Object.class) instead 183 */ 184 @Deprecated 185 public void validateBusinessObject(BusinessObject businessObject); 186 187 /** 188 * Validates the business object primitive attributes against the data dictionary. Adds errors to the map as they 189 * are 190 * encountered. 191 * 192 * @param businessObject - business object to validate 193 * @param validateRequired - whether to execute required field checks 194 * @deprecated since 1.1 - use validate(Object.class) instead 195 */ 196 @Deprecated 197 public void validateBusinessObject(BusinessObject businessObject, boolean validateRequired); 198 199 /** 200 * This method examines the populated BusinessObject bo instance passed in for a member named by the referenceName. 201 * If this 202 * member exists, and if this member is a descendent of BusinessObject, then an existence check proceeds. 203 * 204 * First the foreign keys for this reference are gathered, and then examined to see if they have values. If they do 205 * not have 206 * values, the method ends with a true return value. If they all have values, then an object with those primary 207 * keys 208 * is retrieve 209 * from the database. If one is retrieve, then the reference exists, and True is returned. Otherwise, false is 210 * returned. 211 * 212 * This method assumes that you already have the errorPath set exactly as desired, and adds new errors to the 213 * errorMap with no 214 * prefix, other than what has already been pushed onto the errorMap. 215 * 216 * @param dataObject - the data object whose reference is being tested. 217 * @param reference - The ReferenceDefinition to be existence tested. 218 * @return True if no exceptions occur and the object exists in the db, false otherwise. 219 */ 220 public boolean validateReferenceExists(Object dataObject, ReferenceDefinition reference); 221 222 /** 223 * This method examines the populated BusinessObject bo instance passed in for a member named by the referenceName. 224 * If this 225 * member exists, and if this member is a descendent of BusinessObject, then an existence check proceeds. 226 * 227 * First the foreign keys for this reference are gathered, and then examined to see if they have values. If they do 228 * not have 229 * values, the method ends with a true return value. If they all have values, then an object with those primary 230 * keys 231 * is retrieve 232 * from the database. If one is retrieve, then the reference exists, and True is returned. Otherwise, false is 233 * returned. 234 * 235 * This method assumes that you already have the errorPath set exactly as desired, and adds new errors to the 236 * errorMap with no 237 * prefix, other than what has already been pushed onto the errorMap. 238 * 239 * @param dataObject - the data object whose reference is being tested. 240 * @param referenceName - The name of the member to be existence tested. 241 * @return True if no exceptions occur and the object exists in the db, false otherwise. 242 */ 243 public boolean validateReferenceExists(Object dataObject, String referenceName); 244 245 /** 246 * This method retrieves the reference from the DB, and then tests whether the object is active. 247 * 248 * It will return false if there is no activeIndicator field on this object, if the object doesnt exist in the DB, 249 * if the field 250 * doesnt exist or cannot be cast as a boolean, if the field value is null, or if the field value is false. 251 * 252 * It will only return true if the reference bo is present, the field is present, it is a boolean and non-null, and 253 * the value is 254 * true. 255 * 256 * This method assumes that you already have the errorPath set exactly as desired, and adds new errors to the 257 * errorMap with no 258 * prefix, other than what has already been pushed onto the errorMap. 259 * 260 * @param dataObject 261 * @param reference 262 * @return true if the reference is active 263 */ 264 public boolean validateReferenceIsActive(Object dataObject, ReferenceDefinition reference); 265 266 /** 267 * This method retrieves the reference from the DB, and then tests whether the object is active. 268 * 269 * It will return false if there is no activeIndicator field on this object, if the object doesnt exist in the DB, 270 * if the field 271 * doesnt exist or cannot be cast as a boolean, if the field value is null, or if the field value is false. 272 * 273 * It will only return true if the reference bo is present, the field is present, it is a boolean and non-null, and 274 * the value is 275 * true. 276 * 277 * This method assumes that you already have the errorPath set exactly as desired, and adds new errors to the 278 * errorMap with no 279 * prefix, other than what has already been pushed onto the errorMap. 280 * 281 * @param dataObject 282 * @param referenceName 283 * @return true if the reference is active 284 */ 285 public boolean validateReferenceIsActive(Object dataObject, String referenceName); 286 287 /** 288 * validateReferenceExistsAndIsActive intelligently tests the designated reference on the data object for both existence and 289 * active status, where 290 * appropriate 291 * 292 * <p>It will not test anything if the foreign-key fields for the given reference aren't filled out with values, 293 * and 294 * it 295 * will not test active status if the reference doesn't exist.</p> 296 * 297 * <p>Further, it will only test active status where the correct flag is set.</p> 298 * 299 * <p>On failures of either sort, it will put the relevant errors into the GlobalVariables errorMap, and return a 300 * false. If there 301 * are no failures, or nothing can be tested because the foreign-key fields arent fully filled out, it will return 302 * true and add 303 * no errors.</p> 304 * 305 * <p>This method assumes that you already have the errorPath set exactly as desired, and adds new errors to the 306 * errorMap with no 307 * prefix, other than what has already been pushed onto the errorMap.</p> 308 * 309 * @param dataObject - the data object instance to be tested. 310 * @param reference - the ReferenceDefinition to control the nature of the testing. 311 * @return true or false as per the criteria above 312 */ 313 public boolean validateReferenceExistsAndIsActive(Object dataObject, ReferenceDefinition reference); 314 315 /** 316 * This method intelligently tests the designated reference on the data object for both existence and active status, where 317 * appropriate. 318 * 319 * It will not test anything if the foreign-key fields for the given reference arent filled out with values, and it 320 * will not 321 * test active status if the reference doesnt exist. 322 * 323 * Note that it will not fail or raise any error if all of the foreign-keys are filled with a value. If this needs 324 * to be tested 325 * (ie, the 'if any field is filled, then all must be filled' rule), you'll have to do that separately. 326 * 327 * Further, it will only test active status where the correct flag is set. 328 * 329 * On failures of either sort, it will put the relevant errors into the GlobalVariables errorMap, and return a 330 * false. If there 331 * are no failures, or nothing can be tested because the foreign-key fields arent fully filled out, it will return 332 * true and add 333 * no errors. 334 * 335 * This method assumes that you already have the errorPath set exactly as desired, and adds new errors to the 336 * errorMap with no 337 * prefix, other than what has already been pushed onto the errorMap. 338 * 339 * @param dataObject - the BusinessObject instance to be tested. 340 * @param referenceName - the member name on the data object to be tested for existence and active-state 341 * @param attributeToHighlightOnFail - the fieldName to highlight with the error message on a failure 342 * @param displayFieldName - the human-readable display name of the failed field, to go in the error message 343 * @return true or false as per the criteria above 344 */ 345 public boolean validateReferenceExistsAndIsActive(Object dataObject, String referenceName, 346 String attributeToHighlightOnFail, String displayFieldName); 347 348 /** 349 * This method does an existence check against all references of a BusinessObject as defined in the 350 * MaintenanceDocument.xml file 351 * for that business object. 352 * 353 * Appropriate errors will also be placed in the GlobalVariables.ErrorMap. 354 * 355 * This method assumes that you already have the errorPath set exactly as desired, and adds new errors to the 356 * errorMap with no 357 * prefix, other than what has already been pushed onto the errorMap. 358 * 359 * @param dataObject - BusinessObject instance that should be tested 360 * @return true if all passed existence tests, false if any failed 361 */ 362 public boolean validateDefaultExistenceChecks(Object dataObject); 363 364 /** 365 * Does an existence check against all references configured as a default existence check in the maintenance 366 * document data dictionary file for the given business object 367 * 368 * Appropriate errors will also be placed in the GlobalVariables.ErrorMap. 369 * 370 * This method assumes that you already have the errorPath set exactly as desired, and adds new errors to the 371 * errorMap 372 * with no 373 * prefix, other than what has already been pushed onto the errorMap. 374 * 375 * @param dataObject parent business object instance to retrieve default checks for 376 * @param newCollectionItem new collection line to validate 377 * @param collectionName name of the collection in the parent 378 * @return true if all passed existence tests, false if any failed 379 */ 380 public boolean validateDefaultExistenceChecksForNewCollectionItem(Object dataObject, Object newCollectionItem, 381 String collectionName); 382 383 /** 384 * This method does an existence check against all references of a transactionalDocument 385 * 386 * Appropriate errors will also be placed in the GlobalVariables.ErrorMap. 387 * 388 * This method assumes that you already have the errorPath set exactly as desired, and adds new errors to the 389 * errorMap 390 * with no 391 * prefix, other than what has already been pushed onto the errorMap. 392 * 393 * @param document document instance that should be tested 394 * @return true if all passed existence tests, false if any failed 395 */ 396 public boolean validateDefaultExistenceChecksForTransDoc(TransactionalDocument document); 397 398 /** 399 * This method does an existence check against all references of a transactionalDocument 400 * 401 * Appropriate errors will also be placed in the GlobalVariables.ErrorMap. 402 * 403 * This method assumes that you already have the errorPath set exactly as desired, and adds new errors to the 404 * errorMap 405 * with no 406 * prefix, other than what has already been pushed onto the errorMap. 407 * 408 * @param document document instance that should be tested 409 * @param accountingLine that should be tested 410 * @param collectionName that should be tested 411 * @return true if all passed existence tests, false if any failed 412 */ 413 public boolean validateDefaultExistenceChecksForNewCollectionItem(TransactionalDocument document, 414 BusinessObject accountingLine, String collectionName); 415 416 /** 417 * @deprecated since 1.1 418 */ 419 @Deprecated 420 public void validatePrimitiveFromDescriptor(String entryName, Object object, PropertyDescriptor propertyDescriptor, 421 String errorPrefix, boolean validateRequired); 422 }