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