View Javadoc

1   /***
2    *  Copyright 2003-2010 Terracotta, Inc.
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 net.sf.ehcache.search.attribute;
18  
19  import java.util.HashMap;
20  import java.util.Map;
21  
22  import net.sf.ehcache.search.SearchException;
23  
24  /***
25   * Defines the legal set of runtime types for search attributes
26   *
27   * @author teck
28   */
29  public enum AttributeType {
30  
31      /***
32       * Boolean type
33       */
34      BOOLEAN {
35          /***
36           * {@inheritDoc}
37           */
38          @Override
39          public void validateValue(String name, Object value) {
40              if (!(value instanceof Boolean)) {
41                  throw new SearchException("Expecting a Boolean value for attribute [" + name + "] but was " + type(value));
42              }
43          }
44      },
45  
46      /***
47       * Byte type
48       */
49      BYTE {
50          /***
51           * {@inheritDoc}
52           */
53          @Override
54          public void validateValue(String name, Object value) {
55              if (!(value instanceof Byte)) {
56                  throw new SearchException("Expecting a Byte value for attribute [" + name + "] but was " + type(value));
57              }
58          }
59      },
60  
61      /***
62       * Character type
63       */
64      CHAR {
65          /***
66           * {@inheritDoc}
67           */
68          @Override
69          public void validateValue(String name, Object value) {
70              if (!(value instanceof Character)) {
71                  throw new SearchException("Expecting a Character value for attribute [" + name + "] but was " + type(value));
72              }
73          }
74      },
75  
76      /***
77       * Double type
78       */
79      DOUBLE {
80          /***
81           * {@inheritDoc}
82           */
83          @Override
84          public void validateValue(String name, Object value) {
85              if (!(value instanceof Double)) {
86                  throw new SearchException("Expecting a Double value for attribute [" + name + "] but was " + type(value));
87              }
88          }
89      },
90  
91      /***
92       * Float type
93       */
94      FLOAT {
95          /***
96           * {@inheritDoc}
97           */
98          @Override
99          public void validateValue(String name, Object value) {
100             if (!(value instanceof Float)) {
101                 throw new SearchException("Expecting a Float value for attribute [" + name + "] but was " + type(value));
102             }
103         }
104     },
105 
106     /***
107      * Integer type
108      */
109     INT {
110         /***
111          * {@inheritDoc}
112          */
113         @Override
114         public void validateValue(String name, Object value) {
115             if (!(value instanceof Integer)) {
116                 throw new SearchException("Expecting an Integer value for attribute [" + name + "] but was " + type(value));
117             }
118         }
119     },
120 
121     /***
122      * Long type
123      */
124     LONG {
125         /***
126          * {@inheritDoc}
127          */
128         @Override
129         public void validateValue(String name, Object value) {
130             if (!(value instanceof Long)) {
131                 throw new SearchException("Expecting a Long value for attribute [" + name + "] but was " + type(value));
132             }
133         }
134     },
135 
136     /***
137      * Short type
138      */
139     SHORT {
140         /***
141          * {@inheritDoc}
142          */
143         @Override
144         public void validateValue(String name, Object value) {
145             if (!(value instanceof Short)) {
146                 throw new SearchException("Expecting a Short value for attribute [" + name + "] but was " + type(value));
147             }
148         }
149     },
150 
151     /***
152      * Date type
153      */
154     DATE {
155         /***
156          * {@inheritDoc}
157          */
158         @Override
159         public void validateValue(String name, Object value) {
160             if (value == null || value.getClass() != java.util.Date.class) {
161                 throw new SearchException("Expecting a java.util.Date value for attribute [" + name + "] but was " + type(value));
162             }
163         }
164     },
165 
166     /***
167      * SQL Date type
168      */
169     SQL_DATE {
170         /***
171          * {@inheritDoc}
172          */
173         @Override
174         public void validateValue(String name, Object value) {
175             if (value == null || value.getClass() != java.sql.Date.class) {
176                 throw new SearchException("Expecting a java.sql.Date value for attribute [" + name + "] but was " + type(value));
177             }
178         }
179     },
180 
181     /***
182      * Enum type
183      */
184     ENUM {
185         /***
186          * {@inheritDoc}
187          */
188         @Override
189         public void validateValue(String name, Object value) {
190             if (!(value instanceof Enum)) {
191                 throw new SearchException("Expecting a enum value for attribute [" + name + "] but was " + type(value));
192             }
193         }
194     },
195 
196     /***
197      * String type
198      */
199     STRING {
200         /***
201          * {@inheritDoc}
202          */
203         @Override
204         public void validateValue(String name, Object value) {
205             if (!(value instanceof String)) {
206                 throw new SearchException("Expecting a String value for attribute [" + name + "] but was " + type(value));
207             }
208         }
209     };
210 
211     private static final Map<Class, AttributeType> MAPPINGS = new HashMap<Class, AttributeType>();
212 
213     /***
214      * Get the appropriate @{link {@link AttributeType} enum for the given object value.
215      *
216      * @param name  the attribute name (only meaningful to message if exception thrown)
217      * @param value the value to lookup the type for
218      * @return the attribute type for this value
219      * @throws SearchException if the given value is not valid for a search attribute
220      */
221     public static AttributeType typeFor(String name, Object value) throws SearchException {
222         if (name == null) {
223             throw new NullPointerException("null name");
224         }
225         if (value == null) {
226             throw new NullPointerException("null value");
227         }
228 
229         AttributeType type = typeForOrNull(value);
230         if (type != null) {
231             return type;
232         }
233 
234         throw new SearchException("Unsupported type for search attribute [" + name + "]: " + value.getClass().getName());
235     }
236 
237     private static AttributeType typeForOrNull(Object value) {
238         AttributeType type = MAPPINGS.get(value.getClass());
239         if (type != null) {
240             return type;
241         }
242 
243         // check for enum -- calling getClass().isEnum() isn't correct in this context
244         if (value instanceof Enum) {
245             return ENUM;
246         }
247 
248         return null;
249     }
250 
251     /***
252      * Test the given value to see if it is a legal type
253      *
254      * @param value
255      * @return true if the given value is valid as a search attribute
256      */
257     public static boolean isSupportedType(Object value) {
258         if (value == null) {
259             return true;
260         }
261 
262         return typeForOrNull(value) != null;
263     }
264 
265     /***
266      * Validate that the given value is in fact of the correct type
267      *
268      * @param name  the attribute name (only meaningful to message if exception thrown)
269      * @param value the value to validate against this type
270      * @throws SearchException if the given value is not a valid instance of this type
271      */
272     public abstract void validateValue(String name, Object value) throws SearchException;
273 
274     /***
275      * Is this type comparable?
276      *
277      * @return true if this type is comparable
278      */
279     public boolean isComparable() {
280         // some types might want to override this
281         return true;
282     }
283 
284     private static String type(Object value) {
285         if (value == null) {
286             return "null";
287         }
288         return value.getClass().getName();
289     }
290 
291     static {
292         MAPPINGS.put(Boolean.class, BOOLEAN);
293         MAPPINGS.put(Byte.class, BYTE);
294         MAPPINGS.put(Character.class, CHAR);
295         MAPPINGS.put(Double.class, DOUBLE);
296         MAPPINGS.put(Float.class, FLOAT);
297         MAPPINGS.put(Integer.class, INT);
298         MAPPINGS.put(Long.class, LONG);
299         MAPPINGS.put(Short.class, SHORT);
300         MAPPINGS.put(String.class, STRING);
301         MAPPINGS.put(java.util.Date.class, DATE);
302         MAPPINGS.put(java.sql.Date.class, SQL_DATE);
303     }
304 
305 }