http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/core/runtime/src/test/java/org/apache/polygene/runtime/mixin/JDKMixinTest.java ---------------------------------------------------------------------- diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/mixin/JDKMixinTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/mixin/JDKMixinTest.java index 116e82c..fc4937a 100644 --- a/core/runtime/src/test/java/org/apache/polygene/runtime/mixin/JDKMixinTest.java +++ b/core/runtime/src/test/java/org/apache/polygene/runtime/mixin/JDKMixinTest.java @@ -26,6 +26,9 @@ import java.util.List; import java.util.Map; import java.util.function.Predicate; import java.util.stream.Collectors; +import javax.json.Json; +import javax.json.JsonObject; +import javax.json.JsonObjectBuilder; import org.apache.polygene.api.common.Visibility; import org.apache.polygene.api.concern.Concerns; import org.apache.polygene.api.concern.GenericConcern; @@ -36,7 +39,6 @@ import org.apache.polygene.api.service.ServiceReference; import org.apache.polygene.bootstrap.AssemblyException; import org.apache.polygene.bootstrap.ModuleAssembly; import org.apache.polygene.test.AbstractPolygeneTest; -import org.json.JSONObject; import org.junit.Before; import org.junit.Test; @@ -46,56 +48,46 @@ import static org.junit.Assert.assertThat; /** * Assert that JDK classes are usable as Mixins. */ -public class JDKMixinTest - extends AbstractPolygeneTest +public class JDKMixinTest extends AbstractPolygeneTest { - @Concerns( JDKMixinConcern.class ) - public interface JSONSerializableMap - extends Map<String, String> + public interface JSONSerializableMap extends Map<String, String> { - - JSONObject toJSON(); - + JsonObject toJSON(); } @SuppressWarnings( "serial" ) - public static class ExtendsJDKMixin - extends HashMap<String, String> + public static class ExtendsJDKMixin extends HashMap<String, String> implements JSONSerializableMap { - @Override - public JSONObject toJSON() + public JsonObject toJSON() { System.out.println( ">>>> Call ExtendsJDKMixin.toJSON()" ); - // Copy the Map before handing it to JSONObject so that the JSONObject do not use the Composite - return new JSONObject( new HashMap<String, String>( this ) ); + JsonObjectBuilder builder = Json.createObjectBuilder(); + entrySet().forEach( entry -> builder.add( entry.getKey(), entry.getValue() ) ); + return builder.build(); } - } public static abstract class ComposeWithJDKMixin implements JSONSerializableMap { - @This private Map<String, String> map; @Override - public JSONObject toJSON() + public JsonObject toJSON() { System.out.println( ">>>> Call ComposeWithJDKMixin.toJSON()" ); - // Copy the Map before handing it to JSONObject so that the JSONObject do not use the Composite - return new JSONObject( new HashMap<String, String>( map ) ); + JsonObjectBuilder builder = Json.createObjectBuilder(); + map.entrySet().forEach( entry -> builder.add( entry.getKey(), entry.getValue() ) ); + return builder.build(); } - } - public static class JDKMixinConcern - extends GenericConcern + public static class JDKMixinConcern extends GenericConcern { - @Override public Object invoke( Object proxy, Method method, Object[] args ) throws Throwable @@ -104,13 +96,14 @@ public class JDKMixinTest CONCERN_RECORDS.add( method.getName() ); return next.invoke( proxy, method, args ); } - } private static final Identity EXTENDS_IDENTITY = new StringIdentity( ExtendsJDKMixin.class.getName() ); private static final Identity COMPOSE_IDENTITY = new StringIdentity( ComposeWithJDKMixin.class.getName() ); - private static final Predicate<ServiceReference<?>> EXTENDS_IDENTITY_SPEC = new ServiceIdentitySpec( EXTENDS_IDENTITY ); - private static final Predicate<ServiceReference<?>> COMPOSE_IDENTITY_SPEC = new ServiceIdentitySpec( COMPOSE_IDENTITY ); + private static final Predicate<ServiceReference<?>> EXTENDS_IDENTITY_SPEC = new ServiceIdentitySpec( + EXTENDS_IDENTITY ); + private static final Predicate<ServiceReference<?>> COMPOSE_IDENTITY_SPEC = new ServiceIdentitySpec( + COMPOSE_IDENTITY ); private static final List<String> CONCERN_RECORDS = new ArrayList<String>(); @Before @@ -123,16 +116,16 @@ public class JDKMixinTest public void assemble( ModuleAssembly module ) throws AssemblyException { - module.services( JSONSerializableMap.class ). - identifiedBy( EXTENDS_IDENTITY.toString() ). - withMixins( ExtendsJDKMixin.class ). - instantiateOnStartup(); - - module.layer().module( "compose" ).services( JSONSerializableMap.class ). - visibleIn( Visibility.layer ). - identifiedBy( COMPOSE_IDENTITY.toString() ). - withMixins( HashMap.class, ComposeWithJDKMixin.class ). - instantiateOnStartup(); + module.services( JSONSerializableMap.class ) + .identifiedBy( EXTENDS_IDENTITY.toString() ) + .withMixins( ExtendsJDKMixin.class ) + .instantiateOnStartup(); + + module.layer().module( "compose" ).services( JSONSerializableMap.class ) + .visibleIn( Visibility.layer ) + .identifiedBy( COMPOSE_IDENTITY.toString() ) + .withMixins( HashMap.class, ComposeWithJDKMixin.class ) + .instantiateOnStartup(); } @Test @@ -147,12 +140,12 @@ public class JDKMixinTest JSONSerializableMap extending = services.get( 0 ).get(); extending.put( "foo", "bar" ); // Concern trigger #1 (put) - JSONObject json = extending.toJSON(); // Concern trigger #2, #3 and #4 (toJSON, size, entrySet) + JsonObject json = extending.toJSON(); // Concern trigger #2 and #3 (toJSON, entrySet) - assertThat( json.length(), equalTo( 1 ) ); - assertThat( json.optString( "foo" ), equalTo( "bar" ) ); + assertThat( json.size(), equalTo( 1 ) ); + assertThat( json.getString( "foo" ), equalTo( "bar" ) ); - assertThat( CONCERN_RECORDS.size(), equalTo( 4 ) ); + assertThat( CONCERN_RECORDS.size(), equalTo( 3 ) ); } @Test @@ -167,21 +160,20 @@ public class JDKMixinTest JSONSerializableMap composing = services.get( 0 ).get(); composing.put( "foo", "bar" ); // Concern trigger #1 (put) - JSONObject json = composing.toJSON(); // Concern trigger #2, #3 and #4 (toJSON, size, entrySet) + JsonObject json = composing.toJSON(); // Concern trigger #2 and #3 (toJSON, entrySet) - assertThat( json.length(), equalTo( 1 ) ); - assertThat( json.optString( "foo" ), equalTo( "bar" ) ); + assertThat( json.size(), equalTo( 1 ) ); + assertThat( json.getString( "foo" ), equalTo( "bar" ) ); - assertThat( CONCERN_RECORDS.size(), equalTo( 4 ) ); + assertThat( CONCERN_RECORDS.size(), equalTo( 3 ) ); } private static class ServiceIdentitySpec implements Predicate<ServiceReference<?>> { - private final Identity identity; - ServiceIdentitySpec(Identity identity) + ServiceIdentitySpec( Identity identity ) { this.identity = identity; } @@ -191,7 +183,5 @@ public class JDKMixinTest { return item.identity().equals( identity ); } - } - } \ No newline at end of file
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/core/runtime/src/test/java/org/apache/polygene/runtime/property/ValueNestedBuilderTest.java ---------------------------------------------------------------------- diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/property/ValueNestedBuilderTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/property/ValueNestedBuilderTest.java index caad29d..026cb13 100644 --- a/core/runtime/src/test/java/org/apache/polygene/runtime/property/ValueNestedBuilderTest.java +++ b/core/runtime/src/test/java/org/apache/polygene/runtime/property/ValueNestedBuilderTest.java @@ -30,13 +30,11 @@ import org.apache.polygene.api.value.ValueComposite; import org.apache.polygene.bootstrap.AssemblyException; import org.apache.polygene.bootstrap.ModuleAssembly; import org.apache.polygene.test.AbstractPolygeneTest; -import org.apache.polygene.valueserialization.orgjson.OrgJsonValueSerializationService; import org.junit.Test; public class ValueNestedBuilderTest extends AbstractPolygeneTest { - private interface InnerValue extends ValueComposite { @@ -75,7 +73,6 @@ public class ValueNestedBuilderTest public void assemble( ModuleAssembly module ) throws AssemblyException { - module.services( OrgJsonValueSerializationService.class ); module.values( InnerValue.class, InnerDefaultedValue.class, OuterValue.class, OuterDefaultedValue.class ); } http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/core/runtime/src/test/java/org/apache/polygene/runtime/value/AssociationToValueTest.java ---------------------------------------------------------------------- diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/value/AssociationToValueTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/value/AssociationToValueTest.java index 370883f..18b6935 100644 --- a/core/runtime/src/test/java/org/apache/polygene/runtime/value/AssociationToValueTest.java +++ b/core/runtime/src/test/java/org/apache/polygene/runtime/value/AssociationToValueTest.java @@ -35,12 +35,10 @@ import org.apache.polygene.api.unitofwork.UnitOfWork; import org.apache.polygene.api.unitofwork.UnitOfWorkFactory; import org.apache.polygene.api.unitofwork.concern.UnitOfWorkConcern; import org.apache.polygene.api.unitofwork.concern.UnitOfWorkPropagation; -import org.apache.polygene.api.value.ValueSerialization; import org.apache.polygene.bootstrap.AssemblyException; import org.apache.polygene.bootstrap.ModuleAssembly; import org.apache.polygene.entitystore.memory.MemoryEntityStoreService; import org.apache.polygene.test.AbstractPolygeneTest; -import org.apache.polygene.valueserialization.orgjson.OrgJsonValueSerializationService; import org.junit.Test; import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder; @@ -102,7 +100,6 @@ public class AssociationToValueTest extends AbstractPolygeneTest module.entities( Person.class ); module.values( Person.class ); module.services( PersonRepository.class ).withConcerns( UnitOfWorkConcern.class ); - module.services( OrgJsonValueSerializationService.class ).taggedWith( ValueSerialization.Formats.JSON ); module.services( MemoryEntityStoreService.class ); module.services( Runnable.class ) http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/core/runtime/src/test/java/org/apache/polygene/runtime/value/NestedValueBuilderTest.java ---------------------------------------------------------------------- diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/value/NestedValueBuilderTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/value/NestedValueBuilderTest.java index 55196cb..45859de 100644 --- a/core/runtime/src/test/java/org/apache/polygene/runtime/value/NestedValueBuilderTest.java +++ b/core/runtime/src/test/java/org/apache/polygene/runtime/value/NestedValueBuilderTest.java @@ -23,8 +23,6 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import org.apache.polygene.valueserialization.orgjson.OrgJsonValueSerializationService; -import org.junit.Test; import org.apache.polygene.api.common.UseDefaults; import org.apache.polygene.api.property.Property; import org.apache.polygene.api.value.ValueBuilder; @@ -32,6 +30,7 @@ import org.apache.polygene.api.value.ValueComposite; import org.apache.polygene.bootstrap.AssemblyException; import org.apache.polygene.bootstrap.ModuleAssembly; import org.apache.polygene.test.AbstractPolygeneTest; +import org.junit.Test; import static org.junit.Assert.fail; @@ -78,7 +77,6 @@ public class NestedValueBuilderTest public void assemble( ModuleAssembly module ) throws AssemblyException { - module.services( OrgJsonValueSerializationService.class ); module.values( InnerValue.class, InnerDefaultedValue.class, OuterValue.class, OuterDefaultedValue.class ); } @@ -87,8 +85,8 @@ public class NestedValueBuilderTest { ValueBuilder<InnerValue> innerBuilder = valueBuilderFactory.newValueBuilder( InnerValue.class ); InnerValue inner = innerBuilder.prototype(); - inner.listProp().set( new ArrayList<String>() ); - inner.mapProp().set( new HashMap<String, String>() ); + inner.listProp().set( new ArrayList<>() ); + inner.mapProp().set( new HashMap<>() ); inner = innerBuilder.newInstance(); // If we reach this point, value creation went well try @@ -116,12 +114,12 @@ public class NestedValueBuilderTest { ValueBuilder<InnerValue> innerBuilder = valueBuilderFactory.newValueBuilder( InnerValue.class ); InnerValue innerPrototype = innerBuilder.prototype(); - innerPrototype.listProp().set( new ArrayList<String>() ); - innerPrototype.mapProp().set( new HashMap<String, String>() ); + innerPrototype.listProp().set( new ArrayList<>() ); + innerPrototype.mapProp().set( new HashMap<>() ); InnerValue innerInstance = innerBuilder.newInstance(); ValueBuilder<OuterValue> outerBuilder = valueBuilderFactory.newValueBuilder( OuterValue.class ); OuterValue outerPrototype = outerBuilder.prototype(); - List<InnerValue> inners = new ArrayList<InnerValue>(); + List<InnerValue> inners = new ArrayList<>(); inners.add( innerInstance ); outerPrototype.innerListProp().set( inners ); OuterValue outerInstance = outerBuilder.newInstance(); @@ -171,7 +169,7 @@ public class NestedValueBuilderTest InnerDefaultedValue innerInstance = innerBuilder.newInstance(); ValueBuilder<OuterDefaultedValue> outerBuilder = valueBuilderFactory.newValueBuilder( OuterDefaultedValue.class ); OuterDefaultedValue outerPrototype = outerBuilder.prototype(); - List<InnerDefaultedValue> inners = new ArrayList<InnerDefaultedValue>(); + List<InnerDefaultedValue> inners = new ArrayList<>(); inners.add( innerInstance ); outerPrototype.innerListPropDefault().set( inners ); OuterDefaultedValue outerInstance = outerBuilder.newInstance(); http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/core/runtime/src/test/java/org/apache/polygene/runtime/value/ValueCompositeBasicsTest.java ---------------------------------------------------------------------- diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/value/ValueCompositeBasicsTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/value/ValueCompositeBasicsTest.java index 2ad6db4..bc538f1 100644 --- a/core/runtime/src/test/java/org/apache/polygene/runtime/value/ValueCompositeBasicsTest.java +++ b/core/runtime/src/test/java/org/apache/polygene/runtime/value/ValueCompositeBasicsTest.java @@ -19,15 +19,14 @@ */ package org.apache.polygene.runtime.value; -import org.apache.polygene.test.AbstractPolygeneTest; -import org.apache.polygene.valueserialization.orgjson.OrgJsonValueSerializationService; -import org.junit.Test; import org.apache.polygene.api.injection.scope.This; import org.apache.polygene.api.mixin.Mixins; import org.apache.polygene.api.property.Property; import org.apache.polygene.api.value.ValueBuilder; import org.apache.polygene.bootstrap.AssemblyException; import org.apache.polygene.bootstrap.ModuleAssembly; +import org.apache.polygene.test.AbstractPolygeneTest; +import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -39,7 +38,6 @@ public class ValueCompositeBasicsTest public void assemble( ModuleAssembly module ) throws AssemblyException { - module.services( OrgJsonValueSerializationService.class ); module.values( SomeValue.class ); } http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/core/runtime/src/test/java/org/apache/polygene/runtime/value/ValueSerializationRegressionTest.java ---------------------------------------------------------------------- diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/value/ValueSerializationRegressionTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/value/ValueSerializationRegressionTest.java index 5143909..fe8cdd8 100644 --- a/core/runtime/src/test/java/org/apache/polygene/runtime/value/ValueSerializationRegressionTest.java +++ b/core/runtime/src/test/java/org/apache/polygene/runtime/value/ValueSerializationRegressionTest.java @@ -19,21 +19,19 @@ */ package org.apache.polygene.runtime.value; -import org.apache.polygene.api.identity.HasIdentity; -import org.apache.polygene.api.identity.StringIdentity; -import org.junit.Test; import org.apache.polygene.api.association.Association; import org.apache.polygene.api.association.ManyAssociation; import org.apache.polygene.api.association.NamedAssociation; +import org.apache.polygene.api.identity.HasIdentity; +import org.apache.polygene.api.identity.StringIdentity; import org.apache.polygene.api.property.Property; import org.apache.polygene.api.unitofwork.UnitOfWorkCompletionException; import org.apache.polygene.api.value.ValueBuilder; -import org.apache.polygene.api.value.ValueSerialization; import org.apache.polygene.bootstrap.AssemblyException; import org.apache.polygene.bootstrap.ModuleAssembly; import org.apache.polygene.entitystore.memory.MemoryEntityStoreService; import org.apache.polygene.test.AbstractPolygeneTest; -import org.apache.polygene.valueserialization.orgjson.OrgJsonValueSerializationService; +import org.junit.Test; public class ValueSerializationRegressionTest extends AbstractPolygeneTest { @@ -45,7 +43,6 @@ public class ValueSerializationRegressionTest extends AbstractPolygeneTest module.entities( DualFaced.class ); module.values( DualFaced.class ); module.services( MemoryEntityStoreService.class ); - module.services( OrgJsonValueSerializationService.class ).taggedWith( ValueSerialization.Formats.JSON ); } @Test http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/core/runtime/src/test/java/org/apache/polygene/runtime/value/ValueWithAssociationTest.java ---------------------------------------------------------------------- diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/value/ValueWithAssociationTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/value/ValueWithAssociationTest.java index 175e116..4441a76 100644 --- a/core/runtime/src/test/java/org/apache/polygene/runtime/value/ValueWithAssociationTest.java +++ b/core/runtime/src/test/java/org/apache/polygene/runtime/value/ValueWithAssociationTest.java @@ -19,10 +19,6 @@ */ package org.apache.polygene.runtime.value; -import org.apache.polygene.api.identity.HasIdentity; -import org.apache.polygene.api.identity.Identity; -import org.apache.polygene.api.identity.StringIdentity; -import org.junit.Test; import org.apache.polygene.api.association.Association; import org.apache.polygene.api.association.AssociationStateHolder; import org.apache.polygene.api.association.ManyAssociation; @@ -31,16 +27,18 @@ import org.apache.polygene.api.common.Optional; import org.apache.polygene.api.entity.EntityBuilder; import org.apache.polygene.api.entity.EntityComposite; import org.apache.polygene.api.entity.EntityReference; +import org.apache.polygene.api.identity.HasIdentity; +import org.apache.polygene.api.identity.Identity; +import org.apache.polygene.api.identity.StringIdentity; import org.apache.polygene.api.property.Property; import org.apache.polygene.api.unitofwork.UnitOfWork; import org.apache.polygene.api.unitofwork.UnitOfWorkCompletionException; import org.apache.polygene.api.value.ValueBuilder; -import org.apache.polygene.api.value.ValueSerialization; import org.apache.polygene.bootstrap.AssemblyException; import org.apache.polygene.bootstrap.ModuleAssembly; import org.apache.polygene.entitystore.memory.MemoryEntityStoreService; import org.apache.polygene.test.AbstractPolygeneTest; -import org.apache.polygene.valueserialization.orgjson.OrgJsonValueSerializationService; +import org.junit.Test; import static org.hamcrest.core.IsEqual.equalTo; import static org.junit.Assert.assertThat; @@ -56,7 +54,6 @@ public class ValueWithAssociationTest extends AbstractPolygeneTest module.values( SimpleName.class ); module.values( DualFaced.class ); module.services( MemoryEntityStoreService.class ); - module.services( OrgJsonValueSerializationService.class ).taggedWith( ValueSerialization.Formats.JSON ); } @Test http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/core/runtime/src/test/java/org/apache/polygene/runtime/visibility/VisibilityInUnitOfWorkTest.java ---------------------------------------------------------------------- diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/visibility/VisibilityInUnitOfWorkTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/visibility/VisibilityInUnitOfWorkTest.java index b7dfe66..66c4bc8 100644 --- a/core/runtime/src/test/java/org/apache/polygene/runtime/visibility/VisibilityInUnitOfWorkTest.java +++ b/core/runtime/src/test/java/org/apache/polygene/runtime/visibility/VisibilityInUnitOfWorkTest.java @@ -30,7 +30,6 @@ import org.apache.polygene.api.structure.Application; import org.apache.polygene.api.structure.Module; import org.apache.polygene.api.unitofwork.UnitOfWork; import org.apache.polygene.api.unitofwork.UnitOfWorkFactory; -import org.apache.polygene.api.value.ValueSerialization; import org.apache.polygene.bootstrap.ApplicationAssembly; import org.apache.polygene.bootstrap.AssemblyException; import org.apache.polygene.bootstrap.Energy4Java; @@ -38,7 +37,6 @@ import org.apache.polygene.bootstrap.LayerAssembly; import org.apache.polygene.bootstrap.ModuleAssembly; import org.apache.polygene.bootstrap.unitofwork.DefaultUnitOfWorkAssembler; import org.apache.polygene.entitystore.memory.MemoryEntityStoreService; -import org.apache.polygene.valueserialization.orgjson.OrgJsonValueSerializationService; import org.junit.Test; public class VisibilityInUnitOfWorkTest @@ -155,9 +153,6 @@ public class VisibilityInUnitOfWorkTest yourModule.services( YourService.class ).visibleIn( Visibility.layer ); new DefaultUnitOfWorkAssembler().assemble( yourModule ); infraModule.services( MemoryEntityStoreService.class ).visibleIn( Visibility.layer ); - infraModule.services( OrgJsonValueSerializationService.class ) - .visibleIn( Visibility.layer ) - .taggedWith( ValueSerialization.Formats.JSON ); new DefaultUnitOfWorkAssembler().assemble( infraModule ); return appAssembly; } ); http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/core/runtime/src/test/java/org/apache/polygene/test/performance/entitystore/memory/MemoryEntityStoreTest.java ---------------------------------------------------------------------- diff --git a/core/runtime/src/test/java/org/apache/polygene/test/performance/entitystore/memory/MemoryEntityStoreTest.java b/core/runtime/src/test/java/org/apache/polygene/test/performance/entitystore/memory/MemoryEntityStoreTest.java index ce4b878..25c4a1b 100644 --- a/core/runtime/src/test/java/org/apache/polygene/test/performance/entitystore/memory/MemoryEntityStoreTest.java +++ b/core/runtime/src/test/java/org/apache/polygene/test/performance/entitystore/memory/MemoryEntityStoreTest.java @@ -20,14 +20,12 @@ package org.apache.polygene.test.performance.entitystore.memory; -import org.apache.polygene.api.value.ValueSerialization; import org.apache.polygene.bootstrap.AssemblyException; import org.apache.polygene.bootstrap.ModuleAssembly; import org.apache.polygene.entitystore.memory.MemoryEntityStoreService; import org.apache.polygene.spi.entity.EntityState; import org.apache.polygene.spi.entitystore.StateChangeListener; import org.apache.polygene.test.entity.AbstractEntityStoreTest; -import org.apache.polygene.valueserialization.orgjson.OrgJsonValueSerializationService; import static org.apache.polygene.bootstrap.ImportedServiceDeclaration.NEW_OBJECT; @@ -44,7 +42,6 @@ public class MemoryEntityStoreTest super.assemble( module ); module.services( MemoryEntityStoreService.class ); - module.services( OrgJsonValueSerializationService.class ).taggedWith( ValueSerialization.Formats.JSON ); module.importedServices( StatePrinter.class ).importedBy( NEW_OBJECT ); module.objects( StatePrinter.class ); } http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/core/spi/build.gradle ---------------------------------------------------------------------- diff --git a/core/spi/build.gradle b/core/spi/build.gradle index b6240e9..605d3c7 100644 --- a/core/spi/build.gradle +++ b/core/spi/build.gradle @@ -24,7 +24,9 @@ jar { manifest { name = "Apache Polygene⢠Core SPI" } } dependencies { api polygene.core.api - api libraries.org_json + api libraries.javax_json + + runtimeOnly libraries.johnzon testImplementation polygene.core.testsupport http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/core/spi/src/docs/serialization.txt ---------------------------------------------------------------------- diff --git a/core/spi/src/docs/serialization.txt b/core/spi/src/docs/serialization.txt new file mode 100644 index 0000000..dca8955 --- /dev/null +++ b/core/spi/src/docs/serialization.txt @@ -0,0 +1,83 @@ +/////////////////////////////////////////////////////////////// + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. +/////////////////////////////////////////////////////////////// + +[[core-spi-serialization,Serialization SPI]] += Serialization SPI = + +== Overview == + +The Polygene⢠Core Runtime use Serialization to provide string representation of ValueComposites via their `toString()` +method, and, their instantiation from the very same representation via the `newValueFromSerializedState(..)` method of +the ValueBuilderFactory API. + +In each Module, if no Serialization service is assembled, a default one supporting the JSON format is used. + +// TODO Add sample usage of the Serialization service + +== Implementation notes == + +Simply implement Serialization to create an extension for the Serialization SPI. +The Core SPI module provides adapters to create pull-parsing capable Serializers and pull-parsing and tree-parsing +capable Deserializers. + +The behaviour described here apply to all Serialization services implemented using the Core SPI adapters. Note that +nothing stops you from implementing an extension for the Serialization SPI without relying on theses adapters. + +Theses adapters are tailored for serialization mechanisms that support the following two structures that can be nested: + + * a collection of name/value pairs. In various languages, this is realized as an object, record, struct, + dictionary, hash table, keyed list, or associative array, + * an ordered list of values. In most languages, this is realized as an array, vector, list, or sequence ; + +in other words, a JSON-like structure. + +Special attention is taken when dealing with Maps. They are serialized as an ordered list of collections of +name/value pairs to keep the Map order for least surprise. That way, even when the underlying serialization mechanism +do not keep the collection of name/value pairs order we can rely on it being kept. + +Here is a sample Map with two entries in JSON notation to make things clear: + +[source,javascript] +---- +[ + { "key": "foo", "value": "bar" }, + { "key": "cathedral", "value": "bazar" } +] +---- + +Among Plain Values (see the <<core-api-value,Serialization API>> section) some are considered primitives to +underlying serialization mechanisms and by so handed/come without conversion to/from implementations. + +Primitive values can be one of: + + * String, + * Boolean or boolean, + * Integer or int, + * Long or long, + * Short or short, + * Byte or byte, + * Float or float, + * Double or double. + +Serialization is always done in a streaming manner using a pull-parsing based approach. + +Deserialization is done in a streaming manner using a pull-parsing based approach except when encountering a +ValueComposite. ValueComposite types are deserialized using a tree-parsing based approach. + +All this means that you can serialize and deserialize large collections of values without filling the heap. http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/core/spi/src/docs/spi.txt ---------------------------------------------------------------------- diff --git a/core/spi/src/docs/spi.txt b/core/spi/src/docs/spi.txt index 3980412..9371827 100644 --- a/core/spi/src/docs/spi.txt +++ b/core/spi/src/docs/spi.txt @@ -32,7 +32,7 @@ include::../../build/docs/buildinfo/artifact.txt[] There are currently 5 Core SPI extensions; - * <<core-spi-valueserialization>> + * <<core-spi-serialization>> * <<core-spi-entitystore>> * <<core-spi-cache>> * <<core-spi-indexing>> @@ -45,7 +45,7 @@ can be solved in a support manner, or that we need to extend the Core API to sup :leveloffset: {level3} -include::valueserialization.txt[] +include::serialization.txt[] :leveloffset: {level3} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/core/spi/src/docs/valueserialization.txt ---------------------------------------------------------------------- diff --git a/core/spi/src/docs/valueserialization.txt b/core/spi/src/docs/valueserialization.txt deleted file mode 100644 index 9f76b73..0000000 --- a/core/spi/src/docs/valueserialization.txt +++ /dev/null @@ -1,83 +0,0 @@ -/////////////////////////////////////////////////////////////// - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. -/////////////////////////////////////////////////////////////// - -[[core-spi-valueserialization,ValueSerialization SPI]] -= ValueSerialization SPI = - -== Overview == - -The Polygene⢠Core Runtime use ValueSerialization to provide string representation of ValueComposites via their `toString()` -method, and, their instanciation from the very same representation via the `newValueFromSerializedState(..)` method of -the ValueBuilderFactory API. - -If no ValueSerialization service is visible, a default implementation supporting the JSON format used but note that it -won't be available as a Service. So, in order to use the full ValueSerialization API a ValueSerialization service must -be explicitely assembled in the Application. See the <<extensions>> documentation for details. - -== Implementation notes == - -Simply implement ValueSerialization to create an extension for the ValueSerialization SPI. -The Core SPI module provides adapters to create pull-parsing capable ValueSerializers and pull-parsing and tree-parsing -capable ValueDeserializers. - -The behaviour described here apply to all ValueSerialization services implemented using the Core SPI adapters. Note that -nothing stops you from implementing an extension for the ValueSerialization SPI without relying on theses adapters. - -Theses adapters are tailored for serialization mechanisms that support the following two structures that can be nested: - - * a collection of name/value pairs. In various languages, this is realized as an object, record, struct, - dictionary, hash table, keyed list, or associative array, - * an ordered list of values. In most languages, this is realized as an array, vector, list, or sequence ; - -in other words, a JSON-like structure. - -Special attention is taken when dealing with Maps. They are serialized as an ordered list of collections of -name/value pairs to keep the Map order for least surprise. That way, even when the underlying serialization mechanism -do not keep the collection of name/value pairs order we can rely on it being kept. - -Here is a sample Map with two entries in JSON notation to make things clear: - -[source,javascript] ----- -[ - { "key": "foo", "value": "bar" }, - { "key": "cathedral", "value": "bazar" } -] ----- - -Among Plain Values (see the <<core-api-value,ValueSerialization API>> section) some are considered primitives to -underlying serialization mechanisms and by so handed/come without conversion to/from implementations. - -Primitive values can be one of: - - * String, - * Boolean or boolean, - * Integer or int, - * Long or long, - * Short or short, - * Byte or byte, - * Float or float, - * Double or double. - -Serialization is always done in a streaming manner using a pull-parsing based approach. - -Deserialization is done in a streaming manner using a pull-parsing based approach except when encountering a -ValueComposite. ValueComposite types are deserialized using a tree-parsing based approach. - -All this means that you can serialize and deserialize large collections of values without filling the heap. http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/core/spi/src/main/java/org/apache/polygene/entitystore/memory/MemoryMapEntityStoreMixin.java ---------------------------------------------------------------------- diff --git a/core/spi/src/main/java/org/apache/polygene/entitystore/memory/MemoryMapEntityStoreMixin.java b/core/spi/src/main/java/org/apache/polygene/entitystore/memory/MemoryMapEntityStoreMixin.java index 7c343fa..98b4f8c 100644 --- a/core/spi/src/main/java/org/apache/polygene/entitystore/memory/MemoryMapEntityStoreMixin.java +++ b/core/spi/src/main/java/org/apache/polygene/entitystore/memory/MemoryMapEntityStoreMixin.java @@ -23,11 +23,11 @@ import java.io.IOException; import java.io.Reader; import java.io.StringReader; import java.io.StringWriter; -import java.io.UncheckedIOException; import java.io.Writer; import java.util.HashMap; import java.util.Map; import java.util.stream.Stream; +import javax.json.Json; import org.apache.polygene.api.entity.EntityDescriptor; import org.apache.polygene.api.entity.EntityReference; import org.apache.polygene.spi.entitystore.BackupRestore; @@ -37,9 +37,6 @@ import org.apache.polygene.spi.entitystore.EntityStoreException; import org.apache.polygene.spi.entitystore.helpers.JSONKeys; import org.apache.polygene.spi.entitystore.helpers.MapEntityStore; import org.apache.polygene.spi.entitystore.helpers.MapEntityStoreActivation; -import org.json.JSONException; -import org.json.JSONObject; -import org.json.JSONTokener; /** * In-memory implementation of MapEntityStore. @@ -55,21 +52,15 @@ public class MemoryMapEntityStoreMixin } @Override - public void activateMapEntityStore() - throws Exception - { - // NOOP - } + public void activateMapEntityStore() {} - public boolean contains( EntityReference entityReference, EntityDescriptor descriptor ) - throws EntityStoreException + public boolean contains( EntityReference entityReference, EntityDescriptor descriptor ) throws EntityStoreException { return store.containsKey( entityReference ); } @Override - public Reader get( EntityReference entityReference ) - throws EntityStoreException + public Reader get( EntityReference entityReference ) throws EntityStoreException { String state = store.get( entityReference ); if( state == null ) @@ -81,8 +72,7 @@ public class MemoryMapEntityStoreMixin } @Override - public void applyChanges( MapEntityStore.MapChanges changes ) - throws IOException + public void applyChanges( MapEntityStore.MapChanges changes ) throws Exception { changes.visitMap( new MemoryMapChanger() ); } @@ -100,29 +90,23 @@ public class MemoryMapEntityStoreMixin } @Override - public void restore( final Stream<String> stream ) + public void restore( Stream<String> stream ) { store.clear(); - stream.forEach( item -> { - try + stream.forEach( + item -> { - JSONTokener tokener = new JSONTokener( item ); - JSONObject entity = (JSONObject) tokener.nextValue(); - String id = entity.getString( JSONKeys.IDENTITY ); + String id = Json.createReader( new StringReader( item ) ) + .readObject().getString( JSONKeys.IDENTITY ); store.put( EntityReference.parseEntityReference( id ), item ); - } - catch( JSONException e ) - { - throw new UncheckedIOException( new IOException( e ) ); - } - } ); + } ); } private class MemoryMapChanger implements MapChanger { @Override - public Writer newEntity( final EntityReference ref, EntityDescriptor descriptor ) + public Writer newEntity( EntityReference ref, EntityDescriptor descriptor ) { return new StringWriter( 1000 ) { @@ -142,7 +126,7 @@ public class MemoryMapEntityStoreMixin } @Override - public Writer updateEntity( final EntityReference ref, EntityDescriptor descriptor ) + public Writer updateEntity( MapChange mapChange ) throws IOException { return new StringWriter( 1000 ) @@ -152,11 +136,12 @@ public class MemoryMapEntityStoreMixin throws IOException { super.close(); - String old = store.put( ref, toString() ); + EntityReference reference = mapChange.reference(); + String old = store.put( reference, toString() ); if( old == null ) { - store.remove( ref ); - throw new EntityNotFoundException( ref ); + store.remove( reference ); + throw new EntityNotFoundException( reference ); } } }; http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJson.java ---------------------------------------------------------------------- diff --git a/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJson.java b/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJson.java new file mode 100644 index 0000000..3c44864 --- /dev/null +++ b/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJson.java @@ -0,0 +1,139 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.polygene.serialization.javaxjson; + +import java.util.Map; +import javax.json.Json; +import javax.json.JsonArray; +import javax.json.JsonArrayBuilder; +import javax.json.JsonException; +import javax.json.JsonObject; +import javax.json.JsonObjectBuilder; +import javax.json.JsonString; +import javax.json.JsonStructure; +import javax.json.JsonValue; + +/** + * javax.json utilities. + */ +public class JavaxJson +{ + /** + * Create a {@link JsonObjectBuilder} populated with the state of a {@link JsonObject}. + * + * @param jo the JsonObject + * @return the builder + */ + public static JsonObjectBuilder toBuilder( JsonObject jo ) + { + JsonObjectBuilder job = Json.createObjectBuilder(); + for( Map.Entry<String, JsonValue> entry : jo.entrySet() ) + { + job.add( entry.getKey(), entry.getValue() ); + } + return job; + } + + /** + * Create a {@link JsonArrayBuilder} populated with the state of a {@link JsonArray}. + * + * @param ja the JsonArray + * @return the builder + */ + public static JsonArrayBuilder toBuilder( JsonArray ja ) + { + JsonArrayBuilder job = Json.createArrayBuilder(); + for( JsonValue value : ja ) + { + job.add( value ); + } + return job; + } + + /** + * Create a {@link JsonString} from {@link Object#toString()}. + * + * @param object the Object + * @return the JsonString + */ + public static JsonString toJsonString( Object object ) + { + return Json.createObjectBuilder().add( "value", object.toString() ).build().getJsonString( "value" ); + } + + /** + * Get a {@link String} out of a {@link JsonValue}. + * + * @param jsonValue the JSON value + * @return the String + */ + public static String asString( JsonValue jsonValue ) + { + return jsonValue instanceof JsonString ? ( (JsonString) jsonValue ).getString() : jsonValue.toString(); + } + + /** + * Require a {@link JsonValue} to be a {@link JsonStructure}. + * + * @param json the JSON value + * @return the JSON structure + * @throws JsonException if it is not + */ + public static JsonStructure requireJsonStructure( JsonValue json ) + { + if( json.getValueType() != JsonValue.ValueType.OBJECT && json.getValueType() != JsonValue.ValueType.ARRAY ) + { + throw new JsonException( "Expected a JSON object or array but got " + json ); + } + return (JsonStructure) json; + } + + /** + * Require a {@link JsonValue} to be a {@link JsonObject}. + * + * @param json the JSON value + * @return the JSON object + * @throws JsonException if it is not + */ + public static JsonObject requireJsonObject( JsonValue json ) + { + if( json.getValueType() != JsonValue.ValueType.OBJECT ) + { + throw new JsonException( "Expected a JSON object but got " + json ); + } + return (JsonObject) json; + } + + /** + * Require a {@link JsonValue} to be a {@link JsonArray}. + * + * @param json the JSON value + * @return the JSON array + * @throws JsonException if it is not + */ + public static JsonArray requireJsonArray( JsonValue json ) + { + if( json.getValueType() != JsonValue.ValueType.ARRAY ) + { + throw new JsonException( "Expected a JSON array but got " + json ); + } + return (JsonArray) json; + } + + private JavaxJson() {} +} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonAdapter.java ---------------------------------------------------------------------- diff --git a/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonAdapter.java b/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonAdapter.java new file mode 100644 index 0000000..d8ffcfa --- /dev/null +++ b/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonAdapter.java @@ -0,0 +1,54 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.polygene.serialization.javaxjson; + +import java.util.function.BiFunction; +import java.util.function.Function; +import javax.json.JsonValue; +import org.apache.polygene.api.type.ValueType; + +/** + * Adapter for JSON (de)serialization. + * + * @param <T> the adapted type + */ +public interface JavaxJsonAdapter<T> +{ + /** + * @return the adapted type + */ + Class<T> type(); + + /** + * Serialize. + * + * @param object Object to serialize, never null + * @param serializeFunction Serialization function for nested structure serialization + * @return Serialized JSON representation + */ + JsonValue serialize( Object object, Function<Object, JsonValue> serializeFunction ); + + /** + * Deserialize. + * + * @param json JSON to deserialize from, never null + * @param deserializeFunction Deserialization function for nested structure deserialization + * @return Deserialized object + */ + T deserialize( JsonValue json, BiFunction<JsonValue, ValueType, Object> deserializeFunction ); +} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonAdapters.java ---------------------------------------------------------------------- diff --git a/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonAdapters.java b/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonAdapters.java new file mode 100644 index 0000000..fdc9d27 --- /dev/null +++ b/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonAdapters.java @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.polygene.serialization.javaxjson; + +import java.util.LinkedHashMap; +import java.util.Map; +import org.apache.polygene.api.mixin.Mixins; +import org.apache.polygene.api.type.ValueType; + +import static org.apache.polygene.api.type.HasTypesCollectors.closestType; + +@Mixins( JavaxJsonAdapters.Mixin.class ) +public interface JavaxJsonAdapters +{ + void registerAdapter( ValueType valueType, JavaxJsonAdapter<?> adapter ); + + <T> JavaxJsonAdapter<T> adapterFor( ValueType valueType ); + + default <T> JavaxJsonAdapter<T> adapterFor( Class<T> type ) + { + return adapterFor( ValueType.of( type ) ); + } + + class Mixin implements JavaxJsonAdapters + { + private Map<ValueType, JavaxJsonAdapter<?>> adapters = new LinkedHashMap<>(); + + @Override + public void registerAdapter( ValueType valueType, JavaxJsonAdapter<?> adapter ) + { + adapters.put( valueType, adapter ); + } + + @Override + public <T> JavaxJsonAdapter<T> adapterFor( ValueType valueType ) + { + return castAdapter( adapters.keySet().stream() + .collect( closestType( valueType ) ) + .map( adapters::get ) + .orElse( null ) ); + } + + @SuppressWarnings( "unchecked" ) + private <T> JavaxJsonAdapter<T> castAdapter( JavaxJsonAdapter<?> adapter ) + { + return (JavaxJsonAdapter<T>) adapter; + } + } +} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonDeserializer.java ---------------------------------------------------------------------- diff --git a/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonDeserializer.java b/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonDeserializer.java new file mode 100644 index 0000000..721c884 --- /dev/null +++ b/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonDeserializer.java @@ -0,0 +1,273 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.polygene.serialization.javaxjson; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.util.AbstractMap; +import java.util.ArrayList; +import java.util.Base64; +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Stream; +import javax.json.JsonArray; +import javax.json.JsonObject; +import javax.json.JsonStructure; +import javax.json.JsonValue; +import org.apache.polygene.api.association.AssociationDescriptor; +import org.apache.polygene.api.entity.EntityReference; +import org.apache.polygene.api.injection.scope.This; +import org.apache.polygene.api.injection.scope.Uses; +import org.apache.polygene.api.property.PropertyDescriptor; +import org.apache.polygene.api.serialization.SerializationException; +import org.apache.polygene.api.service.ServiceDescriptor; +import org.apache.polygene.api.structure.ModuleDescriptor; +import org.apache.polygene.api.type.CollectionType; +import org.apache.polygene.api.type.EnumType; +import org.apache.polygene.api.type.MapType; +import org.apache.polygene.api.type.ValueCompositeType; +import org.apache.polygene.api.type.ValueType; +import org.apache.polygene.api.value.ValueBuilder; +import org.apache.polygene.api.value.ValueDescriptor; +import org.apache.polygene.spi.serialization.AbstractTextDeserializer; +import org.apache.polygene.spi.serialization.JsonDeserializer; + +import static java.nio.charset.StandardCharsets.UTF_8; +import static java.util.Collections.unmodifiableList; +import static java.util.Collections.unmodifiableMap; +import static java.util.Collections.unmodifiableSet; +import static java.util.stream.Collectors.toCollection; +import static org.apache.polygene.api.util.Collectors.toMapWithNullValues; +import static org.apache.polygene.serialization.javaxjson.JavaxJson.asString; +import static org.apache.polygene.serialization.javaxjson.JavaxJson.requireJsonArray; +import static org.apache.polygene.serialization.javaxjson.JavaxJson.requireJsonObject; +import static org.apache.polygene.serialization.javaxjson.JavaxJson.requireJsonStructure; + +public class JavaxJsonDeserializer extends AbstractTextDeserializer implements JsonDeserializer +{ + @This + private JavaxJsonAdapters adapters; + + @Uses + private ServiceDescriptor descriptor; + + @Override + public <T> T fromJson( ModuleDescriptor module, ValueType valueType, JsonValue state ) + { + return doDeserialize( module, valueType, state ); + } + + @SuppressWarnings( "unchecked" ) + private <T> T doDeserialize( ModuleDescriptor module, ValueType valueType, JsonValue json ) + { + if( json == null || JsonValue.NULL.equals( json ) ) + { + return null; + } + JavaxJsonAdapter<?> adapter = adapters.adapterFor( valueType ); + if( adapter != null ) + { + return (T) adapter.deserialize( json, ( jsonValue, type ) -> doDeserialize( module, type, jsonValue ) ); + } + Class<? extends ValueType> valueTypeClass = valueType.getClass(); + if( EnumType.class.isAssignableFrom( valueTypeClass ) ) + { + return (T) Enum.valueOf( (Class) valueType.primaryType(), asString( json ) ); + } + if( CollectionType.class.isAssignableFrom( valueTypeClass ) ) + { + return (T) deserializeCollection( module, (CollectionType) valueType, requireJsonArray( json ) ); + } + if( MapType.class.isAssignableFrom( valueTypeClass ) ) + { + return (T) deserializeMap( module, (MapType) valueType, requireJsonStructure( json ) ); + } + if( ValueCompositeType.class.isAssignableFrom( valueTypeClass ) ) + { + return (T) deserializeValueComposite( module, (ValueCompositeType) valueType, requireJsonObject( json ) ); + } + return doGuessDeserialize( module, valueType, json ); + } + + @SuppressWarnings( "unchecked" ) + private <T> T doGuessDeserialize( ModuleDescriptor module, ValueType valueType, JsonValue json ) + { + switch( json.getValueType() ) + { + case OBJECT: + JsonObject object = (JsonObject) json; + String typeInfo = object.getString( getTypeInfoPropertyName(), valueType.primaryType().getName() ); + ValueDescriptor valueDescriptor = module.valueDescriptor( typeInfo ); + if( valueDescriptor != null ) + { + return (T) deserializeValueComposite( module, valueDescriptor.valueType(), object ); + } + case STRING: + return (T) deserializeBase64( asString( json ) ); + default: + throw new SerializationException( "Don't know how to deserialize " + valueType + " from " + json ); + } + } + + private <T> Collection<T> deserializeCollection( ModuleDescriptor module, CollectionType collectionType, + JsonArray json ) + { + return (Collection<T>) json.stream() + .map( item -> doDeserialize( module, collectionType.collectedType(), item ) ) + .collect( toCollection( + () -> collectionType.isSet() ? new LinkedHashSet<>() : new ArrayList<>() ) ); + } + + /** + * Map deserialization. + * + * {@literal JsonObject}s are deserialized to {@literal Map<String, ?>}. + * {@literal JsonArray}s of key/value {@literal JsonObject}s are deserialized to {@literal Map<?, ?>}. + */ + private Map<?, ?> deserializeMap( ModuleDescriptor module, MapType mapType, JsonStructure json ) + { + if( json.getValueType() == JsonValue.ValueType.OBJECT ) + { + JsonObject object = (JsonObject) json; + return object.entrySet().stream() + .map( entry -> new AbstractMap.SimpleImmutableEntry<>( + entry.getKey(), + doDeserialize( module, mapType.valueType(), entry.getValue() ) ) ) + .collect( toMapWithNullValues( LinkedHashMap::new ) ); + } + if( json.getValueType() == JsonValue.ValueType.ARRAY ) + { + JsonArray array = (JsonArray) json; + return array.stream() + .map( JsonObject.class::cast ) + .map( entry -> new AbstractMap.SimpleImmutableEntry<>( + doDeserialize( module, mapType.keyType(), entry.get( "key" ) ), + doDeserialize( module, mapType.valueType(), entry.get( "value" ) ) + ) ) + .collect( toMapWithNullValues( LinkedHashMap::new ) ); + } + throw new SerializationException( "Don't know how to deserialize " + mapType + " from " + json ); + } + + private Object deserializeValueComposite( ModuleDescriptor module, ValueCompositeType valueType, JsonObject json ) + { + String typeInfoName = getTypeInfoPropertyName(); + String typeInfo = json.getString( typeInfoName, null ); + if( typeInfo != null ) + { + ValueDescriptor descriptor = module.valueDescriptor( typeInfo ); + if( descriptor == null ) + { + throw new SerializationException( + typeInfoName + ": " + typeInfo + " could not be resolved while deserializing " + json ); + } + valueType = descriptor.valueType(); + } + ValueBuilder builder = module.instance().newValueBuilderWithState( + valueType.primaryType(), + propertyFunction( module, json ), + associationFunction( module, json ), + manyAssociationFunction( module, json ), + namedAssociationFunction( module, json ) ); + return builder.newInstance(); + } + + private Function<PropertyDescriptor, Object> propertyFunction( ModuleDescriptor module, JsonObject object ) + { + return property -> + { + JsonValue jsonValue = object.get( property.qualifiedName().name() ); + if( jsonValue != null ) + { + Object value = doDeserialize( module, property.valueType(), jsonValue ); + if( property.isImmutable() ) + { + if( value instanceof Set ) + { + return unmodifiableSet( (Set<?>) value ); + } + else if( value instanceof List ) + { + return unmodifiableList( (List<?>) value ); + } + else if( value instanceof Map ) + { + return unmodifiableMap( (Map<?, ?>) value ); + } + } + return value; + } + return property.resolveInitialValue( module ); + }; + } + + private Function<AssociationDescriptor, EntityReference> associationFunction( ModuleDescriptor module, + JsonObject object ) + { + return association -> doDeserialize( module, ValueType.ENTITY_REFERENCE, + object.get( association.qualifiedName().name() ) ); + } + + private Function<AssociationDescriptor, Stream<EntityReference>> manyAssociationFunction( ModuleDescriptor module, + JsonObject object ) + { + return association -> + { + List<EntityReference> list = doDeserialize( module, ENTITY_REF_LIST_VALUE_TYPE, + object.get( association.qualifiedName().name() ) ); + return list == null ? Stream.empty() : list.stream(); + }; + } + + private Function<AssociationDescriptor, Stream<Map.Entry<String, EntityReference>>> namedAssociationFunction( + ModuleDescriptor module, JsonObject object ) + { + return association -> + { + Map<String, EntityReference> map = doDeserialize( module, ENTITY_REF_MAP_VALUE_TYPE, + object.get( association.qualifiedName().name() ) ); + return map == null ? Stream.empty() : map.entrySet().stream(); + }; + } + + private Object deserializeBase64( String inputString ) + { + byte[] bytes = inputString.getBytes( UTF_8 ); + bytes = Base64.getDecoder().decode( bytes ); + try( ObjectInputStream oin = new ObjectInputStream( new ByteArrayInputStream( bytes ) ) ) + { + return oin.readObject(); + } + catch( IOException | ClassNotFoundException ex ) + { + throw new SerializationException( "Unable to deserialize Base64 serialized " + inputString, ex ); + } + } + + private String getTypeInfoPropertyName() + { + return JavaxJsonSettings.orDefault( descriptor.metaInfo( JavaxJsonSettings.class ) ) + .getTypeInfoPropertyName(); + } +} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonSerialization.java ---------------------------------------------------------------------- diff --git a/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonSerialization.java b/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonSerialization.java new file mode 100644 index 0000000..2e034b0 --- /dev/null +++ b/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonSerialization.java @@ -0,0 +1,26 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.polygene.serialization.javaxjson; + +import org.apache.polygene.api.mixin.Mixins; +import org.apache.polygene.spi.serialization.JsonSerialization; + +@Mixins( { JavaxJsonSerializer.class, JavaxJsonDeserializer.class } ) +public interface JavaxJsonSerialization extends JsonSerialization +{ +} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonSerializationService.java ---------------------------------------------------------------------- diff --git a/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonSerializationService.java b/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonSerializationService.java new file mode 100644 index 0000000..2b662ea --- /dev/null +++ b/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonSerializationService.java @@ -0,0 +1,533 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.polygene.serialization.javaxjson; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.time.Duration; +import java.time.Instant; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.OffsetDateTime; +import java.time.Period; +import java.time.ZonedDateTime; +import java.util.function.BiFunction; +import java.util.function.Function; +import javax.json.Json; +import javax.json.JsonNumber; +import javax.json.JsonString; +import javax.json.JsonValue; +import org.apache.polygene.api.entity.EntityReference; +import org.apache.polygene.api.identity.Identity; +import org.apache.polygene.api.identity.StringIdentity; +import org.apache.polygene.api.injection.scope.This; +import org.apache.polygene.api.injection.scope.Uses; +import org.apache.polygene.api.mixin.Mixins; +import org.apache.polygene.api.serialization.SerializationException; +import org.apache.polygene.api.service.ServiceActivation; +import org.apache.polygene.api.service.ServiceDescriptor; +import org.apache.polygene.api.type.ValueType; + +// TODO Move into JavaxJsonSerialization +// TODO Do the same on XML & MessagePack +@Mixins( JavaxJsonSerializationService.Activation.class ) +public interface JavaxJsonSerializationService extends JavaxJsonSerialization, ServiceActivation +{ + class Activation implements ServiceActivation + { + @Uses + private ServiceDescriptor descriptor; + + @This + private JavaxJsonAdapters adapters; + + private boolean registrationDone = false; + + @Override + public void activateService() + { + if( !registrationDone ) + { + registerCustomAdapters(); + registerBaseAdapters(); + registrationDone = true; + } + } + + @Override + public void passivateService() {} + + private void registerCustomAdapters() + { + JavaxJsonSettings.orDefault( descriptor.metaInfo( JavaxJsonSettings.class ) ) + .getAdapters() + .forEach( ( valueType, adapter ) -> adapters.registerAdapter( valueType, adapter ) ); + } + + private void registerBaseAdapters() + { + // Primitive Value types + adapters.registerAdapter( ValueType.STRING, new StringAdapter() ); + adapters.registerAdapter( ValueType.CHARACTER, new CharacterAdapter() ); + adapters.registerAdapter( ValueType.BOOLEAN, new BooleanAdapter() ); + adapters.registerAdapter( ValueType.INTEGER, new IntegerAdapter() ); + adapters.registerAdapter( ValueType.LONG, new LongAdapter() ); + adapters.registerAdapter( ValueType.SHORT, new ShortAdapter() ); + adapters.registerAdapter( ValueType.BYTE, new ByteAdapter() ); + adapters.registerAdapter( ValueType.FLOAT, new FloatAdapter() ); + adapters.registerAdapter( ValueType.DOUBLE, new DoubleAdapter() ); + + // Number types + adapters.registerAdapter( ValueType.BIG_DECIMAL, new BigDecimalAdapter() ); + adapters.registerAdapter( ValueType.BIG_INTEGER, new BigIntegerAdapter() ); + + // Date types + adapters.registerAdapter( ValueType.INSTANT, new InstantAdapter() ); + adapters.registerAdapter( ValueType.ZONED_DATE_TIME, new ZonedDateTimeAdapter() ); + adapters.registerAdapter( ValueType.OFFSET_DATE_TIME, new OffsetDateTimeAdapter() ); + adapters.registerAdapter( ValueType.LOCAL_DATE_TIME, new LocalDateTimeAdapter() ); + adapters.registerAdapter( ValueType.LOCAL_DATE, new LocalDateAdapter() ); + adapters.registerAdapter( ValueType.LOCAL_TIME, new LocalTimeAdapter() ); + adapters.registerAdapter( ValueType.DURATION, new DurationAdapter() ); + adapters.registerAdapter( ValueType.PERIOD, new PeriodAdapter() ); + + // Other supported types + adapters.registerAdapter( ValueType.IDENTITY, new IdentityAdapter() ); + adapters.registerAdapter( ValueType.ENTITY_REFERENCE, new EntityReferenceAdapter() ); + } + + private static abstract class ToJsonStringAdapter<T> implements JavaxJsonAdapter<T> + { + @Override + public JsonValue serialize( Object object, Function<Object, JsonValue> serializeFunction ) + { + return JavaxJson.toJsonString( object ); + } + } + + private static class StringAdapter extends ToJsonStringAdapter<String> + { + @Override + public Class<String> type() { return String.class; } + + @Override + public String deserialize( JsonValue json, BiFunction<JsonValue, ValueType, Object> deserializeFunction ) + { + return JavaxJson.asString( json ); + } + } + + private static class CharacterAdapter extends ToJsonStringAdapter<Character> + { + @Override + public Class<Character> type() { return Character.class; } + + @Override + public Character deserialize( JsonValue json, BiFunction<JsonValue, ValueType, Object> deserializeFunction ) + { + String string = JavaxJson.asString( json ); + return string.isEmpty() ? null : string.charAt( 0 ); + } + } + + private static class BooleanAdapter implements JavaxJsonAdapter<Boolean> + { + @Override + public Class<Boolean> type() { return Boolean.class; } + + @Override + public JsonValue serialize( Object object, Function<Object, JsonValue> serializeFunction ) + { + return type().cast( object ) ? JsonValue.TRUE : JsonValue.FALSE; + } + + @Override + public Boolean deserialize( JsonValue json, BiFunction<JsonValue, ValueType, Object> deserializeFunction ) + { + switch( json.getValueType() ) + { + case TRUE: + return true; + case FALSE: + return false; + case NULL: + return null; + case NUMBER: + return ( (JsonNumber) json ).doubleValue() > 0; + case STRING: + return Boolean.valueOf( ( (JsonString) json ).getString() ); + default: + throw new SerializationException( "Don't know how to deserialize Boolean from " + json ); + } + } + } + + private static class IntegerAdapter implements JavaxJsonAdapter<Integer> + { + @Override + public Class<Integer> type() { return Integer.class; } + + @Override + public JsonValue serialize( Object object, Function<Object, JsonValue> serializeFunction ) + { + return Json.createObjectBuilder().add( "value", type().cast( object ) ).build() + .getJsonNumber( "value" ); + } + + @Override + public Integer deserialize( JsonValue json, BiFunction<JsonValue, ValueType, Object> deserializeFunction ) + { + switch( json.getValueType() ) + { + case NULL: + return null; + case NUMBER: + return ( (JsonNumber) json ).intValueExact(); + case STRING: + String string = ( (JsonString) json ).getString(); + return string.isEmpty() ? 0 : Integer.parseInt( string ); + default: + throw new SerializationException( "Don't know how to deserialize Integer from " + json ); + } + } + } + + private static class LongAdapter implements JavaxJsonAdapter<Long> + { + @Override + public Class<Long> type() { return Long.class; } + + @Override + public JsonValue serialize( Object object, Function<Object, JsonValue> serializeFunction ) + { + return Json.createObjectBuilder().add( "value", type().cast( object ) ).build().getJsonNumber( + "value" ); + } + + @Override + public Long deserialize( JsonValue json, BiFunction<JsonValue, ValueType, Object> deserializeFunction ) + { + switch( json.getValueType() ) + { + case NULL: + return null; + case NUMBER: + return ( (JsonNumber) json ).longValueExact(); + case STRING: + String string = ( (JsonString) json ).getString(); + return string.isEmpty() ? 0L : Long.parseLong( string ); + default: + throw new SerializationException( "Don't know how to deserialize Long from " + json ); + } + } + } + + private static class ShortAdapter implements JavaxJsonAdapter<Short> + { + @Override + public Class<Short> type() { return Short.class; } + + @Override + public JsonValue serialize( Object object, Function<Object, JsonValue> serializeFunction ) + { + return Json.createObjectBuilder().add( "value", type().cast( object ) ).build() + .getJsonNumber( "value" ); + } + + @Override + public Short deserialize( JsonValue json, BiFunction<JsonValue, ValueType, Object> deserializeFunction ) + { + switch( json.getValueType() ) + { + case NULL: + return null; + case NUMBER: + return (short) ( (JsonNumber) json ).intValueExact(); + case STRING: + String string = ( (JsonString) json ).getString(); + return string.isEmpty() ? 0 : Short.parseShort( string ); + default: + throw new SerializationException( "Don't know how to deserialize Short from " + json ); + } + } + } + + private static class ByteAdapter implements JavaxJsonAdapter<Byte> + { + @Override + public Class<Byte> type() { return Byte.class; } + + @Override + public JsonValue serialize( Object object, Function<Object, JsonValue> serializeFunction ) + { + return Json.createObjectBuilder().add( "value", type().cast( object ) ).build() + .getJsonNumber( "value" ); + } + + @Override + public Byte deserialize( JsonValue json, BiFunction<JsonValue, ValueType, Object> deserializeFunction ) + { + switch( json.getValueType() ) + { + case NULL: + return null; + case NUMBER: + return (byte) ( (JsonNumber) json ).intValueExact(); + case STRING: + String string = ( (JsonString) json ).getString(); + return string.isEmpty() ? 0 : Byte.parseByte( string ); + default: + throw new SerializationException( "Don't know how to deserialize Byte from " + json ); + } + } + } + + private static class FloatAdapter implements JavaxJsonAdapter<Float> + { + @Override + public Class<Float> type() { return Float.class; } + + @Override + public JsonValue serialize( Object object, Function<Object, JsonValue> serializeFunction ) + { + return Json.createObjectBuilder().add( "value", type().cast( object ) ).build() + .getJsonNumber( "value" ); + } + + @Override + public Float deserialize( JsonValue json, BiFunction<JsonValue, ValueType, Object> deserializeFunction ) + { + switch( json.getValueType() ) + { + case NULL: + return null; + case NUMBER: + return (float) ( (JsonNumber) json ).doubleValue(); + case STRING: + String string = ( (JsonString) json ).getString(); + return string.isEmpty() ? 0F : Float.parseFloat( string ); + default: + throw new SerializationException( "Don't know how to deserialize Float from " + json ); + } + } + } + + private static class DoubleAdapter implements JavaxJsonAdapter<Double> + { + @Override + public Class<Double> type() { return Double.class; } + + @Override + public JsonValue serialize( Object object, Function<Object, JsonValue> serializeFunction ) + { + return Json.createObjectBuilder().add( "value", type().cast( object ) ).build() + .getJsonNumber( "value" ); + } + + @Override + public Double deserialize( JsonValue json, BiFunction<JsonValue, ValueType, Object> deserializeFunction ) + { + switch( json.getValueType() ) + { + case NULL: + return null; + case NUMBER: + return ( (JsonNumber) json ).doubleValue(); + case STRING: + String string = ( (JsonString) json ).getString(); + return string.isEmpty() ? 0D : Double.parseDouble( string ); + default: + throw new SerializationException( "Don't know how to deserialize Double from " + json ); + } + } + } + + private static class BigDecimalAdapter extends ToJsonStringAdapter<BigDecimal> + { + @Override + public Class<BigDecimal> type() { return BigDecimal.class; } + + @Override + public BigDecimal deserialize( JsonValue json, + BiFunction<JsonValue, ValueType, Object> deserializeFunction ) + { + switch( json.getValueType() ) + { + case NULL: + return null; + case NUMBER: + return new BigDecimal( json.toString() ); + case STRING: + return new BigDecimal( ( (JsonString) json ).getString() ); + default: + throw new SerializationException( + "Don't know how to deserialize BigDecimal from " + json ); + } + } + } + + private static class BigIntegerAdapter extends ToJsonStringAdapter<BigInteger> + { + @Override + public Class<BigInteger> type() { return BigInteger.class; } + + @Override + public BigInteger deserialize( JsonValue json, + BiFunction<JsonValue, ValueType, Object> deserializeFunction ) + { + switch( json.getValueType() ) + { + case NULL: + return null; + case NUMBER: + return new BigInteger( json.toString() ); + case STRING: + return new BigInteger( ( (JsonString) json ).getString() ); + default: + throw new SerializationException( + "Don't know how to deserialize BigInteger from " + json ); + } + } + } + + private static class PeriodAdapter extends ToJsonStringAdapter<Period> + { + @Override + public Class<Period> type() { return Period.class; } + + @Override + public Period deserialize( JsonValue json, BiFunction<JsonValue, ValueType, Object> deserializeFunction ) + { + return Period.parse( JavaxJson.asString( json ) ); + } + } + + private static class DurationAdapter extends ToJsonStringAdapter<Duration> + { + @Override + public Class<Duration> type() { return Duration.class; } + + @Override + public Duration deserialize( JsonValue json, BiFunction<JsonValue, ValueType, Object> deserializeFunction ) + { + return Duration.parse( JavaxJson.asString( json ) ); + } + } + + private static class LocalTimeAdapter extends ToJsonStringAdapter<LocalTime> + { + @Override + public Class<LocalTime> type() { return LocalTime.class; } + + @Override + public LocalTime deserialize( JsonValue json, BiFunction<JsonValue, ValueType, Object> deserializeFunction ) + { + return LocalTime.parse( JavaxJson.asString( json ) ); + } + } + + private static class LocalDateAdapter extends ToJsonStringAdapter<LocalDate> + { + @Override + public Class<LocalDate> type() { return LocalDate.class; } + + @Override + public LocalDate deserialize( JsonValue json, BiFunction<JsonValue, ValueType, Object> deserializeFunction ) + { + return LocalDate.parse( JavaxJson.asString( json ) ); + } + } + + private static class LocalDateTimeAdapter extends ToJsonStringAdapter<LocalDateTime> + { + @Override + public Class<LocalDateTime> type() { return LocalDateTime.class; } + + @Override + public LocalDateTime deserialize( JsonValue json, + BiFunction<JsonValue, ValueType, Object> deserializeFunction ) + { + return LocalDateTime.parse( JavaxJson.asString( json ) ); + } + } + + private static class OffsetDateTimeAdapter extends ToJsonStringAdapter<OffsetDateTime> + { + @Override + public Class<OffsetDateTime> type() { return OffsetDateTime.class; } + + @Override + public OffsetDateTime deserialize( JsonValue json, + BiFunction<JsonValue, ValueType, Object> deserializeFunction ) + { + return OffsetDateTime.parse( JavaxJson.asString( json ) ); + } + } + + private static class ZonedDateTimeAdapter extends ToJsonStringAdapter<ZonedDateTime> + { + @Override + public Class<ZonedDateTime> type() { return ZonedDateTime.class; } + + @Override + public ZonedDateTime deserialize( JsonValue json, + BiFunction<JsonValue, ValueType, Object> deserializeFunction ) + { + return ZonedDateTime.parse( JavaxJson.asString( json ) ); + } + } + + private static class InstantAdapter extends ToJsonStringAdapter<Instant> + { + @Override + public Class<Instant> type() { return Instant.class; } + + @Override + public Instant deserialize( JsonValue json, BiFunction<JsonValue, ValueType, Object> deserializeFunction ) + { + return Instant.parse( JavaxJson.asString( json ) ); + } + } + + private static class IdentityAdapter extends ToJsonStringAdapter<Identity> + { + @Override + public Class<Identity> type() { return Identity.class; } + + @Override + public Identity deserialize( JsonValue json, BiFunction<JsonValue, ValueType, Object> deserializeFunction ) + { + return StringIdentity.fromString( JavaxJson.asString( json ) ); + } + } + + private static class EntityReferenceAdapter extends ToJsonStringAdapter<EntityReference> + { + @Override + public Class<EntityReference> type() { return EntityReference.class; } + + @Override + public EntityReference deserialize( JsonValue json, + BiFunction<JsonValue, ValueType, Object> deserializeFunction ) + { + return EntityReference.parseEntityReference( JavaxJson.asString( json ) ); + } + } + } +}
