Coverage Report - org.kuali.rice.core.api.criteria.CriteriaSupportUtils
 
Classes in this File Line Coverage Branch Coverage Complexity
CriteriaSupportUtils
74%
77/103
76%
61/80
7.636
CriteriaSupportUtils$PropertyConstants
0%
0/1
N/A
7.636
 
 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 org.apache.commons.lang.StringUtils;
 19  
 
 20  
 import javax.xml.bind.annotation.XmlElement;
 21  
 import javax.xml.bind.annotation.XmlElements;
 22  
 import java.lang.reflect.Field;
 23  
 import java.lang.reflect.Method;
 24  
 import java.math.BigDecimal;
 25  
 import java.math.BigInteger;
 26  
 import java.util.ArrayList;
 27  
 import java.util.Calendar;
 28  
 import java.util.Collections;
 29  
 import java.util.Date;
 30  
 import java.util.HashSet;
 31  
 import java.util.List;
 32  
 import java.util.Set;
 33  
 import java.util.concurrent.atomic.AtomicInteger;
 34  
 import java.util.concurrent.atomic.AtomicLong;
 35  
 
 36  
 /**
 37  
  * A class which includes various utilities and constants for use within the criteria API.
 38  
  * This class is intended to be for internal use only within the criteria API.
 39  
  * 
 40  
  * @author Kuali Rice Team (rice.collab@kuali.org)
 41  
  */
 42  
 final class CriteriaSupportUtils {
 43  
         
 44  0
         private CriteriaSupportUtils () {}
 45  
         
 46  
     /**
 47  
      * Defines various property constants for internal use within the criteria package.
 48  
      */
 49  0
     static class PropertyConstants {
 50  
             
 51  
             /**
 52  
              * A constant representing the property name for {@link PropertyPathPredicate#getPropertyPath()}
 53  
              */
 54  
         final static String PROPERTY_PATH = "propertyPath";
 55  
         
 56  
             /**
 57  
              * A constant representing the property name for {@link SingleValuedPredicate#getValue()}
 58  
              */
 59  
         final static String VALUE = "value";
 60  
         
 61  
         /**
 62  
          * A constant representing the method name for {@link SingleValuedPredicate#getValue()}
 63  
          */
 64  
         final static String GET_VALUE_METHOD_NAME = "getValue";
 65  
 
 66  
         /**
 67  
              * A constant representing the property name for {@link MultiValuedPredicate#getValues()}
 68  
              */
 69  
         final static String VALUES = "values";
 70  
 
 71  
         /**
 72  
          * A constant representing the method name for {@link MultiValuedPredicate#getValues()}
 73  
          */
 74  
         final static String GET_VALUES_METHOD_NAME = "getValues";
 75  
     }
 76  
 
 77  
     /**
 78  
      * Validates the various properties of a {@link SingleValuedPredicate}.
 79  
      * 
 80  
      * @param valuedPredicateClass the type of the predicate
 81  
      * @param propertyPath the propertyPath which is being configured on the predicate
 82  
      * @param value the value which is being configured on the predicate
 83  
      * 
 84  
      * @throws IllegalArgumentException if the propertPath is null or blank
 85  
      * @throws IllegalArgumentException if the value is null
 86  
      * @throws IllegalArgumentException if the given {@link SingleValuedPredicate} class does not support the {@link CriteriaValue}
 87  
      */
 88  
     static void validateValuedConstruction(Class<? extends SingleValuedPredicate> valuedPredicateClass, String propertyPath, CriteriaValue<?> value) {
 89  118
             if (StringUtils.isBlank(propertyPath)) {
 90  14
                         throw new IllegalArgumentException("Property path cannot be null or blank.");
 91  
                 }
 92  104
                 if (value == null) {
 93  1
                     throw new IllegalArgumentException("CriteriaValue cannot be null.");
 94  
                 }
 95  103
                 if (!CriteriaSupportUtils.supportsCriteriaValue(valuedPredicateClass, value)) {
 96  6
                     throw new IllegalArgumentException(valuedPredicateClass.getSimpleName() + " does not support the given CriteriaValue");
 97  
                 }
 98  97
     }
 99  
 
 100  
         static boolean supportsCriteriaValue(Class<? extends SingleValuedPredicate> simplePredicateClass, CriteriaValue<?> value) {
 101  112
             if (simplePredicateClass == null) {
 102  2
                 throw new IllegalArgumentException("simplePredicateClass was null");
 103  
             }
 104  110
             if (value == null) {
 105  1
                 throw new IllegalArgumentException("valueClass was null");
 106  
             }
 107  109
             XmlElements elementsAnnotation = CriteriaSupportUtils.findXmlElementsAnnotation(simplePredicateClass);
 108  109
             if (elementsAnnotation != null) {
 109  109
                 XmlElement[] elements = elementsAnnotation.value();
 110  184
                 for (XmlElement element : elements) {
 111  177
                     if (value.getClass().equals(element.type())) {
 112  102
                         return true;
 113  
                     }
 114  
                 }
 115  
             }
 116  7
             return false;
 117  
         }
 118  
         
 119  
         private static XmlElements findXmlElementsAnnotation(Class<?> simplePredicateClass) {
 120  109
                 if (simplePredicateClass != null) {
 121  
                         try{
 122  109
                                 Field valueField = simplePredicateClass.getDeclaredField(PropertyConstants.VALUE);
 123  109
                                 XmlElements elementsAnnotation = valueField.getAnnotation(XmlElements.class);
 124  109
                                 if (elementsAnnotation != null) {
 125  109
                                         return elementsAnnotation;
 126  
                                 }
 127  0
                         } catch (NoSuchFieldException e) {
 128  
                                 // ignore, try the method
 129  0
                         }
 130  
                         try {
 131  0
                                 Method valueMethod = simplePredicateClass.getDeclaredMethod(PropertyConstants.GET_VALUE_METHOD_NAME, (Class<?>[])null);
 132  0
                                 XmlElements elementsAnnotation = valueMethod.getAnnotation(XmlElements.class);
 133  0
                                 if (elementsAnnotation == null) {
 134  0
                                         return CriteriaSupportUtils.findXmlElementsAnnotation(simplePredicateClass.getSuperclass());
 135  
                                 }
 136  0
                                 return elementsAnnotation;
 137  0
                         } catch (NoSuchMethodException e) {
 138  0
                                 return CriteriaSupportUtils.findXmlElementsAnnotation(simplePredicateClass.getSuperclass());
 139  
                         }
 140  
                 }
 141  0
                 return null;
 142  
         }
 143  
         
 144  
         static CriteriaValue<?> determineCriteriaValue(Object object) {
 145  100
                 if (object == null) {
 146  8
                         throw new IllegalArgumentException("Given criteria value cannot be null.");
 147  92
                 } else if (object instanceof CharSequence) {
 148  41
                         return new CriteriaStringValue((CharSequence)object);
 149  51
                 } else if (object instanceof Calendar) {
 150  6
                         return new CriteriaDateTimeValue((Calendar)object);
 151  45
                 } else if (object instanceof Date) {
 152  5
                         return new CriteriaDateTimeValue((Date)object);
 153  40
                 } else if (object instanceof BigInteger) {
 154  0
                         return new CriteriaIntegerValue((BigInteger)object);
 155  40
                 } else if (object instanceof Short) {
 156  1
                         return new CriteriaIntegerValue((Short)object);
 157  39
                 } else if (object instanceof Integer) {
 158  30
                         return new CriteriaIntegerValue((Integer)object);
 159  9
                 } else if (object instanceof AtomicInteger) {
 160  0
                         return new CriteriaIntegerValue((AtomicInteger)object);
 161  9
                 } else if (object instanceof Long) {
 162  1
                         return new CriteriaIntegerValue((Long)object);
 163  8
                 } else if (object instanceof AtomicLong) {
 164  0
                         return new CriteriaIntegerValue((AtomicLong)object);
 165  8
                 } else if (object instanceof BigDecimal) {
 166  8
                         return new CriteriaDecimalValue((BigDecimal)object);
 167  0
                 } else if (object instanceof Float) {
 168  0
                         return new CriteriaDecimalValue((Float)object);
 169  0
                 } else if (object instanceof Double) {
 170  0
                         return new CriteriaDecimalValue((Double)object);
 171  
                 }
 172  0
                 throw new IllegalArgumentException("Failed to translate the given object to a CriteriaValue: " + object);
 173  
         }
 174  
         
 175  
         static Set<CriteriaValue<?>> determineCriteriaValueList(Object[] values) {
 176  17
                 if (values == null) {
 177  2
                         return null;
 178  15
                 } else if (values.length == 0) {
 179  2
                         return Collections.emptySet();
 180  
                 }
 181  13
                 Set<CriteriaValue<?>> criteriaValues = new HashSet<CriteriaValue<?>>();
 182  41
                 for (Object value : values) {
 183  28
                         if (value != null) {
 184  28
                 criteriaValues.add(determineCriteriaValue(value));
 185  
             }
 186  
                 }
 187  13
                 return criteriaValues;
 188  
         }
 189  
 
 190  
     static Set<CriteriaStringValue> createCriteriaStringValueList(CharSequence[] values) {
 191  4
                 if (values == null) {
 192  0
                         return null;
 193  4
                 } else if (values.length == 0) {
 194  0
                         return Collections.emptySet();
 195  
                 }
 196  4
                 Set<CriteriaStringValue> criteriaValues = new HashSet<CriteriaStringValue>();
 197  16
                 for (CharSequence value : values) {
 198  12
                         if (value != null) {
 199  12
                 criteriaValues.add(new CriteriaStringValue(value));
 200  
             }
 201  
                 }
 202  4
                 return criteriaValues;
 203  
         }
 204  
         
 205  
         /**
 206  
      * Validates the incoming list of CriteriaValue to ensure they are valid for a
 207  
      * {@link MultiValuedPredicate}.  To be valid, the following must be true:
 208  
      * 
 209  
      * <ol>
 210  
      *   <li>The list of values must not be null.</li>
 211  
      *   <li>The list of values must not be empty.</li>
 212  
      *   <li>The list of values must all be of the same parameterized {@link CriteriaValue} type.</li>
 213  
      * </ol>
 214  
      */
 215  
     static void validateValuesForMultiValuedPredicate(Set<? extends CriteriaValue<?>> values) {
 216  53
             if (values == null) {
 217  4
                     throw new IllegalArgumentException("Criteria values cannot be null.");
 218  49
             } else if (values.isEmpty()) {
 219  4
                     throw new IllegalArgumentException("Criteria values cannot be empty.");
 220  
             }
 221  45
             Class<?> previousType = null;
 222  45
             for (CriteriaValue<?> value : values) {
 223  125
                     Class<?> currentType = value.getClass();
 224  125
                     if (previousType != null) {
 225  80
                             if (!currentType.equals(previousType)) {
 226  2
                                     throw new IllegalArgumentException("Encountered criteria values which do not match.  One was: " + previousType + " the other was: " + currentType);
 227  
                             }
 228  
                     }
 229  123
                     previousType = currentType;
 230  123
             }
 231  43
     }
 232  
 
 233  
     static String findDynName(String name) {
 234  38
         String correctedName = StringUtils.uncapitalize(name).replace("Predicate", "");
 235  
         //null is a keyword therefore they are called isNull & isNotNull
 236  38
         if (correctedName.equals("null")) {
 237  2
             correctedName = "isNull";
 238  36
         } else if (correctedName.equals("notNull")) {
 239  2
             correctedName = "isNotNull";
 240  
         }
 241  38
         return correctedName;
 242  
     }
 243  
 
 244  
     public static String toString(SingleValuedPredicate p) {
 245  0
         return new StringBuilder(CriteriaSupportUtils.findDynName(p.getClass().getSimpleName())).append("(")
 246  
                 .append(p.getPropertyPath()).append(", ").append(p.getValue().getValue()).append(")").toString();
 247  
     }
 248  
 
 249  
     public static String toString(MultiValuedPredicate p) {
 250  0
         final List<String> values = new ArrayList<String>();
 251  0
         for (CriteriaValue<?> value : p.getValues()) {
 252  0
             values.add(value.getValue().toString());
 253  
         }
 254  
 
 255  0
         return new StringBuilder(CriteriaSupportUtils.findDynName(p.getClass().getSimpleName())).append("(")
 256  
                 .append(p.getPropertyPath()).append(", ").append("[").append(StringUtils.join(values, ", ")).append("]").append(")").toString();
 257  
     }
 258  
 }