View Javadoc
1   /**
2    * Copyright 2005-2014 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.krad.service;
17  
18  import org.kuali.rice.krad.bo.BusinessObject;
19  import org.kuali.rice.krad.datadictionary.DataDictionaryEntry;
20  import org.kuali.rice.krad.datadictionary.ReferenceDefinition;
21  import org.kuali.rice.krad.datadictionary.state.StateMapping;
22  import org.kuali.rice.krad.datadictionary.validation.AttributeValueReader;
23  import org.kuali.rice.krad.datadictionary.validation.result.DictionaryValidationResult;
24  import org.kuali.rice.krad.document.Document;
25  import org.kuali.rice.krad.document.TransactionalDocument;
26  
27  import java.beans.PropertyDescriptor;
28  
29  /**
30   * Defines the API for the validating against the data dictionary.
31   *
32   * @author Kuali Rice Team (rice.collab@kuali.org)
33   */
34  public interface DictionaryValidationService {
35  
36      /**
37       * Validates the contents of a document (i.e. attributes within a document) against the data dictionary.
38       *
39       * @param document - document to validate
40       */
41      public void validateDocument(Document document);
42  
43      /**
44       * Validates the contents of a document and recursively validates any of its updatable references
45       *
46       * @param document the document
47       * @param maxDepth the maximum numbers of levels to recurse
48       * @param validateRequired whether to validate whether a field is required and is currently blank
49       */
50      public void validateDocumentAndUpdatableReferencesRecursively(Document document, int maxDepth,
51              boolean validateRequired);
52  
53      /**
54       * Validates the contents of a document and recursively validates any of its updatable references
55       *
56       * @param document the document
57       * @param maxDepth the maximum numbers of levels to recurse
58       * @param validateRequired whether to validate whether a field is required and is currently blank
59       * @param chompLastLetterSFromCollectionName if true, the error path for any collections encountered will have the
60       * last "s" removed from the collection name if it ends
61       * with the letter "s".  If false, this method acts like {@link #validateDocumentAndUpdatableReferencesRecursively(Document,
62       * int, boolean)}
63       */
64      public void validateDocumentAndUpdatableReferencesRecursively(Document document, int maxDepth,
65              boolean validateRequired, boolean chompLastLetterSFromCollectionName);
66  
67      /**
68       * Validates the specified attribute of the given document against the data dictionary.
69       *
70       * @param document
71       * @param attributeName
72       * @param errorPrefix
73       */
74      public void validateDocumentAttribute(Document document, String attributeName, String errorPrefix);
75  
76      /**
77       * Validates an object using its class name as the entry name to look up its metadata in the dictionary.
78       *
79       * @param object - an object to validate
80       * @return the dictionary validation result object associated with this validation
81       */
82      public DictionaryValidationResult validate(Object object);
83  
84      /**
85       * Validate an object with the passed in dictionary entryName and the specific attribute to be evaluated
86       *
87       * @param object - an object to validate
88       * @param entryName - the dictionary entry name to look up the metadata associated with this object
89       * @param attributeName - the name of the attribute (field) on the object that should be validated
90       * @param doOptionalProcessing true if the validation should do optional validation (e.g. to check if empty values
91       * are required or not), false otherwise
92       * @return the dictionary validation result object associated with this validation
93       * @since 1.1
94       */
95      public DictionaryValidationResult validate(Object object, String entryName, String attributeName,
96              boolean doOptionalProcessing);
97  
98      /**
99       * Same as {@link DictionaryValidationService#validate(Object, String, String, boolean)} except
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 }