View Javadoc

1   /**
2    * Copyright 2005-2012 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.core.api.criteria;
17  
18  import org.apache.commons.lang.StringUtils;
19  import org.kuali.rice.core.api.search.SearchOperator;
20  
21  import java.util.ArrayList;
22  import java.util.Arrays;
23  import java.util.List;
24  import java.util.Map;
25  
26  import static org.kuali.rice.core.api.criteria.PredicateFactory.*;
27  
28  public final class PredicateUtils {
29  
30      private PredicateUtils() {
31          throw new UnsupportedOperationException("do not call");
32      }
33  
34      public static Predicate convertMapToPredicate(Map<String, String> criteria) {
35          List<Predicate> p = new ArrayList<Predicate>();
36          for (Map.Entry<String, String> entry : criteria.entrySet()) {
37              if (StringUtils.isNotBlank(entry.getValue())) {
38                  List<String> values = new ArrayList<String>();
39                  getValueRecursive(entry.getValue(), values);
40                  List<Predicate> tempPredicates = new ArrayList<Predicate>();
41                  p.addAll(tempPredicates);
42  
43                  // TODO: how to handle different types of data when everything comes in as string....
44                  for (String value : values) {
45                      tempPredicates.add(parsePredicate(entry.getKey(), value));
46                  }
47                  if (entry.getValue().contains(SearchOperator.AND.op())) {
48                      p.add(and(tempPredicates.toArray(new Predicate[tempPredicates.size()])));
49                  } else if (entry.getValue().contains(SearchOperator.OR.op())) {
50                      p.add(or(tempPredicates.toArray(new Predicate[tempPredicates.size()])));
51                  } else {
52                      p.addAll(tempPredicates);
53                  }
54              }
55          }
56          //wrap everything in an 'and'
57          return and(p.toArray(new Predicate[p.size()]));
58      }
59  
60      /**
61       * sort of parses a predicate out of a value
62       * @param key the map entry key
63       * @param value the expression value
64       * @return a parsed predicate or null if unable to parse expression
65       */
66      private static Predicate parsePredicate(String key, String value) {
67          if (value.contains(SearchOperator.NULL.op())) {
68              if (isNot(value)) {
69                  return isNotNull(key);
70              } else {
71                  return isNull(key);
72              }
73          } else if (value.contains(SearchOperator.BETWEEN_EXCLUSIVE_UPPER.op())) {
74              String[] betweenVals = StringUtils.split(value, SearchOperator.BETWEEN_EXCLUSIVE_UPPER.op());
75              if (betweenVals.length == 2) {
76                  return and(greaterThanOrEqual(key, betweenVals[0]), lessThan(key, betweenVals[1]));
77              } // else ?
78              return null;
79          } else if (value.contains(SearchOperator.BETWEEN.op())) {
80              String[] betweenVals = StringUtils.split(value, SearchOperator.BETWEEN.op());
81              if (betweenVals.length == 2) {
82                  return and(greaterThanOrEqual(key, betweenVals[0]), lessThanOrEqual(key, betweenVals[1]));
83              } // else ?
84              return null;
85          } else if (value.contains(SearchOperator.GREATER_THAN_EQUAL.op())) {
86              return greaterThanOrEqual(key, StringUtils.replace(value, SearchOperator.GREATER_THAN_EQUAL.op(), ""));
87          } else if (value.contains(SearchOperator.LESS_THAN_EQUAL.op())) {
88              return lessThanOrEqual(key, StringUtils.replace(value, SearchOperator.LESS_THAN_EQUAL.op(), ""));
89          } else if (value.contains(SearchOperator.GREATER_THAN.op())) {
90              return greaterThan(key, StringUtils.replace(value, SearchOperator.GREATER_THAN.op(), ""));
91          } else if (value.contains(SearchOperator.LESS_THAN.op())) {
92              return lessThan(key, StringUtils.replace(value, SearchOperator.LESS_THAN.op(), ""));
93          } else if (value.contains(SearchOperator.LIKE_MANY.op()) || (value.contains(SearchOperator.LIKE_ONE.op()))) {
94              if (isNot(value)) {
95                  return notLike(key, stripNot(value));
96              } else {
97                  return like(key, value);
98              }
99          } else {
100             if (isNot(value)) {
101                 return notEqual(key, stripNot(value));
102             } else {
103                 return equal(key, value);
104             }
105         }
106     }
107 
108     private static void getValueRecursive(String valueEntered, List<String> lRet) {
109  		if(valueEntered == null) {
110  			return;
111  		}
112 
113  		valueEntered = valueEntered.trim();
114 
115  		if(lRet == null){
116  			throw new NullPointerException("The list passed in is by reference and should never be null.");
117  		}
118 
119  		if (StringUtils.contains(valueEntered, SearchOperator.OR.op())) {
120  			List<String> l = Arrays.asList(StringUtils.split(valueEntered, SearchOperator.OR.op()));
121  			for(String value : l){
122  				getValueRecursive(value, lRet);
123  			}
124  			return;
125  		}
126  		if (StringUtils.contains(valueEntered, SearchOperator.AND.op())) {
127  			//splitValueList.addAll(Arrays.asList(StringUtils.split(valueEntered, KRADConstants.AND.op())));
128  			List<String> l = Arrays.asList(StringUtils.split(valueEntered, SearchOperator.AND.op()));
129  			for(String value : l){
130  				getValueRecursive(value, lRet);
131  			}
132  			return;
133  		}
134 
135  		// lRet is pass by ref and should NEVER be null
136  		lRet.add(valueEntered);
137     }
138 
139     private static boolean isNot(String value) {
140         if (value == null) {
141             return false;
142         }
143         return value.contains(SearchOperator.NOT.op());
144     }
145 
146     // oh so hacky
147     private static String stripNot(String value) {
148         if (value.trim().startsWith(SearchOperator.NOT.op())) {
149             value = value.trim().replaceFirst(SearchOperator.NOT.op(), "");
150         }
151         return value;
152     }
153 }
154 
155