Coverage Report - org.kuali.student.enrollment.lpr.mock.CriteriaMatcher
 
Classes in this File Line Coverage Branch Coverage Complexity
CriteriaMatcher
0%
0/146
0%
0/86
5.222
CriteriaMatcher$1
0%
0/1
N/A
5.222
 
 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.enrollment.lpr.mock;
 17  
 
 18  
 import java.beans.BeanInfo;
 19  
 import java.beans.IntrospectionException;
 20  
 import java.beans.Introspector;
 21  
 import java.beans.PropertyDescriptor;
 22  
 import java.sql.Timestamp;
 23  
 import java.text.DateFormat;
 24  
 import java.text.ParseException;
 25  
 import java.text.SimpleDateFormat;
 26  
 import java.util.Date;
 27  
 import java.util.HashMap;
 28  
 import java.util.List;
 29  
 import java.util.Map;
 30  
 import org.kuali.student.common.dto.ContextInfo;
 31  
 import org.kuali.student.common.dto.CriteriaInfo;
 32  
 import org.kuali.student.common.exceptions.DoesNotExistException;
 33  
 import org.kuali.student.common.exceptions.MissingParameterException;
 34  
 import org.kuali.student.common.exceptions.PermissionDeniedException;
 35  
 import org.kuali.student.common.exceptions.InvalidParameterException;
 36  
 import org.kuali.student.common.exceptions.OperationFailedException;
 37  
 import org.kuali.student.common.infc.HoldsDataDictionaryService;
 38  
 import org.kuali.student.datadictionary.dto.AttributeDefinitionInfo;
 39  
 import org.kuali.student.datadictionary.dto.DictionaryEntryInfo;
 40  
 import org.kuali.student.datadictionary.service.DataDictionaryService;
 41  
 
 42  
 /**
 43  
  * A helper class for the Mock implementation to match criteria to values on the object
 44  
  * @author nwright
 45  
  */
 46  
 public class CriteriaMatcher implements HoldsDataDictionaryService {
 47  
 
 48  
     private DataDictionaryService dataDictionaryService;
 49  
 
 50  
     public DataDictionaryService getDataDictionaryService() {
 51  0
         return dataDictionaryService;
 52  
     }
 53  
 
 54  
     public void setDataDictionaryService(DataDictionaryService dataDictionaryService) {
 55  0
         this.dataDictionaryService = dataDictionaryService;
 56  0
     }
 57  
     private List<CriteriaInfo> criterias;
 58  
     private Class<?> infoClass;
 59  
     private String dictEntryKey;
 60  
     private ContextInfo context;
 61  
 
 62  
     public CriteriaMatcher(List<CriteriaInfo> criterias, Class<?> infoClass, ContextInfo context)
 63  
             throws InvalidParameterException,
 64  0
             OperationFailedException {
 65  0
         this.criterias = criterias;
 66  0
         this.infoClass = infoClass;
 67  0
         this.context = context;
 68  0
         this.dictEntryKey = this.calcDictEntryKey();
 69  0
         this.validate();
 70  0
     }
 71  
 
 72  
     private String calcDictEntryKey(Class<?> clazz) {
 73  0
         return initLower(clazz.getSimpleName());
 74  
     }
 75  
 
 76  
     private String calcDictEntryKey() {
 77  0
         return calcDictEntryKey(this.infoClass);
 78  
     }
 79  
 
 80  
     private void validate()
 81  
             throws InvalidParameterException,
 82  
             OperationFailedException {
 83  0
         int i = 0;
 84  0
         for (CriteriaInfo criteria : criterias) {
 85  0
             this.validate(i, criteria);
 86  0
             i++;
 87  
         }
 88  0
     }
 89  
 
 90  
     private void validate(int i, CriteriaInfo criteria)
 91  
             throws InvalidParameterException,
 92  
             OperationFailedException {
 93  0
         String fk = criteria.getFieldKey();
 94  0
         String op = criteria.getOperator();
 95  0
         String fv = criteria.getValue();
 96  0
         AttributeDefinitionInfo ad = this.getAttributeDefinition(fk);
 97  0
         if (ad == null) {
 98  0
             throw new InvalidParameterException("The " + i + "th criteria's field key " + fk + " is invalid");
 99  
         }
 100  0
         if (op == null) {
 101  0
             throw new InvalidParameterException("The " + i + "th criteria's operator is null");
 102  
         }
 103  0
         if (op.equals("=")) {
 104  0
             return;
 105  
         }
 106  0
         if (op.equals("<")) {
 107  0
             return;
 108  
         }
 109  0
         if (op.equals(">")) {
 110  0
             return;
 111  
         }
 112  0
         if (op.equals("!=")) {
 113  0
             return;
 114  
         }
 115  0
         if (op.equals("<=")) {
 116  0
             return;
 117  
         }
 118  0
         if (op.equals(">=")) {
 119  0
             return;
 120  
         }
 121  0
         if (fv == null) {
 122  0
             if (!op.equals("=") && !op.equals("<>")) {
 123  0
                 throw new InvalidParameterException("The " + i + "th criteria's value is null but the operator " + op + " is a comparison operator that does not apply");
 124  
             }
 125  0
             return;
 126  
         }
 127  0
         boolean isList = calcIsList(ad);
 128  0
         switch (ad.getDataType()) {
 129  
             case STRING:
 130  0
                 break;
 131  
             case DATE:
 132  
             case TRUNCATED_DATE:
 133  0
                 break;
 134  
             case BOOLEAN:
 135  0
                 if (op.equals(">") || op.equals("<") || op.equals(">=") || op.equals("<=")) {
 136  0
                     throw new InvalidParameterException("The " + i + "th criteria's operator " + op + " is a comparison operator that does not apply to the field's boolean data type");
 137  
                 }
 138  
             case INTEGER:
 139  
             case FLOAT:
 140  
             case DOUBLE:
 141  
             case LONG:
 142  0
                 break;
 143  
             case COMPLEX:
 144  0
                 if (fv != null) {
 145  0
                     throw new InvalidParameterException("The " + i + "th criteria's value is not null but attribute type is complex. Complex can only be checked to see if it is null or not null");
 146  
                 }
 147  
         }
 148  0
         parseValue (i, criteria, ad);
 149  0
     }
 150  
 
 151  
     private Object parseValue(int i, CriteriaInfo criteria, AttributeDefinitionInfo ad) throws InvalidParameterException {
 152  0
         String fk = criteria.getFieldKey();
 153  0
         String op = criteria.getOperator();
 154  0
         String fv = criteria.getValue();
 155  0
         if (fv == null) {
 156  0
             return null;
 157  
         }
 158  0
         switch (ad.getDataType()) {
 159  
             case STRING:
 160  0
                 return parseString(i, fv);
 161  
             case DATE:
 162  0
                 return parseDateTime(i, fv);
 163  
             case TRUNCATED_DATE:
 164  0
                 return parseDate(i, fv);
 165  
             case BOOLEAN:
 166  0
                 return parseBoolean(i, fv);
 167  
             case INTEGER:
 168  0
                 return parseInteger(i, fv);
 169  
             case FLOAT:
 170  0
                 return parseFloat(i, fv);
 171  
             case DOUBLE:
 172  0
                 return parseDouble(i, fv);
 173  
             case LONG:
 174  0
                 return parseLong(i, fv);
 175  
             case COMPLEX:
 176  0
                 throw new InvalidParameterException("The " + i + "th criteria's value is not null but attribute type is complex. Complex can only be checked to see if it is null or not null");
 177  
             default:
 178  0
                 throw new IllegalArgumentException("Unknown/unhandled datatype " + ad.getDataType());
 179  
         }
 180  
     }
 181  
 
 182  
     private String parseString(int i, String fv) throws InvalidParameterException {
 183  0
         return fv;
 184  
     }
 185  
 
 186  
     private Timestamp parseDateTime(int i, String fv) throws InvalidParameterException {
 187  0
         DateFormat df = new SimpleDateFormat("yyyy-MM-dd-hh.mm.ss");
 188  
         try {
 189  0
             return new Timestamp(df.parse(fv).getTime());
 190  0
         } catch (ParseException ex) {
 191  0
             throw new InvalidParameterException("The " + i + "th criteria's value " + fv + " cannot be parsed as a dateTime");
 192  
         }
 193  
     }
 194  
 
 195  
     private Date parseDate(int i, String fv) throws InvalidParameterException {
 196  0
         DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
 197  
         try {
 198  0
             return df.parse(fv);
 199  0
         } catch (ParseException ex) {
 200  0
             throw new InvalidParameterException("The " + i + "th criteria's value " + fv + " cannot be parsed as a date");
 201  
         }
 202  
     }
 203  
 
 204  
     private Integer parseInteger(int i, String fv) throws InvalidParameterException {
 205  
         try {
 206  0
             return Integer.parseInt(fv);
 207  0
         } catch (NumberFormatException ex) {
 208  0
             throw new InvalidParameterException("The " + i + "th criteria's value " + fv + " cannot be parsed as an integer");
 209  
         }
 210  
     }
 211  
 
 212  
     private Long parseLong(int i, String fv) throws InvalidParameterException {
 213  
         try {
 214  0
             return Long.parseLong(fv);
 215  0
         } catch (NumberFormatException ex) {
 216  0
             throw new InvalidParameterException("The " + i + "th criteria's value " + fv + " cannot be parsed as a Long");
 217  
         }
 218  
     }
 219  
 
 220  
     private Boolean parseBoolean(int i, String fv) throws InvalidParameterException {
 221  0
         if (fv.equalsIgnoreCase("true")) {
 222  0
             return Boolean.TRUE;
 223  
         }
 224  0
         if (fv.equalsIgnoreCase("false")) {
 225  0
             return Boolean.FALSE;
 226  
         }
 227  0
         throw new InvalidParameterException("The " + i + "th criteria's value " + fv + " cannot be parsed as a Boolean");
 228  
 
 229  
     }
 230  
 
 231  
     private Float parseFloat(int i, String fv) throws InvalidParameterException {
 232  
         try {
 233  0
             return Float.parseFloat(fv);
 234  0
         } catch (NumberFormatException ex) {
 235  0
             throw new InvalidParameterException("The " + i + "th criteria's value " + fv + " cannot be parsed as an float");
 236  
         }
 237  
     }
 238  
 
 239  
     private Double parseDouble(int i, String fv) throws InvalidParameterException {
 240  
         try {
 241  0
             return Double.parseDouble(fv);
 242  0
         } catch (NumberFormatException ex) {
 243  0
             throw new InvalidParameterException("The " + i + "th criteria's value " + fv + " cannot be parsed as an double");
 244  
         }
 245  
     }
 246  
 
 247  
     private String initLower(String str) {
 248  0
         if (str == null) {
 249  0
             return null;
 250  
         }
 251  0
         if (str.length() == 0) {
 252  0
             return str;
 253  
         }
 254  0
         if (str.length() == 1) {
 255  0
             return str.toLowerCase();
 256  
         }
 257  0
         return str.substring(0, 1).toLowerCase() + str.substring(1);
 258  
     }
 259  
 
 260  
     private boolean calcIsList(AttributeDefinitionInfo ad) {
 261  0
         if (ad.getMaxOccurs() == null) {
 262  0
             return false;
 263  
         }
 264  0
         if (ad.getMaxOccurs() <= 1) {
 265  0
             return false;
 266  
         }
 267  0
         return true;
 268  
 
 269  
     }
 270  
 
 271  
     private DictionaryEntryInfo getDictionaryEntry()
 272  
             throws InvalidParameterException,
 273  
             OperationFailedException {
 274  0
         DictionaryEntryInfo entry = null;
 275  
         try {
 276  0
             entry = dataDictionaryService.getDataDictionaryEntry(dictEntryKey, context);
 277  0
         } catch (MissingParameterException ex) {
 278  0
             throw new OperationFailedException("failed checking dictionary", ex);
 279  0
         } catch (PermissionDeniedException ex) {
 280  0
             throw new OperationFailedException("failed checking dictionary", ex);
 281  0
         } catch (DoesNotExistException ex) {
 282  0
             throw new OperationFailedException("failed checking dictionary", ex);
 283  0
         }
 284  0
         return entry;
 285  
     }
 286  
 
 287  
     private AttributeDefinitionInfo getAttributeDefinition(String fk)
 288  
             throws InvalidParameterException,
 289  
             OperationFailedException {
 290  0
         return this.getAttributeDefinition(this.getDictionaryEntry(), fk);
 291  
     }
 292  
 
 293  
     private AttributeDefinitionInfo getAttributeDefinition(DictionaryEntryInfo entry, String fk) {
 294  0
         return this.getAttributeDefinition(entry, fk);
 295  
     }
 296  
 
 297  
     private AttributeDefinitionInfo getAttributeDefinition(List<AttributeDefinitionInfo> attributes, String fk) {
 298  0
         for (AttributeDefinitionInfo ad : attributes) {
 299  0
             if (ad.getName().equals(fk)) {
 300  0
                 return ad;
 301  
             }
 302  
         }
 303  0
         return null;
 304  
     }
 305  
 
 306  
     private Map<String, PropertyDescriptor> getBeanInfo(Class<?> clazz) {
 307  0
         Map<String, PropertyDescriptor> properties = new HashMap<String, PropertyDescriptor>();
 308  0
         BeanInfo beanInfo = null;
 309  
         try {
 310  0
             beanInfo = Introspector.getBeanInfo(clazz);
 311  0
         } catch (IntrospectionException e) {
 312  0
             throw new RuntimeException(e);
 313  0
         }
 314  0
         PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
 315  0
         for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
 316  0
             properties.put(propertyDescriptor.getName(), propertyDescriptor);
 317  
         }
 318  0
         return properties;
 319  
     }
 320  
 
 321  
     public boolean matches(Object infoObject)
 322  
             throws InvalidParameterException {
 323  0
         return true;
 324  
     }
 325  
 
 326  
     private boolean equals(int obj1, int obj2) {
 327  0
         if (obj1 == obj2) {
 328  0
             return true;
 329  
         }
 330  0
         return false;
 331  
     }
 332  
 
 333  
     private boolean equals(long obj1, long obj2) {
 334  0
         if (obj1 == obj2) {
 335  0
             return true;
 336  
         }
 337  0
         return false;
 338  
     }
 339  
 
 340  
     private boolean equals(Object obj1, Object obj2) {
 341  0
         if (obj1 == obj2) {
 342  0
             return true;
 343  
         }
 344  0
         if (obj1 == null) {
 345  0
             return false;
 346  
         }
 347  0
         if (obj1.equals(obj2)) {
 348  0
             return true;
 349  
         }
 350  0
         return false;
 351  
     }
 352  
 }
 353