1 /**
2 * Copyright 2005-2015 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 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 }