Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1878 | jmachado | 1 | package com.owlike.genson.convert; |
2 | |||
3 | import java.lang.annotation.Annotation; |
||
4 | import java.lang.reflect.Type; |
||
5 | import java.util.Iterator; |
||
6 | import java.util.List; |
||
7 | import java.util.Map; |
||
8 | |||
9 | import com.owlike.genson.Context; |
||
10 | import com.owlike.genson.Converter; |
||
11 | import com.owlike.genson.Deserializer; |
||
12 | import com.owlike.genson.Factory; |
||
13 | import com.owlike.genson.Genson; |
||
14 | import com.owlike.genson.Operations; |
||
15 | import com.owlike.genson.Serializer; |
||
16 | import com.owlike.genson.Wrapper; |
||
17 | import com.owlike.genson.reflect.BeanDescriptorProvider; |
||
18 | import com.owlike.genson.reflect.TypeUtil; |
||
19 | import com.owlike.genson.stream.ObjectReader; |
||
20 | import com.owlike.genson.stream.ObjectWriter; |
||
21 | |||
22 | /** |
||
23 | * This is the base factory that will create converters based on the default ones and on custom |
||
24 | * Serializer, Deserializer and Converter. But it also uses factories (default and custom) and |
||
25 | * {@link com.owlike.genson.reflect.BeanDescriptorProvider BeanDescriptorProvider} that is |
||
26 | * responsible of creating bean converters. |
||
27 | * <p/> |
||
28 | * When you ask for a Converter it will |
||
29 | * <ul> |
||
30 | * <ol> |
||
31 | * <li>Lookup in the registered Serializers for one that is parameterized with the current type, if |
||
32 | * found we finished (it takes the first one, so the order matters).</li> |
||
33 | * <li>Else we will try the factories by searching the ones that can create and instance of |
||
34 | * Serializer<CurrentType> (again the order is very important). We continue while they return |
||
35 | * null.</li> |
||
36 | * <li>If no factory could create an instance we will use BeanDescriptorProvider.</li> |
||
37 | * </ol> |
||
38 | * </li> |
||
39 | * <li>We apply all the same logic a second time for Deserializer.</li> |
||
40 | * <li>If they are both an instance of Converter then we return one of them</li> |
||
41 | * <li>Otherwise we will wrap both into a Converter.</li> |
||
42 | * </ul> |
||
43 | * <p/> |
||
44 | * Note that the create method from the registered factories will only be called if the type with |
||
45 | * which they are parameterized is assignable from the current type. For example, if we look for a |
||
46 | * serializer of Integer then Factory<Converter<Integer>> and Factory<Serializer<Object>> match |
||
47 | * both, the first registered will be used. |
||
48 | * |
||
49 | * @author eugen |
||
50 | */ |
||
51 | public class BasicConvertersFactory implements Factory<Converter<?>> { |
||
52 | private final Map<Type, Serializer<?>> serializersMap; |
||
53 | private final Map<Type, Deserializer<?>> deserializersMap; |
||
54 | private final List<Factory<?>> factories; |
||
55 | private final BeanDescriptorProvider beanDescriptorProvider; |
||
56 | |||
57 | public BasicConvertersFactory(Map<Type, Serializer<?>> serializersMap, |
||
58 | Map<Type, Deserializer<?>> deserializersMap, List<Factory<?>> factories, |
||
59 | BeanDescriptorProvider beanDescriptorProvider) { |
||
60 | this.serializersMap = serializersMap; |
||
61 | this.deserializersMap = deserializersMap; |
||
62 | this.factories = factories; |
||
63 | this.beanDescriptorProvider = beanDescriptorProvider; |
||
64 | } |
||
65 | |||
66 | @1.5.0/docs/api/java/lang/SuppressWarnings.html">SuppressWarnings({"unchecked", "rawtypes"}) |
||
67 | public Converter<?> create(1.5.0/docs/api/java/lang/reflect/Type.html">Type type, Genson genson) { |
||
68 | Converter<?> converter; |
||
69 | Serializer<?> serializer = provide(Serializer.class, type, serializersMap, genson); |
||
70 | Deserializer<?> deserializer = provide(Deserializer.class, type, deserializersMap, genson); |
||
71 | if (serializer instanceof Converter && deserializer instanceof Converter) { |
||
72 | converter = (Converter<?>) deserializer; |
||
73 | } else { |
||
74 | converter = new DelegatedConverter(serializer, deserializer); |
||
75 | } |
||
76 | return converter; |
||
77 | } |
||
78 | |||
79 | @1.5.0/docs/api/java/lang/SuppressWarnings.html">SuppressWarnings("unchecked") |
||
80 | protected <T> T provide(Class<T> forClass, 1.5.0/docs/api/java/lang/reflect/Type.html">Type withParameterType, |
||
81 | Map<Type, ? extends T> fromTypeMap, Genson genson) { |
||
82 | if (fromTypeMap.containsKey(withParameterType)) return fromTypeMap.get(withParameterType); |
||
83 | |||
84 | 1.5.0/docs/api/java/lang/reflect/Type.html">Type wrappedParameterType = withParameterType; |
||
85 | if (withParameterType instanceof Class<?> && ((Class<?>) withParameterType).isPrimitive()) |
||
86 | wrappedParameterType = TypeUtil.wrap((Class<?>) withParameterType); |
||
87 | |||
88 | for (Iterator<Factory<?>> it = factories.iterator(); it.hasNext(); ) { |
||
89 | Factory<?> factory = it.next(); |
||
90 | 5+0%2Fdocs%2Fapi+Object">Object object; |
||
91 | 1.5.0/docs/api/java/lang/reflect/Type.html">Type factoryType = TypeUtil.lookupGenericType(Factory.class, factory.getClass()); |
||
92 | factoryType = TypeUtil.expandType(factoryType, factory.getClass()); |
||
93 | // it is a parameterized type and we want the parameter corresponding to Serializer from |
||
94 | // Factory<Serializer<?>> |
||
95 | factoryType = TypeUtil.typeOf(0, factoryType); |
||
96 | 1.5.0/docs/api/java/lang/reflect/Type.html">Type factoryParameter = TypeUtil.typeOf(0, factoryType); |
||
97 | if (forClass.isAssignableFrom(TypeUtil.getRawClass(factoryType)) |
||
98 | && TypeUtil.match(wrappedParameterType, factoryParameter, false) |
||
99 | && (object = factory.create(withParameterType, genson)) != null) { |
||
100 | return forClass.cast(object); |
||
101 | } |
||
102 | } |
||
103 | |||
104 | return (T) beanDescriptorProvider.provide(TypeUtil.getRawClass(withParameterType), |
||
105 | withParameterType, genson); |
||
106 | } |
||
107 | |||
108 | private class DelegatedConverter<T> extends Wrapper<Converter<T>> implements Converter<T> { |
||
109 | private final Serializer<T> serializer; |
||
110 | private final Deserializer<T> deserializer; |
||
111 | |||
112 | public DelegatedConverter(Serializer<T> serializer, Deserializer<T> deserializer) { |
||
113 | this.serializer = serializer; |
||
114 | this.deserializer = deserializer; |
||
115 | } |
||
116 | |||
117 | public void serialize(T obj, ObjectWriter writer, 5+0%2Fdocs%2Fapi+Context">Context ctx) throws 1.5.0/docs/api/java/lang/Exception.html">Exception { |
||
118 | serializer.serialize(obj, writer, ctx); |
||
119 | } |
||
120 | |||
121 | public T deserialize(ObjectReader reader, 5+0%2Fdocs%2Fapi+Context">Context ctx) throws 1.5.0/docs/api/java/lang/Exception.html">Exception { |
||
122 | return deserializer.deserialize(reader, ctx); |
||
123 | } |
||
124 | |||
125 | @1.5.0/docs/api/java/lang/Override.html">Override |
||
126 | public <A extends Annotation> A getAnnotation(Class<A> aClass) { |
||
127 | A a = null; |
||
128 | if (serializer != null) a = toAnnotatedElement(serializer).getAnnotation(aClass); |
||
129 | if (deserializer != null && a == null) |
||
130 | a = toAnnotatedElement(deserializer).getAnnotation(aClass); |
||
131 | return a; |
||
132 | } |
||
133 | |||
134 | @1.5.0/docs/api/java/lang/Override.html">Override |
||
135 | public 5+0%2Fdocs%2Fapi+Annotation">Annotation[] getAnnotations() { |
||
136 | if (serializer != null && deserializer != null) |
||
137 | return Operations.union(5+0%2Fdocs%2Fapi+Annotation">Annotation[].class, toAnnotatedElement(serializer) |
||
138 | .getAnnotations(), toAnnotatedElement(deserializer).getAnnotations()); |
||
139 | if (serializer != null) return toAnnotatedElement(serializer).getAnnotations(); |
||
140 | if (deserializer != null) return toAnnotatedElement(deserializer).getAnnotations(); |
||
141 | |||
142 | return new 5+0%2Fdocs%2Fapi+Annotation">Annotation[0]; |
||
143 | } |
||
144 | |||
145 | @1.5.0/docs/api/java/lang/Override.html">Override |
||
146 | public 5+0%2Fdocs%2Fapi+Annotation">Annotation[] getDeclaredAnnotations() { |
||
147 | if (serializer != null && deserializer != null) |
||
148 | return Operations.union(5+0%2Fdocs%2Fapi+Annotation">Annotation[].class, toAnnotatedElement(serializer) |
||
149 | .getDeclaredAnnotations(), toAnnotatedElement(deserializer) |
||
150 | .getDeclaredAnnotations()); |
||
151 | if (serializer != null) return toAnnotatedElement(serializer).getDeclaredAnnotations(); |
||
152 | if (deserializer != null) |
||
153 | return toAnnotatedElement(deserializer).getDeclaredAnnotations(); |
||
154 | |||
155 | return new 5+0%2Fdocs%2Fapi+Annotation">Annotation[0]; |
||
156 | } |
||
157 | |||
158 | @1.5.0/docs/api/java/lang/Override.html">Override |
||
159 | public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) { |
||
160 | if (serializer != null) |
||
161 | return toAnnotatedElement(serializer).isAnnotationPresent(annotationClass); |
||
162 | if (deserializer != null) |
||
163 | return toAnnotatedElement(deserializer).isAnnotationPresent(annotationClass); |
||
164 | return false; |
||
165 | } |
||
166 | } |
||
167 | } |