/* * Copyright 2004-2015 the Seasar Foundation and the Others. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. See the License for the specific language * governing permissions and limitations under the License. */ package org.seasar.extension.jdbc.gen.internal.argtype; import java.io.File; import java.lang.reflect.Constructor; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import org.seasar.framework.beans.PropertyDesc; import org.seasar.framework.util.ClassUtil; import org.seasar.framework.util.tiger.ReflectionUtil; /** * {@link ArgumentType}を管理するクラスです。 * * @author taedium */ public class ArgumentTypeRegistry { /** クラスをキー、 {@link ArgumentType}のコンストラクタを値とするマップ */ protected static Map<Class<?>, Constructor<? extends ArgumentType<?>>> argTypeMap = new ConcurrentHashMap<Class<?>, Constructor<? extends ArgumentType<?>>>(); static { argTypeMap.put(Boolean.class, ReflectionUtil.getConstructor( BooleanType.class, null)); argTypeMap.put(Character.class, ReflectionUtil.getConstructor( CharacterType.class, null)); argTypeMap.put(String.class, ReflectionUtil.getConstructor( StringType.class, null)); argTypeMap.put(File.class, ReflectionUtil.getConstructor( FileType.class, null)); argTypeMap.put(Class.class, ReflectionUtil.getConstructor( ClassType.class, null)); } /** コレクション型のクラスをキー、 コレクション型の{@link ArgumentType}のコンストラクタを値とするマップ */ @SuppressWarnings("unchecked") protected static Map<Class<? extends Collection>, Constructor<? extends CollectionType>> collectionArgTypeMap = new ConcurrentHashMap<Class<? extends Collection>, Constructor<? extends CollectionType>>(); static { collectionArgTypeMap.put(List.class, ReflectionUtil.getConstructor( ListType.class, ArgumentType.class)); collectionArgTypeMap.put(Set.class, ReflectionUtil.getConstructor( SetType.class, ArgumentType.class)); collectionArgTypeMap.put(Collection.class, ReflectionUtil .getConstructor(CollectionType.class, ArgumentType.class)); } /** * {@link ArgumentType}を返します。 * * @param <T> * 引数の型 * @param propertyDesc * プロパティ記述 * @return {@link ArgumentType} */ public static <T> ArgumentType<T> getArgumentType(PropertyDesc propertyDesc) { Class<?> propertyType = propertyDesc.getPropertyType(); if (propertyDesc.isParameterized() && Collection.class.isAssignableFrom(propertyType)) { Class<?> elementClass = propertyDesc.getElementClassOfCollection(); return getCollectionArgumentType(propertyType, elementClass); } return getArgumentType(propertyType); } /** * {@link ArgumentType}を返します。 * * @param <T> * 引数の型 * @param clazz * 引数のクラス * @return {@link ArgumentType} */ @SuppressWarnings("unchecked") protected static <T> ArgumentType<T> getArgumentType(Class<?> clazz) { clazz = ClassUtil.getWrapperClassIfPrimitive(clazz); if (argTypeMap.containsKey(clazz)) { Constructor<? extends ArgumentType<?>> constructor = argTypeMap .get(clazz); return (ArgumentType<T>) ReflectionUtil.newInstance(constructor, null); } if (Number.class.isAssignableFrom(clazz)) { return new NumberType(clazz); } if (Enum.class.isAssignableFrom(clazz)) { return new EnumType(clazz); } return null; } /** * {@link ArgumentType}を返します。 * * @param <T> * 引数の型 * @param collectioinClass * コレクションのクラス * @param elementClass * コレクションの要素のクラス * @return {@link ArgumentType}を返します。 */ @SuppressWarnings("unchecked") protected static <T> ArgumentType<T> getCollectionArgumentType( Class<?> collectioinClass, Class<?> elementClass) { ArgumentType<?> argumentType = getArgumentType(elementClass); if (collectionArgTypeMap.containsKey(collectioinClass)) { Constructor<? extends CollectionType> constructor = collectionArgTypeMap .get(collectioinClass); return ReflectionUtil.newInstance(constructor, argumentType); } return null; } /** * {@link ArgumentType}を登録します。 * * @param clazz * 引数のクラス * @param argumentTypeClass * 引数の型を表すクラス */ public static void registerArgumentType(Class<?> clazz, Class<? extends ArgumentType<?>> argumentTypeClass) { if (clazz == null) { throw new NullPointerException("clazz"); } if (argumentTypeClass == null) { throw new NullPointerException("argumentTypeClass"); } Constructor<? extends ArgumentType<?>> constructor = ReflectionUtil .getConstructor(argumentTypeClass, null); argTypeMap.put(clazz, constructor); } /** * {@link ArgumentType}を削除します。 * * @param clazz * 引数のクラス */ public static void deregisterArgumentType(Class<?> clazz) { if (clazz == null) { throw new NullPointerException("clazz"); } argTypeMap.remove(clazz); } /** * コレクション型の{@link ArgumentType}を登録します。 * * @param collectionClass * コレクション型のクラス * @param argumentTypeClass * 引数の型を表すクラス */ @SuppressWarnings("unchecked") public static void registerCollectionArgumentType( Class<? extends Collection> collectionClass, Class<? extends CollectionType> argumentTypeClass) { if (collectionClass == null) { throw new NullPointerException("collectionClass"); } if (argumentTypeClass == null) { throw new NullPointerException("argumentTypeClass"); } Constructor<? extends CollectionType> constructor = ReflectionUtil .getConstructor(argumentTypeClass, ArgumentType.class); collectionArgTypeMap.put(collectionClass, constructor); } /** * コレクション型の{@link ArgumentType}を削除します。 * * @param collectionClass * コレクション型の引数のクラス */ @SuppressWarnings("unchecked") public static void deregisterCollectionArgumentType( Class<? extends Collection> collectionClass) { if (collectionClass == null) { throw new NullPointerException("collectionClass"); } collectionArgTypeMap.remove(collectionClass); } }