View Javadoc

1   /*
2    * Copyright 2004-2009 the original author or authors.
3    *
4    * Licensed under the Apache 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.apache.org/licenses/LICENSE-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  
17  package org.springmodules.validation.valang.predicates;
18  
19  import java.math.BigDecimal;
20  import java.util.ArrayList;
21  import java.util.Collection;
22  import java.util.Iterator;
23  import java.util.Set;
24  
25  import org.apache.commons.collections.Predicate;
26  import org.apache.commons.collections.functors.AnyPredicate;
27  import org.apache.commons.collections.functors.FalsePredicate;
28  import org.springmodules.validation.valang.functions.Function;
29  import org.springmodules.validation.valang.functions.LiteralFunction;
30  
31  /**
32   * Tests if a value is in a list.
33   *
34   * @author David Winterfeldt
35   */
36  public class InTestPredicate extends AbstractPropertyPredicate {
37      
38      /**
39       * <p>Constructor taking two functions and an operator.
40       *
41       * @param leftFunction the left function
42       * @param operator the operator.
43       */
44      public InTestPredicate(Function leftFunction, Operator operator, Function rightFunction, int line, int column) {
45          super(leftFunction, operator, rightFunction, line, column);
46      }
47  
48  
49      /**
50       * <p>The evaluate method takes the result of both functions and tests with the operator.
51       *
52       * @param   target      The target bean.
53       * @return  boolean      Whether or not the test passed.
54       */
55      public boolean evaluate(Object target) {
56          // constructor checks that left function is never null
57          Object leftValue = getLeftFunction().getResult(target);
58          Object rightValue = (getRightFunction() != null ? getRightFunction().getResult(target) : null);
59          
60          if (leftValue instanceof Number) {
61              leftValue = new BigDecimal(leftValue.toString());
62          }
63          if (rightValue instanceof Number) {
64              rightValue = new BigDecimal(rightValue.toString());
65          }
66  
67          // FIX ME: make all collections and lists more efficient (also handle arrays)
68          if (rightValue instanceof Set) {
69              Set<?> lComparisonValues = (Set<?>) rightValue;
70              
71              return lComparisonValues.contains(leftValue);
72          } else {
73              Collection<Predicate> predicates = new ArrayList<Predicate>();
74              
75              for (Iterator iter = getIterator(rightValue); iter.hasNext();) {
76                  Object o = iter.next();
77                  if (o instanceof Function) {
78                      predicates.add(new EqualsTestPredicate(new LiteralFunction(leftValue), Operator.EQUAL, (Function) o, getLine(), getColumn()));
79                  } else {
80                      predicates.add(new EqualsTestPredicate(new LiteralFunction(leftValue), Operator.EQUAL, new LiteralFunction(o), getLine(), getColumn()));
81                  }
82              }
83              
84              if (predicates.isEmpty()) {
85                  throw new IllegalStateException("IN expression contains no elements!");
86              } else if (predicates.size() == 1) {
87                  predicates.add(FalsePredicate.getInstance());
88              }
89  
90              return AnyPredicate.getInstance(predicates).evaluate(target);
91          }
92      }
93  
94    }