blob: 716be65f55a20bceeb9952a98059ca5b06abb83c [file] [log] [blame]
/*
* 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 java.util.function.BiFunction;
import java.util.function.Function;
import org.apache.polygene.api.injection.scope.This;
import org.apache.polygene.api.injection.scope.Uses;
import org.apache.polygene.api.mixin.Initializable;
import org.apache.polygene.api.mixin.Mixins;
import org.apache.polygene.api.serialization.Converters;
import org.apache.polygene.api.service.ServiceDescriptor;
import org.apache.polygene.api.type.ValueType;
import org.apache.polygene.spi.serialization.BuiltInConverters;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import static org.apache.polygene.api.type.HasTypesCollectors.closestType;
import static org.apache.polygene.serialization.javaxxml.JavaxXmlSettings.orDefault;
@Mixins( JavaxXmlAdapters.Mixin.class )
public interface JavaxXmlAdapters
{
void registerAdapter( ValueType valueType, JavaxXmlAdapter<?> adapter );
<T> JavaxXmlAdapter<T> adapterFor( ValueType valueType );
default <T> JavaxXmlAdapter<T> adapterFor( Class<T> type )
{
return adapterFor( ValueType.of( type ) );
}
class Mixin implements JavaxXmlAdapters, Initializable
{
private Map<ValueType, JavaxXmlAdapter<?>> adapters = new LinkedHashMap<>();
@Uses
private ServiceDescriptor descriptor;
@This
private BuiltInConverters builtInConverters;
@This
private Converters converters;
@Override
public void initialize() throws Exception
{
JavaxXmlSettings settings = orDefault( descriptor.metaInfo( JavaxXmlSettings.class ) );
settings.getConverters()
.forEach( ( type, converter ) -> converters.registerConverter( type, converter ) );
builtInConverters.registerBuiltInConverters( converters );
settings.getAdapters().forEach( adapters::put );
registerBaseJavaxXmlAdapters();
}
@Override
public void registerAdapter( final ValueType valueType, final JavaxXmlAdapter<?> adapter )
{
adapters.put( valueType, adapter );
}
@Override
public <T> JavaxXmlAdapter<T> adapterFor( final ValueType valueType )
{
return castAdapter( adapters.keySet().stream()
.collect( closestType( valueType ) )
.map( adapters::get )
.orElse( null ) );
}
@SuppressWarnings( "unchecked" )
private <T> JavaxXmlAdapter<T> castAdapter( JavaxXmlAdapter<?> adapter )
{
return (JavaxXmlAdapter<T>) adapter;
}
private void registerBaseJavaxXmlAdapters()
{
// Primitive Value types
adapters.put( ValueType.STRING, new StringAdapter() );
adapters.put( ValueType.CHARACTER, new CharacterAdapter() );
adapters.put( ValueType.BOOLEAN, new BooleanAdapter() );
adapters.put( ValueType.INTEGER, new IntegerAdapter() );
adapters.put( ValueType.LONG, new LongAdapter() );
adapters.put( ValueType.SHORT, new ShortAdapter() );
adapters.put( ValueType.BYTE, new ByteAdapter() );
adapters.put( ValueType.FLOAT, new FloatAdapter() );
adapters.put( ValueType.DOUBLE, new DoubleAdapter() );
}
private static abstract class ToStringTextNodeAdapter<T> implements JavaxXmlAdapter<T>
{
@Override
public Node serialize( Document document, Object object, Function<Object, Node> serialize )
{
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> deserialize )
{
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> deserialize )
{
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> deserialize )
{
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> deserialize )
{
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> deserialize )
{
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> deserialize )
{
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> deserialize )
{
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> deserialize )
{
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> deserialize )
{
return Double.valueOf( node.getNodeValue() );
}
}
}
}