Clover Coverage Report - KS Enroll API 1.3.0-SNAPSHOT
Coverage timestamp: Tue Apr 19 2011 12:34:23 EST
../../../../../img/srcFileCovDistChart1.png 42% of files have more coverage
156   364   87   7.09
76   279   0.56   11
22     3.95  
2    
 
  CriteriaValidatorParser       Line # 50 156 0% 87 238 6.3% 0.062992126
  CriteriaValidatorParser.Operator       Line # 52 0 - 0 0 - -1.0
 
  (1)
 
1    /*
2    * Copyright 2011 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.osedu.org/licenses/ECL-2.0
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.student.datadictionary.util;
17   
18    import java.sql.Timestamp;
19    import java.text.DateFormat;
20    import java.text.ParseException;
21    import java.text.SimpleDateFormat;
22    import java.util.ArrayList;
23    import java.util.Date;
24    import java.util.List;
25   
26    import org.kuali.rice.kns.datadictionary.validation.DataType;
27    import org.kuali.student.common.infc.Comparison;
28    import org.kuali.student.common.infc.Criteria;
29    import org.kuali.student.datadictionary.infc.AttributeDefinitionInfc;
30    import org.kuali.student.datadictionary.infc.DictionaryEntry;
31    import org.kuali.student.r2.common.exceptions.InvalidParameterException;
32    import org.kuali.student.r2.common.exceptions.OperationFailedException;
33   
34    /**
35    * A class that validates the criteria against the dictionary
36    *
37    * It also sets the parsedValues and parsedOperators so they may be used in the implementation
38    * The call sequence is sometehing like this:
39    * <ol>
40    * <li>construct this validator
41    * <li>Configure this validator with criteria to be valiated
42    * <li>Get the dictionary entry of the object to be validated by calling DataDictionaryServiceInfc.getDataDictionaryEntry (the ref object's URI)
43    * <li>Configure this validator with the dictionary entry that you just got from the dictionary
44    * <li>Call the validate () method which will throw exceptions if problems
45    * <li>get the parsed values (@see getParsedValues ()) and use them in the implementation
46    * <li>Get the parsed operators and use in the implementation, if you want
47    * </ol>
48    * @author nwright
49    */
 
50    public class CriteriaValidatorParser {
51   
 
52    public enum Operator {
53   
54    EQ, IN, GT, LT, NEQ, GTE, LTE, LIKE, BETWEEN;
55    }
56    private Criteria criteria;
57    private DictionaryEntry dictionaryEntry;
58    private transient List<Object> parsedValues;
59    private transient List<Operator> parsedOperators;
60   
 
61  3 toggle public CriteriaValidatorParser() {
62    }
63   
 
64  0 toggle public Criteria getCriteria() {
65  0 return criteria;
66    }
67   
 
68  3 toggle public void setCriteria(Criteria criteria) {
69  3 this.criteria = criteria;
70    }
71   
 
72  0 toggle public DictionaryEntry getDictionaryEntry() {
73  0 return dictionaryEntry;
74    }
75   
 
76  3 toggle public void setDictionaryEntry(DictionaryEntry dictionaryEntry) {
77  3 this.dictionaryEntry = dictionaryEntry;
78    }
79   
80    /**
81    * Get the string operators translated as an Operator enum
82    * @return list of operators in the same ordinal position as the supplied operators in the list of ComparisonInfc objects
83    */
 
84  3 toggle public List<Operator> getParsedOperators() {
85  3 return parsedOperators;
86    }
87   
88    /**
89    * The values parsed as their respective data types, String, Date, Integer, etc.
90    *
91    * Special considerations:
92    * IN operators return a List of one or more parsed values who's order is the samne as the order in the ComparisonInfc
93    * BETWEEN operators return a list of two parsed values who's values coorespond to the from to values of a between operation.
94    *
95    * @return a list of parsed values in the same ordinal positions as the unparsed values in the list of ComparisonInfc objects
96    */
 
97  3 toggle public List<Object> getParsedValues() {
98  3 return parsedValues;
99    }
100   
101   
102   
103    /**
104    * Validate the criteria thowing an InvalidParameterException if there are problems
105    *
106    * TODO: Consider getting all the errors and throw them as a group instead of as we find them
107    *
108    * @throws InvalidParameterException
109    * @throws OperationFailedException
110    */
 
111  3 toggle public void validate()
112    throws InvalidParameterException,
113    OperationFailedException {
114  3 parsedValues = new ArrayList<Object>();
115  3 parsedOperators = new ArrayList <Operator> ();
116  3 if (this.criteria.getComparisons() == null) {
117  0 throw new InvalidParameterException ("Comparisons list is null -- to select all specify an empty list");
118    }
119  3 int i = 0;
120  3 for (Comparison comparison : this.criteria.getComparisons()) {
121  0 this.validate(i, comparison);
122  0 i++;
123    }
124    }
125   
 
126  0 toggle private void validate(int i, Comparison comparison)
127    throws InvalidParameterException,
128    OperationFailedException {
129  0 String fieldKey = comparison.getFieldKey();
130  0 String operator = comparison.getOperator();
131  0 List<String> values = comparison.getValues();
132  0 AttributeDefinitionInfc ad = this.getAttributeDefinition(fieldKey);
133  0 if (ad == null) {
134  0 throw new InvalidParameterException("The " + i + "th comparison's field key " + fieldKey + " is not defined in the dictionary");
135    }
136  0 if (operator == null) {
137  0 throw new InvalidParameterException("The " + i + "th comparison's operator is null");
138    }
139  0 if (operator.equals("=")) {
140  0 this.parsedOperators.add(Operator.EQ);
141  0 } else if (operator.equals("<")) {
142  0 this.parsedOperators.add(Operator.LT);
143  0 } else if (operator.equals(">")) {
144  0 this.parsedOperators.add(Operator.GT);
145  0 } else if (operator.equals("!=")) {
146  0 this.parsedOperators.add(Operator.NEQ);
147  0 } else if (operator.equals("<=")) {
148  0 this.parsedOperators.add(Operator.LTE);
149  0 } else if (operator.equals(">=")) {
150  0 this.parsedOperators.add(Operator.GTE);
151  0 } else if (operator.equals("in")) {
152  0 this.parsedOperators.add(Operator.IN);
153  0 } else if (operator.equals("between")) {
154  0 this.parsedOperators.add(Operator.BETWEEN);
155  0 } else if (operator.equals("like")) {
156  0 this.parsedOperators.add(Operator.LIKE);
157  0 if (ad.getDataType().equals (DataType.STRING)) {
158  0 throw new InvalidParameterException("The " + i + "th comparison's operator is LIKE which can only be applied to strings, " + ad.getDataType() + " is invalid.");
159    }
160    } else {
161  0 throw new InvalidParameterException("The " + i + "th comparison's operator, " + operator + ", is invalid.");
162    }
163  0 if (values == null) {
164  0 throw new InvalidParameterException("The " + i + "th comparison's values list is required and cannot be null");
165    }
166  0 if (values.isEmpty()) {
167  0 throw new InvalidParameterException("The " + i + "th comparison's values list is required and cannot be an empty list");
168    }
169  0 if (values.get(0) == null) {
170  0 if (!operator.equals("=") && !operator.equals("!=")) {
171  0 throw new InvalidParameterException("The " + i + "th comparison's value is null but the operator " + operator + " is a comparison operator that does not apply");
172    }
173  0 return;
174    }
175  0 if (operator.equals("between")) {
176  0 if (values.size() != 2) {
177  0 throw new InvalidParameterException("The " + i + "th comparison is a between operator which requires two values, found " + values.size());
178    }
179  0 if (values.get(0) == null) {
180  0 throw new InvalidParameterException("The " + i + "th comparison is a between operator but the first value is null");
181    }
182  0 if (values.get(1) == null) {
183  0 throw new InvalidParameterException("The " + i + "th comparison is a between operator but the second value is null");
184    }
185  0 } else if (values.size() > 1) {
186  0 if (!operator.equals("in")) {
187  0 throw new InvalidParameterException("The " + i + "th comparison's value is a list but the operator " + operator + " is a comparison operator that does not apply");
188    }
189    }
190  0 switch (ad.getDataType()) {
191  0 case STRING:
192  0 break;
193  0 case DATE:
194  0 case TRUNCATED_DATE:
195  0 break;
196  0 case BOOLEAN:
197  0 if (! operator.equals("=") && !operator.equals("!=")) {
198  0 throw new InvalidParameterException("The " + i + "th comparison's operator " + operator + " is a comparison operator that does not apply to the field's boolean data type");
199    }
200  0 case INTEGER:
201  0 case FLOAT:
202  0 case DOUBLE:
203  0 case LONG:
204  0 break;
205  0 case COMPLEX:
206  0 if (! operator.equals("=") && !operator.equals("!=")) {
207  0 throw new InvalidParameterException("The " + i + "th comparison's operator " + operator + " is a comparison operator that does not apply to the field's complex data type");
208    }
209  0 if (values.get(0) == null) {
210  0 throw new InvalidParameterException("The " + i + "th comparison's value is not null but attribute type is complex. Complex can only be checked to see if it is null or not null");
211    }
212    }
213  0 parsedValues.add(parseValues(i, ad.getDataType(), comparison.getValues(), comparison.isIgnoreCase()));
214    }
215   
 
216  0 toggle private Object parseValues(int i, DataType dataType, List<String> values, boolean ignoreCase)
217    throws InvalidParameterException {
218  0 if (values.size() == 1) {
219  0 return parseValue(i, dataType, values.get(0), ignoreCase);
220    }
221  0 List<Object> list = new ArrayList<Object>();
222  0 for (String value : values) {
223  0 list.add(parseValue(i, dataType, value, ignoreCase));
224    }
225  0 return list;
226    }
227   
 
228  0 toggle private Object parseValue(int i, DataType dataType, String value, boolean ignoreCase)
229    throws InvalidParameterException {
230  0 if (value == null) {
231  0 return null;
232    }
233  0 switch (dataType) {
234  0 case STRING:
235  0 return parseString(i, value, ignoreCase);
236  0 case DATE:
237  0 return parseDateTime(i, value);
238  0 case TRUNCATED_DATE:
239  0 return parseDate(i, value);
240  0 case BOOLEAN:
241  0 return parseBoolean(i, value);
242  0 case INTEGER:
243  0 return parseInteger(i, value);
244  0 case FLOAT:
245  0 return parseFloat(i, value);
246  0 case DOUBLE:
247  0 return parseDouble(i, value);
248  0 case LONG:
249  0 return parseLong(i, value);
250  0 case COMPLEX:
251  0 throw new InvalidParameterException("The " + i + "th comparison's value is not null but attribute type is complex. Complex can only be checked to see if it is null or not null");
252  0 default:
253  0 throw new IllegalArgumentException("Unknown/unhandled datatype " + dataType);
254    }
255    }
256   
 
257  0 toggle private String parseString(int i, String cv, boolean ignoreCase) throws InvalidParameterException {
258  0 if (cv == null) {
259  0 return null;
260    }
261  0 if (ignoreCase) {
262  0 return cv.toLowerCase();
263    }
264  0 return cv;
265    }
266   
 
267  0 toggle private Timestamp parseDateTime(int i, String cv) throws InvalidParameterException {
268  0 DateFormat df = new SimpleDateFormat("yyyy-MM-dd-hh.mm.ss");
269  0 try {
270  0 return new Timestamp(df.parse(cv).getTime());
271    } catch (ParseException ex) {
272  0 throw new InvalidParameterException("The " + i + "th comparison's value " + cv + " cannot be parsed as a dateTime");
273    }
274    }
275   
 
276  0 toggle private Date parseDate(int i, String cv) throws InvalidParameterException {
277  0 DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
278  0 try {
279  0 return df.parse(cv);
280    } catch (ParseException ex) {
281  0 throw new InvalidParameterException("The " + i + "th comparison's value " + cv + " cannot be parsed as a date");
282    }
283    }
284   
 
285  0 toggle private Integer parseInteger(int i, String cv) throws InvalidParameterException {
286  0 try {
287  0 return Integer.parseInt(cv);
288    } catch (NumberFormatException ex) {
289  0 throw new InvalidParameterException("The " + i + "th comparison's value " + cv + " cannot be parsed as an integer");
290    }
291    }
292   
 
293  0 toggle private Long parseLong(int i, String cv) throws InvalidParameterException {
294  0 try {
295  0 return Long.parseLong(cv);
296    } catch (NumberFormatException ex) {
297  0 throw new InvalidParameterException("The " + i + "th comparison's value " + cv + " cannot be parsed as a Long");
298    }
299    }
300   
 
301  0 toggle private Boolean parseBoolean(int i, String cv) throws InvalidParameterException {
302  0 if (cv.equalsIgnoreCase("true")) {
303  0 return Boolean.TRUE;
304    }
305  0 if (cv.equalsIgnoreCase("false")) {
306  0 return Boolean.FALSE;
307    }
308  0 throw new InvalidParameterException("The " + i + "th comparison's value " + cv + " cannot be parsed as a Boolean");
309   
310    }
311   
 
312  0 toggle private Float parseFloat(int i, String cv) throws InvalidParameterException {
313  0 try {
314  0 return Float.parseFloat(cv);
315    } catch (NumberFormatException ex) {
316  0 throw new InvalidParameterException("The " + i + "th comparison's value " + cv + " cannot be parsed as an float");
317    }
318    }
319   
 
320  0 toggle private Double parseDouble(int i, String cv) throws InvalidParameterException {
321  0 try {
322  0 return Double.parseDouble(cv);
323    } catch (NumberFormatException ex) {
324  0 throw new InvalidParameterException("The " + i + "th comparison's value " + cv + " cannot be parsed as an double");
325    }
326    }
327   
 
328  0 toggle private String initLower(String str) {
329  0 if (str == null) {
330  0 return null;
331    }
332  0 if (str.length() == 0) {
333  0 return str;
334    }
335  0 if (str.length() == 1) {
336  0 return str.toLowerCase();
337    }
338  0 return str.substring(0, 1).toLowerCase() + str.substring(1);
339    }
340   
 
341  0 toggle private boolean calcIsList(AttributeDefinitionInfc ad) {
342  0 if (ad.getMaxOccurs() == null) {
343  0 return false;
344    }
345  0 if (ad.getMaxOccurs() <= 1) {
346  0 return false;
347    }
348  0 return true;
349   
350    }
351   
 
352  0 toggle private AttributeDefinitionInfc getAttributeDefinition(String fk)
353    throws InvalidParameterException,
354    OperationFailedException {
355  0 for (AttributeDefinitionInfc ad : this.dictionaryEntry.getAttributes()) {
356  0 if (ad.getName().equals(fk)) {
357  0 return ad;
358    }
359    }
360  0 return null;
361    }
362   
363    }
364