You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@polygene.apache.org by pa...@apache.org on 2017/03/13 10:35:14 UTC
[22/50] [abbrv] polygene-java git commit: New (de)serialization API
and SPI & new implementations
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/c9dd7229/extensions/serialization-javaxjson/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonSerializationAssembler.java
----------------------------------------------------------------------
diff --git a/extensions/serialization-javaxjson/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonSerializationAssembler.java b/extensions/serialization-javaxjson/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonSerializationAssembler.java
new file mode 100644
index 0000000..36b84d6
--- /dev/null
+++ b/extensions/serialization-javaxjson/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonSerializationAssembler.java
@@ -0,0 +1,58 @@
+/*
+ * 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.serialization.Deserializer;
+import org.apache.polygene.api.serialization.Serialization;
+import org.apache.polygene.api.serialization.Serializer;
+import org.apache.polygene.bootstrap.Assemblers;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.ServiceDeclaration;
+import org.apache.polygene.spi.serialization.JsonDeserializer;
+import org.apache.polygene.spi.serialization.JsonSerialization;
+import org.apache.polygene.spi.serialization.JsonSerializer;
+
+public class JavaxJsonSerializationAssembler extends Assemblers.VisibilityIdentity<JavaxJsonSerializationAssembler>
+{
+ private JavaxJsonSettings settings;
+
+ public JavaxJsonSerializationAssembler withJsonSettings( JavaxJsonSettings settings )
+ {
+ this.settings = settings;
+ return this;
+ }
+
+ @Override
+ public void assemble( ModuleAssembly module )
+ {
+ ServiceDeclaration declaration = module.services( JavaxJsonSerializationService.class )
+ .withTypes( Serialization.class,
+ Serializer.class, Deserializer.class,
+ JsonSerialization.class,
+ JsonSerializer.class, JsonDeserializer.class )
+ .visibleIn( visibility() );
+ if( hasIdentity() )
+ {
+ declaration.identifiedBy( identity() );
+ }
+ if( settings != null )
+ {
+ declaration.setMetaInfo( settings );
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/c9dd7229/extensions/serialization-javaxjson/src/main/java/org/apache/polygene/serialization/javaxjson/package.html
----------------------------------------------------------------------
diff --git a/extensions/serialization-javaxjson/src/main/java/org/apache/polygene/serialization/javaxjson/package.html b/extensions/serialization-javaxjson/src/main/java/org/apache/polygene/serialization/javaxjson/package.html
new file mode 100644
index 0000000..43db1d9
--- /dev/null
+++ b/extensions/serialization-javaxjson/src/main/java/org/apache/polygene/serialization/javaxjson/package.html
@@ -0,0 +1,24 @@
+<!--
+ ~ 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.
+ ~
+ ~
+ -->
+<html>
+ <body>
+ <h2>javax.json Serialization.</h2>
+ </body>
+</html>
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/c9dd7229/extensions/serialization-javaxjson/src/test/java/org/apache/polygene/serialization/javaxjson/CustomJsonAdapterTest.java
----------------------------------------------------------------------
diff --git a/extensions/serialization-javaxjson/src/test/java/org/apache/polygene/serialization/javaxjson/CustomJsonAdapterTest.java b/extensions/serialization-javaxjson/src/test/java/org/apache/polygene/serialization/javaxjson/CustomJsonAdapterTest.java
new file mode 100644
index 0000000..bed0492
--- /dev/null
+++ b/extensions/serialization-javaxjson/src/test/java/org/apache/polygene/serialization/javaxjson/CustomJsonAdapterTest.java
@@ -0,0 +1,180 @@
+/*
+ * 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.time.LocalDate;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import javax.json.Json;
+import javax.json.JsonObject;
+import javax.json.JsonString;
+import javax.json.JsonValue;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.serialization.SerializationException;
+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.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+
+public class CustomJsonAdapterTest extends AbstractPolygeneTest
+{
+ @Override
+ public void assemble( ModuleAssembly module )
+ {
+ new JavaxJsonSerializationAssembler()
+ .withJsonSettings( new JavaxJsonSettings().withJsonAdapter( new CustomValueAdapter() )
+ .withJsonAdapter( new CustomStructureAdapter() ) )
+ .assemble( module );
+ module.values( SomeValue.class );
+ }
+
+ interface SomeValue
+ {
+ Property<CustomValue> customValue();
+
+ Property<CustomStructure> customStructure();
+ }
+
+ static class CustomValue
+ {
+ String state;
+
+ CustomValue( String state )
+ {
+ this.state = state;
+ }
+ }
+
+ static class CustomStructure
+ {
+ String foo;
+ LocalDate bar;
+
+ CustomStructure( String foo, LocalDate bar )
+ {
+ this.foo = foo;
+ this.bar = bar;
+ }
+ }
+
+ static class CustomValueAdapter implements JavaxJsonAdapter<CustomValue>
+ {
+ @Override
+ public Class<CustomValue> type() { return CustomValue.class; }
+
+ @Override
+ public JsonValue serialize( Object object, Function<Object, JsonValue> serializeFunction )
+ {
+ return JavaxJson.toJsonString( type().cast( object ).state );
+ }
+
+ @Override
+ public CustomValue deserialize( JsonValue json, BiFunction<JsonValue, ValueType, Object> deserializeFunction )
+ {
+ switch( json.getValueType() )
+ {
+ case STRING:
+ return new CustomValue( ( (JsonString) json ).getString() );
+ default:
+ throw new SerializationException( "Don't know how to deserialize CustomValue from " + json );
+ }
+ }
+ }
+
+ static class CustomStructureAdapter implements JavaxJsonAdapter<CustomStructure>
+ {
+ @Override
+ public Class<CustomStructure> type() { return CustomStructure.class; }
+
+ @Override
+ public JsonValue serialize( Object object, Function<Object, JsonValue> serializeFunction )
+ {
+ CustomStructure customStructure = type().cast( object );
+ return Json.createObjectBuilder()
+ .add( "foo", customStructure.foo )
+ .add( "bar", serializeFunction.apply( customStructure.bar ) )
+ .build();
+ }
+
+ @Override
+ public CustomStructure deserialize( JsonValue json, BiFunction<JsonValue, ValueType, Object> deserializeFunction )
+ {
+ if( json.getValueType() != JsonValue.ValueType.OBJECT )
+ {
+ throw new SerializationException( "Don't know how to deserialize CustomStructure from " + json );
+ }
+ JsonObject jsonObject = (JsonObject) json;
+ String foo = jsonObject.getString( "foo" );
+ LocalDate bar = (LocalDate) deserializeFunction.apply( jsonObject.get( "bar" ), ValueType.of( LocalDate.class ) );
+ return new CustomStructure( foo, bar );
+ }
+ }
+
+ @Service
+ private JavaxJsonSerialization serialization;
+
+ @Test
+ public void customJsonAdapterForPropertyValue()
+ {
+ ValueBuilder<SomeValue> builder = valueBuilderFactory.newValueBuilder( SomeValue.class );
+ builder.prototype().customValue().set( new CustomValue( "custom-value-state" ) );
+ builder.prototype().customStructure().set( new CustomStructure( "foo", LocalDate.of( 2017, 1, 1 ) ) );
+ SomeValue someValue = builder.newInstance();
+
+ System.out.println( someValue.toString() );
+
+ JsonValue serialized = serialization.toJson( someValue );
+ assertThat( serialized.getValueType(), is( JsonValue.ValueType.OBJECT ) );
+
+ JsonObject jsonObject = (JsonObject) serialized;
+ assertThat( jsonObject.getString( "customValue" ), equalTo( "custom-value-state" ) );
+ JsonObject structure = jsonObject.getJsonObject( "customStructure" );
+ assertThat( structure.getString( "foo" ), equalTo( "foo" ) );
+ assertThat( structure.getString( "bar" ), equalTo( "2017-01-01" ) );
+
+ SomeValue deserialized = serialization.fromJson( module, ValueCompositeType.of( SomeValue.class ), serialized );
+
+ assertThat( deserialized.customValue().get().state, equalTo( "custom-value-state" ) );
+ assertThat( deserialized.customStructure().get().foo, equalTo( "foo" ) );
+ assertThat( deserialized.customStructure().get().bar, equalTo( LocalDate.of( 2017, 1, 1 ) ) );
+ }
+
+ @Test
+ public void customJsonAdapterForDirectObject()
+ {
+ CustomValue customValueObject = new CustomValue( "custom-value-state" );
+ JsonValue serialized = serialization.toJson( customValueObject );
+ assertThat( serialized.getValueType(), is( JsonValue.ValueType.STRING ) );
+ JsonString jsonString = (JsonString) serialized;
+ assertThat( jsonString.getString(), equalTo( "custom-value-state" ) );
+
+ CustomStructure customStructureObject = new CustomStructure( "foo", LocalDate.of( 2017, 1, 1 ) );
+ serialized = serialization.toJson( customStructureObject );
+ assertThat( serialized.getValueType(), is( JsonValue.ValueType.OBJECT ) );
+ JsonObject jsonObject = (JsonObject) serialized;
+ assertThat( jsonObject.getString( "foo" ), equalTo( "foo" ) );
+ assertThat( jsonObject.getString( "bar" ), equalTo( "2017-01-01" ) );
+ }
+}
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/c9dd7229/extensions/serialization-javaxjson/src/test/java/org/apache/polygene/serialization/javaxjson/JavaxJsonCollectionSerializationTest.java
----------------------------------------------------------------------
diff --git a/extensions/serialization-javaxjson/src/test/java/org/apache/polygene/serialization/javaxjson/JavaxJsonCollectionSerializationTest.java b/extensions/serialization-javaxjson/src/test/java/org/apache/polygene/serialization/javaxjson/JavaxJsonCollectionSerializationTest.java
new file mode 100644
index 0000000..517b630
--- /dev/null
+++ b/extensions/serialization-javaxjson/src/test/java/org/apache/polygene/serialization/javaxjson/JavaxJsonCollectionSerializationTest.java
@@ -0,0 +1,24 @@
+/*
+ * 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.test.serialization.AbstractCollectionSerializationTest;
+
+public class JavaxJsonCollectionSerializationTest extends AbstractCollectionSerializationTest
+{
+}
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/c9dd7229/extensions/serialization-javaxjson/src/test/java/org/apache/polygene/serialization/javaxjson/JavaxJsonConfigurationDeserializationTest.java
----------------------------------------------------------------------
diff --git a/extensions/serialization-javaxjson/src/test/java/org/apache/polygene/serialization/javaxjson/JavaxJsonConfigurationDeserializationTest.java b/extensions/serialization-javaxjson/src/test/java/org/apache/polygene/serialization/javaxjson/JavaxJsonConfigurationDeserializationTest.java
new file mode 100644
index 0000000..f054561
--- /dev/null
+++ b/extensions/serialization-javaxjson/src/test/java/org/apache/polygene/serialization/javaxjson/JavaxJsonConfigurationDeserializationTest.java
@@ -0,0 +1,24 @@
+/*
+ * 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.test.entity.AbstractConfigurationDeserializationTest;
+
+public class JavaxJsonConfigurationDeserializationTest extends AbstractConfigurationDeserializationTest
+{
+}
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/c9dd7229/extensions/serialization-javaxjson/src/test/java/org/apache/polygene/serialization/javaxjson/JavaxJsonDateFormatSerializationTest.java
----------------------------------------------------------------------
diff --git a/extensions/serialization-javaxjson/src/test/java/org/apache/polygene/serialization/javaxjson/JavaxJsonDateFormatSerializationTest.java b/extensions/serialization-javaxjson/src/test/java/org/apache/polygene/serialization/javaxjson/JavaxJsonDateFormatSerializationTest.java
new file mode 100644
index 0000000..7c0f510
--- /dev/null
+++ b/extensions/serialization-javaxjson/src/test/java/org/apache/polygene/serialization/javaxjson/JavaxJsonDateFormatSerializationTest.java
@@ -0,0 +1,24 @@
+/*
+ * 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.test.serialization.AbstractDateFormatSerializationTest;
+
+public class JavaxJsonDateFormatSerializationTest extends AbstractDateFormatSerializationTest
+{
+}
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/c9dd7229/extensions/serialization-javaxjson/src/test/java/org/apache/polygene/serialization/javaxjson/JavaxJsonPlainValueSerializationTest.java
----------------------------------------------------------------------
diff --git a/extensions/serialization-javaxjson/src/test/java/org/apache/polygene/serialization/javaxjson/JavaxJsonPlainValueSerializationTest.java b/extensions/serialization-javaxjson/src/test/java/org/apache/polygene/serialization/javaxjson/JavaxJsonPlainValueSerializationTest.java
new file mode 100644
index 0000000..00391e7
--- /dev/null
+++ b/extensions/serialization-javaxjson/src/test/java/org/apache/polygene/serialization/javaxjson/JavaxJsonPlainValueSerializationTest.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.test.serialization.AbstractPlainValueSerializationTest;
+
+public class JavaxJsonPlainValueSerializationTest extends AbstractPlainValueSerializationTest
+{
+}
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/c9dd7229/extensions/serialization-javaxjson/src/test/java/org/apache/polygene/serialization/javaxjson/JavaxJsonValueCompositeSerializationTest.java
----------------------------------------------------------------------
diff --git a/extensions/serialization-javaxjson/src/test/java/org/apache/polygene/serialization/javaxjson/JavaxJsonValueCompositeSerializationTest.java b/extensions/serialization-javaxjson/src/test/java/org/apache/polygene/serialization/javaxjson/JavaxJsonValueCompositeSerializationTest.java
new file mode 100644
index 0000000..5fe4f5f
--- /dev/null
+++ b/extensions/serialization-javaxjson/src/test/java/org/apache/polygene/serialization/javaxjson/JavaxJsonValueCompositeSerializationTest.java
@@ -0,0 +1,60 @@
+/*
+ * 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.StringReader;
+import javax.json.Json;
+import javax.json.JsonObject;
+import javax.json.JsonValue;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.spi.serialization.JsonSerialization;
+import org.apache.polygene.test.serialization.AbstractValueCompositeSerializationTest;
+import org.junit.Test;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+public class JavaxJsonValueCompositeSerializationTest extends AbstractValueCompositeSerializationTest
+{
+ @Service
+ private JsonSerialization jsonSerialization;
+
+ @Test
+ public void valueCompositeJsonEquality()
+ {
+ try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork() )
+ {
+ Some some = buildSomeValue( moduleInstance, uow, "42" );
+
+ // Serialize using injected service
+ JsonValue jsonState = jsonSerialization.toJson( some );
+ String stateString = jsonState.toString();
+ System.out.println( jsonState.toString() );
+
+ // Deserialize using Module API
+ Some some2 = moduleInstance.newValueFromSerializedState( Some.class, stateString );
+
+ assertThat( "Value equality", some, equalTo( some2 ) );
+
+ JsonObject jsonState2 = Json.createReader( new StringReader( some2.toString() ) ).readObject();
+
+ assertThat( "JSON equality", jsonState, equalTo( jsonState2 ) );
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/c9dd7229/extensions/serialization-javaxjson/src/test/resources/configtest.json
----------------------------------------------------------------------
diff --git a/extensions/serialization-javaxjson/src/test/resources/configtest.json b/extensions/serialization-javaxjson/src/test/resources/configtest.json
new file mode 100644
index 0000000..4c5600b
--- /dev/null
+++ b/extensions/serialization-javaxjson/src/test/resources/configtest.json
@@ -0,0 +1,8 @@
+{
+ "identity": "configtest",
+ "host": {
+ "ip": "12.23.34.45",
+ "port": 1234
+ },
+ "name": "main"
+}
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/c9dd7229/extensions/serialization-javaxxml/build.gradle
----------------------------------------------------------------------
diff --git a/extensions/serialization-javaxxml/build.gradle b/extensions/serialization-javaxxml/build.gradle
new file mode 100644
index 0000000..4c095f9
--- /dev/null
+++ b/extensions/serialization-javaxxml/build.gradle
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+apply plugin: 'polygene-extension'
+
+description = "Apache Polygene\u2122 javax.xml Serialization Extension"
+
+jar { manifest { name = "Apache Polygene\u2122 Extension - Serialization - javax.xml" } }
+
+dependencies {
+ api polygene.core.bootstrap
+
+ runtimeOnly polygene.core.runtime
+
+ testImplementation polygene.core.testsupport
+ testImplementation libraries.xmlunit
+
+ testRuntimeOnly libraries.logback
+}
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/c9dd7229/extensions/serialization-javaxxml/dev-status.xml
----------------------------------------------------------------------
diff --git a/extensions/serialization-javaxxml/dev-status.xml b/extensions/serialization-javaxxml/dev-status.xml
new file mode 100644
index 0000000..81841be
--- /dev/null
+++ b/extensions/serialization-javaxxml/dev-status.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+ ~ 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.
+ ~
+ ~
+ -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+ http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
+ <status>
+ <!--none,early,beta,stable,mature-->
+ <codebase>early</codebase>
+
+ <!-- none, brief, good, complete -->
+ <documentation>none</documentation>
+
+ <!-- none, some, good, complete -->
+ <unittests>good</unittests>
+ </status>
+ <licenses>
+ <license>ALv2</license>
+ </licenses>
+</module>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/c9dd7229/extensions/serialization-javaxxml/src/docs/serialization-javaxxml.txt
----------------------------------------------------------------------
diff --git a/extensions/serialization-javaxxml/src/docs/serialization-javaxxml.txt b/extensions/serialization-javaxxml/src/docs/serialization-javaxxml.txt
new file mode 100644
index 0000000..6fe6d75
--- /dev/null
+++ b/extensions/serialization-javaxxml/src/docs/serialization-javaxxml.txt
@@ -0,0 +1,30 @@
+///////////////////////////////////////////////////////////////
+ * 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.
+///////////////////////////////////////////////////////////////
+
+[[extension-serialization-javaxxml,javax.xml serialization]]
+= javax.xml serialization =
+
+[devstatus]
+--------------
+source=extensions/serialization-javaxxml/dev-status.xml
+--------------
+
+// TODO Document usage of XmlSerialization
+// TODO Include sample model and its output from test code & resources
+// TODO Assembly - Serialization extension or sole Service, settings & adapters
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/c9dd7229/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXml.java
----------------------------------------------------------------------
diff --git a/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXml.java b/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXml.java
new file mode 100644
index 0000000..3289d30
--- /dev/null
+++ b/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXml.java
@@ -0,0 +1,161 @@
+/*
+ * 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.javaxxml;
+
+import java.util.Optional;
+import java.util.Spliterator;
+import java.util.Spliterators;
+import java.util.function.Consumer;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * javax.xml utilities.
+ */
+public class JavaxXml
+{
+ /**
+ * Find child elements.
+ *
+ * @param parent the parent node
+ * @return a stream of elements
+ */
+ public static Stream<Element> childElements( Node parent )
+ {
+ return toStream( parent.getChildNodes() ).filter( JavaxXml::isElement )
+ .map( JavaxXml::castToElement );
+ }
+
+ /**
+ * Find the first child element.
+ *
+ * @param parent the parent node
+ * @return an optional element
+ */
+ public static Optional<Element> firstChildElement( Node parent )
+ {
+ return childElements( parent ).findFirst();
+ }
+
+ /**
+ * Find child elements named {@literal tagName}.
+ *
+ * @param parent the parent node
+ * @param tagName the tag name
+ * @return a stream of elements named {@literal tagName}
+ */
+ public static Stream<Element> childElementsNamed( Node parent, String tagName )
+ {
+ return childElements( parent ).filter( element -> tagName.equals( element.getTagName() ) );
+ }
+
+ /**
+ * Find the first child element named {@literal tagName}.
+ *
+ * @param parent the parent node
+ * @param tagName the tag name
+ * @return an optional element named {@literal tagName}
+ */
+ public static Optional<Element> firstChildElementNamed( Node parent, String tagName )
+ {
+ return childElementsNamed( parent, tagName ).findFirst();
+ }
+
+ /**
+ * Find child nodes holding state.
+ *
+ * @param parent the parent node
+ * @return a stream or child state nodes
+ */
+ public static Stream<Node> stateChildNodes( Node parent )
+ {
+ return toStream( parent.getChildNodes() ).filter( JavaxXml::isStateNode );
+ }
+
+ /**
+ * Find the first child node holding state.
+ *
+ * @param parent the parent node
+ * @return an optional child state node
+ */
+ public static Optional<Node> firstStateChildNode( Node parent )
+ {
+ return stateChildNodes( parent ).findFirst();
+ }
+
+ /**
+ * Test if a node holds state.
+ *
+ * Types of nodes holding state:
+ * <ul>
+ * <li>{@link Node#ELEMENT_NODE}</li>
+ * <li>{@link Node#CDATA_SECTION_NODE}</li>
+ * <li>{@link Node#TEXT_NODE}</li>
+ * </ul>
+ *
+ * @param node the node
+ * @return {@literal true} if {@literal node} holds state
+ */
+ public static boolean isStateNode( Node node )
+ {
+ switch( node.getNodeType() )
+ {
+ case Node.ELEMENT_NODE:
+ case Node.CDATA_SECTION_NODE:
+ case Node.TEXT_NODE:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ private static boolean isElement( Node node )
+ {
+ return node.getNodeType() == Node.ELEMENT_NODE;
+ }
+
+ private static Element castToElement( Node node )
+ {
+ return (Element) node;
+ }
+
+ private static Stream<Node> toStream( NodeList nodeList )
+ {
+ return StreamSupport.stream( new Spliterators.AbstractSpliterator<Node>( Long.MAX_VALUE, Spliterator.ORDERED )
+ {
+ private int nextIndex = 0;
+
+ @Override
+ public boolean tryAdvance( Consumer<? super Node> action )
+ {
+ if( nextIndex >= nodeList.getLength() )
+ {
+ return false;
+ }
+ action.accept( nodeList.item( nextIndex ) );
+ nextIndex++;
+ return true;
+ }
+ }, false );
+ }
+
+ private JavaxXml() {}
+}
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/c9dd7229/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlAdapter.java
----------------------------------------------------------------------
diff --git a/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlAdapter.java b/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlAdapter.java
new file mode 100644
index 0000000..3761198
--- /dev/null
+++ b/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlAdapter.java
@@ -0,0 +1,56 @@
+/*
+ * 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.javaxxml;
+
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import org.apache.polygene.api.type.ValueType;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+/**
+ * Adapter for XML (de)serialization.
+ *
+ * @param <T> the adapted type
+ */
+public interface JavaxXmlAdapter<T>
+{
+ /**
+ * @return the adapted type
+ */
+ Class<T> type();
+
+ /**
+ * Serialize.
+ *
+ * @param document the Document to use as a Node factory
+ * @param object Object to serialize, never null
+ * @param serializationFunction Serialization function for nested structure serialization
+ * @return Serialized XML representation
+ */
+ Node serialize( Document document, Object object, Function<Object, Node> serializationFunction );
+
+ /**
+ * Deserialize.
+ *
+ * @param node XML to deserialize from, never null
+ * @param deserializationFunction Deserialization function for nested structure deserialization
+ * @return Deserialized object
+ */
+ T deserialize( Node node, BiFunction<Node, ValueType, Object> deserializationFunction );
+}
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/c9dd7229/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlAdapters.java
----------------------------------------------------------------------
diff --git a/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlAdapters.java b/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlAdapters.java
new file mode 100644
index 0000000..273789d
--- /dev/null
+++ b/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlAdapters.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.javaxxml;
+
+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( JavaxXmlAdapters.Mixin.class )
+public interface JavaxXmlAdapters
+{
+ void registerAdapter( ValueType valueType, JavaxXmlAdapter<?> adapter );
+
+ <T> JavaxXmlAdapter<T> adapterFor( ValueType valueType );
+
+ default <T> JavaxXmlAdapter<T> adapterFor( Class<T> type )
+ {
+ return adapterFor( ValueType.of( type ) );
+ }
+
+ class Mixin implements JavaxXmlAdapters
+ {
+ private Map<ValueType, JavaxXmlAdapter<?>> adapters = new LinkedHashMap<>();
+
+ @Override
+ public void registerAdapter( final ValueType valueType, final JavaxXmlAdapter<?> adapter )
+ {
+ adapters.put( valueType, adapter );
+ }
+
+ @Override
+ public <T> JavaxXmlAdapter<T> adapterFor( final ValueType valueType )
+ {
+ return castAdapter( adapters.keySet().stream()
+ .collect( closestType( valueType ) )
+ .map( adapters::get )
+ .orElse( null ) );
+ }
+
+ @SuppressWarnings( "unchecked" )
+ private <T> JavaxXmlAdapter<T> castAdapter( JavaxXmlAdapter<?> adapter )
+ {
+ return (JavaxXmlAdapter<T>) adapter;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/c9dd7229/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlDeserializer.java
----------------------------------------------------------------------
diff --git a/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlDeserializer.java b/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlDeserializer.java
new file mode 100644
index 0000000..992e000
--- /dev/null
+++ b/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlDeserializer.java
@@ -0,0 +1,325 @@
+/*
+ * 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.javaxxml;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.util.ArrayList;
+import java.util.Base64;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.function.Supplier;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+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.XmlDeserializer;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+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 org.apache.polygene.api.util.Collectors.toMapWithNullValues;
+
+public class JavaxXmlDeserializer extends AbstractTextDeserializer implements XmlDeserializer
+{
+ private static final String NULL_ELEMENT_NAME = "null";
+
+ @This
+ private JavaxXmlAdapters adapters;
+
+ @Uses
+ private ServiceDescriptor descriptor;
+
+ @Override
+ public <T> T fromXml( ModuleDescriptor module, ValueType valueType, Document state )
+ {
+ Optional<Element> stateElement = JavaxXml.firstChildElementNamed( state, getSettings().getRootTagName() );
+ if( stateElement.isPresent() )
+ {
+ Optional<Node> stateNode = JavaxXml.firstStateChildNode( stateElement.get() );
+ if( stateNode.isPresent() )
+ {
+ return doDeserialize( module, valueType, stateNode.get() );
+ }
+ }
+ return null;
+ }
+
+ @SuppressWarnings( "unchecked" )
+ private <T> T doDeserialize( ModuleDescriptor module, ValueType valueType, Node xml )
+ {
+ if( xml == null )
+ {
+ return valueType.hasType( String.class ) ? (T) "" : null;
+ }
+ if( xml.getNodeType() == Node.ELEMENT_NODE && NULL_ELEMENT_NAME.equals( ( (Element) xml ).getTagName() ) )
+ {
+ return null;
+ }
+ JavaxXmlAdapter<?> adapter = adapters.adapterFor( valueType );
+ if( adapter != null )
+ {
+ return (T) adapter.deserialize( xml, ( element, type ) -> doDeserialize( module, type, element ) );
+ }
+ if( EnumType.class.isAssignableFrom( valueType.getClass() ) )
+ {
+ return (T) Enum.valueOf( (Class) valueType.primaryType(), xml.getNodeValue() );
+ }
+ if( CollectionType.class.isAssignableFrom( valueType.getClass() ) )
+ {
+ return (T) deserializeCollection( module, (CollectionType) valueType, xml );
+ }
+ if( MapType.class.isAssignableFrom( valueType.getClass() ) )
+ {
+ return (T) deserializeMap( module, (MapType) valueType, xml );
+ }
+ if( ValueCompositeType.class.isAssignableFrom( valueType.getClass() ) )
+ {
+ return (T) deserializeValueComposite( module, (ValueCompositeType) valueType, xml );
+ }
+ return (T) doGuessDeserialize( module, valueType, xml );
+ }
+
+ private Object deserializeValueComposite( ModuleDescriptor module, ValueCompositeType valueType, Node xml )
+ {
+ Optional<String> typeInfo = getTypeInfo( xml );
+ if( typeInfo.isPresent() )
+ {
+ ValueDescriptor descriptor = module.valueDescriptor( typeInfo.get() );
+ if( descriptor == null )
+ {
+ String typeInfoName = getSettings().getTypeInfoTagName();
+ throw new SerializationException(
+ typeInfoName + ": " + typeInfo.get() + " could not be resolved while deserializing " + xml );
+ }
+ valueType = descriptor.valueType();
+ }
+ ValueBuilder builder = module.instance().newValueBuilderWithState(
+ valueType.primaryType(),
+ propertyFunction( module, xml ),
+ associationFunction( module, xml ),
+ manyAssociationFunction( module, xml ),
+ namedAssociationFunction( module, xml ) );
+ return builder.newInstance();
+ }
+
+ private Function<PropertyDescriptor, Object> propertyFunction( ModuleDescriptor module, Node xml )
+ {
+ return property ->
+ {
+ Optional<Element> element = JavaxXml.firstChildElementNamed( xml, property.qualifiedName().name() );
+ if( element.isPresent() )
+ {
+ Node valueNode = JavaxXml.firstStateChildNode( element.get() ).orElse( null );
+ Object value = doDeserialize( module, property.valueType(), valueNode );
+ 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, Node xml )
+ {
+ return association ->
+ (EntityReference) JavaxXml.firstChildElementNamed( xml, association.qualifiedName().name() )
+ .map( element -> doDeserialize( module,
+ ValueType.ENTITY_REFERENCE,
+ JavaxXml.firstStateChildNode( element )
+ .orElse( null ) ) )
+ .orElse( null );
+ }
+
+ private Function<AssociationDescriptor, Stream<EntityReference>> manyAssociationFunction( ModuleDescriptor module,
+ Node xml )
+ {
+ return association ->
+ JavaxXml.firstChildElementNamed( xml, association.qualifiedName().name() )
+ .map( element -> (List) doDeserialize( module,
+ ENTITY_REF_LIST_VALUE_TYPE,
+ JavaxXml.firstStateChildNode( element )
+ .orElse( null ) ) )
+ .map( List::stream )
+ .orElse( Stream.empty() );
+ }
+
+ private Function<AssociationDescriptor, Stream<Map.Entry<String, EntityReference>>> namedAssociationFunction(
+ ModuleDescriptor module, Node xml )
+ {
+ return association ->
+ (Stream) JavaxXml.firstChildElementNamed( xml, association.qualifiedName().name() )
+ .map( element -> (Map) doDeserialize( module,
+ ENTITY_REF_MAP_VALUE_TYPE,
+ JavaxXml.firstStateChildNode( element )
+ .orElse( null ) ) )
+ .map( Map::entrySet ).map( Set::stream )
+ .orElse( Stream.empty() );
+ }
+
+ @SuppressWarnings( "unchecked" )
+ private Collection deserializeCollection( ModuleDescriptor module, CollectionType collectionType, Node xml )
+ {
+ Supplier<Collection> collectionSupplier = () -> collectionType.isSet()
+ ? new LinkedHashSet<>()
+ : new ArrayList<>();
+ if( !xml.hasChildNodes() )
+ {
+ return collectionSupplier.get();
+ }
+ return JavaxXml
+ .childElements( xml )
+ .map( element ->
+ {
+ if( getSettings().getCollectionElementTagName().equals( element.getTagName() ) )
+ {
+ return doDeserialize( module, collectionType.collectedType(),
+ JavaxXml.firstStateChildNode( element ).get() );
+ }
+ return doDeserialize( module, collectionType.collectedType(), element );
+ } )
+ .collect( Collectors.toCollection( collectionSupplier ) );
+ }
+
+ @SuppressWarnings( "unchecked" )
+ private Map deserializeMap( ModuleDescriptor module, MapType mapType, Node xml )
+ {
+ if( !xml.hasChildNodes() )
+ {
+ return new LinkedHashMap<>();
+ }
+ Predicate<Element> complexMapping = element -> getSettings().getMapEntryTagName().equals( element.getTagName() )
+ && JavaxXml.firstChildElementNamed( element, "key" )
+ .isPresent();
+ // This allows deserializing mixed simple/complex mappings for a given map
+ return JavaxXml.childElements( xml ).map(
+ element ->
+ {
+ if( complexMapping.test( element ) )
+ {
+ Node keyNode = JavaxXml.firstChildElementNamed( element, "key" )
+ .flatMap( JavaxXml::firstStateChildNode )
+ .get();
+ Optional<Node> valueNode = JavaxXml.firstChildElementNamed( element, "value" )
+ .flatMap( JavaxXml::firstStateChildNode );
+ Object key = doDeserialize( module, mapType.keyType(), keyNode );
+ Object value = valueNode.map( node -> doDeserialize( module, mapType.valueType(), node ) )
+ .orElse( null );
+ return new HashMap.SimpleImmutableEntry<>( key, value );
+ }
+ String key = element.getTagName();
+ Object value = JavaxXml.firstStateChildNode( element )
+ .map( node -> doDeserialize( module, mapType.valueType(), node ) )
+ .orElse( null );
+ return (Map.Entry) new HashMap.SimpleImmutableEntry<>( key, value );
+ }
+ ).collect( toMapWithNullValues( LinkedHashMap::new ) );
+ }
+
+ private Object doGuessDeserialize( ModuleDescriptor module, ValueType valueType, Node xml )
+ {
+ // TODO Could do better by detecting <collection/>, <map/> and <value/>
+ Optional<String> typeInfo = getTypeInfo( xml );
+ if( typeInfo.isPresent() )
+ {
+ ValueDescriptor valueDescriptor = module.valueDescriptor( typeInfo.get() );
+ if( valueDescriptor != null )
+ {
+ return deserializeValueComposite( module, valueDescriptor.valueType(), xml );
+ }
+ }
+ if( xml.getNodeType() == Node.CDATA_SECTION_NODE )
+ {
+ return deserializeBase64( xml.getNodeValue() );
+ }
+ throw new SerializationException( "Don't know how to deserialize " + valueType + " from " + xml );
+ }
+
+ 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 Optional<String> getTypeInfo( Node xml )
+ {
+ if( xml.getNodeType() != Node.ELEMENT_NODE )
+ {
+ return Optional.empty();
+ }
+ String typeInfo = ( (Element) xml ).getAttribute( getSettings().getTypeInfoTagName() );
+ if( typeInfo.isEmpty() )
+ {
+ return Optional.empty();
+ }
+ return Optional.of( typeInfo );
+ }
+
+ private JavaxXmlSettings getSettings()
+ {
+ return JavaxXmlSettings.orDefault( descriptor.metaInfo( JavaxXmlSettings.class ) );
+ }
+}
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/c9dd7229/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlSerialization.java
----------------------------------------------------------------------
diff --git a/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlSerialization.java b/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlSerialization.java
new file mode 100644
index 0000000..529bdee
--- /dev/null
+++ b/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlSerialization.java
@@ -0,0 +1,88 @@
+/*
+ * 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.javaxxml;
+
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.spi.serialization.XmlSerialization;
+
+/**
+ * javax.xml state serialization.
+ *
+ * The XML representations consumed and produced by this service are, by default, verbose, and safe to deserialize.
+ * This is because the default mapping is purely structural.
+ * You can customize the XML representations using {@link JavaxXmlSettings} and {@link JavaxXmlAdapters}.
+ *
+ * The following describe how state is represented by default.
+ *
+ * Because a valid XML document can only contain a single node and it must be an element, all
+ * {@link org.w3c.dom.Document}s have a root element {@literal <state/>}. This serialization implementation
+ * also impose that the root element can only contain a single node, of any type.
+ *
+ * {@literal null} is represented as {@literal <null/>}.
+ * Plain values are represented as {@link org.w3c.dom.Text} nodes.
+ * Iterables and Streams are represented as {@literal <collection/>} {@link org.w3c.dom.Element}s.
+ * Maps are represented as {@literal <dictionary/>} {@link org.w3c.dom.Element}s.
+ *
+ * This is how a {@literal null} plain value is represented: {@literal <state><null/></state>}.
+ * And a plain {@literal LocalDate}: {@literal <state>2017-01-01</state>}
+ *
+ * This is how a fictional value including a collection and a map is represented:
+ * <code>
+ * <state>
+ * <stringProperty>and it's value</stringProperty>
+ * <bigDecimalProperty>4.22376931348623157E+310</bigDecimalProperty>
+ * <nullProperty><null/></nullProperty>
+ * <booleanProperty>false</booleanProperty>
+ * <stringCollectionProperty>
+ * <collection>
+ * item1
+ * item2 <!-- As multiple text nodes -->
+ * </collection>
+ * </stringCollectionProperty>
+ * <mapProperty>
+ * <map>
+ * <foo>bar</foo>
+ * <bazar>cathedral</bazar>
+ * </map>
+ * </mapProperty>
+ * <complexKeyMapProperty>
+ * <map>
+ * <entry>
+ * <key>
+ * <foo>bar</foo>
+ * <bazar>cathedral</bazar>
+ * </key>
+ * <value>23</value>
+ * </entry>
+ * <entry>
+ * <key>
+ * <foo>baz</foo>
+ * <bazar>bar</bazar>
+ * </key>
+ * <value>42</value>
+ * </entry>
+ * </map>
+ * </complexKeyMapProperty>
+ * </state>
+ * </code>
+ *
+ */
+@Mixins( { JavaxXmlSerializer.class, JavaxXmlDeserializer.class } )
+public interface JavaxXmlSerialization extends XmlSerialization
+{
+}
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/c9dd7229/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlSerializationAssembler.java
----------------------------------------------------------------------
diff --git a/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlSerializationAssembler.java b/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlSerializationAssembler.java
new file mode 100644
index 0000000..b97bf12
--- /dev/null
+++ b/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlSerializationAssembler.java
@@ -0,0 +1,58 @@
+/*
+ * 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.javaxxml;
+
+import org.apache.polygene.api.serialization.Deserializer;
+import org.apache.polygene.api.serialization.Serialization;
+import org.apache.polygene.api.serialization.Serializer;
+import org.apache.polygene.bootstrap.Assemblers;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.ServiceDeclaration;
+import org.apache.polygene.spi.serialization.XmlDeserializer;
+import org.apache.polygene.spi.serialization.XmlSerialization;
+import org.apache.polygene.spi.serialization.XmlSerializer;
+
+public class JavaxXmlSerializationAssembler extends Assemblers.VisibilityIdentity<JavaxXmlSerializationAssembler>
+{
+ private JavaxXmlSettings settings;
+
+ public JavaxXmlSerializationAssembler withXmlSettings( JavaxXmlSettings settings )
+ {
+ this.settings = settings;
+ return this;
+ }
+
+ @Override
+ public void assemble( ModuleAssembly module )
+ {
+ ServiceDeclaration declaration = module.services( JavaxXmlSerializationService.class )
+ .withTypes( Serialization.class,
+ Serializer.class, Deserializer.class,
+ XmlSerialization.class,
+ XmlSerializer.class, XmlDeserializer.class )
+ .visibleIn( visibility() );
+ if( hasIdentity() )
+ {
+ declaration.identifiedBy( identity() );
+ }
+ if( settings != null )
+ {
+ declaration.setMetaInfo( settings );
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/c9dd7229/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlSerializationService.java
----------------------------------------------------------------------
diff --git a/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlSerializationService.java b/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlSerializationService.java
new file mode 100644
index 0000000..3917340
--- /dev/null
+++ b/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlSerializationService.java
@@ -0,0 +1,372 @@
+/*
+ * 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.javaxxml;
+
+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 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.service.ServiceActivation;
+import org.apache.polygene.api.service.ServiceDescriptor;
+import org.apache.polygene.api.type.ValueType;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+@Mixins( JavaxXmlSerializationService.Activation.class )
+public interface JavaxXmlSerializationService extends JavaxXmlSerialization, ServiceActivation
+{
+ class Activation implements ServiceActivation
+ {
+ @Uses
+ private ServiceDescriptor descriptor;
+
+ @This
+ private JavaxXmlAdapters adapters;
+
+ private boolean registrationDone = false;
+
+ @Override
+ public void activateService()
+ {
+ if( !registrationDone )
+ {
+ registerCustomAdapters();
+ registerBaseAdapters();
+ registrationDone = true;
+ }
+ }
+
+ @Override
+ public void passivateService() {}
+
+ private void registerCustomAdapters()
+ {
+ JavaxXmlSettings.orDefault( descriptor.metaInfo( JavaxXmlSettings.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 ToStringTextNodeAdapter<T> implements JavaxXmlAdapter<T>
+ {
+ @Override
+ public Node serialize( Document document, Object object, Function<Object, Node> serializationFunction )
+ {
+ return document.createTextNode( object.toString() );
+ }
+ }
+
+ private static class StringAdapter extends ToStringTextNodeAdapter<String>
+ {
+ @Override
+ public Class<String> type() { return String.class; }
+
+ @Override
+ public String deserialize( Node node, BiFunction<Node, ValueType, Object> deserializationFunction )
+ {
+ return node.getNodeValue();
+ }
+ }
+
+ private static class CharacterAdapter extends ToStringTextNodeAdapter<Character>
+ {
+ @Override
+ public Class<Character> type() { return Character.class; }
+
+ @Override
+ public Character deserialize( Node node, BiFunction<Node, ValueType, Object> deserializationFunction )
+ {
+ String string = node.getNodeValue();
+ return string.isEmpty() ? null : string.charAt( 0 );
+ }
+ }
+
+ private static class BooleanAdapter extends ToStringTextNodeAdapter<Boolean>
+ {
+ @Override
+ public Class<Boolean> type() { return Boolean.class; }
+
+ @Override
+ public Boolean deserialize( Node node, BiFunction<Node, ValueType, Object> deserializationFunction )
+ {
+ return Boolean.valueOf( node.getNodeValue() );
+ }
+ }
+
+ private static class IntegerAdapter extends ToStringTextNodeAdapter<Integer>
+ {
+ @Override
+ public Class<Integer> type() { return Integer.class; }
+
+ @Override
+ public Integer deserialize( Node node, BiFunction<Node, ValueType, Object> deserializationFunction )
+ {
+ return Integer.valueOf( node.getNodeValue() );
+ }
+ }
+
+ private static class LongAdapter extends ToStringTextNodeAdapter<Long>
+ {
+ @Override
+ public Class<Long> type() { return Long.class; }
+
+ @Override
+ public Long deserialize( Node node, BiFunction<Node, ValueType, Object> deserializationFunction )
+ {
+ return Long.valueOf( node.getNodeValue() );
+ }
+ }
+
+ private static class ShortAdapter extends ToStringTextNodeAdapter<Short>
+ {
+ @Override
+ public Class<Short> type() { return Short.class; }
+
+ @Override
+ public Short deserialize( Node node, BiFunction<Node, ValueType, Object> deserializationFunction )
+ {
+ return Short.valueOf( node.getNodeValue() );
+ }
+ }
+
+ private static class ByteAdapter extends ToStringTextNodeAdapter<Byte>
+ {
+ @Override
+ public Class<Byte> type() { return Byte.class; }
+
+ @Override
+ public Byte deserialize( Node node, BiFunction<Node, ValueType, Object> deserializationFunction )
+ {
+ return Byte.valueOf( node.getNodeValue() );
+ }
+ }
+
+ private static class FloatAdapter extends ToStringTextNodeAdapter<Float>
+ {
+ @Override
+ public Class<Float> type() { return Float.class; }
+
+ @Override
+ public Float deserialize( Node node, BiFunction<Node, ValueType, Object> deserializationFunction )
+ {
+ return Float.valueOf( node.getNodeValue() );
+ }
+ }
+
+ private static class DoubleAdapter extends ToStringTextNodeAdapter<Double>
+ {
+ @Override
+ public Class<Double> type() { return Double.class; }
+
+ @Override
+ public Double deserialize( Node node, BiFunction<Node, ValueType, Object> deserializationFunction )
+ {
+ return Double.valueOf( node.getNodeValue() );
+ }
+ }
+
+ private static class BigDecimalAdapter extends ToStringTextNodeAdapter<BigDecimal>
+ {
+ @Override
+ public Class<BigDecimal> type() { return BigDecimal.class; }
+
+ @Override
+ public BigDecimal deserialize( Node node, BiFunction<Node, ValueType, Object> deserializationFunction )
+ {
+ return new BigDecimal( node.getNodeValue() );
+ }
+ }
+
+ private static class BigIntegerAdapter extends ToStringTextNodeAdapter<BigInteger>
+ {
+ @Override
+ public Class<BigInteger> type() { return BigInteger.class; }
+
+ @Override
+ public BigInteger deserialize( Node node, BiFunction<Node, ValueType, Object> deserializationFunction )
+ {
+ return new BigInteger( node.getNodeValue() );
+ }
+ }
+
+ private static class InstantAdapter extends ToStringTextNodeAdapter<Instant>
+ {
+ @Override
+ public Class<Instant> type() { return Instant.class; }
+
+ @Override
+ public Instant deserialize( Node node, BiFunction<Node, ValueType, Object> deserializationFunction )
+ {
+ return Instant.parse( node.getNodeValue() );
+ }
+ }
+
+ private static class ZonedDateTimeAdapter extends ToStringTextNodeAdapter<ZonedDateTime>
+ {
+ @Override
+ public Class<ZonedDateTime> type() { return ZonedDateTime.class; }
+
+ @Override
+ public ZonedDateTime deserialize( Node node, BiFunction<Node, ValueType, Object> deserializationFunction )
+ {
+ return ZonedDateTime.parse( node.getNodeValue() );
+ }
+ }
+
+ private static class OffsetDateTimeAdapter extends ToStringTextNodeAdapter<OffsetDateTime>
+ {
+ @Override
+ public Class<OffsetDateTime> type() { return OffsetDateTime.class; }
+
+ @Override
+ public OffsetDateTime deserialize( Node node, BiFunction<Node, ValueType, Object> deserializationFunction )
+ {
+ return OffsetDateTime.parse( node.getNodeValue() );
+ }
+ }
+
+ private static class LocalDateTimeAdapter extends ToStringTextNodeAdapter<LocalDateTime>
+ {
+ @Override
+ public Class<LocalDateTime> type() { return LocalDateTime.class; }
+
+ @Override
+ public LocalDateTime deserialize( Node node, BiFunction<Node, ValueType, Object> deserializationFunction )
+ {
+ return LocalDateTime.parse( node.getNodeValue() );
+ }
+ }
+
+ private static class LocalDateAdapter extends ToStringTextNodeAdapter<LocalDate>
+ {
+ @Override
+ public Class<LocalDate> type() { return LocalDate.class; }
+
+ @Override
+ public LocalDate deserialize( Node node, BiFunction<Node, ValueType, Object> deserializationFunction )
+ {
+ return LocalDate.parse( node.getNodeValue() );
+ }
+ }
+
+ private static class LocalTimeAdapter extends ToStringTextNodeAdapter<LocalTime>
+ {
+ @Override
+ public Class<LocalTime> type() { return LocalTime.class; }
+
+ @Override
+ public LocalTime deserialize( Node node, BiFunction<Node, ValueType, Object> deserializationFunction )
+ {
+ return LocalTime.parse( node.getNodeValue() );
+ }
+ }
+
+ private static class DurationAdapter extends ToStringTextNodeAdapter<Duration>
+ {
+ @Override
+ public Class<Duration> type() { return Duration.class; }
+
+ @Override
+ public Duration deserialize( Node node, BiFunction<Node, ValueType, Object> deserializationFunction )
+ {
+ return Duration.parse( node.getNodeValue() );
+ }
+ }
+
+ private static class PeriodAdapter extends ToStringTextNodeAdapter<Period>
+ {
+ @Override
+ public Class<Period> type() { return Period.class; }
+
+ @Override
+ public Period deserialize( Node node, BiFunction<Node, ValueType, Object> deserializationFunction )
+ {
+ return Period.parse( node.getNodeValue() );
+ }
+ }
+
+ private static class IdentityAdapter extends ToStringTextNodeAdapter<Identity>
+ {
+ @Override
+ public Class<Identity> type() { return Identity.class; }
+
+ @Override
+ public Identity deserialize( Node node, BiFunction<Node, ValueType, Object> deserializationFunction )
+ {
+ return StringIdentity.fromString( node.getNodeValue() );
+ }
+ }
+
+ private static class EntityReferenceAdapter extends ToStringTextNodeAdapter<EntityReference>
+ {
+ @Override
+ public Class<EntityReference> type() { return EntityReference.class; }
+
+ @Override
+ public EntityReference deserialize( Node node, BiFunction<Node, ValueType, Object> deserializationFunction )
+ {
+ return EntityReference.parseEntityReference( node.getNodeValue() );
+ }
+ }
+ }
+}