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 15:28:35 UTC
[12/48] polygene-java git commit: New (de)serialization API and SPI &
new implementations
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlSerializer.java
----------------------------------------------------------------------
diff --git a/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlSerializer.java b/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlSerializer.java
new file mode 100644
index 0000000..bf26f0c
--- /dev/null
+++ b/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlSerializer.java
@@ -0,0 +1,271 @@
+/*
+ * 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.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectOutputStream;
+import java.io.UncheckedIOException;
+import java.util.Base64;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import org.apache.polygene.api.PolygeneAPI;
+import org.apache.polygene.api.association.AssociationStateHolder;
+import org.apache.polygene.api.composite.CompositeInstance;
+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.serialization.SerializationException;
+import org.apache.polygene.api.service.ServiceDescriptor;
+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.value.ValueComposite;
+import org.apache.polygene.api.value.ValueDescriptor;
+import org.apache.polygene.spi.serialization.AbstractTextSerializer;
+import org.apache.polygene.spi.serialization.XmlSerializer;
+import org.w3c.dom.DOMException;
+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 org.apache.polygene.api.util.Collectors.toMap;
+
+/**
+ * XML Serializer.
+ */
+public class JavaxXmlSerializer extends AbstractTextSerializer implements XmlSerializer
+{
+ private static final String NULL_ELEMENT_NAME = "null";
+
+ @This
+ private JavaxXmlAdapters adapters;
+
+ @Uses
+ private ServiceDescriptor descriptor;
+
+ @Override
+ public <T> Function<T, Document> toXmlFunction( Options options )
+ {
+ return object -> doSerializeRoot( options, object );
+ }
+
+ private <T> Document doSerializeRoot( Options options, T object )
+ {
+ try
+ {
+ Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
+ doc.setXmlVersion( "1.1" );
+ doc.setXmlStandalone( true );
+ Element stateElement = doc.createElement( getSettings().getRootTagName() );
+ Node node = doSerialize( doc, options, object, true );
+ stateElement.appendChild( node );
+ doc.appendChild( stateElement );
+ return doc;
+ }
+ catch( ParserConfigurationException ex )
+ {
+ throw new SerializationException( "Unable to create XML document. "
+ + "Is your javax.xml subsystem correctly set up?", ex );
+ }
+ }
+
+ private <T> Node doSerialize( Document document, Options options, T object, boolean root )
+ {
+ if( object == null )
+ {
+ return document.createElement( NULL_ELEMENT_NAME );
+ }
+ Class<?> objectClass = object.getClass();
+ JavaxXmlAdapter<?> adapter = adapters.adapterFor( objectClass );
+ if( adapter != null )
+ {
+ return adapter.serialize( document, object, value -> doSerialize( document, options, value, false ) );
+ }
+ if( EnumType.isEnum( objectClass ) )
+ {
+ return document.createTextNode( object.toString() );
+ }
+ if( ValueCompositeType.isValueComposite( objectClass ) )
+ {
+ return serializeValueComposite( document, options, object, root );
+ }
+ if( MapType.isMap( objectClass ) )
+ {
+ return serializeMap( document, options, (Map<?, ?>) object );
+ }
+ if( Iterable.class.isAssignableFrom( objectClass ) )
+ {
+ return serializeIterable( document, options, (Iterable<?>) object );
+ }
+ if( Stream.class.isAssignableFrom( objectClass ) )
+ {
+ return serializeStream( document, options, (Stream<?>) object );
+ }
+ // Fallback to Java Serialization in Base 64
+ // Include all arrays!
+ return serializeBase64( document, object );
+ }
+
+ private <T> Node serializeValueComposite( Document document, Options options, T composite, boolean root )
+ {
+ CompositeInstance instance = PolygeneAPI.FUNCTION_COMPOSITE_INSTANCE_OF.apply( (ValueComposite) composite );
+ ValueDescriptor descriptor = (ValueDescriptor) instance.descriptor();
+ AssociationStateHolder state = (AssociationStateHolder) instance.state();
+ ValueCompositeType valueType = descriptor.valueType();
+
+ Element valueElement = document.createElement( getSettings().getValueTagName() );
+ valueType.properties().forEach(
+ property ->
+ {
+ Object value = state.propertyFor( property.accessor() ).get();
+ Element element = document.createElement( property.qualifiedName().name() );
+ element.appendChild( doSerialize( document, options, value, false ) );
+ valueElement.appendChild( element );
+ } );
+ valueType.associations().forEach(
+ association ->
+ {
+ EntityReference value = state.associationFor( association.accessor() ).reference();
+ Element element = document.createElement( association.qualifiedName().name() );
+ element.appendChild( doSerialize( document, options, value, false ) );
+ valueElement.appendChild( element );
+ }
+ );
+ valueType.manyAssociations().forEach(
+ association ->
+ {
+ Stream<EntityReference> value = state.manyAssociationFor( association.accessor() ).references();
+ Element element = document.createElement( association.qualifiedName().name() );
+ element.appendChild( doSerialize( document, options, value, false ) );
+ valueElement.appendChild( element );
+ }
+ );
+ valueType.namedAssociations().forEach(
+ association ->
+ {
+ Map<String, EntityReference> value = state.namedAssociationFor( association.accessor() ).references()
+ .collect( toMap() );
+ Element element = document.createElement( association.qualifiedName().name() );
+ element.appendChild( doSerialize( document, options, value, false ) );
+ valueElement.appendChild( element );
+ }
+ );
+ if( !root && options.includeTypeInfo() )
+ {
+ valueElement.setAttribute( getSettings().getTypeInfoTagName(), valueType.primaryType().getName() );
+ }
+ return valueElement;
+ }
+
+ private Node serializeMap( Document document, Options options, Map<?, ?> map )
+ {
+ JavaxXmlSettings settings = getSettings();
+ Element mapElement = document.createElement( settings.getMapTagName() );
+ if( map.isEmpty() )
+ {
+ return mapElement;
+ }
+ Function<Map.Entry, Node> complexMapping = entry ->
+ {
+ Element entryElement = document.createElement( settings.getMapEntryTagName() );
+
+ Element keyElement = document.createElement( "key" );
+ keyElement.appendChild( doSerialize( document, options, entry.getKey(), false ) );
+ entryElement.appendChild( keyElement );
+
+ Element valueElement = document.createElement( "value" );
+ valueElement.appendChild( doSerialize( document, options, entry.getValue(), false ) );
+ entryElement.appendChild( valueElement );
+
+ return entryElement;
+ };
+
+ if( map.keySet().iterator().next() instanceof CharSequence )
+ {
+ map.entrySet().stream()
+ .map( entry ->
+ {
+ try
+ {
+ Element element = document.createElement( entry.getKey().toString() );
+ element.appendChild( doSerialize( document, options, entry.getValue(), false ) );
+ return element;
+ }
+ catch( DOMException ex )
+ {
+ // The key name cannot be encoded as a tag name, fallback to complex mapping
+ // Tag names cannot start with a digit, some characters cannot be escaped etc...
+ return complexMapping.apply( entry );
+ }
+ } )
+ .forEach( mapElement::appendChild );
+ }
+ else
+ {
+ map.entrySet().stream()
+ .map( complexMapping )
+ .forEach( mapElement::appendChild );
+ }
+ return mapElement;
+ }
+
+ private Node serializeIterable( Document document, Options options, Iterable<?> object )
+ {
+ return serializeStream( document, options, StreamSupport.stream( object.spliterator(), false ) );
+ }
+
+ private Node serializeStream( Document document, Options options, Stream<?> object )
+ {
+ JavaxXmlSettings settings = getSettings();
+ Element collectionElement = document.createElement( settings.getCollectionTagName() );
+ object.map( each -> doSerialize( document, options, each, false ) )
+ .forEach( itemValueNode ->
+ {
+ Element itemElement = document.createElement( settings.getCollectionElementTagName() );
+ itemElement.appendChild( itemValueNode );
+ collectionElement.appendChild( itemElement );
+ } );
+ return collectionElement;
+ }
+
+ private <T> Node serializeBase64( Document document, T object )
+ {
+ ByteArrayOutputStream bout = new ByteArrayOutputStream();
+ try( ObjectOutputStream out = new ObjectOutputStream( bout ) )
+ {
+ out.writeUnshared( object );
+ byte[] bytes = Base64.getEncoder().encode( bout.toByteArray() );
+ return document.createCDATASection( new String( bytes, UTF_8 ) );
+ }
+ catch( IOException ex )
+ {
+ throw new UncheckedIOException( ex );
+ }
+ }
+
+ private JavaxXmlSettings getSettings()
+ {
+ return JavaxXmlSettings.orDefault( descriptor.metaInfo( JavaxXmlSettings.class ) );
+ }
+}
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlSettings.java
----------------------------------------------------------------------
diff --git a/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlSettings.java b/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlSettings.java
new file mode 100644
index 0000000..b5c5702
--- /dev/null
+++ b/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlSettings.java
@@ -0,0 +1,134 @@
+/*
+ * 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.type.ValueType;
+
+/**
+ * javax.xml settings.
+ *
+ * Must be registered as meta-info at assembly time.
+ */
+// TODO javax.xml properties
+public class JavaxXmlSettings
+{
+ public static final JavaxXmlSettings DEFAULT = new JavaxXmlSettings();
+
+ public static JavaxXmlSettings orDefault( JavaxXmlSettings settings )
+ {
+ return settings != null ? settings : DEFAULT;
+ }
+
+ private String rootTagName;
+ private String collectionTagName;
+ private String collectionElementTagName;
+ private String mapTagName;
+ private String mapEntryTagName;
+ private String valueTagName;
+ private String typeInfoTagName;
+ private Map<ValueType, JavaxXmlAdapter<?>> adapters;
+
+ public JavaxXmlSettings()
+ {
+ rootTagName = "state";
+ collectionTagName = "collection";
+ collectionElementTagName = "element";
+ mapTagName = "map";
+ mapEntryTagName = "entry";
+ valueTagName = "value";
+ typeInfoTagName = "_type";
+ adapters = new LinkedHashMap<>();
+ }
+
+ public String getRootTagName()
+ {
+ return rootTagName;
+ }
+
+ public void setRootTagName( final String rootTagName )
+ {
+ this.rootTagName = rootTagName;
+ }
+
+ public String getCollectionTagName()
+ {
+ return collectionTagName;
+ }
+
+ public void setCollectionTagName( final String collectionTagName )
+ {
+ this.collectionTagName = collectionTagName;
+ }
+
+ public String getCollectionElementTagName()
+ {
+ return collectionElementTagName;
+ }
+
+ public void setCollectionElementTagName( final String collectionElementTagName )
+ {
+ this.collectionElementTagName = collectionElementTagName;
+ }
+
+ public String getMapTagName()
+ {
+ return mapTagName;
+ }
+
+ public void setMapTagName( final String mapTagName )
+ {
+ this.mapTagName = mapTagName;
+ }
+
+ public String getMapEntryTagName()
+ {
+ return mapEntryTagName;
+ }
+
+ public void setMapEntryTagName( final String mapEntryTagName )
+ {
+ this.mapEntryTagName = mapEntryTagName;
+ }
+
+ public String getValueTagName()
+ {
+ return valueTagName;
+ }
+
+ public void setValueTagName( final String valueTagName )
+ {
+ this.valueTagName = valueTagName;
+ }
+
+ public String getTypeInfoTagName()
+ {
+ return typeInfoTagName;
+ }
+
+ public void setTypeInfoTagName( final String typeInfoTagName )
+ {
+ this.typeInfoTagName = typeInfoTagName;
+ }
+
+ public Map<ValueType, JavaxXmlAdapter<?>> getAdapters()
+ {
+ return adapters;
+ }
+}
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/package.html
----------------------------------------------------------------------
diff --git a/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/package.html b/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/package.html
new file mode 100644
index 0000000..f81a030
--- /dev/null
+++ b/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/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.xml Serialization.</h2>
+ </body>
+</html>
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/extensions/serialization-javaxxml/src/test/java/org/apache/polygene/serialization/javaxxml/JavaxXmlAdaptersTest.java
----------------------------------------------------------------------
diff --git a/extensions/serialization-javaxxml/src/test/java/org/apache/polygene/serialization/javaxxml/JavaxXmlAdaptersTest.java b/extensions/serialization-javaxxml/src/test/java/org/apache/polygene/serialization/javaxxml/JavaxXmlAdaptersTest.java
new file mode 100644
index 0000000..16a2fb3
--- /dev/null
+++ b/extensions/serialization-javaxxml/src/test/java/org/apache/polygene/serialization/javaxxml/JavaxXmlAdaptersTest.java
@@ -0,0 +1,39 @@
+package org.apache.polygene.serialization.javaxxml;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+public class JavaxXmlAdaptersTest extends AbstractPolygeneTest
+{
+ @Override
+ public void assemble( ModuleAssembly module )
+ {
+ new JavaxXmlSerializationAssembler().assemble( module );
+ module.services( JavaxXmlSerializationService.class )
+ .withTypes( JavaxXmlAdapters.class );
+ }
+
+ @Service
+ private JavaxXmlAdapters adapters;
+
+ @Test
+ public void test() throws ParserConfigurationException
+ {
+ JavaxXmlAdapter<String> adapter = adapters.adapterFor( String.class );
+ Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
+ String original = "Cou<cou>\u20ac���#\u2030��";
+ Node node = adapter.serialize( doc, original, null );
+ assertThat( node.getNodeValue(), equalTo( original ) );
+ String result = adapter.deserialize( node, null );
+ assertThat( result, equalTo( original ) );
+ }
+}
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/extensions/serialization-javaxxml/src/test/java/org/apache/polygene/serialization/javaxxml/JavaxXmlCollectionTest.java
----------------------------------------------------------------------
diff --git a/extensions/serialization-javaxxml/src/test/java/org/apache/polygene/serialization/javaxxml/JavaxXmlCollectionTest.java b/extensions/serialization-javaxxml/src/test/java/org/apache/polygene/serialization/javaxxml/JavaxXmlCollectionTest.java
new file mode 100644
index 0000000..5f0bf3c
--- /dev/null
+++ b/extensions/serialization-javaxxml/src/test/java/org/apache/polygene/serialization/javaxxml/JavaxXmlCollectionTest.java
@@ -0,0 +1,31 @@
+/*
+ * 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.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.serialization.AbstractCollectionSerializationTest;
+
+public class JavaxXmlCollectionTest extends AbstractCollectionSerializationTest
+{
+ @Override
+ public void assemble( ModuleAssembly module )
+ {
+ new JavaxXmlSerializationAssembler().assemble( module );
+ super.assemble( module );
+ }
+}
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/extensions/serialization-javaxxml/src/test/java/org/apache/polygene/serialization/javaxxml/JavaxXmlDateFormatTest.java
----------------------------------------------------------------------
diff --git a/extensions/serialization-javaxxml/src/test/java/org/apache/polygene/serialization/javaxxml/JavaxXmlDateFormatTest.java b/extensions/serialization-javaxxml/src/test/java/org/apache/polygene/serialization/javaxxml/JavaxXmlDateFormatTest.java
new file mode 100644
index 0000000..6f69bbe
--- /dev/null
+++ b/extensions/serialization-javaxxml/src/test/java/org/apache/polygene/serialization/javaxxml/JavaxXmlDateFormatTest.java
@@ -0,0 +1,33 @@
+/*
+ * 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.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.serialization.AbstractDateFormatSerializationTest;
+import org.junit.Ignore;
+
+@Ignore( "Super test assume JSON" )
+public class JavaxXmlDateFormatTest extends AbstractDateFormatSerializationTest
+{
+ @Override
+ public void assemble( ModuleAssembly module )
+ {
+ new JavaxXmlSerializationAssembler().assemble( module );
+ super.assemble( module );
+ }
+}
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/extensions/serialization-javaxxml/src/test/java/org/apache/polygene/serialization/javaxxml/JavaxXmlPlainValueTest.java
----------------------------------------------------------------------
diff --git a/extensions/serialization-javaxxml/src/test/java/org/apache/polygene/serialization/javaxxml/JavaxXmlPlainValueTest.java b/extensions/serialization-javaxxml/src/test/java/org/apache/polygene/serialization/javaxxml/JavaxXmlPlainValueTest.java
new file mode 100644
index 0000000..51d8e8a
--- /dev/null
+++ b/extensions/serialization-javaxxml/src/test/java/org/apache/polygene/serialization/javaxxml/JavaxXmlPlainValueTest.java
@@ -0,0 +1,35 @@
+/*
+ * 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.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.serialization.AbstractPlainValueSerializationTest;
+import org.junit.Ignore;
+
+@Ignore( "Super test assume JSON" )
+public class JavaxXmlPlainValueTest extends AbstractPlainValueSerializationTest
+{
+ @Override
+ public void assemble( ModuleAssembly module )
+ {
+ new JavaxXmlSerializationAssembler().assemble( module );
+ super.assemble( module );
+ }
+}
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/extensions/serialization-javaxxml/src/test/java/org/apache/polygene/serialization/javaxxml/JavaxXmlValueCompositeTest.java
----------------------------------------------------------------------
diff --git a/extensions/serialization-javaxxml/src/test/java/org/apache/polygene/serialization/javaxxml/JavaxXmlValueCompositeTest.java b/extensions/serialization-javaxxml/src/test/java/org/apache/polygene/serialization/javaxxml/JavaxXmlValueCompositeTest.java
new file mode 100644
index 0000000..59d0e3e
--- /dev/null
+++ b/extensions/serialization-javaxxml/src/test/java/org/apache/polygene/serialization/javaxxml/JavaxXmlValueCompositeTest.java
@@ -0,0 +1,68 @@
+/*
+ * 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.injection.scope.Service;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.spi.serialization.XmlSerialization;
+import org.apache.polygene.test.serialization.AbstractValueCompositeSerializationTest;
+import org.junit.Test;
+import org.xmlunit.diff.DefaultNodeMatcher;
+import org.xmlunit.diff.ElementSelectors;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.junit.Assert.assertThat;
+import static org.xmlunit.matchers.CompareMatcher.isSimilarTo;
+
+public class JavaxXmlValueCompositeTest extends AbstractValueCompositeSerializationTest
+{
+ @Override
+ public void assemble( ModuleAssembly module )
+ {
+ new JavaxXmlSerializationAssembler().assemble( module );
+ super.assemble( module );
+ }
+
+ @Service
+ XmlSerialization xmlSerialization;
+
+ @Test
+ public void valueCompositeXmlEquality()
+ {
+ try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork() )
+ {
+ Some some = buildSomeValue( moduleInstance, uow, "23" );
+
+ // Serialize using injected service
+ String stateString = serialization.serialize( some );
+ System.out.println( stateString );
+
+ // Deserialize using Module API
+ Some some2 = moduleInstance.newValueFromSerializedState( Some.class, stateString );
+
+ assertThat( "Value equality", some, equalTo( some2 ) );
+
+ // Need to loosely compare because of HashMaps not retaining order
+ assertThat( "XML equality",
+ stateString,
+ isSimilarTo( some2.toString() )
+ .withNodeMatcher( new DefaultNodeMatcher( ElementSelectors.byNameAndAllAttributes ) ) );
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/extensions/serialization-msgpack/build.gradle
----------------------------------------------------------------------
diff --git a/extensions/serialization-msgpack/build.gradle b/extensions/serialization-msgpack/build.gradle
new file mode 100644
index 0000000..6f51948
--- /dev/null
+++ b/extensions/serialization-msgpack/build.gradle
@@ -0,0 +1,36 @@
+/*
+ * 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 MessagePack Serialization Extension"
+
+jar { manifest { name = "Apache Polygene\u2122 Extension - Serialization - MessagePack" } }
+
+dependencies {
+ api polygene.core.bootstrap
+ api libraries.msgpack
+
+ implementation libraries.commons_lang
+
+ runtimeOnly polygene.core.runtime
+
+ testImplementation polygene.core.testsupport
+
+ testRuntimeOnly libraries.logback
+}
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/extensions/serialization-msgpack/dev-status.xml
----------------------------------------------------------------------
diff --git a/extensions/serialization-msgpack/dev-status.xml b/extensions/serialization-msgpack/dev-status.xml
new file mode 100644
index 0000000..8086fb0
--- /dev/null
+++ b/extensions/serialization-msgpack/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>some</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/7c2814ee/extensions/serialization-msgpack/src/docs/serialization-msgpack.txt
----------------------------------------------------------------------
diff --git a/extensions/serialization-msgpack/src/docs/serialization-msgpack.txt b/extensions/serialization-msgpack/src/docs/serialization-msgpack.txt
new file mode 100644
index 0000000..ad50c08
--- /dev/null
+++ b/extensions/serialization-msgpack/src/docs/serialization-msgpack.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-msgpack,MessagePack serialization]]
+= MessagePack serialization =
+
+[devstatus]
+--------------
+source=extensions/serialization-msgpack/dev-status.xml
+--------------
+
+// TODO Document usage of MessagePackSerialization
+// 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/7c2814ee/extensions/serialization-msgpack/src/main/java/org/apache/polygene/serialization/msgpack/MessagePackAdapter.java
----------------------------------------------------------------------
diff --git a/extensions/serialization-msgpack/src/main/java/org/apache/polygene/serialization/msgpack/MessagePackAdapter.java b/extensions/serialization-msgpack/src/main/java/org/apache/polygene/serialization/msgpack/MessagePackAdapter.java
new file mode 100644
index 0000000..6d99e69
--- /dev/null
+++ b/extensions/serialization-msgpack/src/main/java/org/apache/polygene/serialization/msgpack/MessagePackAdapter.java
@@ -0,0 +1,57 @@
+/*
+ * 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.msgpack;
+
+import java.io.IOException;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import org.apache.polygene.api.type.ValueType;
+import org.msgpack.value.Value;
+
+/**
+ * Adapter for MessagePack (de)serialization.
+ *
+ * @param <T> the adapted type
+ */
+public interface MessagePackAdapter<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 MessagePack Value
+ */
+ Value serialize( Object object, Function<Object, Value> serializeFunction )
+ throws IOException;
+
+ /**
+ * Deserialize.
+ *
+ * @param value MessagePack value
+ * @param deserializeFunction Deserialization function for nested structure deserialization
+ * @return Deserialized object
+ */
+ T deserialize( Value value, BiFunction<Value, ValueType, Object> deserializeFunction )
+ throws IOException;
+}
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/extensions/serialization-msgpack/src/main/java/org/apache/polygene/serialization/msgpack/MessagePackAdapters.java
----------------------------------------------------------------------
diff --git a/extensions/serialization-msgpack/src/main/java/org/apache/polygene/serialization/msgpack/MessagePackAdapters.java b/extensions/serialization-msgpack/src/main/java/org/apache/polygene/serialization/msgpack/MessagePackAdapters.java
new file mode 100644
index 0000000..892b389
--- /dev/null
+++ b/extensions/serialization-msgpack/src/main/java/org/apache/polygene/serialization/msgpack/MessagePackAdapters.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.msgpack;
+
+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( MessagePackAdapters.Mixin.class )
+public interface MessagePackAdapters
+{
+ void registerAdapter( ValueType valueType, MessagePackAdapter<?> adapter );
+
+ <T> MessagePackAdapter<T> adapterFor( ValueType valueType );
+
+ default <T> MessagePackAdapter<T> adapterFor( Class<T> type )
+ {
+ return adapterFor( ValueType.of( type ) );
+ }
+
+ class Mixin implements MessagePackAdapters
+ {
+ private Map<ValueType, MessagePackAdapter<?>> adapters = new LinkedHashMap<>();
+
+ @Override
+ public void registerAdapter( ValueType valueType, MessagePackAdapter<?> adapter )
+ {
+ adapters.put( valueType, adapter );
+ }
+
+ @Override
+ public <T> MessagePackAdapter<T> adapterFor( final ValueType valueType )
+ {
+ return castAdapter( adapters.keySet().stream()
+ .collect( closestType( valueType ) )
+ .map( adapters::get )
+ .orElse( null ) );
+ }
+
+ @SuppressWarnings( "unchecked" )
+ private <T> MessagePackAdapter<T> castAdapter( MessagePackAdapter<?> adapter )
+ {
+ return (MessagePackAdapter<T>) adapter;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/extensions/serialization-msgpack/src/main/java/org/apache/polygene/serialization/msgpack/MessagePackDeserializer.java
----------------------------------------------------------------------
diff --git a/extensions/serialization-msgpack/src/main/java/org/apache/polygene/serialization/msgpack/MessagePackDeserializer.java b/extensions/serialization-msgpack/src/main/java/org/apache/polygene/serialization/msgpack/MessagePackDeserializer.java
new file mode 100644
index 0000000..84508a4
--- /dev/null
+++ b/extensions/serialization-msgpack/src/main/java/org/apache/polygene/serialization/msgpack/MessagePackDeserializer.java
@@ -0,0 +1,295 @@
+/*
+ * 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.msgpack;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.util.AbstractMap;
+import java.util.ArrayList;
+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.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.mixin.Mixins;
+import org.apache.polygene.api.property.PropertyDescriptor;
+import org.apache.polygene.api.serialization.Deserializer;
+import org.apache.polygene.api.serialization.SerializationException;
+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.AbstractBinaryDeserializer;
+import org.msgpack.core.MessagePack;
+import org.msgpack.core.MessageUnpacker;
+import org.msgpack.value.ArrayValue;
+import org.msgpack.value.BinaryValue;
+import org.msgpack.value.ImmutableValue;
+import org.msgpack.value.MapValue;
+import org.msgpack.value.Value;
+
+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.toMap;
+
+// TODO Test all deserializations for: missing & spurious entries
+@Mixins( MessagePackDeserializer.Mixin.class )
+public interface MessagePackDeserializer extends Deserializer
+{
+ class Mixin extends AbstractBinaryDeserializer
+ {
+ @This
+ private MessagePackAdapters adapters;
+
+ @Override
+ public <T> T deserialize( ModuleDescriptor module, ValueType valueType, InputStream state )
+ {
+ MessageUnpacker unpacker = MessagePack.newDefaultUnpacker( state );
+ try
+ {
+ if( !unpacker.hasNext() )
+ {
+ return null;
+ }
+ ImmutableValue value = unpacker.unpackValue();
+ return doDeserialize( module, valueType, value );
+ }
+ catch( IOException e )
+ {
+ throw new SerializationException( "Unable to deserialize " + valueType );
+ }
+ }
+
+ @SuppressWarnings( "unchecked" )
+ private <T> T doDeserialize( ModuleDescriptor module, ValueType valueType, Value value )
+ {
+ try
+ {
+ if( value.isNilValue() )
+ {
+ return null;
+ }
+ MessagePackAdapter<?> adapter = adapters.adapterFor( valueType );
+ if( adapter != null )
+ {
+ return (T) adapter.deserialize( value, ( val, type ) -> doDeserialize( module, valueType, val ) );
+ }
+ if( EnumType.class.isAssignableFrom( valueType.getClass() ) )
+ {
+ return (T) Enum.valueOf( (Class) valueType.primaryType(), value.asStringValue().asString() );
+ }
+ if( CollectionType.class.isAssignableFrom( valueType.getClass() ) )
+ {
+ return (T) deserializeCollection( module, (CollectionType) valueType, value.asArrayValue() );
+ }
+ if( MapType.class.isAssignableFrom( valueType.getClass() ) )
+ {
+ return (T) deserializeMap( module, (MapType) valueType, value.asMapValue() );
+ }
+ if( ValueCompositeType.class.isAssignableFrom( valueType.getClass() ) )
+ {
+ return (T) deserializeValueComposite( module, (ValueCompositeType) valueType, value.asMapValue() );
+ }
+ return (T) doGuessDeserialize( module, valueType, value );
+ }
+ catch( IOException | ClassNotFoundException ex )
+ {
+ throw new SerializationException( "Unable to deserialize " + valueType + " from: " + value );
+ }
+ }
+
+ private Collection<?> deserializeCollection( ModuleDescriptor module, CollectionType collectionType,
+ ArrayValue value ) throws IOException
+ {
+ Collection<?> collection = collectionType.isSet() ? new LinkedHashSet( value.size() )
+ : new ArrayList( value.size() );
+ for( Value element : value.list() )
+ {
+ collection.add( doDeserialize( module, collectionType.collectedType(), element ) );
+ }
+ return collection;
+ }
+
+ private Map<Object, Object> deserializeMap( ModuleDescriptor module, MapType mapType, MapValue value )
+ throws IOException
+ {
+ Map<Object, Object> map = new LinkedHashMap<>( value.size() );
+ for( Map.Entry<Value, Value> entry : value.entrySet() )
+ {
+ Object key = doDeserialize( module, mapType.keyType(), entry.getKey() );
+ Object val = doDeserialize( module, mapType.valueType(), entry.getValue() );
+ map.put( key, val );
+ }
+ return map;
+ }
+
+ private Object deserializeValueComposite( ModuleDescriptor module, ValueCompositeType valueType,
+ MapValue value ) throws IOException
+ {
+ Map<String, Value> namedValues = value.map().entrySet().stream().map(
+ entry ->
+ {
+ String key = doDeserialize( module, ValueType.STRING, entry.getKey() );
+ return new AbstractMap.SimpleImmutableEntry<>( key, entry.getValue() );
+ }
+ ).collect( toMap( HashMap::new ) );
+
+ String typeInfo = null;
+ if( namedValues.containsKey( "_type" ) )
+ {
+ typeInfo = doDeserialize( module, ValueType.STRING, namedValues.get( "_type" ) );
+ }
+ if( typeInfo != null )
+ {
+ ValueDescriptor descriptor = module.valueDescriptor( typeInfo );
+ if( descriptor == null )
+ {
+ throw new SerializationException(
+ "_type: " + typeInfo + " could not be resolved while deserializing " + value );
+ }
+ valueType = descriptor.valueType();
+ }
+
+ ValueBuilder builder = module.instance().newValueBuilderWithState(
+ valueType.primaryType(),
+ propertyFunction( module, namedValues ),
+ associationFunction( module, namedValues ),
+ manyAssociationFunction( module, namedValues ),
+ namedAssociationFunction( module, namedValues ) );
+ return builder.newInstance();
+ }
+
+ private Function<PropertyDescriptor, Object> propertyFunction( ModuleDescriptor module,
+ Map<String, Value> namedValues )
+ {
+ return property ->
+ {
+ Value value = namedValues.get( property.qualifiedName().name() );
+ if( value != null )
+ {
+ Object propertyValue = doDeserialize( module, property.valueType(), value );
+ if( property.isImmutable() )
+ {
+ if( propertyValue instanceof Set )
+ {
+ return unmodifiableSet( (Set<?>) propertyValue );
+ }
+ else if( propertyValue instanceof List )
+ {
+ return unmodifiableList( (List<?>) propertyValue );
+ }
+ else if( propertyValue instanceof Map )
+ {
+ return unmodifiableMap( (Map<?, ?>) propertyValue );
+ }
+ }
+ return propertyValue;
+ }
+ return property.resolveInitialValue( module );
+ };
+ }
+
+ private Function<AssociationDescriptor, EntityReference> associationFunction( ModuleDescriptor module,
+ Map<String, Value> namedValues )
+ {
+ return association -> doDeserialize( module, ValueType.ENTITY_REFERENCE,
+ namedValues.get( association.qualifiedName().name() ) );
+ }
+
+ private Function<AssociationDescriptor, Stream<EntityReference>> manyAssociationFunction(
+ ModuleDescriptor module, Map<String, Value> namedValues )
+ {
+ return association ->
+ {
+ List list = doDeserialize( module, ENTITY_REF_LIST_VALUE_TYPE,
+ namedValues.get( association.qualifiedName().name() ) );
+ return list == null ? Stream.empty() : list.stream();
+ };
+ }
+
+ private Function<AssociationDescriptor, Stream<Map.Entry<String, EntityReference>>> namedAssociationFunction(
+ ModuleDescriptor module, Map<String, Value> namedValues )
+ {
+ return association ->
+ {
+ Map map = doDeserialize( module, ENTITY_REF_MAP_VALUE_TYPE,
+ namedValues.get( association.qualifiedName().name() ) );
+ return map == null ? Stream.empty() : map.entrySet().stream();
+ };
+ }
+
+ private Object doGuessDeserialize( ModuleDescriptor module, ValueType valueType, Value value )
+ throws IOException, ClassNotFoundException
+ {
+ switch( value.getValueType() )
+ {
+ case BINARY:
+ return deserializeJava( value.asBinaryValue() );
+ case MAP:
+ MapValue mapValue = value.asMapValue();
+ Optional<String> typeInfo = mapValue
+ .entrySet().stream()
+ .filter( entry -> entry.getKey().isStringValue() )
+ .map( entry ->
+ {
+ String key = doDeserialize( module, ValueType.STRING, entry.getKey() );
+ return new AbstractMap.SimpleImmutableEntry<>( key, entry.getValue() );
+ } )
+ .filter( entry -> "_type".equals( entry.getKey() ) )
+ .findFirst()
+ .map( entry -> doDeserialize( module, ValueType.STRING, entry.getValue() ) );
+ if( typeInfo.isPresent() )
+ {
+ ValueDescriptor valueDescriptor = module.valueDescriptor( typeInfo.get() );
+ if( valueDescriptor != null )
+ {
+ return deserializeValueComposite( module, valueDescriptor.valueType(), mapValue );
+ }
+ }
+ default:
+ throw new SerializationException( "Don't know how to deserialize " + valueType + " from " + value
+ + " (" + value.getValueType() + ")" );
+ }
+ }
+
+ private Object deserializeJava( BinaryValue value )
+ throws IOException, ClassNotFoundException
+ {
+ byte[] bytes = value.asByteArray();
+ try( ObjectInputStream oin = new ObjectInputStream( new ByteArrayInputStream( bytes ) ) )
+ {
+ return oin.readObject();
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/extensions/serialization-msgpack/src/main/java/org/apache/polygene/serialization/msgpack/MessagePackSerialization.java
----------------------------------------------------------------------
diff --git a/extensions/serialization-msgpack/src/main/java/org/apache/polygene/serialization/msgpack/MessagePackSerialization.java b/extensions/serialization-msgpack/src/main/java/org/apache/polygene/serialization/msgpack/MessagePackSerialization.java
new file mode 100644
index 0000000..d24d597
--- /dev/null
+++ b/extensions/serialization-msgpack/src/main/java/org/apache/polygene/serialization/msgpack/MessagePackSerialization.java
@@ -0,0 +1,22 @@
+/*
+ * 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.msgpack;
+
+public interface MessagePackSerialization extends MessagePackSerializer, MessagePackDeserializer
+{
+}
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/extensions/serialization-msgpack/src/main/java/org/apache/polygene/serialization/msgpack/MessagePackSerializationAssembler.java
----------------------------------------------------------------------
diff --git a/extensions/serialization-msgpack/src/main/java/org/apache/polygene/serialization/msgpack/MessagePackSerializationAssembler.java b/extensions/serialization-msgpack/src/main/java/org/apache/polygene/serialization/msgpack/MessagePackSerializationAssembler.java
new file mode 100644
index 0000000..63536cc
--- /dev/null
+++ b/extensions/serialization-msgpack/src/main/java/org/apache/polygene/serialization/msgpack/MessagePackSerializationAssembler.java
@@ -0,0 +1,52 @@
+/*
+ * 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.msgpack;
+
+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;
+
+public class MessagePackSerializationAssembler extends Assemblers.VisibilityIdentity<MessagePackSerializationAssembler>
+{
+ private MessagePackSettings settings;
+
+ public MessagePackSerializationAssembler withMessagePackSettings( MessagePackSettings settings )
+ {
+ this.settings = settings;
+ return this;
+ }
+
+ @Override
+ public void assemble( ModuleAssembly module )
+ {
+ ServiceDeclaration declaration = module.services( MessagePackSerializationService.class )
+ .withTypes( Serialization.class, Serializer.class, Deserializer.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/7c2814ee/extensions/serialization-msgpack/src/main/java/org/apache/polygene/serialization/msgpack/MessagePackSerializationService.java
----------------------------------------------------------------------
diff --git a/extensions/serialization-msgpack/src/main/java/org/apache/polygene/serialization/msgpack/MessagePackSerializationService.java b/extensions/serialization-msgpack/src/main/java/org/apache/polygene/serialization/msgpack/MessagePackSerializationService.java
new file mode 100644
index 0000000..4cd23b7
--- /dev/null
+++ b/extensions/serialization-msgpack/src/main/java/org/apache/polygene/serialization/msgpack/MessagePackSerializationService.java
@@ -0,0 +1,414 @@
+/*
+ * 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.msgpack;
+
+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.msgpack.value.Value;
+import org.msgpack.value.ValueFactory;
+
+@Mixins( MessagePackSerializationService.Activation.class )
+public interface MessagePackSerializationService extends MessagePackSerialization, ServiceActivation
+{
+ class Activation implements ServiceActivation
+ {
+ @Uses
+ private ServiceDescriptor descriptor;
+
+ @This
+ private MessagePackAdapters adapters;
+
+ private boolean registrationDone = false;
+
+ @Override
+ public void activateService()
+ {
+ if( !registrationDone )
+ {
+ registerCustomAdapters();
+ registerBaseAdapters();
+ registrationDone = true;
+ }
+ }
+
+ @Override
+ public void passivateService() {}
+
+ private void registerCustomAdapters()
+ {
+ MessagePackSettings.orDefault( descriptor.metaInfo( MessagePackSettings.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 ToStringAdapter<T> implements MessagePackAdapter<T>
+ {
+ @Override
+ public Value serialize( Object object, Function<Object, Value> serializeFunction )
+ {
+ return ValueFactory.newString( object.toString() );
+ }
+ }
+
+ private static class StringAdapter extends ToStringAdapter<String>
+ {
+ @Override
+ public Class<String> type() { return String.class; }
+
+ @Override
+ public String deserialize( Value value, BiFunction<Value, ValueType, Object> deserializeFunction )
+ {
+ return value.asStringValue().asString();
+ }
+ }
+
+ private static class CharacterAdapter extends ToStringAdapter<Character>
+ {
+ @Override
+ public Class<Character> type() { return Character.class; }
+
+ @Override
+ public Character deserialize( Value value, BiFunction<Value, ValueType, Object> deserializeFunction )
+ {
+ String string = value.asStringValue().asString();
+ return string.isEmpty() ? null : string.charAt( 0 );
+ }
+ }
+
+ private static class BooleanAdapter implements MessagePackAdapter<Boolean>
+ {
+ @Override
+ public Class<Boolean> type() { return Boolean.class; }
+
+ @Override
+ public Value serialize( Object object, Function<Object, Value> serializeFunction )
+ {
+ return ValueFactory.newBoolean( (Boolean) object );
+ }
+
+ @Override
+ public Boolean deserialize( Value value, BiFunction<Value, ValueType, Object> deserializeFunction )
+ {
+ return value.asBooleanValue().getBoolean();
+ }
+ }
+
+ private static class IntegerAdapter implements MessagePackAdapter<Integer>
+ {
+ @Override
+ public Class<Integer> type() { return Integer.class; }
+
+ @Override
+ public Value serialize( Object object, Function<Object, Value> serializeFunction )
+ {
+ return ValueFactory.newInteger( (Integer) object );
+ }
+
+ @Override
+ public Integer deserialize( Value value, BiFunction<Value, ValueType, Object> deserializeFunction )
+ {
+ return value.asIntegerValue().asInt();
+ }
+ }
+
+ private static class LongAdapter implements MessagePackAdapter<Long>
+ {
+ @Override
+ public Class<Long> type() { return Long.class; }
+
+ @Override
+ public Value serialize( Object object, Function<Object, Value> serializeFunction )
+ {
+ return ValueFactory.newInteger( (Long) object );
+ }
+
+ @Override
+ public Long deserialize( Value value, BiFunction<Value, ValueType, Object> deserializeFunction )
+ {
+ return value.asIntegerValue().asLong();
+ }
+ }
+
+ private static class ShortAdapter implements MessagePackAdapter<Short>
+ {
+ @Override
+ public Class<Short> type() { return Short.class; }
+
+ @Override
+ public Value serialize( Object object, Function<Object, Value> serializeFunction )
+ {
+ return ValueFactory.newInteger( (Short) object );
+ }
+
+ @Override
+ public Short deserialize( Value value, BiFunction<Value, ValueType, Object> deserializeFunction )
+ {
+ return value.asIntegerValue().asShort();
+ }
+ }
+
+ private static class ByteAdapter implements MessagePackAdapter<Byte>
+ {
+ @Override
+ public Class<Byte> type() { return Byte.class; }
+
+ @Override
+ public Value serialize( Object object, Function<Object, Value> serializeFunction )
+ {
+ return ValueFactory.newInteger( (Byte) object );
+ }
+
+ @Override
+ public Byte deserialize( Value value, BiFunction<Value, ValueType, Object> deserializeFunction )
+ {
+ return value.asIntegerValue().asByte();
+ }
+ }
+
+ private static class FloatAdapter implements MessagePackAdapter<Float>
+ {
+ @Override
+ public Class<Float> type() { return Float.class; }
+
+ @Override
+ public Value serialize( Object object, Function<Object, Value> serializeFunction )
+ {
+ return ValueFactory.newFloat( (Float) object );
+ }
+
+ @Override
+ public Float deserialize( Value value, BiFunction<Value, ValueType, Object> deserializeFunction )
+ {
+ return value.asFloatValue().toFloat();
+ }
+ }
+
+ private static class DoubleAdapter implements MessagePackAdapter<Double>
+ {
+ @Override
+ public Class<Double> type() { return Double.class; }
+
+ @Override
+ public Value serialize( Object object, Function<Object, Value> serializeFunction )
+ {
+ return ValueFactory.newFloat( (Double) object );
+ }
+
+ @Override
+ public Double deserialize( Value value, BiFunction<Value, ValueType, Object> deserializeFunction )
+ {
+ return value.asFloatValue().toDouble();
+ }
+ }
+
+ private static class BigDecimalAdapter extends ToStringAdapter<BigDecimal>
+ {
+ @Override
+ public Class<BigDecimal> type() { return BigDecimal.class; }
+
+ @Override
+ public BigDecimal deserialize( Value value, BiFunction<Value, ValueType, Object> deserializeFunction )
+ {
+ return new BigDecimal( value.asStringValue().asString() );
+ }
+ }
+
+ private static class BigIntegerAdapter extends ToStringAdapter<BigInteger>
+ {
+ @Override
+ public Class<BigInteger> type() { return BigInteger.class; }
+
+ @Override
+ public BigInteger deserialize( Value value, BiFunction<Value, ValueType, Object> deserializeFunction )
+ {
+ return new BigInteger( value.asStringValue().asString() );
+ }
+ }
+
+ private static class InstantAdapter extends ToStringAdapter<Instant>
+ {
+ @Override
+ public Class<Instant> type() { return Instant.class; }
+
+ @Override
+ public Instant deserialize( Value value, BiFunction<Value, ValueType, Object> deserializeFunction )
+ {
+ return Instant.parse( value.asStringValue().asString() );
+ }
+ }
+
+ private static class ZonedDateTimeAdapter extends ToStringAdapter<ZonedDateTime>
+ {
+ @Override
+ public Class<ZonedDateTime> type() { return ZonedDateTime.class; }
+
+ @Override
+ public ZonedDateTime deserialize( Value value, BiFunction<Value, ValueType, Object> deserializeFunction )
+ {
+ return ZonedDateTime.parse( value.asStringValue().asString() );
+ }
+ }
+
+ private static class OffsetDateTimeAdapter extends ToStringAdapter<OffsetDateTime>
+ {
+ @Override
+ public Class<OffsetDateTime> type() { return OffsetDateTime.class; }
+
+ @Override
+ public OffsetDateTime deserialize( Value value, BiFunction<Value, ValueType, Object> deserializeFunction )
+ {
+ return OffsetDateTime.parse( value.asStringValue().asString() );
+ }
+ }
+
+ private static class LocalDateTimeAdapter extends ToStringAdapter<LocalDateTime>
+ {
+ @Override
+ public Class<LocalDateTime> type() { return LocalDateTime.class; }
+
+ @Override
+ public LocalDateTime deserialize( Value value, BiFunction<Value, ValueType, Object> deserializeFunction )
+ {
+ return LocalDateTime.parse( value.asStringValue().asString() );
+ }
+ }
+
+ private static class LocalDateAdapter extends ToStringAdapter<LocalDate>
+ {
+ @Override
+ public Class<LocalDate> type() { return LocalDate.class; }
+
+ @Override
+ public LocalDate deserialize( Value value, BiFunction<Value, ValueType, Object> deserializeFunction )
+ {
+ return LocalDate.parse( value.asStringValue().asString() );
+ }
+ }
+
+ private static class LocalTimeAdapter extends ToStringAdapter<LocalTime>
+ {
+ @Override
+ public Class<LocalTime> type() { return LocalTime.class; }
+
+ @Override
+ public LocalTime deserialize( Value value, BiFunction<Value, ValueType, Object> deserializeFunction )
+ {
+ return LocalTime.parse( value.asStringValue().asString() );
+ }
+ }
+
+ private static class DurationAdapter extends ToStringAdapter<Duration>
+ {
+ @Override
+ public Class<Duration> type() { return Duration.class; }
+
+ @Override
+ public Duration deserialize( Value value, BiFunction<Value, ValueType, Object> deserializeFunction )
+ {
+ return Duration.parse( value.asStringValue().asString() );
+ }
+ }
+
+ private static class PeriodAdapter extends ToStringAdapter<Period>
+ {
+ @Override
+ public Class<Period> type() { return Period.class; }
+
+ @Override
+ public Period deserialize( Value value, BiFunction<Value, ValueType, Object> deserializeFunction )
+ {
+ return Period.parse( value.asStringValue().asString() );
+ }
+ }
+
+ private static class IdentityAdapter extends ToStringAdapter<Identity>
+ {
+ @Override
+ public Class<Identity> type() { return Identity.class; }
+
+ @Override
+ public Identity deserialize( Value value, BiFunction<Value, ValueType, Object> deserializeFunction )
+ {
+ return StringIdentity.fromString( value.asStringValue().asString() );
+ }
+ }
+
+ private static class EntityReferenceAdapter extends ToStringAdapter<EntityReference>
+ {
+ @Override
+ public Class<EntityReference> type() { return EntityReference.class; }
+
+ @Override
+ public EntityReference deserialize( Value value, BiFunction<Value, ValueType, Object> deserializeFunction )
+ {
+ return EntityReference.parseEntityReference( value.asStringValue().asString() );
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/extensions/serialization-msgpack/src/main/java/org/apache/polygene/serialization/msgpack/MessagePackSerializer.java
----------------------------------------------------------------------
diff --git a/extensions/serialization-msgpack/src/main/java/org/apache/polygene/serialization/msgpack/MessagePackSerializer.java b/extensions/serialization-msgpack/src/main/java/org/apache/polygene/serialization/msgpack/MessagePackSerializer.java
new file mode 100644
index 0000000..7321e6d
--- /dev/null
+++ b/extensions/serialization-msgpack/src/main/java/org/apache/polygene/serialization/msgpack/MessagePackSerializer.java
@@ -0,0 +1,187 @@
+/*
+ * 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.msgpack;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectOutputStream;
+import java.io.OutputStream;
+import java.util.Map;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+import org.apache.polygene.api.PolygeneAPI;
+import org.apache.polygene.api.association.AssociationStateHolder;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.composite.CompositeInstance;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.serialization.SerializationException;
+import org.apache.polygene.api.serialization.Serializer;
+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.value.ValueComposite;
+import org.apache.polygene.api.value.ValueDescriptor;
+import org.apache.polygene.spi.serialization.AbstractBinarySerializer;
+import org.msgpack.core.MessagePack;
+import org.msgpack.core.MessagePacker;
+import org.msgpack.value.ArrayValue;
+import org.msgpack.value.BinaryValue;
+import org.msgpack.value.MapValue;
+import org.msgpack.value.Value;
+import org.msgpack.value.ValueFactory;
+
+import static java.util.stream.Collectors.toList;
+import static org.apache.polygene.api.util.Collectors.toMap;
+
+@Mixins( MessagePackSerializer.Mixin.class )
+public interface MessagePackSerializer extends Serializer
+{
+ class Mixin extends AbstractBinarySerializer
+ {
+ @This
+ private MessagePackAdapters adapters;
+
+ @Override
+ public void serialize( Options options, OutputStream output, @Optional Object object )
+ {
+ MessagePacker packer = MessagePack.newDefaultPacker( output );
+ Value value = doSerialize( options, object, true );
+ try
+ {
+ packer.packValue( value );
+ packer.flush();
+ }
+ catch( IOException ex )
+ {
+ throw new SerializationException( "Unable to serialize " + object, ex );
+ }
+ }
+
+ private Value doSerialize( Options options, Object object, boolean root )
+ {
+ try
+ {
+ if( object == null )
+ {
+ return ValueFactory.newNil();
+ }
+ Class<?> objectClass = object.getClass();
+ MessagePackAdapter<?> adapter = adapters.adapterFor( objectClass );
+ if( adapter != null )
+ {
+ return adapter.serialize( object, obj -> doSerialize( options, obj, false ) );
+ }
+ if( EnumType.isEnum( objectClass ) )
+ {
+ return ValueFactory.newString( object.toString() );
+ }
+ if( ValueCompositeType.isValueComposite( objectClass ) )
+ {
+ return serializeValueComposite( options, object, root );
+ }
+ if( MapType.isMap( objectClass ) )
+ {
+ return serializeMap( options, (Map<?, ?>) object );
+ }
+ if( Iterable.class.isAssignableFrom( objectClass ) )
+ {
+ return serializeIterable( options, (Iterable<?>) object );
+ }
+ if( Stream.class.isAssignableFrom( objectClass ) )
+ {
+ return serializeStream( options, (Stream<?>) object );
+ }
+ // Fallback to Java Serialization
+ // Include all arrays!
+ return serializeJava( object );
+ }
+ catch( IOException ex )
+ {
+ throw new SerializationException( "Unable to serialize " + object, ex );
+ }
+ }
+
+ private MapValue serializeValueComposite( Options options, Object composite, boolean root )
+ {
+ CompositeInstance instance = PolygeneAPI.FUNCTION_COMPOSITE_INSTANCE_OF.apply( (ValueComposite) composite );
+ ValueDescriptor descriptor = (ValueDescriptor) instance.descriptor();
+ AssociationStateHolder state = (AssociationStateHolder) instance.state();
+ ValueCompositeType valueType = descriptor.valueType();
+
+ ValueFactory.MapBuilder builder = ValueFactory.newMapBuilder();
+ valueType.properties().forEach(
+ property -> builder.put(
+ ValueFactory.newString( property.qualifiedName().name() ),
+ doSerialize( options, state.propertyFor( property.accessor() ).get(), false ) ) );
+ valueType.associations().forEach(
+ association -> builder.put(
+ ValueFactory.newString( association.qualifiedName().name() ),
+ doSerialize( options, state.associationFor( association.accessor() ).reference(), false ) ) );
+ valueType.manyAssociations().forEach(
+ association -> builder.put(
+ ValueFactory.newString( association.qualifiedName().name() ),
+ doSerialize( options,
+ state.manyAssociationFor( association.accessor() ).references().collect( toList() ),
+ false ) ) );
+ valueType.namedAssociations().forEach(
+ association -> builder.put(
+ ValueFactory.newString( association.qualifiedName().name() ),
+ doSerialize( options,
+ state.namedAssociationFor( association.accessor() ).references().collect( toMap() ),
+ false ) ) );
+
+ if( !root && options.includeTypeInfo() )
+ {
+ builder.put( ValueFactory.newString( "_type" ),
+ ValueFactory.newString( valueType.primaryType().getName() ) );
+ }
+ return builder.build();
+ }
+
+ private MapValue serializeMap( Options options, Map<?, ?> map )
+ {
+ ValueFactory.MapBuilder builder = ValueFactory.newMapBuilder();
+ map.forEach( ( key, value ) -> builder.put( doSerialize( options, key, false ),
+ doSerialize( options, value, false ) ) );
+ return builder.build();
+ }
+
+ private ArrayValue serializeIterable( Options options, Iterable<?> iterable )
+ {
+ return serializeStream( options, StreamSupport.stream( iterable.spliterator(), false ) );
+ }
+
+ private ArrayValue serializeStream( Options options, Stream<?> stream )
+ {
+ return ValueFactory.newArray( stream.map( element -> doSerialize( options, element, false ) )
+ .collect( toList() ) );
+ }
+
+ private BinaryValue serializeJava( Object object ) throws IOException
+ {
+ ByteArrayOutputStream bout = new ByteArrayOutputStream();
+ try( ObjectOutputStream out = new ObjectOutputStream( bout ) )
+ {
+ out.writeUnshared( object );
+ byte[] bytes = bout.toByteArray();
+ return ValueFactory.newBinary( bytes );
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/extensions/serialization-msgpack/src/main/java/org/apache/polygene/serialization/msgpack/MessagePackSettings.java
----------------------------------------------------------------------
diff --git a/extensions/serialization-msgpack/src/main/java/org/apache/polygene/serialization/msgpack/MessagePackSettings.java b/extensions/serialization-msgpack/src/main/java/org/apache/polygene/serialization/msgpack/MessagePackSettings.java
new file mode 100644
index 0000000..8080d94
--- /dev/null
+++ b/extensions/serialization-msgpack/src/main/java/org/apache/polygene/serialization/msgpack/MessagePackSettings.java
@@ -0,0 +1,44 @@
+/*
+ * 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.msgpack;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import org.apache.polygene.api.type.ValueType;
+
+public class MessagePackSettings
+{
+ public static final MessagePackSettings DEFAULT = new MessagePackSettings();
+
+ public static MessagePackSettings orDefault( MessagePackSettings settings )
+ {
+ return settings != null ? settings : DEFAULT;
+ }
+
+ private Map<ValueType, MessagePackAdapter<?>> adapters;
+
+ public MessagePackSettings()
+ {
+ adapters = new LinkedHashMap<>();
+ }
+
+ public Map<ValueType, MessagePackAdapter<?>> getAdapters()
+ {
+ return adapters;
+ }
+}