polygene-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From paulmer...@apache.org
Subject [05/19] polygene-java git commit: Serialization 3 step 1
Date Fri, 03 Feb 2017 07:58:06 GMT
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/e4cca11e/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..d5a0e5b
--- /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.initialValue( 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/e4cca11e/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 &lt;state/&gt;}. This serialization implementation
+ * also impose that the root element can only contain a single node, of any type.
+ *
+ * {@literal null} is represented as {@literal &lt;null/&gt;}.
+ * Plain values are represented as {@link org.w3c.dom.Text} nodes.
+ * Iterables and Streams are represented as {@literal &lt;collection/&gt;} {@link org.w3c.dom.Element}s.
+ * Maps are represented as {@literal &lt;dictionary/&gt;} {@link org.w3c.dom.Element}s.
+ *
+ * This is how a {@literal null} plain value is represented: {@literal &lt;state&gt;&lt;null/&gt;&lt;/state&gt;}.
+ * And a plain {@literal LocalDate}: {@literal &lt;state&gt;2017-01-01&lt;/state&gt;}
+ *
+ * This is how a fictional value including a collection and a map is represented:
+ * <code>
+ *     &lt;state&gt;
+ *         &lt;stringProperty&gt;and it's value&lt;/stringProperty&gt;
+ *         &lt;bigDecimalProperty&gt;4.22376931348623157E+310&lt;/bigDecimalProperty&gt;
+ *         &lt;nullProperty&gt;&lt;null/&gt;&lt;/nullProperty&gt;
+ *         &lt;booleanProperty&gt;false&lt;/booleanProperty&gt;
+ *         &lt;stringCollectionProperty&gt;
+ *             &lt;collection&gt;
+ *                  item1
+ *                  item2 &lt;!-- As multiple text nodes --&gt;
+ *             &lt;/collection&gt;
+ *         &lt;/stringCollectionProperty&gt;
+ *         &lt;mapProperty&gt;
+ *             &lt;map&gt;
+ *                 &lt;foo&gt;bar&lt;/foo&gt;
+ *                 &lt;bazar&gt;cathedral&lt;/bazar&gt;
+ *             &lt;/map&gt;
+ *         &lt;/mapProperty&gt;
+ *         &lt;complexKeyMapProperty&gt;
+ *             &lt;map&gt;
+ *                 &lt;entry&gt;
+ *                     &lt;key&gt;
+ *                         &lt;foo&gt;bar&lt;/foo&gt;
+ *                         &lt;bazar&gt;cathedral&lt;/bazar&gt;
+ *                     &lt;/key&gt;
+ *                     &lt;value&gt;23&lt;/value&gt;
+ *                 &lt;/entry&gt;
+ *                 &lt;entry&gt;
+ *                     &lt;key&gt;
+ *                         &lt;foo&gt;baz&lt;/foo&gt;
+ *                         &lt;bazar&gt;bar&lt;/bazar&gt;
+ *                     &lt;/key&gt;
+ *                     &lt;value&gt;42&lt;/value&gt;
+ *                 &lt;/entry&gt;
+ *             &lt;/map&gt;
+ *         &lt;/complexKeyMapProperty&gt;
+ *     &lt;/state&gt;
+ * </code>
+ *
+ */
+@Mixins( { JavaxXmlSerializer.class, JavaxXmlDeserializer.class } )
+public interface JavaxXmlSerialization extends XmlSerialization
+{
+}

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/e4cca11e/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/e4cca11e/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() );
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/e4cca11e/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..8790aa5
--- /dev/null
+++ b/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlSerializer.java
@@ -0,0 +1,269 @@
+/*
+ *  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();
+            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/e4cca11e/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/e4cca11e/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/e4cca11e/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>€ôÙÔ#‰¥Ô";
+        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/e4cca11e/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/e4cca11e/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/e4cca11e/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/e4cca11e/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/e4cca11e/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..c35690b
--- /dev/null
+++ b/extensions/serialization-msgpack/build.gradle
@@ -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.
+ */
+
+apply plugin: 'polygene-extension'
+
+description = "Apache Polygene™ MessagePack Serialization Extension"
+
+jar { manifest { name = "Apache Polygene™ Extension - Serialization - MessagePack" } }
+
+dependencies {
+  compile polygene.core.bootstrap
+  compile libraries.msgpack
+
+  runtime polygene.core.runtime
+
+  testCompile polygene.core.testsupport
+
+  testRuntime libraries.logback
+}
+

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/e4cca11e/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/e4cca11e/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/e4cca11e/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/e4cca11e/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;
+        }
+    }
+}


Mime
View raw message