diff --git a/CHANGELOG.md b/CHANGELOG.md
index c3bf74f..4dd099f 100755
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
## Unreleased
There are currently no unreleased changes.
+## [0.8.0](https://github.com/marcospassos/java-php-serializer/releases/tag/0.8.0) (2018-02-28)
+
+### Changed
+
+- Fix bug that registers `DoubleAdapter` for type `Integer` instead of `Double`.
+- Add tests to ensure that calling `registerBuiltinAdapters()` registers all builtin adapters.
+
## [0.7.0](https://github.com/marcospassos/java-php-serializer/releases/tag/0.7.0) (2018-02-28)
### Changed
diff --git a/README.md b/README.md
index 2edf1b3..d0cc167 100644
--- a/README.md
+++ b/README.md
@@ -56,7 +56,7 @@ to the `dependencies` section of its `pom.xml` file:
com.marcospassos
phpserializer
- 0.7.0
+ 0.8.0
```
@@ -241,8 +241,8 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
```
-[maven-central-badge]: https://img.shields.io/badge/maven%20central-v0.7.0-blue.svg
-[maven-central-latest]: http://search.maven.org/#artifactdetails%7Ccom.marcospassos%7Cphpserializer%7C0.7.0%7Cjar
+[maven-central-badge]: https://img.shields.io/badge/maven%20central-v0.8.0-blue.svg
+[maven-central-latest]: http://search.maven.org/#artifactdetails%7Ccom.marcospassos%7Cphpserializer%7C0.8.0%7Cjar
[coverall-status]: https://coveralls.io/github/marcospassos/java-php-serializer
[coverall-badge]: https://coveralls.io/repos/github/marcospassos/java-php-serializer/badge.svg
[travis-badge]: https://travis-ci.org/marcospassos/java-php-serializer.svg?branch=master
@@ -257,4 +257,4 @@ DEALINGS IN THE SOFTWARE.
[issue-tracker]: https://github.com/marcospassos/java-php-serializer/issues
[repository]: https://github.com/marcospassos/java-php-serializer
[releases-page]: https://github.com/marcospassos/java-php-serializer/releases
-[latest-release]: https://github.com/marcospassos/java-php-serializer/releases/tag/0.7.0
+[latest-release]: https://github.com/marcospassos/java-php-serializer/releases/tag/0.8.0
diff --git a/pom.xml b/pom.xml
index 7c1bb2f..f66e904 100755
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
com.marcospassos
phpserializer
- 0.7.0-SNAPSHOT
+ 0.8.0-SNAPSHOT
jar
Java PHP Serializer
diff --git a/src/main/java/com/marcospassos/phpserializer/AdapterRegistry.java b/src/main/java/com/marcospassos/phpserializer/AdapterRegistry.java
index 4d614a3..85a7079 100755
--- a/src/main/java/com/marcospassos/phpserializer/AdapterRegistry.java
+++ b/src/main/java/com/marcospassos/phpserializer/AdapterRegistry.java
@@ -1,6 +1,7 @@
package com.marcospassos.phpserializer;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@@ -23,6 +24,22 @@ public class AdapterRegistry
*/
private List classes;
+ /**
+ * The list of primitive types.
+ */
+ private static Map primitives = new HashMap<>();
+
+ static {
+ primitives.put(int.class, Integer.class);
+ primitives.put(long.class, Long.class);
+ primitives.put(double.class, Double.class);
+ primitives.put(float.class, Float.class);
+ primitives.put(boolean.class, Boolean.class);
+ primitives.put(char.class, Character.class);
+ primitives.put(byte.class, Byte.class);
+ primitives.put(short.class, Short.class);
+ }
+
/**
* Creates a registry containing the specified adapters.
*
@@ -103,7 +120,7 @@ public TypeAdapter getAdapter(Class type)
for (int index = 0, size = classes.size(); index < size; index++) {
Class> currentClass = classes.get(index);
- if (currentClass.isAssignableFrom(type)) {
+ if (isAssignableFrom(currentClass, type)) {
return adapters.get(index);
}
}
@@ -113,4 +130,39 @@ public TypeAdapter getAdapter(Class type)
type
));
}
+
+ /**
+ * Determines if the class or interface represented by {@code left} Class
+ * object is either the same as, or is a superclass or superinterface of,
+ * the class or interface represented by the {@code right} Class parameter.
+ *
+ * If the {@code left} Class object represents a primitive type, this method
+ * returns true if the exactly {@code left} Class object or if the unboxed
+ * type of this type is assignable from the {@code right} class.
+ *
+ * @param left The class to check if is the same as, or a subtype of the
+ * {@code right} class.
+ * @param right The class to check if is the same as or is a supertype of
+ * the {@code left} class.
+ *
+ * @return the {@code boolean} value indicating whether objects of the
+ * type {@code left} can be assigned to objects of type {@code right}.
+ */
+ private static boolean isAssignableFrom(Class> left, Class> right)
+ {
+ if (left.isArray() && right.isArray()) {
+ left = left.getComponentType();
+ right = right.getComponentType();
+ }
+
+ if (primitives.containsKey(left)) {
+ left = primitives.get(left);
+ }
+
+ if (primitives.containsKey(right)) {
+ right = primitives.get(right);
+ }
+
+ return left.isAssignableFrom(right);
+ }
}
diff --git a/src/main/java/com/marcospassos/phpserializer/SerializerBuilder.java b/src/main/java/com/marcospassos/phpserializer/SerializerBuilder.java
index c03a144..71ed55f 100755
--- a/src/main/java/com/marcospassos/phpserializer/SerializerBuilder.java
+++ b/src/main/java/com/marcospassos/phpserializer/SerializerBuilder.java
@@ -9,6 +9,7 @@
import com.marcospassos.phpserializer.adapter.ArrayAdapter;
import com.marcospassos.phpserializer.adapter.BooleanAdapter;
import com.marcospassos.phpserializer.adapter.CollectionAdapter;
+import com.marcospassos.phpserializer.adapter.DoubleAdapter;
import com.marcospassos.phpserializer.adapter.IntegerAdapter;
import com.marcospassos.phpserializer.adapter.LongAdapter;
import com.marcospassos.phpserializer.adapter.MapAdapter;
@@ -161,7 +162,7 @@ public SerializerBuilder addExclusionStrategy(FieldExclusionStrategy strategy)
*
* @return The current builder.
*/
- public SerializerBuilder registerAdapter(Class type, TypeAdapter adapter)
+ public SerializerBuilder registerAdapter(Class type, TypeAdapter adapter)
{
adapterMap.put(type, adapter);
@@ -180,22 +181,11 @@ public SerializerBuilder registerAdapter(Class type, TypeAdapter adapter)
*/
public SerializerBuilder registerBuiltinAdapters()
{
- ArrayAdapter arrayAdapter = new ArrayAdapter();
-
- registerAdapter(Object[].class, arrayAdapter);
- registerAdapter(int[].class, arrayAdapter);
- registerAdapter(float[].class, arrayAdapter);
- registerAdapter(byte[].class, arrayAdapter);
- registerAdapter(boolean[].class, arrayAdapter);
- registerAdapter(long[].class, arrayAdapter);
- registerAdapter(double[].class, arrayAdapter);
- registerAdapter(char[].class, arrayAdapter);
- registerAdapter(short[].class, arrayAdapter);
-
- registerAdapter(Map.class, new MapAdapter());
- registerAdapter(Collection.class, new CollectionAdapter());
+ registerAdapter(Object[].class, new ArrayAdapter<>());
+ registerAdapter(Map.class, new MapAdapter<>());
+ registerAdapter(Collection.class, new CollectionAdapter<>());
registerAdapter(Boolean.class, new BooleanAdapter());
- registerAdapter(Double.class, new IntegerAdapter());
+ registerAdapter(Double.class, new DoubleAdapter());
registerAdapter(Integer.class, new IntegerAdapter());
registerAdapter(Long.class, new LongAdapter());
registerAdapter(String.class, new StringAdapter());
diff --git a/src/test/java/com/marcospassos/phpserializer/AdapterRegistryTest.java b/src/test/java/com/marcospassos/phpserializer/AdapterRegistryTest.java
index 6c87208..946abc6 100755
--- a/src/test/java/com/marcospassos/phpserializer/AdapterRegistryTest.java
+++ b/src/test/java/com/marcospassos/phpserializer/AdapterRegistryTest.java
@@ -24,28 +24,59 @@ public class AdapterRegistryTest
public void getAdapterReturnsMostSpecializedAdapter() throws Exception
{
TypeAdapter numberAdapter = mock(TypeAdapter.class);
+ TypeAdapter byteAdapter = mock(TypeAdapter.class);
+ TypeAdapter longAdapter = mock(TypeAdapter.class);
+ TypeAdapter booleanAdapter = mock(TypeAdapter.class);
+ TypeAdapter charAdapter = mock(TypeAdapter.class);
+ TypeAdapter shortAdapter = mock(TypeAdapter.class);
TypeAdapter integerAdapter = mock(TypeAdapter.class);
TypeAdapter doubleAdapter = mock(TypeAdapter.class);
TypeAdapter collectionAdapter = mock(TypeAdapter.class);
TypeAdapter setAdapter = mock(TypeAdapter.class);
TypeAdapter hashSetAdapter = mock(TypeAdapter.class);
+ TypeAdapter arrayOfIntegerAdapter = mock(TypeAdapter.class);
+ TypeAdapter arrayOfObjectsAdapter = mock(TypeAdapter.class);
Map adapters = new LinkedHashMap<>();
adapters.put(Double.class, doubleAdapter);
+ adapters.put(Byte.class, byteAdapter);
+ adapters.put(Long.class, longAdapter);
+ adapters.put(Boolean.class, booleanAdapter);
+ adapters.put(Character.class, charAdapter);
+ adapters.put(Short.class, shortAdapter);
adapters.put(Set.class, setAdapter);
adapters.put(Collection.class, collectionAdapter);
adapters.put(Number.class, numberAdapter);
adapters.put(HashSet.class, hashSetAdapter);
adapters.put(Integer.class, integerAdapter);
+ adapters.put(int[].class, arrayOfIntegerAdapter);
+ adapters.put(Object[].class, arrayOfObjectsAdapter);
AdapterRegistry registry = new AdapterRegistry(adapters);
assertSame(doubleAdapter, registry.getAdapter(Double.class));
+ assertSame(doubleAdapter, registry.getAdapter(double.class));
assertSame(integerAdapter, registry.getAdapter(Integer.class));
+ assertSame(integerAdapter, registry.getAdapter(int.class));
+ assertSame(charAdapter, registry.getAdapter(Character.class));
+ assertSame(charAdapter, registry.getAdapter(char.class));
+ assertSame(longAdapter, registry.getAdapter(Long.class));
+ assertSame(longAdapter, registry.getAdapter(long.class));
+ assertSame(byteAdapter, registry.getAdapter(Byte.class));
+ assertSame(byteAdapter, registry.getAdapter(byte.class));
+ assertSame(shortAdapter, registry.getAdapter(Short.class));
+ assertSame(shortAdapter, registry.getAdapter(short.class));
+ assertSame(booleanAdapter, registry.getAdapter(Boolean.class));
+ assertSame(booleanAdapter, registry.getAdapter(boolean.class));
assertSame(numberAdapter, registry.getAdapter(Float.class));
+ assertSame(numberAdapter, registry.getAdapter(float.class));
assertSame(hashSetAdapter, registry.getAdapter(HashSet.class));
assertSame(setAdapter, registry.getAdapter(TreeSet.class));
assertSame(collectionAdapter, registry.getAdapter(List.class));
+ assertSame(arrayOfIntegerAdapter, registry.getAdapter(int[].class));
+ assertSame(arrayOfObjectsAdapter, registry.getAdapter(double[].class));
+ assertSame(arrayOfObjectsAdapter, registry.getAdapter(Object[].class));
+ assertSame(arrayOfObjectsAdapter, registry.getAdapter(Double[].class));
}
@Test(expected = IllegalArgumentException.class)
diff --git a/src/test/java/com/marcospassos/phpserializer/SerializerBuilderTest.java b/src/test/java/com/marcospassos/phpserializer/SerializerBuilderTest.java
index 9fcfd75..4bc5021 100755
--- a/src/test/java/com/marcospassos/phpserializer/SerializerBuilderTest.java
+++ b/src/test/java/com/marcospassos/phpserializer/SerializerBuilderTest.java
@@ -2,17 +2,32 @@
import java.lang.reflect.Field;
import java.nio.charset.Charset;
+import java.util.Collection;
import java.util.Map;
+import com.marcospassos.phpserializer.adapter.ArrayAdapter;
+import com.marcospassos.phpserializer.adapter.BooleanAdapter;
+import com.marcospassos.phpserializer.adapter.CollectionAdapter;
+import com.marcospassos.phpserializer.adapter.DoubleAdapter;
+import com.marcospassos.phpserializer.adapter.IntegerAdapter;
+import com.marcospassos.phpserializer.adapter.LongAdapter;
+import com.marcospassos.phpserializer.adapter.MapAdapter;
+import com.marcospassos.phpserializer.adapter.ObjectAdapter;
+import com.marcospassos.phpserializer.adapter.ReferableObjectAdapter;
+import com.marcospassos.phpserializer.adapter.StringAdapter;
import com.marcospassos.phpserializer.exclusion.DisjunctionExclusionStrategy;
import com.marcospassos.phpserializer.exclusion.NoExclusionStrategy;
import com.marcospassos.phpserializer.naming.PsrNamingStrategy;
+import org.hamcrest.CoreMatchers;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
+import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.isA;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
@@ -180,6 +195,73 @@ public void builderRegistersBuiltinAdaptersIfNoAdapterIsRegistered()
assertFalse(adapters.isEmpty());
}
+ @Test
+ public void builderRegistersAllBuiltinAdapters() throws Exception
+ {
+ SerializerFactory factory = mock(SerializerFactory.class);
+
+ SerializerBuilder builder = new SerializerBuilder(factory);
+
+ builder.registerBuiltinAdapters();
+ builder.build();
+
+ ArgumentCaptor adapterRegistryArgument =
+ ArgumentCaptor.forClass(AdapterRegistry.class);
+
+ verify(factory).create(
+ any(NamingStrategy.class),
+ any(FieldExclusionStrategy.class),
+ adapterRegistryArgument.capture()
+ );
+
+ AdapterRegistry registry = adapterRegistryArgument.getValue();
+
+ assertThat(
+ registry.getAdapter(Object[].class),
+ instanceOf(ArrayAdapter.class)
+ );
+
+ assertThat(
+ registry.getAdapter(Map.class),
+ instanceOf(MapAdapter.class)
+ );
+
+ assertThat(
+ registry.getAdapter(Collection.class),
+ instanceOf(CollectionAdapter.class)
+ );
+
+ assertThat(
+ registry.getAdapter(Boolean.class),
+ instanceOf(BooleanAdapter.class)
+ );
+
+ assertThat(
+ registry.getAdapter(Double.class),
+ instanceOf(DoubleAdapter.class)
+ );
+
+ assertThat(
+ registry.getAdapter(Integer.class),
+ instanceOf(IntegerAdapter.class)
+ );
+
+ assertThat(
+ registry.getAdapter(Long.class),
+ instanceOf(LongAdapter.class)
+ );
+
+ assertThat(
+ registry.getAdapter(String.class),
+ instanceOf(StringAdapter.class)
+ );
+
+ assertThat(
+ registry.getAdapter(Object.class),
+ instanceOf(ReferableObjectAdapter.class)
+ );
+ }
+
@Test
public void builderRegisterStringAdapterUsingUtf8CharsetByDefault() throws Exception
{