Coverage Report - org.kuali.rice.core.api.criteria.CriteriaSupportUtils
 
Classes in this File Line Coverage Branch Coverage Complexity
CriteriaSupportUtils
80%
66/82
84%
54/64
10
CriteriaSupportUtils$PropertyConstants
0%
0/1
N/A
10
 
 1  
 /*
 2  
  * Copyright 2011 The Kuali Foundation
 3  
  *
 4  
  * Licensed under the Educational Community License, Version 1.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/ecl1.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.core.api.criteria;
 17  
 
 18  
 import java.lang.reflect.Field;
 19  
 import java.lang.reflect.Method;
 20  
 import java.math.BigDecimal;
 21  
 import java.math.BigInteger;
 22  
 import java.util.ArrayList;
 23  
 import java.util.Calendar;
 24  
 import java.util.Collections;
 25  
 import java.util.Date;
 26  
 import java.util.List;
 27  
 import java.util.concurrent.atomic.AtomicInteger;
 28  
 import java.util.concurrent.atomic.AtomicLong;
 29  
 
 30  
 import javax.xml.bind.annotation.XmlElement;
 31  
 import javax.xml.bind.annotation.XmlElements;
 32  
 
 33  
 import org.apache.commons.lang.StringUtils;
 34  
 
 35  
 /**
 36  
  * A class which includes various utilities and constants for use within the criteria API.
 37  
  * This class is intended to be for internal use only within the criteria API.
 38  
  * 
 39  
  * @author Kuali Rice Team (rice.collab@kuali.org)
 40  
  */
 41  
 final class CriteriaSupportUtils {
 42  
         
 43  0
         private CriteriaSupportUtils () {}
 44  
         
 45  
     /**
 46  
      * Defines various property constants for internal use within the criteria package.
 47  
      */
 48  0
     static class PropertyConstants {
 49  
             
 50  
             /**
 51  
              * A constant representing the property name for {@link PropertyPathExpression#getPropertyPath()}
 52  
              */
 53  
         final static String PROPERTY_PATH = "propertyPath";
 54  
         
 55  
             /**
 56  
              * A constant representing the property name for {@link ValuedExpression#getValue()}
 57  
              */
 58  
         final static String VALUE = "value";
 59  
         
 60  
         /**
 61  
          * A constant representing the method name for {@link ValuedExpression#getValue()}
 62  
          */
 63  
         final static String GET_VALUE_METHOD_NAME = "getValue";
 64  
     }
 65  
 
 66  
     /**
 67  
      * Validates the various properties of a {@link ValuedExpression}. 
 68  
      * 
 69  
      * @param valuedExpressionClass the type of the expression
 70  
      * @param propertyPath the propertyPath which is being configured on the expression
 71  
      * @param value the value which is being configured on the expression
 72  
      * 
 73  
      * @throws IllegalArgumentException if the propertPath is null or blank
 74  
      * @throws IllegalArgumentException if the value is null
 75  
      * @throws IllegalArgumentException if the given {@link ValuedExpression} class does not support the {@link CriteriaValue}
 76  
      */
 77  
     static void validateValuedExpressionConstruction(Class<? extends ValuedExpression> valuedExpressionClass, String propertyPath, CriteriaValue<?> value) {
 78  90
             if (StringUtils.isBlank(propertyPath)) {
 79  13
                         throw new IllegalArgumentException("Property path cannot be null or blank.");
 80  
                 }
 81  77
                 if (value == null) {
 82  1
                     throw new IllegalArgumentException("CriteriaValue cannot be null.");
 83  
                 }
 84  76
                 if (!CriteriaSupportUtils.supportsCriteriaValue(valuedExpressionClass, value)) {
 85  6
                     throw new IllegalArgumentException(valuedExpressionClass.getSimpleName() + " does not support the given CriteriaValue");
 86  
                 }
 87  70
     }
 88  
 
 89  
         static boolean supportsCriteriaValue(Class<? extends ValuedExpression> simpleExpressionClass, CriteriaValue<?> value) {
 90  85
             if (simpleExpressionClass == null) {
 91  2
                 throw new IllegalArgumentException("simpleExpressionClass was null");
 92  
             }
 93  83
             if (value == null) {
 94  1
                 throw new IllegalArgumentException("valueClass was null");
 95  
             }
 96  82
             XmlElements elementsAnnotation = CriteriaSupportUtils.findXmlElementsAnnotation(simpleExpressionClass);
 97  82
             if (elementsAnnotation != null) {
 98  82
                 XmlElement[] elements = elementsAnnotation.value();
 99  149
                 for (XmlElement element : elements) {
 100  142
                     if (value.getClass().equals(element.type())) {
 101  75
                         return true;
 102  
                     }
 103  
                 }
 104  
             }
 105  7
             return false;
 106  
         }
 107  
         
 108  
         private static XmlElements findXmlElementsAnnotation(Class<?> simpleExpressionClass) {
 109  82
                 if (simpleExpressionClass != null) {
 110  
                         try{
 111  82
                                 Field valueField = simpleExpressionClass.getDeclaredField(PropertyConstants.VALUE);
 112  82
                                 XmlElements elementsAnnotation = valueField.getAnnotation(XmlElements.class);
 113  82
                                 if (elementsAnnotation != null) {
 114  82
                                         return elementsAnnotation;
 115  
                                 }
 116  0
                         } catch (NoSuchFieldException e) {
 117  
                                 // ignore, try the method
 118  0
                         }
 119  
                         try {
 120  0
                                 Method valueMethod = simpleExpressionClass.getDeclaredMethod(PropertyConstants.GET_VALUE_METHOD_NAME, (Class<?>[])null);
 121  0
                                 XmlElements elementsAnnotation = valueMethod.getAnnotation(XmlElements.class);
 122  0
                                 if (elementsAnnotation == null) {
 123  0
                                         return CriteriaSupportUtils.findXmlElementsAnnotation(simpleExpressionClass.getSuperclass());
 124  
                                 }
 125  0
                                 return elementsAnnotation;
 126  0
                         } catch (NoSuchMethodException e) {
 127  0
                                 return CriteriaSupportUtils.findXmlElementsAnnotation(simpleExpressionClass.getSuperclass());
 128  
                         }
 129  
                 }
 130  0
                 return null;
 131  
         }
 132  
         
 133  
         static CriteriaValue<?> determineCriteriaValue(Object object) {
 134  59
                 if (object == null) {
 135  7
                         throw new IllegalArgumentException("Given criteria value cannot be null.");
 136  52
                 } else if (object instanceof CharSequence) {
 137  21
                         return new CriteriaStringValue((CharSequence)object);
 138  31
                 } else if (object instanceof Calendar) {
 139  6
                         return new CriteriaDateTimeValue((Calendar)object);
 140  25
                 } else if (object instanceof Date) {
 141  5
                         return new CriteriaDateTimeValue((Date)object);
 142  20
                 } else if (object instanceof BigInteger) {
 143  0
                         return new CriteriaIntegerValue((BigInteger)object);
 144  20
                 } else if (object instanceof Short) {
 145  1
                         return new CriteriaIntegerValue((Short)object);
 146  19
                 } else if (object instanceof Integer) {
 147  10
                         return new CriteriaIntegerValue((Integer)object);
 148  9
                 } else if (object instanceof AtomicInteger) {
 149  0
                         return new CriteriaIntegerValue((AtomicInteger)object);
 150  9
                 } else if (object instanceof Long) {
 151  1
                         return new CriteriaIntegerValue((Long)object);
 152  8
                 } else if (object instanceof AtomicLong) {
 153  0
                         return new CriteriaIntegerValue((AtomicLong)object);
 154  8
                 } else if (object instanceof BigDecimal) {
 155  3
                         return new CriteriaDecimalValue((BigDecimal)object);
 156  5
                 } else if (object instanceof Float) {
 157  0
                         return new CriteriaDecimalValue((Float)object);
 158  5
                 } else if (object instanceof Double) {
 159  5
                         return new CriteriaDecimalValue((Double)object);
 160  
                 }
 161  0
                 throw new IllegalArgumentException("Failed to translate the given object to a CriteriaValue: " + object);
 162  
         }
 163  
         
 164  
         static List<CriteriaValue<?>> determineCriteriaValueList(List<? extends Object> values) {
 165  13
                 if (values == null) {
 166  2
                         return null;
 167  11
                 } else if (values.isEmpty()) {
 168  2
                         return Collections.emptyList();
 169  
                 }
 170  9
                 List<CriteriaValue<?>> criteriaValues = new ArrayList<CriteriaValue<?>>();
 171  9
                 for (Object value : values) {
 172  16
                         criteriaValues.add(determineCriteriaValue(value));
 173  
                 }
 174  9
                 return criteriaValues;
 175  
         }
 176  
         
 177  
         /**
 178  
      * Validates the incoming list of CriteriaValue to ensure they are valid for a
 179  
      * {@link MultiValuedExpression}.  To be valid, the following must be true:
 180  
      * 
 181  
      * <ol>
 182  
      *   <li>The list of values must not be null.</li>
 183  
      *   <li>The list of values must not be empty.</li>
 184  
      *   <li>The list of values must all be of the same parameterized {@link CriteriaValue} type.</li>
 185  
      * </ol>
 186  
      */
 187  
     static void validateValuesForMultiValuedExpression(List<? extends CriteriaValue<?>> values) {
 188  49
             if (values == null) {
 189  4
                     throw new IllegalArgumentException("Criteria values cannot be null.");
 190  45
             } else if (values.isEmpty()) {
 191  4
                     throw new IllegalArgumentException("Criteria values cannot be empty.");
 192  
             }
 193  41
             Class<?> previousType = null;
 194  41
             for (CriteriaValue<?> value : values) {
 195  116
                     Class<?> currentType = value.getClass();
 196  116
                     if (previousType != null) {
 197  75
                             if (!currentType.equals(previousType)) {
 198  2
                                     throw new IllegalArgumentException("Encountered criteria values which do not match.  One was: " + previousType + " the other was: " + currentType);
 199  
                             }
 200  
                     }
 201  114
                     previousType = currentType;
 202  114
             }
 203  39
     }
 204  
         
 205  
 }