TypeAliasRegistry.java

  1. /*
  2.  *    Copyright 2009-2024 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.  *       https://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. import java.math.BigDecimal;
  18. import java.math.BigInteger;
  19. import java.sql.ResultSet;
  20. import java.util.ArrayList;
  21. import java.util.Collection;
  22. import java.util.Collections;
  23. import java.util.Date;
  24. import java.util.HashMap;
  25. import java.util.Iterator;
  26. import java.util.List;
  27. import java.util.Locale;
  28. import java.util.Map;
  29. import java.util.Set;

  30. import org.apache.ibatis.io.ResolverUtil;
  31. import org.apache.ibatis.io.Resources;

  32. /**
  33.  * @author Clinton Begin
  34.  */
  35. public class TypeAliasRegistry {

  36.   private final Map<String, Class<?>> typeAliases = new HashMap<>();

  37.   public TypeAliasRegistry() {
  38.     registerAlias("string", String.class);

  39.     registerAlias("byte", Byte.class);
  40.     registerAlias("char", Character.class);
  41.     registerAlias("character", Character.class);
  42.     registerAlias("long", Long.class);
  43.     registerAlias("short", Short.class);
  44.     registerAlias("int", Integer.class);
  45.     registerAlias("integer", Integer.class);
  46.     registerAlias("double", Double.class);
  47.     registerAlias("float", Float.class);
  48.     registerAlias("boolean", Boolean.class);

  49.     registerAlias("byte[]", Byte[].class);
  50.     registerAlias("char[]", Character[].class);
  51.     registerAlias("character[]", Character[].class);
  52.     registerAlias("long[]", Long[].class);
  53.     registerAlias("short[]", Short[].class);
  54.     registerAlias("int[]", Integer[].class);
  55.     registerAlias("integer[]", Integer[].class);
  56.     registerAlias("double[]", Double[].class);
  57.     registerAlias("float[]", Float[].class);
  58.     registerAlias("boolean[]", Boolean[].class);

  59.     registerAlias("_byte", byte.class);
  60.     registerAlias("_char", char.class);
  61.     registerAlias("_character", char.class);
  62.     registerAlias("_long", long.class);
  63.     registerAlias("_short", short.class);
  64.     registerAlias("_int", int.class);
  65.     registerAlias("_integer", int.class);
  66.     registerAlias("_double", double.class);
  67.     registerAlias("_float", float.class);
  68.     registerAlias("_boolean", boolean.class);

  69.     registerAlias("_byte[]", byte[].class);
  70.     registerAlias("_char[]", char[].class);
  71.     registerAlias("_character[]", char[].class);
  72.     registerAlias("_long[]", long[].class);
  73.     registerAlias("_short[]", short[].class);
  74.     registerAlias("_int[]", int[].class);
  75.     registerAlias("_integer[]", int[].class);
  76.     registerAlias("_double[]", double[].class);
  77.     registerAlias("_float[]", float[].class);
  78.     registerAlias("_boolean[]", boolean[].class);

  79.     registerAlias("date", Date.class);
  80.     registerAlias("decimal", BigDecimal.class);
  81.     registerAlias("bigdecimal", BigDecimal.class);
  82.     registerAlias("biginteger", BigInteger.class);
  83.     registerAlias("object", Object.class);

  84.     registerAlias("date[]", Date[].class);
  85.     registerAlias("decimal[]", BigDecimal[].class);
  86.     registerAlias("bigdecimal[]", BigDecimal[].class);
  87.     registerAlias("biginteger[]", BigInteger[].class);
  88.     registerAlias("object[]", Object[].class);

  89.     registerAlias("map", Map.class);
  90.     registerAlias("hashmap", HashMap.class);
  91.     registerAlias("list", List.class);
  92.     registerAlias("arraylist", ArrayList.class);
  93.     registerAlias("collection", Collection.class);
  94.     registerAlias("iterator", Iterator.class);

  95.     registerAlias("ResultSet", ResultSet.class);
  96.   }

  97.   @SuppressWarnings("unchecked")
  98.   // throws class cast exception as well if types cannot be assigned
  99.   public <T> Class<T> resolveAlias(String string) {
  100.     try {
  101.       if (string == null) {
  102.         return null;
  103.       }
  104.       // issue #748
  105.       String key = string.toLowerCase(Locale.ENGLISH);
  106.       Class<T> value;
  107.       if (typeAliases.containsKey(key)) {
  108.         value = (Class<T>) typeAliases.get(key);
  109.       } else {
  110.         value = (Class<T>) Resources.classForName(string);
  111.       }
  112.       return value;
  113.     } catch (ClassNotFoundException e) {
  114.       throw new TypeException("Could not resolve type alias '" + string + "'.  Cause: " + e, e);
  115.     }
  116.   }

  117.   public void registerAliases(String packageName) {
  118.     registerAliases(packageName, Object.class);
  119.   }

  120.   public void registerAliases(String packageName, Class<?> superType) {
  121.     ResolverUtil<Class<?>> resolverUtil = new ResolverUtil<>();
  122.     resolverUtil.find(new ResolverUtil.IsA(superType), packageName);
  123.     Set<Class<? extends Class<?>>> typeSet = resolverUtil.getClasses();
  124.     for (Class<?> type : typeSet) {
  125.       // Ignore inner classes and interfaces (including package-info.java)
  126.       // Skip also inner classes. See issue #6
  127.       if (!type.isAnonymousClass() && !type.isInterface() && !type.isMemberClass()) {
  128.         registerAlias(type);
  129.       }
  130.     }
  131.   }

  132.   public void registerAlias(Class<?> type) {
  133.     String alias = type.getSimpleName();
  134.     Alias aliasAnnotation = type.getAnnotation(Alias.class);
  135.     if (aliasAnnotation != null) {
  136.       alias = aliasAnnotation.value();
  137.     }
  138.     registerAlias(alias, type);
  139.   }

  140.   public void registerAlias(String alias, Class<?> value) {
  141.     if (alias == null) {
  142.       throw new TypeException("The parameter alias cannot be null");
  143.     }
  144.     // issue #748
  145.     String key = alias.toLowerCase(Locale.ENGLISH);
  146.     if (typeAliases.containsKey(key) && typeAliases.get(key) != null && !typeAliases.get(key).equals(value)) {
  147.       throw new TypeException(
  148.           "The alias '" + alias + "' is already mapped to the value '" + typeAliases.get(key).getName() + "'.");
  149.     }
  150.     typeAliases.put(key, value);
  151.   }

  152.   public void registerAlias(String alias, String value) {
  153.     try {
  154.       registerAlias(alias, Resources.classForName(value));
  155.     } catch (ClassNotFoundException e) {
  156.       throw new TypeException("Error registering type alias " + alias + " for " + value + ". Cause: " + e, e);
  157.     }
  158.   }

  159.   /**
  160.    * Gets the type aliases.
  161.    *
  162.    * @return the type aliases
  163.    *
  164.    * @since 3.2.2
  165.    */
  166.   public Map<String, Class<?>> getTypeAliases() {
  167.     return Collections.unmodifiableMap(typeAliases);
  168.   }

  169. }