From bbac38efbfe96ac6ff593efd23403ac279a67e37 Mon Sep 17 00:00:00 2001 From: Marcos Passos Date: Wed, 28 Feb 2018 11:26:03 -0300 Subject: [PATCH 1/4] Fix message of travis build commit --- .travis/deploy-javadocs.sh | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.travis/deploy-javadocs.sh b/.travis/deploy-javadocs.sh index 129880c..eab1841 100755 --- a/.travis/deploy-javadocs.sh +++ b/.travis/deploy-javadocs.sh @@ -16,23 +16,23 @@ fi REPOSITORY=${REPOSITORY:-"https://${GH_TOKEN}@github.com/${TRAVIS_REPO_SLUG}.git"} BRANCH=${BRANCH:-"gh-pages"} POM_VERSION=$(xmllint --xpath "//*[local-name()='project']/*[local-name()='version']/text()" pom.xml) -VERSION=${POM_VERSION} -VERSION_MAJOR="$(echo "${VERSION}" | cut -d '.' -f 1)" -VERSION_MINOR="$(echo "${VERSION}" | cut -d '.' -f 2)" +VERSION_MAJOR="$(echo "${POM_VERSION}" | cut -d '.' -f 1)" +VERSION_MINOR="$(echo "${POM_VERSION}" | cut -d '.' -f 2)" +VERSION_SHORT="${VERSION_MAJOR}.${VERSION_MINOR}" # Commit settings COMMIT_AUTHOR_NAME="Travis" COMMIT_AUTHOR_EMAIL="travis@travis-ci.org" -COMMIT_MESSAGE="Update documentation to version ${VERSION}" +COMMIT_MESSAGE="Update documentation to version ${VERSION_SHORT}" # Documentation paths API_DOCS_SRC="${TRAVIS_BUILD_DIR}/target/apidocs" API_DOCS="docs/api" API_LATEST="${API_DOCS}/latest" -API_DIR="${VERSION_MAJOR}.${VERSION_MINOR}" +API_DIR=VERSION_SHORT API_VERSION="${API_DOCS}/${API_DIR}" -echo "Updating javadocs to version ${VERSION_MAJOR}.${VERSION_MINOR}" +echo "Updating javadocs to version ${VERSION_SHORT}" # Import repository echo "Cloning repository..." @@ -59,4 +59,4 @@ git commit -m "${COMMIT_MESSAGE}" # Push changes to remote server git push origin HEAD -echo "Documentation successfully updated to version ${VERSION}" \ No newline at end of file +echo "Documentation successfully updated to version ${VERSION_SHORT}" \ No newline at end of file From 26173664b015eeb6a4ad5c4a05b856f8484acf37 Mon Sep 17 00:00:00 2001 From: Marcos Passos Date: Wed, 28 Feb 2018 18:48:08 -0300 Subject: [PATCH 2/4] - Fix bug that registers DoubleAdapter for type Integer instead of Double - Change signature of `registerAdapter` to avoid type/adapter mismatch mistake - Add tests to ensure that calling `registerBuiltinAdapters()` registers all builtin adapters --- .../phpserializer/AdapterRegistry.java | 54 +++++++++++- .../phpserializer/SerializerBuilder.java | 22 ++--- .../phpserializer/AdapterRegistryTest.java | 31 +++++++ .../phpserializer/SerializerBuilderTest.java | 82 +++++++++++++++++++ 4 files changed, 172 insertions(+), 17 deletions(-) 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..30d3002 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 { From 73178ecb7dcc6e4e59b7cc5804985cf75db549ca Mon Sep 17 00:00:00 2001 From: Marcos Passos Date: Wed, 28 Feb 2018 19:18:06 -0300 Subject: [PATCH 3/4] - Revert change to signature of `registerAdapter` --- .../java/com/marcospassos/phpserializer/SerializerBuilder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/marcospassos/phpserializer/SerializerBuilder.java b/src/main/java/com/marcospassos/phpserializer/SerializerBuilder.java index 30d3002..71ed55f 100755 --- a/src/main/java/com/marcospassos/phpserializer/SerializerBuilder.java +++ b/src/main/java/com/marcospassos/phpserializer/SerializerBuilder.java @@ -162,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); From 80b055aab0e6bceba6099a9f14575d81ef49b7ea Mon Sep 17 00:00:00 2001 From: Marcos Passos Date: Wed, 28 Feb 2018 19:24:00 -0300 Subject: [PATCH 4/4] Bump version to 0.8.0 --- CHANGELOG.md | 7 +++++++ README.md | 8 ++++---- pom.xml | 2 +- 3 files changed, 12 insertions(+), 5 deletions(-) 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