001 /**
002 * Copyright 2005-2013 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 */
016 package org.kuali.rice.krad.service;
017
018 import org.kuali.rice.krad.bo.BusinessObject;
019 import org.kuali.rice.krad.datadictionary.DataDictionaryEntry;
020 import org.kuali.rice.krad.datadictionary.ReferenceDefinition;
021 import org.kuali.rice.krad.datadictionary.state.StateMapping;
022 import org.kuali.rice.krad.datadictionary.validation.AttributeValueReader;
023 import org.kuali.rice.krad.datadictionary.validation.result.DictionaryValidationResult;
024 import org.kuali.rice.krad.document.Document;
025 import org.kuali.rice.krad.document.TransactionalDocument;
026
027 import java.beans.PropertyDescriptor;
028
029 /**
030 * Defines the API for the validating against the data dictionary.
031 *
032 * @author Kuali Rice Team (rice.collab@kuali.org)
033 */
034 public interface DictionaryValidationService {
035
036 /**
037 * Validates the contents of a document (i.e. attributes within a document) against the data dictionary.
038 *
039 * @param document - document to validate
040 */
041 public void validateDocument(Document document);
042
043 /**
044 * Validates the contents of a document and recursively validates any of its updatable references
045 *
046 * @param document the document
047 * @param maxDepth the maximum numbers of levels to recurse
048 * @param validateRequired whether to validate whether a field is required and is currently blank
049 */
050 public void validateDocumentAndUpdatableReferencesRecursively(Document document, int maxDepth,
051 boolean validateRequired);
052
053 /**
054 * Validates the contents of a document and recursively validates any of its updatable references
055 *
056 * @param document the document
057 * @param maxDepth the maximum numbers of levels to recurse
058 * @param validateRequired whether to validate whether a field is required and is currently blank
059 * @param chompLastLetterSFromCollectionName if true, the error path for any collections encountered will have the
060 * last "s" removed from the collection name if it ends
061 * with the letter "s". If false, this method acts like {@link #validateDocumentAndUpdatableReferencesRecursively(Document,
062 * int, boolean)}
063 */
064 public void validateDocumentAndUpdatableReferencesRecursively(Document document, int maxDepth,
065 boolean validateRequired, boolean chompLastLetterSFromCollectionName);
066
067 /**
068 * Validates the specified attribute of the given document against the data dictionary.
069 *
070 * @param document
071 * @param attributeName
072 * @param errorPrefix
073 */
074 public void validateDocumentAttribute(Document document, String attributeName, String errorPrefix);
075
076 /**
077 * Validates an object using its class name as the entry name to look up its metadata in the dictionary.
078 *
079 * @param object - an object to validate
080 * @return the dictionary validation result object associated with this validation
081 */
082 public DictionaryValidationResult validate(Object object);
083
084 /**
085 * Validate an object with the passed in dictionary entryName and the specific attribute to be evaluated
086 *
087 * @param object - an object to validate
088 * @param entryName - the dictionary entry name to look up the metadata associated with this object
089 * @param attributeName - the name of the attribute (field) on the object that should be validated
090 * @param doOptionalProcessing true if the validation should do optional validation (e.g. to check if empty values
091 * are required or not), false otherwise
092 * @return the dictionary validation result object associated with this validation
093 * @since 1.1
094 */
095 public DictionaryValidationResult validate(Object object, String entryName, String attributeName,
096 boolean doOptionalProcessing);
097
098 /**
099 * Same as {@link DictionaryValidationService#validate(Object, String, String, boolean) except that it provides an
100 * explicit
101 * data dictionary
102 * entry to use for the purpose of validation.
103 *
104 * @param object - an object to validate
105 * @param entryName - the dictionary entry name to use in association with error look ups
106 * @param entry - the dictionary entry to use for validation
107 * @param doOptionalProcessing true if the validation should do optional validation (e.g. to check if empty values
108 * are required or not), false otherwise
109 * @return the dictionary validation result object associated with this validation
110 * @since 1.1
111 */
112 public DictionaryValidationResult validate(Object object, String entryName, DataDictionaryEntry entry,
113 boolean doOptionalProcessing);
114
115 /**
116 * Validates the object agains the next state (or current state if there is no next state).
117 *
118 * <p>When no stateMapping exists on the DataDictionaryEntry that applies for this object, validation is considered
119 * stateless and all constraints are processed regardless of their states attribute.</p>
120 *
121 * @param object
122 * @return the dictionary validation result object associated with this validation
123 * @since 2.2
124 */
125 public DictionaryValidationResult validateAgainstNextState(Object object);
126
127 /**
128 * Validates the object against the state specified.
129 *
130 * <p>Important note: Alternatively the state can be changed on the
131 * object itself and another validation method can be used instead of this one (in practice, you'd revert the
132 * state on the object if validation returns errors).</p>
133 *
134 * @param object
135 * @param validationState
136 * @return the dictionary validation result object associated with this validation
137 * @since 2.2
138 */
139 public DictionaryValidationResult validateAgainstState(Object object, String validationState);
140
141 /**
142 * Same as other validate methods, except allows you to provide the attributeValueReader directly for evaluation
143 *
144 * @param valueReader - an object to validate
145 * @param doOptionalProcessing true if the validation should do optional validation (e.g. to check if empty values
146 * are required or not), false otherwise
147 * @return the dictionary validation result object associated with this validation
148 * @since 1.1
149 */
150 public DictionaryValidationResult validate(AttributeValueReader valueReader, boolean doOptionalProcessing,
151 String validationState, StateMapping stateMapping);
152
153 /**
154 * Encapsulates <code>{@link #validateBusinessObject(BusinessObject) and returns boolean so one doesn't need to
155 * check the
156 * ErrorMap.Validates the business object primitive attributes against the data dictionary. Adds errors to the map
157 * as they are
158 * encountered.<br/>
159 * <br/>
160 * Makes no error path adjustments
161 *
162 * @param businessObject - business object to validate
163 * @return boolean validOrNot
164 */
165 public boolean isBusinessObjectValid(BusinessObject businessObject);
166
167 /**
168 * Encapsulates <code>{@link #validateBusinessObject(BusinessObject) and returns boolean so one doesn't need to
169 * check the
170 * ErrorMap.Validates the business object primitive attributes against the data dictionary. Adds errors to the map
171 * as they are
172 * encountered.<br/>
173 * <br/>
174 * Makes no error path adjustments
175 *
176 * @param businessObject - business object to validate
177 * @param prefix - error prefix
178 * @return boolean valid or not
179 */
180 public boolean isBusinessObjectValid(BusinessObject businessObject, String prefix);
181
182 /**
183 * Validates the business object primitive attributes against the data dictionary. Adds errors to the map as they
184 * are
185 * encountered.
186 *
187 * @param businessObject - business object to validate
188 * @deprecated since 1.1 - use validate(Object.class) instead
189 */
190 @Deprecated
191 public void validateBusinessObject(BusinessObject businessObject);
192
193 /**
194 * Validates the business object primitive attributes against the data dictionary. Adds errors to the map as they
195 * are
196 * encountered.
197 *
198 * @param businessObject - business object to validate
199 * @param validateRequired - whether to execute required field checks
200 * @deprecated since 1.1 - use validate(Object.class) instead
201 */
202 @Deprecated
203 public void validateBusinessObject(BusinessObject businessObject, boolean validateRequired);
204
205 /**
206 * This method examines the populated BusinessObject bo instance passed in for a member named by the referenceName.
207 * If this
208 * member exists, and if this member is a descendent of BusinessObject, then an existence check proceeds.
209 *
210 * First the foreign keys for this reference are gathered, and then examined to see if they have values. If they do
211 * not have
212 * values, the method ends with a true return value. If they all have values, then an object with those primary
213 * keys
214 * is retrieve
215 * from the database. If one is retrieve, then the reference exists, and True is returned. Otherwise, false is
216 * returned.
217 *
218 * This method assumes that you already have the errorPath set exactly as desired, and adds new errors to the
219 * errorMap with no
220 * prefix, other than what has already been pushed onto the errorMap.
221 *
222 * @param bo - The bo whose reference is being tested.
223 * @param reference - The ReferenceDefinition to be existence tested.
224 * @return True if no exceptions occur and the object exists in the db, false otherwise.
225 */
226 public boolean validateReferenceExists(BusinessObject bo, ReferenceDefinition reference);
227
228 /**
229 * This method examines the populated BusinessObject bo instance passed in for a member named by the referenceName.
230 * If this
231 * member exists, and if this member is a descendent of BusinessObject, then an existence check proceeds.
232 *
233 * First the foreign keys for this reference are gathered, and then examined to see if they have values. If they do
234 * not have
235 * values, the method ends with a true return value. If they all have values, then an object with those primary
236 * keys
237 * is retrieve
238 * from the database. If one is retrieve, then the reference exists, and True is returned. Otherwise, false is
239 * returned.
240 *
241 * This method assumes that you already have the errorPath set exactly as desired, and adds new errors to the
242 * errorMap with no
243 * prefix, other than what has already been pushed onto the errorMap.
244 *
245 * @param bo - The bo whose reference is being tested.
246 * @param referenceName - The name of the member to be existence tested.
247 * @return True if no exceptions occur and the object exists in the db, false otherwise.
248 */
249 public boolean validateReferenceExists(BusinessObject bo, String referenceName);
250
251 /**
252 * This method retrieves the reference from the DB, and then tests whether the object is active.
253 *
254 * It will return false if there is no activeIndicator field on this object, if the object doesnt exist in the DB,
255 * if the field
256 * doesnt exist or cannot be cast as a boolean, if the field value is null, or if the field value is false.
257 *
258 * It will only return true if the reference bo is present, the field is present, it is a boolean and non-null, and
259 * the value is
260 * true.
261 *
262 * This method assumes that you already have the errorPath set exactly as desired, and adds new errors to the
263 * errorMap with no
264 * prefix, other than what has already been pushed onto the errorMap.
265 *
266 * @param bo
267 * @param reference
268 * @return
269 */
270 public boolean validateReferenceIsActive(BusinessObject bo, ReferenceDefinition reference);
271
272 /**
273 * This method retrieves the reference from the DB, and then tests whether the object is active.
274 *
275 * It will return false if there is no activeIndicator field on this object, if the object doesnt exist in the DB,
276 * if the field
277 * doesnt exist or cannot be cast as a boolean, if the field value is null, or if the field value is false.
278 *
279 * It will only return true if the reference bo is present, the field is present, it is a boolean and non-null, and
280 * the value is
281 * true.
282 *
283 * This method assumes that you already have the errorPath set exactly as desired, and adds new errors to the
284 * errorMap with no
285 * prefix, other than what has already been pushed onto the errorMap.
286 *
287 * @param bo
288 * @param referenceName
289 * @return
290 */
291 public boolean validateReferenceIsActive(BusinessObject bo, String referenceName);
292
293 /**
294 * validateReferenceExistsAndIsActive intelligently tests the designated reference on the bo for both existence and
295 * active status, where
296 * appropriate
297 *
298 * <p>It will not test anything if the foreign-key fields for the given reference aren't filled out with values,
299 * and
300 * it
301 * will not test active status if the reference doesn't exist.</p>
302 *
303 * <p>Further, it will only test active status where the correct flag is set.</p>
304 *
305 * <p>On failures of either sort, it will put the relevant errors into the GlobalVariables errorMap, and return a
306 * false. If there
307 * are no failures, or nothing can be tested because the foreign-key fields arent fully filled out, it will return
308 * true and add
309 * no errors.</p>
310 *
311 * <p>This method assumes that you already have the errorPath set exactly as desired, and adds new errors to the
312 * errorMap with no
313 * prefix, other than what has already been pushed onto the errorMap.</p>
314 *
315 * @param bo - the BusinessObject instance to be tested.
316 * @param reference - the ReferenceDefinition to control the nature of the testing.
317 * @return true or false as per the criteria above
318 */
319 public boolean validateReferenceExistsAndIsActive(BusinessObject bo, ReferenceDefinition reference);
320
321 /**
322 * This method intelligently tests the designated reference on the bo for both existence and active status, where
323 * appropriate.
324 *
325 * It will not test anything if the foreign-key fields for the given reference arent filled out with values, and it
326 * will not
327 * test active status if the reference doesnt exist.
328 *
329 * Note that it will not fail or raise any error if all of the foreign-keys are filled with a value. If this needs
330 * to be tested
331 * (ie, the 'if any field is filled, then all must be filled' rule), you'll have to do that separately.
332 *
333 * Further, it will only test active status where the correct flag is set.
334 *
335 * On failures of either sort, it will put the relevant errors into the GlobalVariables errorMap, and return a
336 * false. If there
337 * are no failures, or nothing can be tested because the foreign-key fields arent fully filled out, it will return
338 * true and add
339 * no errors.
340 *
341 * This method assumes that you already have the errorPath set exactly as desired, and adds new errors to the
342 * errorMap with no
343 * prefix, other than what has already been pushed onto the errorMap.
344 *
345 * @param bo - the BusinessObject instance to be tested.
346 * @param referenceName - the member name on the bo to be tested for existence and active-state
347 * @param attributeToHighlightOnFail - the fieldName to highlight with the error message on a failure
348 * @param displayFieldName - the human-readable display name of the failed field, to go in the error message
349 * @return true or false as per the criteria above
350 */
351 public boolean validateReferenceExistsAndIsActive(BusinessObject bo, String referenceName,
352 String attributeToHighlightOnFail, String displayFieldName);
353
354 /**
355 * This method does an existence check against all references of a BusinessObject as defined in the
356 * MaintenanceDocument.xml file
357 * for that business object.
358 *
359 * Appropriate errors will also be placed in the GlobalVariables.ErrorMap.
360 *
361 * This method assumes that you already have the errorPath set exactly as desired, and adds new errors to the
362 * errorMap with no
363 * prefix, other than what has already been pushed onto the errorMap.
364 *
365 * @param bo - BusinessObject instance that should be tested
366 * @return true if all passed existence tests, false if any failed
367 */
368 public boolean validateDefaultExistenceChecks(BusinessObject bo);
369
370 /**
371 * Does an existence check against all references configured as a default existence check in the maintenance
372 * document data dictionary file for the given business object
373 *
374 * Appropriate errors will also be placed in the GlobalVariables.ErrorMap.
375 *
376 * This method assumes that you already have the errorPath set exactly as desired, and adds new errors to the
377 * errorMap
378 * with no
379 * prefix, other than what has already been pushed onto the errorMap.
380 *
381 * @param bo parent business object instance to retrieve default checks for
382 * @param newCollectionItem new collection line to validate
383 * @param collectionName name of the collection in the parent
384 * @return true if all passed existence tests, false if any failed
385 */
386 public boolean validateDefaultExistenceChecksForNewCollectionItem(BusinessObject bo,
387 BusinessObject newCollectionItem, String collectionName);
388
389 /**
390 * This method does an existence check against all references of a transactionalDocument
391 *
392 * Appropriate errors will also be placed in the GlobalVariables.ErrorMap.
393 *
394 * This method assumes that you already have the errorPath set exactly as desired, and adds new errors to the
395 * errorMap
396 * with no
397 * prefix, other than what has already been pushed onto the errorMap.
398 *
399 * @param document document instance that should be tested
400 * @return true if all passed existence tests, false if any failed
401 */
402 public boolean validateDefaultExistenceChecksForTransDoc(TransactionalDocument document);
403
404 /**
405 * This method does an existence check against all references of a transactionalDocument
406 *
407 * Appropriate errors will also be placed in the GlobalVariables.ErrorMap.
408 *
409 * This method assumes that you already have the errorPath set exactly as desired, and adds new errors to the
410 * errorMap
411 * with no
412 * prefix, other than what has already been pushed onto the errorMap.
413 *
414 * @param document document instance that should be tested
415 * @param accountingLine that should be tested
416 * @param collectionName that should be tested
417 * @return true if all passed existence tests, false if any failed
418 */
419 public boolean validateDefaultExistenceChecksForNewCollectionItem(TransactionalDocument document,
420 BusinessObject accountingLine, String collectionName);
421
422 /**
423 * @deprecated since 1.1
424 */
425 @Deprecated
426 public void validatePrimitiveFromDescriptor(String entryName, Object object, PropertyDescriptor propertyDescriptor,
427 String errorPrefix, boolean validateRequired);
428 }