package org.jboss.seam.remoting.wrapper; import java.lang.reflect.Constructor; import java.math.BigDecimal; import java.math.BigInteger; import java.util.Calendar; import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.Map; import javax.enterprise.inject.spi.BeanManager; /** * @author Shane Bryzak */ public class WrapperFactory { /** * Singleton instance. */ private static final WrapperFactory factory = new WrapperFactory(); /** * A registry of wrapper types */ private Map<String, Class<?>> wrapperRegistry = new HashMap<String, Class<?>>(); @SuppressWarnings("unchecked") private Map<Class, Class> classRegistry = new HashMap<Class, Class>(); /** * Private constructor */ private WrapperFactory() { // Register the defaults registerWrapper("str", StringWrapper.class); registerWrapper("bool", BooleanWrapper.class); registerWrapper("bean", BeanWrapper.class); registerWrapper("number", NumberWrapper.class); registerWrapper("null", NullWrapper.class); registerWrapper("bag", BagWrapper.class); registerWrapper("map", MapWrapper.class); registerWrapper("date", DateWrapper.class); // String types registerWrapperClass(String.class, StringWrapper.class); registerWrapperClass(StringBuilder.class, StringWrapper.class); registerWrapperClass(StringBuffer.class, StringWrapper.class); registerWrapperClass(Character.class, StringWrapper.class); // Big numbers are handled by StringWrapper registerWrapperClass(BigDecimal.class, StringWrapper.class); registerWrapperClass(BigInteger.class, StringWrapper.class); // Number types registerWrapperClass(Integer.class, NumberWrapper.class); registerWrapperClass(Long.class, NumberWrapper.class); registerWrapperClass(Short.class, NumberWrapper.class); registerWrapperClass(Double.class, NumberWrapper.class); registerWrapperClass(Float.class, NumberWrapper.class); registerWrapperClass(Byte.class, NumberWrapper.class); } public void registerWrapper(String type, Class<?> wrapperClass) { wrapperRegistry.put(type, wrapperClass); } public void registerWrapperClass(Class<?> cls, Class<?> wrapperClass) { classRegistry.put(cls, wrapperClass); } public static WrapperFactory getInstance() { return factory; } @SuppressWarnings("unchecked") public Wrapper createWrapper(String type, BeanManager beanManager) { Class wrapperClass = wrapperRegistry.get(type); if (wrapperClass != null) { try { Constructor<Wrapper> c = wrapperClass .getConstructor(BeanManager.class); Wrapper wrapper = c.newInstance(beanManager); return wrapper; } catch (Exception ex) { } } throw new RuntimeException(String.format( "Failed to create wrapper for type: %s", type)); } @SuppressWarnings("unchecked") public Wrapper getWrapperForObject(Object obj, BeanManager beanManager) { if (obj == null) return new NullWrapper(beanManager); Wrapper w = null; if (Map.class.isAssignableFrom(obj.getClass())) w = new MapWrapper(beanManager); else if (obj.getClass().isArray() || Collection.class.isAssignableFrom(obj.getClass())) w = new BagWrapper(beanManager); else if (obj.getClass().equals(Boolean.class) || obj.getClass().equals(Boolean.TYPE)) w = new BooleanWrapper(beanManager); else if (obj.getClass().isEnum()) w = new StringWrapper(beanManager); else if (Date.class.isAssignableFrom(obj.getClass()) || Calendar.class.isAssignableFrom(obj.getClass())) w = new DateWrapper(beanManager); else if (classRegistry.containsKey(obj.getClass())) { try { Constructor<Wrapper> c = classRegistry.get(obj.getClass()) .getConstructor(BeanManager.class); w = c.newInstance(beanManager); } catch (Exception ex) { throw new RuntimeException("Failed to create wrapper instance."); } } else w = new BeanWrapper(beanManager); w.setValue(obj); return w; } }