001 /**
002 * Copyright 2005-2014 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
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 }