001    /**
002     * Copyright 2005-2012 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.validation.AttributeValueReader;
022    import org.kuali.rice.krad.datadictionary.validation.result.DictionaryValidationResult;
023    import org.kuali.rice.krad.document.Document;
024    import org.kuali.rice.krad.document.TransactionalDocument;
025    
026    import 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     */
033    public 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    }