Skip to content

Commit 26c8bbc

Browse files
authored
Several improvements (#10)
1 parent 8ea4020 commit 26c8bbc

File tree

4 files changed

+172
-17
lines changed

4 files changed

+172
-17
lines changed

src/main/java/com/marcospassos/phpserializer/AdapterRegistry.java

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.marcospassos.phpserializer;
22

33
import java.util.ArrayList;
4+
import java.util.HashMap;
45
import java.util.LinkedHashMap;
56
import java.util.List;
67
import java.util.Map;
@@ -23,6 +24,22 @@ public class AdapterRegistry
2324
*/
2425
private List<Class> classes;
2526

27+
/**
28+
* The list of primitive types.
29+
*/
30+
private static Map<Class, Class> primitives = new HashMap<>();
31+
32+
static {
33+
primitives.put(int.class, Integer.class);
34+
primitives.put(long.class, Long.class);
35+
primitives.put(double.class, Double.class);
36+
primitives.put(float.class, Float.class);
37+
primitives.put(boolean.class, Boolean.class);
38+
primitives.put(char.class, Character.class);
39+
primitives.put(byte.class, Byte.class);
40+
primitives.put(short.class, Short.class);
41+
}
42+
2643
/**
2744
* Creates a registry containing the specified adapters.
2845
*
@@ -103,7 +120,7 @@ public TypeAdapter getAdapter(Class type)
103120
for (int index = 0, size = classes.size(); index < size; index++) {
104121
Class<?> currentClass = classes.get(index);
105122

106-
if (currentClass.isAssignableFrom(type)) {
123+
if (isAssignableFrom(currentClass, type)) {
107124
return adapters.get(index);
108125
}
109126
}
@@ -113,4 +130,39 @@ public TypeAdapter getAdapter(Class type)
113130
type
114131
));
115132
}
133+
134+
/**
135+
* Determines if the class or interface represented by {@code left} Class
136+
* object is either the same as, or is a superclass or superinterface of,
137+
* the class or interface represented by the {@code right} Class parameter.
138+
*
139+
* If the {@code left} Class object represents a primitive type, this method
140+
* returns true if the exactly {@code left} Class object or if the unboxed
141+
* type of this type is assignable from the {@code right} class.
142+
*
143+
* @param left The class to check if is the same as, or a subtype of the
144+
* {@code right} class.
145+
* @param right The class to check if is the same as or is a supertype of
146+
* the {@code left} class.
147+
*
148+
* @return the {@code boolean} value indicating whether objects of the
149+
* type {@code left} can be assigned to objects of type {@code right}.
150+
*/
151+
private static boolean isAssignableFrom(Class<?> left, Class<?> right)
152+
{
153+
if (left.isArray() && right.isArray()) {
154+
left = left.getComponentType();
155+
right = right.getComponentType();
156+
}
157+
158+
if (primitives.containsKey(left)) {
159+
left = primitives.get(left);
160+
}
161+
162+
if (primitives.containsKey(right)) {
163+
right = primitives.get(right);
164+
}
165+
166+
return left.isAssignableFrom(right);
167+
}
116168
}

src/main/java/com/marcospassos/phpserializer/SerializerBuilder.java

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import com.marcospassos.phpserializer.adapter.ArrayAdapter;
1010
import com.marcospassos.phpserializer.adapter.BooleanAdapter;
1111
import com.marcospassos.phpserializer.adapter.CollectionAdapter;
12+
import com.marcospassos.phpserializer.adapter.DoubleAdapter;
1213
import com.marcospassos.phpserializer.adapter.IntegerAdapter;
1314
import com.marcospassos.phpserializer.adapter.LongAdapter;
1415
import com.marcospassos.phpserializer.adapter.MapAdapter;
@@ -161,7 +162,7 @@ public SerializerBuilder addExclusionStrategy(FieldExclusionStrategy strategy)
161162
*
162163
* @return The current builder.
163164
*/
164-
public SerializerBuilder registerAdapter(Class type, TypeAdapter adapter)
165+
public <T> SerializerBuilder registerAdapter(Class type, TypeAdapter adapter)
165166
{
166167
adapterMap.put(type, adapter);
167168

@@ -180,22 +181,11 @@ public SerializerBuilder registerAdapter(Class type, TypeAdapter adapter)
180181
*/
181182
public SerializerBuilder registerBuiltinAdapters()
182183
{
183-
ArrayAdapter arrayAdapter = new ArrayAdapter();
184-
185-
registerAdapter(Object[].class, arrayAdapter);
186-
registerAdapter(int[].class, arrayAdapter);
187-
registerAdapter(float[].class, arrayAdapter);
188-
registerAdapter(byte[].class, arrayAdapter);
189-
registerAdapter(boolean[].class, arrayAdapter);
190-
registerAdapter(long[].class, arrayAdapter);
191-
registerAdapter(double[].class, arrayAdapter);
192-
registerAdapter(char[].class, arrayAdapter);
193-
registerAdapter(short[].class, arrayAdapter);
194-
195-
registerAdapter(Map.class, new MapAdapter());
196-
registerAdapter(Collection.class, new CollectionAdapter());
184+
registerAdapter(Object[].class, new ArrayAdapter<>());
185+
registerAdapter(Map.class, new MapAdapter<>());
186+
registerAdapter(Collection.class, new CollectionAdapter<>());
197187
registerAdapter(Boolean.class, new BooleanAdapter());
198-
registerAdapter(Double.class, new IntegerAdapter());
188+
registerAdapter(Double.class, new DoubleAdapter());
199189
registerAdapter(Integer.class, new IntegerAdapter());
200190
registerAdapter(Long.class, new LongAdapter());
201191
registerAdapter(String.class, new StringAdapter());

src/test/java/com/marcospassos/phpserializer/AdapterRegistryTest.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,28 +24,59 @@ public class AdapterRegistryTest
2424
public void getAdapterReturnsMostSpecializedAdapter() throws Exception
2525
{
2626
TypeAdapter numberAdapter = mock(TypeAdapter.class);
27+
TypeAdapter byteAdapter = mock(TypeAdapter.class);
28+
TypeAdapter longAdapter = mock(TypeAdapter.class);
29+
TypeAdapter booleanAdapter = mock(TypeAdapter.class);
30+
TypeAdapter charAdapter = mock(TypeAdapter.class);
31+
TypeAdapter shortAdapter = mock(TypeAdapter.class);
2732
TypeAdapter integerAdapter = mock(TypeAdapter.class);
2833
TypeAdapter doubleAdapter = mock(TypeAdapter.class);
2934
TypeAdapter collectionAdapter = mock(TypeAdapter.class);
3035
TypeAdapter setAdapter = mock(TypeAdapter.class);
3136
TypeAdapter hashSetAdapter = mock(TypeAdapter.class);
37+
TypeAdapter arrayOfIntegerAdapter = mock(TypeAdapter.class);
38+
TypeAdapter arrayOfObjectsAdapter = mock(TypeAdapter.class);
3239

3340
Map<Class, TypeAdapter> adapters = new LinkedHashMap<>();
3441
adapters.put(Double.class, doubleAdapter);
42+
adapters.put(Byte.class, byteAdapter);
43+
adapters.put(Long.class, longAdapter);
44+
adapters.put(Boolean.class, booleanAdapter);
45+
adapters.put(Character.class, charAdapter);
46+
adapters.put(Short.class, shortAdapter);
3547
adapters.put(Set.class, setAdapter);
3648
adapters.put(Collection.class, collectionAdapter);
3749
adapters.put(Number.class, numberAdapter);
3850
adapters.put(HashSet.class, hashSetAdapter);
3951
adapters.put(Integer.class, integerAdapter);
52+
adapters.put(int[].class, arrayOfIntegerAdapter);
53+
adapters.put(Object[].class, arrayOfObjectsAdapter);
4054

4155
AdapterRegistry registry = new AdapterRegistry(adapters);
4256

4357
assertSame(doubleAdapter, registry.getAdapter(Double.class));
58+
assertSame(doubleAdapter, registry.getAdapter(double.class));
4459
assertSame(integerAdapter, registry.getAdapter(Integer.class));
60+
assertSame(integerAdapter, registry.getAdapter(int.class));
61+
assertSame(charAdapter, registry.getAdapter(Character.class));
62+
assertSame(charAdapter, registry.getAdapter(char.class));
63+
assertSame(longAdapter, registry.getAdapter(Long.class));
64+
assertSame(longAdapter, registry.getAdapter(long.class));
65+
assertSame(byteAdapter, registry.getAdapter(Byte.class));
66+
assertSame(byteAdapter, registry.getAdapter(byte.class));
67+
assertSame(shortAdapter, registry.getAdapter(Short.class));
68+
assertSame(shortAdapter, registry.getAdapter(short.class));
69+
assertSame(booleanAdapter, registry.getAdapter(Boolean.class));
70+
assertSame(booleanAdapter, registry.getAdapter(boolean.class));
4571
assertSame(numberAdapter, registry.getAdapter(Float.class));
72+
assertSame(numberAdapter, registry.getAdapter(float.class));
4673
assertSame(hashSetAdapter, registry.getAdapter(HashSet.class));
4774
assertSame(setAdapter, registry.getAdapter(TreeSet.class));
4875
assertSame(collectionAdapter, registry.getAdapter(List.class));
76+
assertSame(arrayOfIntegerAdapter, registry.getAdapter(int[].class));
77+
assertSame(arrayOfObjectsAdapter, registry.getAdapter(double[].class));
78+
assertSame(arrayOfObjectsAdapter, registry.getAdapter(Object[].class));
79+
assertSame(arrayOfObjectsAdapter, registry.getAdapter(Double[].class));
4980
}
5081

5182
@Test(expected = IllegalArgumentException.class)

src/test/java/com/marcospassos/phpserializer/SerializerBuilderTest.java

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,32 @@
22

33
import java.lang.reflect.Field;
44
import java.nio.charset.Charset;
5+
import java.util.Collection;
56
import java.util.Map;
7+
import com.marcospassos.phpserializer.adapter.ArrayAdapter;
8+
import com.marcospassos.phpserializer.adapter.BooleanAdapter;
9+
import com.marcospassos.phpserializer.adapter.CollectionAdapter;
10+
import com.marcospassos.phpserializer.adapter.DoubleAdapter;
11+
import com.marcospassos.phpserializer.adapter.IntegerAdapter;
12+
import com.marcospassos.phpserializer.adapter.LongAdapter;
13+
import com.marcospassos.phpserializer.adapter.MapAdapter;
14+
import com.marcospassos.phpserializer.adapter.ObjectAdapter;
15+
import com.marcospassos.phpserializer.adapter.ReferableObjectAdapter;
16+
import com.marcospassos.phpserializer.adapter.StringAdapter;
617
import com.marcospassos.phpserializer.exclusion.DisjunctionExclusionStrategy;
718
import com.marcospassos.phpserializer.exclusion.NoExclusionStrategy;
819
import com.marcospassos.phpserializer.naming.PsrNamingStrategy;
20+
import org.hamcrest.CoreMatchers;
921
import org.junit.Test;
1022
import org.mockito.ArgumentCaptor;
1123

24+
import static org.hamcrest.CoreMatchers.*;
1225
import static org.junit.Assert.assertFalse;
1326
import static org.junit.Assert.assertSame;
27+
import static org.junit.Assert.assertThat;
1428
import static org.junit.Assert.assertTrue;
1529
import static org.mockito.ArgumentMatchers.any;
30+
import static org.mockito.ArgumentMatchers.isA;
1631
import static org.mockito.Mockito.mock;
1732
import static org.mockito.Mockito.verify;
1833
import static org.mockito.Mockito.verifyNoMoreInteractions;
@@ -180,6 +195,73 @@ public void builderRegistersBuiltinAdaptersIfNoAdapterIsRegistered()
180195
assertFalse(adapters.isEmpty());
181196
}
182197

198+
@Test
199+
public void builderRegistersAllBuiltinAdapters() throws Exception
200+
{
201+
SerializerFactory factory = mock(SerializerFactory.class);
202+
203+
SerializerBuilder builder = new SerializerBuilder(factory);
204+
205+
builder.registerBuiltinAdapters();
206+
builder.build();
207+
208+
ArgumentCaptor<AdapterRegistry> adapterRegistryArgument =
209+
ArgumentCaptor.forClass(AdapterRegistry.class);
210+
211+
verify(factory).create(
212+
any(NamingStrategy.class),
213+
any(FieldExclusionStrategy.class),
214+
adapterRegistryArgument.capture()
215+
);
216+
217+
AdapterRegistry registry = adapterRegistryArgument.getValue();
218+
219+
assertThat(
220+
registry.getAdapter(Object[].class),
221+
instanceOf(ArrayAdapter.class)
222+
);
223+
224+
assertThat(
225+
registry.getAdapter(Map.class),
226+
instanceOf(MapAdapter.class)
227+
);
228+
229+
assertThat(
230+
registry.getAdapter(Collection.class),
231+
instanceOf(CollectionAdapter.class)
232+
);
233+
234+
assertThat(
235+
registry.getAdapter(Boolean.class),
236+
instanceOf(BooleanAdapter.class)
237+
);
238+
239+
assertThat(
240+
registry.getAdapter(Double.class),
241+
instanceOf(DoubleAdapter.class)
242+
);
243+
244+
assertThat(
245+
registry.getAdapter(Integer.class),
246+
instanceOf(IntegerAdapter.class)
247+
);
248+
249+
assertThat(
250+
registry.getAdapter(Long.class),
251+
instanceOf(LongAdapter.class)
252+
);
253+
254+
assertThat(
255+
registry.getAdapter(String.class),
256+
instanceOf(StringAdapter.class)
257+
);
258+
259+
assertThat(
260+
registry.getAdapter(Object.class),
261+
instanceOf(ReferableObjectAdapter.class)
262+
);
263+
}
264+
183265
@Test
184266
public void builderRegisterStringAdapterUsingUtf8CharsetByDefault() throws Exception
185267
{

0 commit comments

Comments
 (0)