/* * Copyright (C) 2010 Red Hat, Inc. and/or its affiliates. * * 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.jboss.errai.common.client.types; import org.jboss.errai.common.client.types.handlers.collections.*; import org.jboss.errai.common.client.types.handlers.numbers.*; import java.util.*; public class TypeHandlerFactory { private static Map<Class, Map<Class, TypeHandler>> handlers = new HashMap<Class, Map<Class, TypeHandler>>(); private static Map<Class, Class> inheritanceMap = new HashMap<Class, Class>(); static { /** * Declare all the default coercion handlers. */ final Map<Class, TypeHandler> collectionHandlers = new HashMap<Class, TypeHandler>(); collectionHandlers.put(Object[].class, new CollectionToObjArray()); collectionHandlers.put(String[].class, new CollectionToStringArray()); collectionHandlers.put(Integer[].class, new CollectionToIntArray()); collectionHandlers.put(Long[].class, new CollectionToLongArray()); collectionHandlers.put(Boolean[].class, new CollectionToBooleanArray()); collectionHandlers.put(Double[].class, new CollectionToDoubleArray()); collectionHandlers.put(Set.class, new CollectionToSet()); collectionHandlers.put(List.class, new CollectionToList()); collectionHandlers.put(Queue.class, new CollectionToQueue()); handlers.put(Collection.class, collectionHandlers); final Map<Class, TypeHandler> numberHandlers = new HashMap<Class, TypeHandler>(); numberHandlers.put(Integer.class, new NumberToInt()); numberHandlers.put(Long.class, new NumberToLong()); numberHandlers.put(Short.class, new NumberToShort()); numberHandlers.put(Float.class, new NumberToFloat()); numberHandlers.put(Double.class, new NumberToFloat()); numberHandlers.put(Byte.class, new NumberToByte()); numberHandlers.put(java.util.Date.class, new NumberToDate()); numberHandlers.put(java.sql.Date.class, new NumberToSQLDate()); handlers.put(Number.class, numberHandlers); /** * Build an inheretence Map. */ inheritanceMap.put(Integer.class, Number.class); inheritanceMap.put(Long.class, Number.class); inheritanceMap.put(Short.class, Number.class); inheritanceMap.put(Float.class, Number.class); inheritanceMap.put(Double.class, Number.class); inheritanceMap.put(ArrayList.class, List.class); inheritanceMap.put(LinkedList.class, List.class); inheritanceMap.put(AbstractList.class, List.class); inheritanceMap.put(Stack.class, List.class); inheritanceMap.put(HashSet.class, Set.class); inheritanceMap.put(AbstractSet.class, Set.class); inheritanceMap.put(Set.class, Collection.class); inheritanceMap.put(List.class, Collection.class); addHandler(String.class, Character.class, new TypeHandler<String, Character>() { public Character getConverted(final String in) { return in.charAt(0); } }); } public static Map<Class, TypeHandler> getHandler(final Class from) { if (!handlers.containsKey(from) && inheritanceMap.containsKey(from)) { return getHandler(inheritanceMap.get(from)); } else { return handlers.get(from); } } public static <T> T convert(final Object value, final Class<T> to) { if (value == null) return null; return convert(value.getClass(), to, value); } public static <T> T convert(final Class from, final Class<T> to, final Object value) { if (value.getClass() == to) return (T) value; final Map<Class, TypeHandler> toHandlers = getHandler(from); if (toHandlers == null) { if (value instanceof String) { /** * We assume that this may be an enum type. It may not be, but we try to decode it * as such. */ try { T val = (T) Enum.valueOf((Class<? extends Enum>) to, (String) value); /** * If we successfully decoded an enum, then we cache this handler for future * use. */ addHandler(from, to, new TypeHandler<String, T>() { public T getConverted(final String in) { return (T) Enum.valueOf((Class<? extends Enum>) to, in); } }); return val; } catch (Exception e) { /** * Definitely not an enum, so do nothing. */ return (T) value; } } return (T) value; } if (toHandlers.containsKey(to)) { return (T) toHandlers.get(to).getConverted(value); } else { return (T) value; } } public static void addHandler(final Class from, final Class to, final TypeHandler handler) { if (!handlers.containsKey(from)) { handlers.put(from, new HashMap<Class, TypeHandler>()); } handlers.get(from).put(to, handler); } }