View Javadoc

1   /*
2   Copyright (C) 2006 Grid Systems, S.A.
3   
4   This program is free software; you can redistribute it and/or modify
5   it under the terms of the GNU General Public License, version 2, as
6   published by the Free Software Foundation.
7   
8   This program is distributed in the hope that it will be useful,
9   but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12  
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  */
17  package com.gridsystems.beanfilter;
18  
19  import java.lang.reflect.Array;
20  import java.util.HashSet;
21  
22  /**
23   * Collection operations node (contains, in).
24   *
25   * @author Xmas
26   * @version 1.0
27   */
28  public final class ArrayValue extends EvalValue {
29  
30    /**
31     * Forms to access to this array.
32     */
33    public enum ArrayType { INDEXED, ALL_ITEMS, ANY_ITEMS };
34  
35    /**
36     * Array Type.
37     */
38    private ArrayType arrayType;
39  
40    /**
41     * Left operand.
42     */
43    private EvalValue value;
44  
45    /**
46     * If Array if Indexed, then contains position of this array.
47     */
48    private Integer index = null;
49  
50    /**
51     * Creates a new instance.
52     *
53     * @param token  The token
54     * @param value  The value
55     * @param parentClass Parent Class
56     * @param arrayIndexType    The array index
57     * @throws EvalException If an error occurs
58     */
59    public ArrayValue(Token token, EvalValue value, Token arrayIndexType,
60      Class<?> parentClass) throws EvalException {
61      super(token.beginLine, token.beginColumn);
62      // Check if is array
63      Class<?> valueClass = value.getClassValue(parentClass);
64      if (!valueClass.isArray()) {
65        // FTR010=The variable at position [{0}, {1}] is not an array.
66        throw new EvalException("FTR010", token.beginLine, token.beginColumn);
67      }
68      // Set data
69      this.value = value;
70      switch (arrayIndexType.kind) {
71        case FilterParserConstants.NUMBER:
72          this.index = Integer.parseInt(arrayIndexType.image);
73          if (this.index < 0) {
74            // FTR009
75            // In the array at position [{0}, {1}], the index {2} is out of bounds.
76            throw new EvalException("FTR009", token.beginLine, token.beginColumn, index);
77          }
78          this.arrayType = ArrayType.INDEXED;
79          break;
80        case FilterParserConstants.ALLITEMS:
81          this.arrayType = ArrayType.ALL_ITEMS;
82          break;
83        case FilterParserConstants.ANYITEMS:
84          this.arrayType = ArrayType.ANY_ITEMS;
85          break;
86        default:
87          throw new EvalException("UNK000", "Unknown array indexation type "
88              + arrayIndexType.kind);
89      }
90    }
91  
92    /**
93     * {@inheritDoc}
94     */
95    @Override public Object getValue(Object src) throws EvalException {
96      Object myarray = value.getValue(src);
97      if (myarray == null) {
98        return null;
99      }
100     if (index == null) {
101       HashSet<Object> hash;
102       hash = arrayToHash(myarray, this.arrayType);
103       return hash;
104     } else {
105       int count = Array.getLength(myarray);
106       int i = index.intValue();
107       if ((i < 0) || (i >= count)) {
108         // We suppose that arrays are infinite. The values not defined has value null.
109         return null;
110       }
111       Object obj = Array.get(myarray, i);
112       return processObject(obj);
113     }
114   }
115 
116   /**
117    * Convert an object array to HashSet.
118    *
119    * @param myarray Array to convert
120    * @param arrayType type of returned hash: AND or OR
121    * @return HashSet with the content of array.
122    */
123   public static HashSet<Object> arrayToHash(Object myarray, ArrayType arrayType) {
124     HashSet<Object> hash;
125     int count = Array.getLength(myarray);
126     if (arrayType == ArrayType.ALL_ITEMS) {
127       hash = new AllItemsHashSet(count);
128     } else {
129       hash = new AnyItemsHashSet(count);
130     }
131     for (int i = 0; i < count; i++) {
132       hash.add(processObject(Array.get(myarray, i)));
133     }
134     return hash;
135   }
136 
137   /**
138    * Convert objects Number to Long or Double.
139    * @param obj Original Object
140    * @return <code>obj</code> if <code>obj</code> is not a number.
141    *   Otherwise return the representation in Long or Double of <code>obj</code>.
142    */
143   private static Object processObject(Object obj) {
144     if (obj == null) {
145       return null;
146     }
147     if (obj instanceof Number) {
148       if (obj instanceof Long || obj instanceof Integer
149            || obj instanceof Short || obj instanceof Byte) {
150         return ((Number)obj).longValue();
151       } else {
152         return ((Number)obj).doubleValue();
153       }
154     }
155     return obj;
156   }
157 
158   /**
159    * {@inheritDoc}
160    */
161   @Override public String toString() {
162     return value + "[" + ((index == null) ? "*" : index.toString()) + "]";
163   }
164 
165   /**
166    * {@inheritDoc}
167    */
168   @Override
169   public Class<?> getClassValue(Class<?> parentClass) throws EvalException {
170     Class<?> valueClass = value.getClassValue(parentClass);
171     return valueClass.getComponentType();
172   }
173 }