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    }