View Javadoc
1   /**
2    *    Copyright 2009-2015 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  package org.apache.ibatis.type;
17  
18  import java.math.BigDecimal;
19  import java.math.BigInteger;
20  import java.sql.ResultSet;
21  import java.util.ArrayList;
22  import java.util.Collection;
23  import java.util.Collections;
24  import java.util.Date;
25  import java.util.HashMap;
26  import java.util.Iterator;
27  import java.util.List;
28  import java.util.Locale;
29  import java.util.Map;
30  import java.util.Set;
31  
32  import org.apache.ibatis.io.ResolverUtil;
33  import org.apache.ibatis.io.Resources;
34  
35  /**
36   * @author Clinton Begin
37   */
38  public class TypeAliasRegistry {
39  
40    private final Map<String, Class<?>> TYPE_ALIASES = new HashMap<String, Class<?>>();
41  
42    public TypeAliasRegistry() {
43      registerAlias("string", String.class);
44  
45      registerAlias("byte", Byte.class);
46      registerAlias("long", Long.class);
47      registerAlias("short", Short.class);
48      registerAlias("int", Integer.class);
49      registerAlias("integer", Integer.class);
50      registerAlias("double", Double.class);
51      registerAlias("float", Float.class);
52      registerAlias("boolean", Boolean.class);
53  
54      registerAlias("byte[]", Byte[].class);
55      registerAlias("long[]", Long[].class);
56      registerAlias("short[]", Short[].class);
57      registerAlias("int[]", Integer[].class);
58      registerAlias("integer[]", Integer[].class);
59      registerAlias("double[]", Double[].class);
60      registerAlias("float[]", Float[].class);
61      registerAlias("boolean[]", Boolean[].class);
62  
63      registerAlias("_byte", byte.class);
64      registerAlias("_long", long.class);
65      registerAlias("_short", short.class);
66      registerAlias("_int", int.class);
67      registerAlias("_integer", int.class);
68      registerAlias("_double", double.class);
69      registerAlias("_float", float.class);
70      registerAlias("_boolean", boolean.class);
71  
72      registerAlias("_byte[]", byte[].class);
73      registerAlias("_long[]", long[].class);
74      registerAlias("_short[]", short[].class);
75      registerAlias("_int[]", int[].class);
76      registerAlias("_integer[]", int[].class);
77      registerAlias("_double[]", double[].class);
78      registerAlias("_float[]", float[].class);
79      registerAlias("_boolean[]", boolean[].class);
80  
81      registerAlias("date", Date.class);
82      registerAlias("decimal", BigDecimal.class);
83      registerAlias("bigdecimal", BigDecimal.class);
84      registerAlias("biginteger", BigInteger.class);
85      registerAlias("object", Object.class);
86  
87      registerAlias("date[]", Date[].class);
88      registerAlias("decimal[]", BigDecimal[].class);
89      registerAlias("bigdecimal[]", BigDecimal[].class);
90      registerAlias("biginteger[]", BigInteger[].class);
91      registerAlias("object[]", Object[].class);
92  
93      registerAlias("map", Map.class);
94      registerAlias("hashmap", HashMap.class);
95      registerAlias("list", List.class);
96      registerAlias("arraylist", ArrayList.class);
97      registerAlias("collection", Collection.class);
98      registerAlias("iterator", Iterator.class);
99  
100     registerAlias("ResultSet", ResultSet.class);
101   }
102 
103   @SuppressWarnings("unchecked")
104   // throws class cast exception as well if types cannot be assigned
105   public <T> Class<T> resolveAlias(String string) {
106     try {
107       if (string == null) {
108         return null;
109       }
110       // issue #748
111       String key = string.toLowerCase(Locale.ENGLISH);
112       Class<T> value;
113       if (TYPE_ALIASES.containsKey(key)) {
114         value = (Class<T>) TYPE_ALIASES.get(key);
115       } else {
116         value = (Class<T>) Resources.classForName(string);
117       }
118       return value;
119     } catch (ClassNotFoundException e) {
120       throw new TypeException("Could not resolve type alias '" + string + "'.  Cause: " + e, e);
121     }
122   }
123 
124   public void registerAliases(String packageName){
125     registerAliases(packageName, Object.class);
126   }
127 
128   public void registerAliases(String packageName, Class<?> superType){
129     ResolverUtil<Class<?>> resolverUtil = new ResolverUtil<Class<?>>();
130     resolverUtil.find(new ResolverUtil.IsA(superType), packageName);
131     Set<Class<? extends Class<?>>> typeSet = resolverUtil.getClasses();
132     for(Class<?> type : typeSet){
133       // Ignore inner classes and interfaces (including package-info.java)
134       // Skip also inner classes. See issue #6
135       if (!type.isAnonymousClass() && !type.isInterface() && !type.isMemberClass()) {
136         registerAlias(type);
137       }
138     }
139   }
140 
141   public void registerAlias(Class<?> type) {
142     String alias = type.getSimpleName();
143     Alias aliasAnnotation = type.getAnnotation(Alias.class);
144     if (aliasAnnotation != null) {
145       alias = aliasAnnotation.value();
146     } 
147     registerAlias(alias, type);
148   }
149 
150   public void registerAlias(String alias, Class<?> value) {
151     if (alias == null) {
152       throw new TypeException("The parameter alias cannot be null");
153     }
154     // issue #748
155     String key = alias.toLowerCase(Locale.ENGLISH);
156     if (TYPE_ALIASES.containsKey(key) && TYPE_ALIASES.get(key) != null && !TYPE_ALIASES.get(key).equals(value)) {
157       throw new TypeException("The alias '" + alias + "' is already mapped to the value '" + TYPE_ALIASES.get(key).getName() + "'.");
158     }
159     TYPE_ALIASES.put(key, value);
160   }
161 
162   public void registerAlias(String alias, String value) {
163     try {
164       registerAlias(alias, Resources.classForName(value));
165     } catch (ClassNotFoundException e) {
166       throw new TypeException("Error registering type alias "+alias+" for "+value+". Cause: " + e, e);
167     }
168   }
169   
170   /**
171    * @since 3.2.2
172    */
173   public Map<String, Class<?>> getTypeAliases() {
174     return Collections.unmodifiableMap(TYPE_ALIASES);
175   }
176 
177 }