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:43 UTC
[20/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/core/spi/src/main/java/org/apache/polygene/spi/type/ValueTypeFactory.java
----------------------------------------------------------------------
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/type/ValueTypeFactory.java b/core/spi/src/main/java/org/apache/polygene/spi/type/ValueTypeFactory.java
new file mode 100644
index 0000000..73f79eb
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/type/ValueTypeFactory.java
@@ -0,0 +1,11 @@
+package org.apache.polygene.spi.type;
+
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.type.ValueType;
+
+public interface ValueTypeFactory
+{
+ ValueType valueTypeOf( ModuleDescriptor module, Object object );
+
+ ValueType valueTypeOf( ModuleDescriptor module, Class<?> type );
+}
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/core/spi/src/main/java/org/apache/polygene/spi/value/ValueDeserializerAdapter.java
----------------------------------------------------------------------
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/value/ValueDeserializerAdapter.java b/core/spi/src/main/java/org/apache/polygene/spi/value/ValueDeserializerAdapter.java
deleted file mode 100644
index c586498..0000000
--- a/core/spi/src/main/java/org/apache/polygene/spi/value/ValueDeserializerAdapter.java
+++ /dev/null
@@ -1,1001 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- *
- */
-package org.apache.polygene.spi.value;
-
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
-import java.io.ObjectInputStream;
-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.ArrayList;
-import java.util.Base64;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Scanner;
-import java.util.Set;
-import java.util.function.Function;
-import java.util.stream.Stream;
-import java.util.stream.StreamSupport;
-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.property.Property;
-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.Serialization;
-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.api.value.ValueDeserializer;
-import org.apache.polygene.api.value.ValueSerializationException;
-
-/**
- * Adapter for pull-parsing and tree-parsing capable ValueDeserializers.
- *
- * <p>
- * Among Plain values (see {@link ValueDeserializer}) some are considered primitives to underlying serialization
- * mechanisms and by so handed/come without conversion to/from implementations. Primitive values can be one of:
- * </p>
- * <ul>
- * <li>String,</li>
- * <li>Character or char,</li>
- * <li>Boolean or boolean,</li>
- * <li>Integer or int,</li>
- * <li>Long or long,</li>
- * <li>Short or short,</li>
- * <li>Byte or byte,</li>
- * <li>Float or float,</li>
- * <li>Double or double.</li>
- * </ul>
- * <p>
- * Some other Plain values are expected in given formats:
- * </p>
- * <ul>
- * <li>BigInteger and BigDecimal depends on {@link org.apache.polygene.api.value.ValueSerializer.Options};</li>
- * <li>Date as String in ISO-8601, {@literal @millis@} or {@literal /Date(..)} Microsoft format;</li>
- * <li>DateTime (JodaTime) as a ISO-8601 String with optional timezone offset;</li>
- * <li>LocalDateTime (JodaTime) as whatever {@link LocalDateTime#parse} accept as {@literal instant};</li>
- * <li>LocalDate (JodaTime) as whatever {@link LocalDate#parse} accept as {@literal instant};</li>
- * </ul>
- *
- * @param <InputType> Implementor pull-parser type
- * @param <InputNodeType> Implementor tree-parser node type
- */
-public abstract class ValueDeserializerAdapter<InputType, InputNodeType>
- implements ValueDeserializer
-{
- public interface ComplexDeserializer<T, InputType, InputNodeType>
- {
- T deserializePull( InputType input )
- throws Exception;
-
- T deserializeTree( InputNodeType inputNode )
- throws Exception;
- }
-
- private static final String UTF_8 = "UTF-8";
- private final Map<Class<?>, Function<Object, Object>> deserializers = new HashMap<>( 16 );
- private final Map<Class<?>, ComplexDeserializer<Object, InputType, InputNodeType>> complexDeserializers = new HashMap<>( 2 );
-
- /**
- * Register a Plain Value type deserialization Function.
- *
- * @param <T> Plain Value parametrized Type
- * @param type Plain Value Type
- * @param deserializer Deserialization Function
- */
- @SuppressWarnings( "unchecked" )
- protected final <T> void registerDeserializer( Class<T> type, Function<Object, T> deserializer )
- {
- deserializers.put( type, (Function<Object, Object>) deserializer );
- }
-
- @SuppressWarnings( { "UnusedDeclaration", "unchecked" } )
- protected final <T> void registerComplexDeserializer( Class<T> type,
- ComplexDeserializer<T, InputType, InputNodeType> deserializer
- )
- {
- complexDeserializers.put( type, (ComplexDeserializer<Object, InputType, InputNodeType>) deserializer );
- }
-
- protected ValueDeserializerAdapter()
- {
-
- // Primitive Value types
- registerDeserializer( String.class, Object::toString );
- registerDeserializer( Character.class, input -> input.toString().charAt( 0 ) );
- registerDeserializer( Boolean.class, input -> ( input instanceof String )
- ? Boolean.parseBoolean( (String) input )
- : (Boolean) input );
- registerDeserializer( Integer.class, input -> ( input instanceof String )
- ? Integer.parseInt( (String) input )
- : ( (Number) input ).intValue() );
- registerDeserializer( Long.class, input -> ( input instanceof String )
- ? Long.parseLong( (String) input )
- : ( (Number) input ).longValue() );
- registerDeserializer( Short.class, input -> ( input instanceof String )
- ? Short.parseShort( (String) input )
- : ( (Number) input ).shortValue() );
- registerDeserializer( Byte.class, input -> ( input instanceof String )
- ? Byte.parseByte( (String) input )
- : ( (Number) input ).byteValue() );
- registerDeserializer( Float.class, input -> ( input instanceof String )
- ? Float.parseFloat( (String) input )
- : ( (Number) input ).floatValue() );
- registerDeserializer( Double.class, input -> ( input instanceof String )
- ? Double.parseDouble( (String) input )
- : ( (Number) input ).doubleValue() );
-
- // Number types
- registerDeserializer( BigDecimal.class, input -> new BigDecimal( input.toString() ) );
- registerDeserializer( BigInteger.class, input -> new BigInteger( input.toString() ) );
- registerDeserializer( Identity.class, input -> StringIdentity.fromString( input.toString() ) );
-
- // Date types
- registerDeserializer( Instant.class, input -> Instant.parse( input.toString() ) );
- registerDeserializer( ZonedDateTime.class, input -> ZonedDateTime.parse( input.toString() ) );
- registerDeserializer( OffsetDateTime.class, input -> OffsetDateTime.parse( input.toString() ) );
- registerDeserializer( LocalDateTime.class, input -> LocalDateTime.parse( input.toString() ) );
- registerDeserializer( LocalDate.class, input -> LocalDate.parse( input.toString() ));
- registerDeserializer( LocalTime.class, input -> LocalTime.parse( input.toString() ));
- registerDeserializer( Duration.class, input -> Duration.parse( input.toString() ));
- registerDeserializer( Period.class, input -> Period.parse( input.toString() ));
-
- // Other supported types
- registerDeserializer( EntityReference.class, input -> EntityReference.parseEntityReference( input.toString() ) );
- }
-
- @Override
- public <T> Function<String, T> deserialize( ModuleDescriptor module, Class<T> type )
- {
- if( CollectionType.isCollection( type ) )
- {
- ValueType objectValueType = new ValueType( Object.class );
- return deserialize( module, new CollectionType( type, objectValueType ) );
- }
- if( MapType.isMap( type ) )
- {
- ValueType objectValueType = new ValueType( Object.class );
- return deserialize( module, new MapType( type, objectValueType, objectValueType ) );
- }
- return deserialize( module, new ValueType( type ) );
- }
-
- @Override
- public final <T> Function<String, T> deserialize( ModuleDescriptor module, ValueType valueType )
- {
- return input -> deserialize( module, valueType, input );
- }
-
- @Override
- public final <T> T deserialize( ModuleDescriptor module, Class<?> type, String input )
- throws ValueSerializationException
- {
- if( CollectionType.isCollection( type ) )
- {
- ValueType objectValueType = new ValueType( Object.class );
- return deserialize( module, new CollectionType( type, objectValueType ), input );
- }
- if( MapType.isMap( type ) )
- {
- ValueType objectValueType = new ValueType( Object.class );
- return deserialize( module, new MapType( type, objectValueType, objectValueType ), input );
- }
- return deserialize( module, new ValueType( type ), input );
- }
-
- @Override
- public final <T> T deserialize( ModuleDescriptor module, ValueType valueType, String input )
- throws ValueSerializationException
- {
- try
- {
- return deserializeRoot( module, valueType, new ByteArrayInputStream( input.getBytes( UTF_8 ) ) );
- }
- catch( ValueSerializationException ex )
- {
- throw ex;
- }
- catch( Exception ex )
- {
- throw new ValueSerializationException( "Could not deserialize value", ex );
- }
- }
-
- @Override
- public final <T> T deserialize( ModuleDescriptor module, Class<?> type, InputStream input )
- throws ValueSerializationException
- {
- if( CollectionType.isCollection( type ) )
- {
- ValueType objectValueType = new ValueType( Object.class );
- return deserialize( module, new CollectionType( type, objectValueType ), input );
- }
- if( MapType.isMap( type ) )
- {
- ValueType objectValueType = new ValueType( Object.class );
- return deserialize( module, new MapType( type, objectValueType, objectValueType ), input );
- }
- return deserialize( module, new ValueType( type ), input );
- }
-
- @Override
- public final <T> T deserialize( ModuleDescriptor module, ValueType valueType, InputStream input )
- throws ValueSerializationException
- {
- try
- {
- return deserializeRoot( module, valueType, input );
- }
- catch( ValueSerializationException ex )
- {
- throw ex;
- }
- catch( Exception ex )
- {
- throw new ValueSerializationException( "Could not deserialize value", ex );
- }
- }
-
- @SuppressWarnings( "unchecked" )
- private <T> T deserializeRoot( ModuleDescriptor module, ValueType valueType, InputStream input )
- throws Exception
- {
- Class<?> type = valueType.types().findFirst().orElse( null );
-
- if( Identity.class.isAssignableFrom( type ) )
- {
- type = Identity.class;
- }
-
- // Plain ValueType
- Function<Object, Object> deserializationFunction = deserializers.get( type );
- if( deserializationFunction != null )
- {
- Scanner scanner = new Scanner( input, UTF_8 ).useDelimiter( "\\A" );
- if( !scanner.hasNext() )
- {
- return String.class.equals( type ) ? (T) "" : null;
- }
- String string = scanner.next();
- return (T) deserializationFunction.apply( string );
- }
- else // Array ValueType
- if( type.isArray() )
- {
- Scanner scanner = new Scanner( input, UTF_8 ).useDelimiter( "\\A" );
- if( !scanner.hasNext() )
- {
- return null;
- }
- String string = scanner.next();
- return (T) deserializeBase64Serialized( module, string );
- }
- else if( type.isEnum() )
- {
- Scanner scanner = new Scanner( input, UTF_8 ).useDelimiter( "\\A" );
- if( !scanner.hasNext() )
- {
- return String.class.equals( type ) ? (T) "" : null;
- }
- String string = scanner.next();
- return (T) Enum.valueOf( (Class) type, string );
- }
- else // Complex ValueType
- {
- InputType adaptedInput = adaptInput( module, input );
- onDeserializationStart( module, valueType, adaptedInput );
- T deserialized = doDeserialize( module, valueType, adaptedInput );
- onDeserializationEnd( module, valueType, adaptedInput );
- return deserialized;
- }
- }
-
- @SuppressWarnings( "unchecked" )
- private <T> T doDeserialize( ModuleDescriptor module, ValueType valueType, InputType input )
- throws Exception
- {
- final Class<?> type = valueType.types().findFirst().orElse( null );
- // Registered deserializers
- if( deserializers.get( type ) != null )
- {
- Object value = readPlainValue( module, input );
- if( value == null )
- {
- return null;
- }
- return (T) deserializers.get( type ).apply( value );
- }
- else if( complexDeserializers.get( type ) != null )
- {
- return (T) complexDeserializers.get( type ).deserializePull( input );
- }
- else // Explicit ValueComposite
- if( ValueCompositeType.class.isAssignableFrom( valueType.getClass() ) )
- {
- return (T) deserializeValueComposite( module, valueType, input );
- }
- else // Explicit Collections
- if( CollectionType.class.isAssignableFrom( valueType.getClass() ) )
- {
- return (T) deserializeCollection( module, (CollectionType) valueType, input );
- }
- else // Explicit Map
- if( MapType.class.isAssignableFrom( valueType.getClass() ) )
- {
- return (T) deserializeMap( module, (MapType) valueType, input );
- }
- else // Enum
- if( EnumType.class.isAssignableFrom( valueType.getClass() ) || type.isEnum() )
- {
- return (T) Enum.valueOf( (Class) type, readPlainValue( module, input ).toString() );
- }
- else // Array
- if( type.isArray() )
- {
- return (T) deserializeBase64Serialized( module, readPlainValue( module, input ).toString() );
- }
- // Guessed Deserialization
- return (T) deserializeGuessed( module, valueType, input );
- }
-
- private <T> Function<InputType, T> buildDeserializeInputFunction( ModuleDescriptor module, ValueType valueType )
- {
- return input -> {
- try
- {
- return doDeserialize( module, valueType, input );
- }
- catch( ValueSerializationException ex )
- {
- throw ex;
- }
- catch( Exception ex )
- {
- throw new ValueSerializationException( ex );
- }
- };
- }
-
- private <T> Collection<T> deserializeCollection( ModuleDescriptor module, CollectionType collectionType, InputType input )
- throws Exception
- {
- Collection<T> collection;
- Class<?> collectionMainType = collectionType.types().findFirst().orElse( null );
- if( Set.class.equals( collectionMainType ) )
- {
- collection = new LinkedHashSet<>();
- }
- else
- {
- collection = new ArrayList<>();
- }
- return readArrayInCollection( module,
- input,
- this.buildDeserializeInputFunction( module, collectionType.collectedType() ),
- collection );
- }
-
- private <K, V> Map<K, V> deserializeMap( ModuleDescriptor module, MapType mapType, InputType input )
- throws Exception
- {
- return readMapInMap( module,
- input,
- this.<K>buildDeserializeInputFunction( module, mapType.keyType() ),
- this.<V>buildDeserializeInputFunction( module, mapType.valueType() ),
- new HashMap<>() );
- }
-
- private <T> T deserializeValueComposite( ModuleDescriptor module, ValueType valueType, InputType input )
- throws Exception
- {
- InputNodeType inputNode = readObjectTree( module, input );
- if( inputNode == null )
- {
- return null;
- }
- return deserializeNodeValueComposite( module, valueType, inputNode );
- }
-
- private <T> T deserializeNodeValueComposite( ModuleDescriptor module, ValueType valueType, InputNodeType inputNode )
- throws Exception
- {
- ValueCompositeType valueCompositeType = (ValueCompositeType) valueType;
- Class<?> valueBuilderType = valueCompositeType.types().findFirst().orElse( null );
- String typeInfo = this.getObjectFieldValue(
- module,
- inputNode,
- "_type",
- this.<String>buildDeserializeInputNodeFunction( module, new ValueType( String.class ) ) );
- if( typeInfo != null )
- {
- ValueDescriptor valueDescriptor = module.valueDescriptor( typeInfo );
- if( valueDescriptor == null )
- {
- throw new ValueSerializationException( "Specified value type could not be resolved: " + typeInfo );
- }
- valueCompositeType = valueDescriptor.valueType();
- valueBuilderType = Class.forName( typeInfo );
- }
- return deserializeValueComposite( module, valueCompositeType, valueBuilderType, inputNode );
- }
-
- @SuppressWarnings( "unchecked" )
- private <T> T deserializeValueComposite( ModuleDescriptor module,
- ValueCompositeType valueCompositeType,
- Class<?> valueBuilderType,
- InputNodeType inputNode
- )
- throws Exception
- {
- final Map<String, Object> stateMap = new HashMap<>();
-
- // Properties
- valueCompositeType.properties().forEach( propertyDescriptor -> {
- String propertyName = null;
- Object value;
- try
- {
- propertyName = propertyDescriptor.qualifiedName().name();
- if( objectHasField( module, inputNode, propertyName ) )
- {
- value = getObjectFieldValue(
- module,
- inputNode,
- propertyName,
- buildDeserializeInputNodeFunction( module, propertyDescriptor.valueType() ) );
- if( propertyDescriptor.isImmutable() )
- {
- if( value instanceof Set )
- {
- value = Collections.unmodifiableSet( (Set<?>) value );
- }
- else if( value instanceof List )
- {
- value = Collections.unmodifiableList( (List<?>) value );
- }
- else if( value instanceof Map )
- {
- value = Collections.unmodifiableMap( (Map<?, ?>) value );
- }
- }
- }
- else
- {
- // Serialized object does not contain the field, try to default it
- value = propertyDescriptor.resolveInitialValue(module);
- }
- }
- catch( Exception e )
- {
- throw new ValueSerializationException( "Unable to deserialize property " + propertyDescriptor, e );
- }
- stateMap.put( propertyName, value );
- } );
-
- // Associations
- valueCompositeType.associations().forEach( association -> {
- try
- {
- String associationName = association.qualifiedName().name();
- if( objectHasField( module, inputNode, associationName ) )
- {
- Object value = getObjectFieldValue(
- module,
- inputNode,
- associationName,
- buildDeserializeInputNodeFunction( module, new ValueType( EntityReference.class ) ) );
- stateMap.put( associationName, value );
- }
- }
- catch( Exception e )
- {
- throw new ValueSerializationException( "Unable to deserialize association " + association, e );
- }
- } );
-
- // ManyAssociations
- valueCompositeType.manyAssociations().forEach( manyAssociation -> {
- try
- {
- String manyAssociationName = manyAssociation.qualifiedName().name();
- if( objectHasField( module, inputNode, manyAssociationName ) )
- {
- Object value = getObjectFieldValue(
- module,
- inputNode,
- manyAssociationName,
- buildDeserializeInputNodeFunction(
- module,
- new CollectionType(
- Collection.class,
- new ValueType( EntityReference.class ) ) ) );
- stateMap.put( manyAssociationName, value );
- }
- }
- catch( Exception e )
- {
- throw new ValueSerializationException( "Unable to deserialize manyassociation " + manyAssociation, e );
- }
- } );
-
- // NamedAssociations
- valueCompositeType.namedAssociations().forEach( namedAssociation -> {
- try
- {
- String namedAssociationName = namedAssociation.qualifiedName().name();
- if( objectHasField( module, inputNode, namedAssociationName ) )
- {
- Object value = getObjectFieldValue(
- module,
- inputNode,
- namedAssociationName,
- buildDeserializeInputNodeFunction( module, MapType.of( String.class, EntityReference.class, Serialization.Variant.object ) ) );
- stateMap.put( namedAssociationName, value );
- }
- }
- catch( Exception e )
- {
- throw new ValueSerializationException( "Unable to deserialize namedassociation " + namedAssociation, e );
- }
- } );
-
- ValueBuilder<?> valueBuilder = buildNewValueBuilderWithState( module, valueBuilderType, stateMap );
- return (T) valueBuilder.newInstance(); // Unchecked cast because the builder could use a type != T
- }
-
- private <T> Function<InputNodeType, T> buildDeserializeInputNodeFunction( ModuleDescriptor module, final ValueType valueType )
- {
- return inputNode -> {
- try
- {
- return doDeserializeInputNodeValue( module, valueType, inputNode );
- }
- catch( ValueSerializationException ex )
- {
- throw ex;
- }
- catch( Exception ex )
- {
- throw new ValueSerializationException( ex );
- }
- };
- }
-
- @SuppressWarnings( "unchecked" )
- private <T> T doDeserializeInputNodeValue( ModuleDescriptor module, ValueType valueType, InputNodeType inputNode )
- throws Exception
- {
- if( inputNode == null )
- {
- return null;
- }
- final Class<?> type = valueType.types().findFirst().orElse( null );
- // Registered deserializers
- if( deserializers.get( type ) != null )
- {
- Object value = asSimpleValue( module, inputNode );
- if( value == null )
- {
- return null;
- }
- return (T) deserializers.get( type ).apply( value );
- }
- else if( complexDeserializers.get( type ) != null )
- {
- return (T) complexDeserializers.get( type ).deserializeTree( inputNode );
- }
- else // Explicit ValueComposite
- if( ValueCompositeType.class.isAssignableFrom( valueType.getClass() ) )
- {
- return (T) deserializeNodeValueComposite( module, valueType, inputNode );
- }
- else // Explicit Collections
- if( CollectionType.class.isAssignableFrom( valueType.getClass() ) )
- {
- return (T) deserializeNodeCollection( module, (CollectionType) valueType, inputNode );
- }
- else // Explicit Map
- if( MapType.class.isAssignableFrom( valueType.getClass() ) )
- {
- MapType mapType = (MapType) valueType;
- if( mapType.variant().equals( Serialization.Variant.entry ) )
- {
- return (T) deserializeNodeEntryMap( module, (MapType) valueType, inputNode );
- }
- else
- {
- return (T) deserializeNodeObjectMap( module, (MapType) valueType, inputNode );
- }
- }
- else // Enum
- if( EnumType.class.isAssignableFrom( valueType.getClass() ) || type.isEnum() )
- {
- Object value = asSimpleValue( module, inputNode );
- if( value == null )
- {
- return null;
- }
- return (T) Enum.valueOf( (Class) type, value.toString() );
- }
- // Guessed deserialization
- return (T) deserializeNodeGuessed( module, valueType, inputNode );
- }
-
- private ValueBuilder<?> buildNewValueBuilderWithState( ModuleDescriptor module,
- Class<?> type,
- final Map<String, Object> stateMap
- )
- {
- return module.instance().newValueBuilderWithState(
- type,
- property -> stateMap.get( property.qualifiedName().name() ),
- association -> {
- Object entityRef = stateMap.get( association.qualifiedName().name() );
- if( entityRef == null )
- {
- return null;
- }
- return (EntityReference) entityRef;
- },
- manyAssociation -> {
- Object entityRefs = stateMap.get( manyAssociation.qualifiedName().name() );
- if( entityRefs == null )
- {
- return Stream.empty();
- }
- //noinspection unchecked
- return StreamSupport.stream( ( (Iterable<EntityReference>) entityRefs ).spliterator(), false );
- },
- namedAssociation -> {
- Object entityRefs = stateMap.get( namedAssociation.qualifiedName().name() );
- if( entityRefs == null )
- {
- return Stream.empty();
- }
- //noinspection unchecked
- return ( (Map<String, EntityReference>) entityRefs ).entrySet().stream();
- } );
- }
-
- @SuppressWarnings( "unchecked" )
- private <T> T deserializeGuessed( ModuleDescriptor module, ValueType valueType, InputType input )
- throws Exception
- {
- InputNodeType inputNode = readObjectTree( module, input );
- if( inputNode == null )
- {
- return null;
- }
- return deserializeNodeGuessed( module, valueType, inputNode );
- }
-
- private <T> Collection<T> deserializeNodeCollection( ModuleDescriptor module,
- CollectionType collectionType,
- InputNodeType inputNode
- )
- throws Exception
- {
- Collection<T> collection;
- Class<?> collectionMainType = collectionType.types().findFirst().orElse( null );
- if( Set.class.equals( collectionMainType ) )
- {
- collection = new LinkedHashSet<>();
- }
- else
- {
- collection = new ArrayList<>();
- }
- putArrayNodeInCollection( module,
- inputNode,
- this.buildDeserializeInputNodeFunction( module, collectionType.collectedType() ),
- collection );
- return collection;
- }
-
- private <K, V> Map<K, V> deserializeNodeEntryMap( ModuleDescriptor module, MapType mapType, InputNodeType inputNode )
- throws Exception
- {
- Map<K, V> map = new HashMap<>();
- putArrayNodeInMap( module,
- inputNode,
- this.buildDeserializeInputNodeFunction( module, mapType.keyType() ),
- this.buildDeserializeInputNodeFunction( module, mapType.valueType() ),
- map );
- return map;
- }
-
- private <V> Map<String, V> deserializeNodeObjectMap( ModuleDescriptor module, MapType mapType, InputNodeType inputNode )
- throws Exception
- {
- Map<String, V> map = new HashMap<>();
- putObjectNodeInMap( module,
- inputNode,
- this.buildDeserializeInputNodeFunction( module, mapType.valueType() ),
- map );
- return map;
- }
-
- @SuppressWarnings( "unchecked" )
- private <T> T deserializeNodeGuessed( ModuleDescriptor module, ValueType valueType, InputNodeType inputNode )
- throws Exception
- {
- if( isObjectValue( module, inputNode ) )
- {
- // Attempt ValueComposite deserialization
- ValueCompositeType valueCompositeType;
- if( objectHasField( module, inputNode, "_type" ) ) // with _type info
- {
- String typeInfo = this.getObjectFieldValue(
- module,
- inputNode,
- "_type",
- this.<String>buildDeserializeInputNodeFunction( module, new ValueType( String.class ) ) );
- ValueDescriptor valueDescriptor = module.valueDescriptor( typeInfo );
- if( valueDescriptor == null )
- {
- throw new ValueSerializationException( "Specified value type could not be resolved: " + typeInfo );
- }
- valueCompositeType = valueDescriptor.valueType();
- }
- else // without _type info
- {
- ValueDescriptor valueDescriptor = module.valueDescriptor( valueType.types()
- .findFirst()
- .get()
- .getName() );
- if( valueDescriptor == null )
- {
- throw new ValueSerializationException( "Don't know how to deserialize " + inputNode );
- }
- valueCompositeType = valueDescriptor.valueType();
- }
- Class<?> valueBuilderType = valueCompositeType.types().findFirst().orElse( null );
- return deserializeValueComposite( module, valueCompositeType, valueBuilderType, inputNode );
- }
- // Last resort : base64 java deserialization
- return (T) deserializeBase64Serialized( module, inputNode );
- }
-
- @SuppressWarnings( "unchecked" )
- private <T> T deserializeBase64Serialized( ModuleDescriptor module, InputNodeType inputNode )
- throws Exception
- {
- Object value = asSimpleValue( module, inputNode );
- if( value == null )
- {
- return null;
- }
- String base64 = value.toString();
- return deserializeBase64Serialized( module, base64 );
- }
-
- @SuppressWarnings( "unchecked" )
- private <T> T deserializeBase64Serialized( ModuleDescriptor module, String inputString )
- throws Exception
- {
- byte[] bytes = inputString.getBytes( UTF_8 );
- bytes = Base64.getDecoder().decode( bytes );
- Object result;
- try (ObjectInputStream oin = new ObjectInputStream( new ByteArrayInputStream( bytes ) ))
- {
- result = oin.readObject();
- }
- return (T) result;
- }
-
- //
- // Deserialization Extension Points
- //
-
- /**
- * Called by the adapter on deserialization start, after {@link #adaptInput(ModuleDescriptor, java.io.InputStream)}.
- *
- * @param module Module descriptor
- * @param valueType ValueType
- * @param input Input
- *
- * @throws Exception that will be wrapped in a {@link ValueSerializationException}
- */
- @SuppressWarnings( "UnusedParameters" )
- protected void onDeserializationStart( ModuleDescriptor module, ValueType valueType, InputType input )
- throws Exception
- {
- // NOOP
- }
-
- /**
- * Called by the adapter on deserialization end.
- *
- * @param module Module descriptor
- * @param valueType ValueType
- * @param input Input
- *
- * @throws Exception that will be wrapped in a {@link ValueSerializationException}
- */
- protected void onDeserializationEnd( ModuleDescriptor module, ValueType valueType, InputType input )
- throws Exception
- {
- // NOOP
- }
-
- //
- // Pull Parsing Deserialization
- //
-
- /**
- * This method is always called first, this is a chance to wrap the input type.
- *
- * @param module Module descriptor
- * @param input InputStream to adapt
- *
- * @return Adapted input
- *
- * @throws Exception that will be wrapped in a {@link ValueSerializationException}
- */
- protected abstract InputType adaptInput( ModuleDescriptor module, InputStream input )
- throws Exception;
-
- /**
- * @param module Module descriptor
- * @param input Input
- *
- * @return a Plain Value read from the input
- *
- * @throws Exception that will be wrapped in a {@link ValueSerializationException}
- */
- protected abstract Object readPlainValue( ModuleDescriptor module, InputType input )
- throws Exception;
-
- /**
- * @param module Module descriptor
- * @param input Input
- * @param deserializer Deserialization function
- * @param collection Collection
- * @param <T> Parameterized collection type
- *
- * @return The filled collection or null if no array
- *
- * @throws Exception that will be wrapped in a {@link ValueSerializationException}
- */
- protected abstract <T> Collection<T> readArrayInCollection( ModuleDescriptor module,
- InputType input,
- Function<InputType, T> deserializer,
- Collection<T> collection
- )
- throws Exception;
-
- /**
- * A Map<K,V> is serialized in an array of entries objects.
- *
- * <p>Here is an example in JSON:</p>
- * <pre>
- * [
- * { "key": "foo", "value": "bar" },
- * { "key": "cathedral", "value": "bazar" }
- * ]
- * </pre>
- * <p>And an empty Map:</p>
- * <pre>[]</pre>
- * <p>
- * This allow to use any type as keys and values while keeping the Map order at the cost of having
- * non-predictible order of key/value inside an entry object.
- * </p>
- *
- * @param module Module descriptor
- * @param input Input
- * @param keyDeserializer Map key deserialization function
- * @param valueDeserializer Map value deserialization function
- * @param map Map
- * @param <K> Parameterized map key type
- * @param <V> Parameterized map value type
- *
- * @return The filled map or null if no array
- *
- * @throws Exception that will be wrapped in a {@link ValueSerializationException}
- */
- protected abstract <K, V> Map<K, V> readMapInMap( ModuleDescriptor module,
- InputType input,
- Function<InputType, K> keyDeserializer,
- Function<InputType, V> valueDeserializer,
- Map<K, V> map
- )
- throws Exception;
-
- /**
- * @param module Module descriptor
- * @param input Input
- *
- * @return an InputNodeType or null if the value was null
- *
- * @throws Exception that will be wrapped in a {@link ValueSerializationException}
- */
- protected abstract InputNodeType readObjectTree( ModuleDescriptor module, InputType input )
- throws Exception;
-
- //
- // Tree Parsing Deserialization
- //
- protected abstract Object asSimpleValue( ModuleDescriptor module, InputNodeType inputNode )
- throws Exception;
-
- protected abstract boolean isObjectValue( ModuleDescriptor module, InputNodeType inputNode )
- throws Exception;
-
- protected abstract boolean objectHasField( ModuleDescriptor module, InputNodeType inputNode, String key )
- throws Exception;
-
- /**
- * Return null if the field do not exists.
- *
- * @param module Module descriptor
- * @param inputNode Input Node
- * @param key Object key
- * @param valueDeserializer Deserialization function
- * @param <T> Parameterized object field value type
- *
- * @return The value of the field.
- *
- * @throws Exception that will be wrapped in a {@link ValueSerializationException}
- */
- protected abstract <T> T getObjectFieldValue( ModuleDescriptor module,
- InputNodeType inputNode,
- String key,
- Function<InputNodeType, T> valueDeserializer
- )
- throws Exception;
-
- protected abstract <T> void putArrayNodeInCollection( ModuleDescriptor module,
- InputNodeType inputNode,
- Function<InputNodeType, T> deserializer,
- Collection<T> collection
- )
- throws Exception;
-
- protected abstract <K, V> void putArrayNodeInMap( ModuleDescriptor module,
- InputNodeType inputNode,
- Function<InputNodeType, K> keyDeserializer,
- Function<InputNodeType, V> valueDeserializer,
- Map<K, V> map
- )
- throws Exception;
-
- protected abstract <V> void putObjectNodeInMap( ModuleDescriptor module,
- InputNodeType inputNode,
- Function<InputNodeType, V> valueDeserializer,
- Map<String, V> map
- )
- throws Exception;
-}
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/core/spi/src/main/java/org/apache/polygene/spi/value/ValueSerializerAdapter.java
----------------------------------------------------------------------
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/value/ValueSerializerAdapter.java b/core/spi/src/main/java/org/apache/polygene/spi/value/ValueSerializerAdapter.java
deleted file mode 100644
index e9313b5..0000000
--- a/core/spi/src/main/java/org/apache/polygene/spi/value/ValueSerializerAdapter.java
+++ /dev/null
@@ -1,570 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- *
- */
-package org.apache.polygene.spi.value;
-
-import java.io.ByteArrayOutputStream;
-import java.io.ObjectOutputStream;
-import java.io.OutputStream;
-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.Base64;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.function.BiFunction;
-import java.util.function.Function;
-import org.apache.polygene.api.PolygeneAPI;
-import org.apache.polygene.api.association.Association;
-import org.apache.polygene.api.association.AssociationStateHolder;
-import org.apache.polygene.api.association.ManyAssociation;
-import org.apache.polygene.api.association.NamedAssociation;
-import org.apache.polygene.api.composite.CompositeInstance;
-import org.apache.polygene.api.entity.EntityComposite;
-import org.apache.polygene.api.entity.EntityReference;
-import org.apache.polygene.api.identity.Identity;
-import org.apache.polygene.api.property.Property;
-import org.apache.polygene.api.value.ValueComposite;
-import org.apache.polygene.api.value.ValueDescriptor;
-import org.apache.polygene.api.value.ValueSerializationException;
-import org.apache.polygene.api.value.ValueSerializer;
-
-/**
- * Adapter for pull-parsing capable ValueSerializers.
- *
- * <p>
- * Among Plain values (see {@link ValueSerializer}) some are considered primitives to underlying serialization
- * mechanisms and by so handed/come without conversion to/from implementations. Primitive values can be one of:
- * </p>
- * <ul>
- * <li>String,</li>
- * <li>Character or char,</li>
- * <li>Boolean or boolean,</li>
- * <li>Integer or int,</li>
- * <li>Long or long,</li>
- * <li>Short or short,</li>
- * <li>Byte or byte,</li>
- * <li>Float or float,</li>
- * <li>Double or double.</li>
- * </ul>
- * <p>
- * Some other Plain values are transformed before being handed to implementations:
- * </p>
- * <ul>
- * <li>BigInteger and BigDecimal depends on ValueSerializer.{@link org.apache.polygene.api.value.ValueSerializer.Options};</li>
- * <li>Date as a ISO-8601 UTC String;</li>
- * <li>DateTime (JodaTime) as a ISO-8601 String with timezone offset or Z for UTC;</li>
- * <li>LocalDateTime (JodaTime) as a ISO-8601 String with no timezone offset;</li>
- * <li>LocalDate (JodaTime) as a ISO-8601 String with no time info;</li>
- * </ul>
- *
- * @param <OutputType> Implementor output type
- */
-public abstract class ValueSerializerAdapter<OutputType>
- implements ValueSerializer
-{
-
- public interface ComplexSerializer<T, OutputType>
- {
- void serialize( Options options, T object, OutputType output )
- throws Exception;
- }
-
- private static final String UTF_8 = "UTF-8";
-
- private static <TO, FROM extends TO> BiFunction<Options, FROM, TO> identitySerializer()
- {
- return ( options, from ) -> from;
- }
-
- private final Map<Class<?>, BiFunction<Options, Object, Object>> serializers = new HashMap<>( 16 );
- private final Map<Class<?>, ComplexSerializer<Object, OutputType>> complexSerializers = new HashMap<>( 2 );
-
- /**
- * Register a Plain Value type serialization Function.
- *
- * @param <T> Plain Value parametrized Type
- * @param type Plain Value Type
- * @param serializer Serialization Function
- */
- @SuppressWarnings( "unchecked" )
- protected final <T> void registerSerializer( Class<T> type, BiFunction<Options, T, Object> serializer )
- {
- serializers.put( type, (BiFunction<Options, Object, Object>) serializer );
- }
-
- /**
- * Register a Complex Value type serialization Function.
- *
- * @param <T> Complex Value parametrized Type
- * @param type Complex Value Type
- * @param serializer Serialization Function
- */
- @SuppressWarnings( "unchecked" )
- protected final <T> void registerComplexSerializer( Class<T> type, ComplexSerializer<T, OutputType> serializer )
- {
- complexSerializers.put( type, (ComplexSerializer<Object, OutputType>) serializer );
- }
-
- public ValueSerializerAdapter()
- {
- // Primitive Value types
- registerSerializer( String.class, ValueSerializerAdapter.identitySerializer() );
- registerSerializer( Character.class, ValueSerializerAdapter.identitySerializer() );
- registerSerializer( Boolean.class, ValueSerializerAdapter.identitySerializer() );
- registerSerializer( Integer.class, ValueSerializerAdapter.identitySerializer() );
- registerSerializer( Long.class, ValueSerializerAdapter.identitySerializer() );
- registerSerializer( Short.class, ValueSerializerAdapter.identitySerializer() );
- registerSerializer( Byte.class, ValueSerializerAdapter.identitySerializer() );
- registerSerializer( Float.class, ValueSerializerAdapter.identitySerializer() );
- registerSerializer( Double.class, ValueSerializerAdapter.identitySerializer() );
-
- // Number types
- registerSerializer( BigDecimal.class, ( options, bigDecimal ) -> bigDecimal.toString() );
- registerSerializer( BigInteger.class, ( options, bigInteger ) -> bigInteger.toString() );
- registerSerializer( Identity.class, ( options, identity ) -> identity.toString() );
-
- // Date types
- registerSerializer( Instant.class, ( options, date ) -> date.toString() );
- registerSerializer( Duration.class, ( options, date ) -> date.toString() );
- registerSerializer( Period.class, ( options, date ) -> date.toString() );
- registerSerializer( ZonedDateTime.class, ( options, date ) -> date.toString() );
- registerSerializer( OffsetDateTime.class, ( options, date ) -> date.toString() );
- registerSerializer( LocalDateTime.class, ( options, date ) -> date.toString() );
- registerSerializer( LocalDate.class, ( options, date ) -> date.toString() );
- registerSerializer( LocalTime.class, ( options, date ) -> date.toString() );
-
- // Other supported types
- registerSerializer( EntityReference.class, ( options, ref ) -> ref.toString() );
- }
-
- @Override
- public final <T> Function<T, String> serialize()
- {
- return this::serialize;
- }
-
- @Override
- public final <T> Function<T, String> serialize( final Options options )
- {
- return object -> serialize( options, object );
- }
-
- @Override
- public final String serialize( Object object )
- throws ValueSerializationException
- {
- return serialize( new Options(), object );
- }
-
- @Override
- public final String serialize( Options options, Object object )
- throws ValueSerializationException
- {
- try
- {
- ByteArrayOutputStream output = new ByteArrayOutputStream();
- serializeRoot( options, object, output );
- return output.toString( UTF_8 );
- }
- catch( ValueSerializationException ex )
- {
- throw ex;
- }
- catch( Exception ex )
- {
- throw new ValueSerializationException( "Could not serialize value", ex );
- }
- }
-
- @Override
- public final void serialize( Object object, OutputStream output )
- throws ValueSerializationException
- {
- serialize( new Options(), object, output );
- }
-
- @Override
- public final void serialize( Options options, Object object, OutputStream output )
- throws ValueSerializationException
- {
- try
- {
- serializeRoot( options, object, output );
- }
- catch( ValueSerializationException ex )
- {
- throw ex;
- }
- catch( Exception ex )
- {
- throw new ValueSerializationException( "Could not serialize value", ex );
- }
- }
-
- private void serializeRoot( Options options, Object object, OutputStream output )
- throws Exception
- {
- if( object != null )
- {
- if( serializers.get( object.getClass() ) != null )
- {
- // Plain Value
- Object serialized = serializers.get( object.getClass() ).apply( options, object );
- output.write( serialized.toString().getBytes( UTF_8 ) );
- }
- else if( object instanceof Identity )
- {
- Object serialized = serializers.get( Identity.class ).apply( options, object );
- output.write( serialized.toString().getBytes( UTF_8 ) );
- }
- else if( object.getClass().isEnum() )
- {
- // Enum Value
- output.write( object.toString().getBytes( UTF_8 ) );
- }
- else if( object.getClass().isArray() )
- {
- // Array Value
- output.write( serializeBase64Serializable( object ).getBytes( UTF_8 ) );
- }
- else
- {
- // Complex Value
- OutputType adaptedOutput = adaptOutput( output );
- onSerializationStart( object, adaptedOutput );
- doSerialize( options, object, adaptedOutput, true );
- onSerializationEnd( object, adaptedOutput );
- }
- }
- }
-
- private void doSerialize( Options options, Object object, OutputType output, boolean rootPass )
- throws Exception
- {
- // Null
- if( object == null )
- {
- onValue( output, null );
- }
- else // Registered serializer
- if( serializers.get( object.getClass() ) != null )
- {
- onValue( output, serializers.get( object.getClass() ).apply( options, object ) );
- }
- else if( complexSerializers.get( object.getClass() ) != null )
- {
- complexSerializers.get( object.getClass() ).serialize( options, object, output );
- }
- else // ValueComposite
- if( Identity.class.isAssignableFrom( object.getClass() ) )
- {
- serializeIdentity( object, output );
- }
- else if( ValueComposite.class.isAssignableFrom( object.getClass() ) )
- {
- serializeValueComposite( options, object, output, rootPass );
- }
- else // EntityComposite
- if( EntityComposite.class.isAssignableFrom( object.getClass() ) )
- {
- serializeEntityComposite( object, output );
- }
- else // Collection - Iterable
- if( Iterable.class.isAssignableFrom( object.getClass() ) )
- {
- serializeIterable( options, object, output );
- }
- else // Array - QUID Remove this and use java serialization for arrays?
- if( object.getClass().isArray() )
- {
- serializeBase64Serializable( object, output );
- }
- else // Map
- if( Map.class.isAssignableFrom( object.getClass() ) )
- {
- serializeMap( options, object, output );
- }
- else // Enum
- if( object.getClass().isEnum() )
- {
- onValue( output, object.toString() );
- }
- else // Fallback to Base64 encoded Java Serialization
- {
- serializeBase64Serializable( object, output );
- }
- }
-
- private void serializeIdentity( Object object, OutputType output )
- throws Exception
- {
- onValue( output, object.toString() );
- }
-
- private void serializeValueComposite( Options options, Object object, OutputType output, boolean rootPass )
- throws Exception
- {
- CompositeInstance valueInstance = PolygeneAPI.FUNCTION_COMPOSITE_INSTANCE_OF.apply( (ValueComposite) object );
- ValueDescriptor descriptor = (ValueDescriptor) valueInstance.descriptor();
- AssociationStateHolder state = (AssociationStateHolder) valueInstance.state();
-
- onObjectStart( output );
-
- //noinspection ConstantConditions
- if( options.getBoolean( Options.INCLUDE_TYPE_INFO ) && !rootPass )
- {
- onFieldStart( output, "_type" );
- onValueStart( output );
- onValue( output, descriptor.valueType().types().findFirst().get().getName());
- onValueEnd( output );
- onFieldEnd( output );
- }
-
- descriptor.valueType().properties().forEach( persistentProperty -> {
- Property<?> property = state.propertyFor( persistentProperty.accessor() );
- try
- {
- onFieldStart( output, persistentProperty.qualifiedName().name() );
- onValueStart( output );
- doSerialize( options, property.get(), output, false );
- onValueEnd( output );
- onFieldEnd( output );
- }
- catch( Exception e )
- {
- throw new ValueSerializationException( "Unable to serialize property " + persistentProperty, e );
- }
- } );
- descriptor.valueType().associations().forEach(associationDescriptor -> {
- Association<?> association = state.associationFor( associationDescriptor.accessor() );
- try
- {
- onFieldStart( output, associationDescriptor.qualifiedName().name() );
- onValueStart( output );
- EntityReference ref = association.reference();
- if( ref == null )
- {
- onValue( output, null );
- }
- else
- {
- onValue( output, ref.identity().toString() );
- }
- onValueEnd( output );
- onFieldEnd( output );
- }
- catch( Exception e )
- {
- throw new ValueSerializationException( "Unable to serialize association " + associationDescriptor, e );
- }
- } );
- descriptor.valueType().manyAssociations().forEach( associationDescriptor -> {
- ManyAssociation<?> manyAssociation = state.manyAssociationFor( associationDescriptor.accessor() );
- try
- {
- onFieldStart( output, associationDescriptor.qualifiedName().name() );
- onValueStart( output );
- onArrayStart( output );
- for( Iterator<EntityReference> it = manyAssociation.references().iterator(); it.hasNext(); )
- {
- onValueStart( output );
- onValue( output, it.next().identity().toString() );
- onValueEnd( output );
- }
- onArrayEnd( output );
- onValueEnd( output );
- onFieldEnd( output );
- }
- catch( Exception e )
- {
- throw new ValueSerializationException( "Unable to serialize manyassociation " + associationDescriptor, e );
- }
- });
- descriptor.valueType().namedAssociations().forEach( associationDescriptor -> {
- NamedAssociation<?> namedAssociation = state.namedAssociationFor( associationDescriptor.accessor() );
- try
- {
- onFieldStart( output, associationDescriptor.qualifiedName().name() );
- onValueStart( output );
- onObjectStart( output );
- for( String name : namedAssociation )
- {
- onFieldStart( output, name );
- onValueStart( output );
- EntityReference ref = namedAssociation.referenceOf( name );
- onValue( output, ref.identity().toString() );
- onValueEnd( output );
- onFieldEnd( output );
- }
- onObjectEnd( output );
- onValueEnd( output );
- onFieldEnd( output );
- }
- catch( Exception e )
- {
- throw new ValueSerializationException( "Unable to serialize namedassociation " + associationDescriptor, e );
- }
- } );
-
- onObjectEnd( output );
- }
-
- private void serializeEntityComposite( Object object, OutputType output )
- throws Exception
- {
- onValue( output, EntityReference.entityReferenceFor( object ) );
- }
-
- private void serializeIterable( Options options, Object object, OutputType output )
- throws Exception
- {
- @SuppressWarnings( "unchecked" )
- Iterable<Object> collection = (Iterable<Object>) object;
- onArrayStart( output );
- for( Object item : collection )
- {
- onValueStart( output );
- doSerialize( options, item, output, false );
- onValueEnd( output );
- }
- onArrayEnd( output );
- }
-
- private void serializeMap( Options options, Object object, OutputType output )
- throws Exception
- {
- @SuppressWarnings( "unchecked" )
- Map<Object, Object> map = (Map<Object, Object>) object;
- //noinspection ConstantConditions
- if( options.getBoolean( Options.MAP_ENTRIES_AS_OBJECTS ) )
- {
- onObjectStart( output );
- for( Map.Entry<Object, Object> entry : map.entrySet() )
- {
- onFieldStart( output, entry.getKey().toString() );
- onValueStart( output );
- doSerialize( options, entry.getValue(), output, false );
- onValueEnd( output );
- onFieldEnd( output );
- }
- onObjectEnd( output );
- }
- else
- {
- onArrayStart( output );
- for( Map.Entry<Object, Object> entry : map.entrySet() )
- {
- onObjectStart( output );
-
- onFieldStart( output, "key" );
- onValueStart( output );
- onValue( output, entry.getKey().toString() );
- onValueEnd( output );
- onFieldEnd( output );
-
- onFieldStart( output, "value" );
- onValueStart( output );
- doSerialize( options, entry.getValue(), output, false );
- onValueEnd( output );
- onFieldEnd( output );
-
- onObjectEnd( output );
- }
- onArrayEnd( output );
- }
- }
-
- private void serializeBase64Serializable( Object object, OutputType output )
- throws Exception
- {
- onValue( output, serializeBase64Serializable( object ) );
- }
-
- private String serializeBase64Serializable( Object object )
- throws Exception
- {
- ByteArrayOutputStream bout = new ByteArrayOutputStream();
- try (ObjectOutputStream out = new ObjectOutputStream( bout ))
- {
- out.writeUnshared( object );
- }
- byte[] bytes = Base64.getEncoder().encode( bout.toByteArray() );
- return new String( bytes, UTF_8 );
- }
-
- protected abstract OutputType adaptOutput( OutputStream output )
- throws Exception;
-
- protected void onSerializationStart( Object object, OutputType output )
- throws Exception
- {
- // NOOP
- }
-
- protected void onSerializationEnd( Object object, OutputType output )
- throws Exception
- {
- // NOOP
- }
-
- protected abstract void onArrayStart( OutputType output )
- throws Exception;
-
- protected abstract void onArrayEnd( OutputType output )
- throws Exception;
-
- protected abstract void onObjectStart( OutputType output )
- throws Exception;
-
- protected abstract void onObjectEnd( OutputType output )
- throws Exception;
-
- protected abstract void onFieldStart( OutputType output, String fieldName )
- throws Exception;
-
- protected void onFieldEnd( OutputType output )
- throws Exception
- {
- // NOOP
- }
-
- protected void onValueStart( OutputType output )
- throws Exception
- {
- // NOOP
- }
-
- protected abstract void onValue( OutputType output, Object value )
- throws Exception;
-
- protected void onValueEnd( OutputType output )
- throws Exception
- {
- // NOOP
- }
-}
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/core/spi/src/main/java/org/apache/polygene/spi/value/package.html
----------------------------------------------------------------------
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/value/package.html b/core/spi/src/main/java/org/apache/polygene/spi/value/package.html
deleted file mode 100644
index 936e083..0000000
--- a/core/spi/src/main/java/org/apache/polygene/spi/value/package.html
+++ /dev/null
@@ -1,24 +0,0 @@
-<!--
- ~ Licensed to the Apache Software Foundation (ASF) under one
- ~ or more contributor license agreements. See the NOTICE file
- ~ distributed with this work for additional information
- ~ regarding copyright ownership. The ASF licenses this file
- ~ to you under the Apache License, Version 2.0 (the
- ~ "License"); you may not use this file except in compliance
- ~ with the License. You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- ~
- ~
- -->
-<html>
- <body>
- <h2>Value SPI.</h2>
- </body>
-</html>
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/core/spi/src/main/java/org/apache/polygene/valueserialization/orgjson/OrgJsonValueDeserializer.java
----------------------------------------------------------------------
diff --git a/core/spi/src/main/java/org/apache/polygene/valueserialization/orgjson/OrgJsonValueDeserializer.java b/core/spi/src/main/java/org/apache/polygene/valueserialization/orgjson/OrgJsonValueDeserializer.java
deleted file mode 100644
index c543b3c..0000000
--- a/core/spi/src/main/java/org/apache/polygene/valueserialization/orgjson/OrgJsonValueDeserializer.java
+++ /dev/null
@@ -1,485 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- *
- */
-package org.apache.polygene.valueserialization.orgjson;
-
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.function.Function;
-import org.apache.polygene.api.structure.ModuleDescriptor;
-import org.apache.polygene.api.value.ValueSerializationException;
-import org.apache.polygene.spi.value.ValueDeserializerAdapter;
-import org.json.JSONArray;
-import org.json.JSONObject;
-import org.json.JSONTokener;
-
-/**
- * ValueDeserializer reading Values from JSON documents using org.json.
- */
-public class OrgJsonValueDeserializer
- extends ValueDeserializerAdapter<JSONTokener, Object>
-{
-
- @Override
- protected JSONTokener adaptInput( ModuleDescriptor module, InputStream input )
- throws Exception
- {
- return new JSONTokener( new InputStreamReader( input, "UTF-8" ) );
- }
-
- @Override
- protected Object readPlainValue( ModuleDescriptor module, JSONTokener input )
- throws Exception
- {
- Object nextValue = input.nextValue();
- if( JSONObject.NULL.equals( nextValue ) )
- {
- return null;
- }
- else // Object or Array
- if( JSONObject.class.isAssignableFrom( nextValue.getClass() )
- || JSONArray.class.isAssignableFrom( nextValue.getClass() ) )
- {
- throw new ValueSerializationException( "Asked for a Value but found an Object or an Array." );
- }
- return nextValue;
- }
-
- @Override
- protected <T> Collection<T> readArrayInCollection( ModuleDescriptor module,
- JSONTokener input,
- Function<JSONTokener, T> deserializer,
- Collection<T> collection
- )
- throws Exception
- {
- char c = input.nextClean();
- char q;
- if( c == 'n' ) // null?
- {
- /*
- * Handle unquoted text. This could be the values true, false, or
- * null, or it can be a number. An implementation (such as this one)
- * is allowed to also accept non-standard forms.
- *
- * Accumulate characters until we reach the end of the text or a
- * formatting character.
- */
- StringBuilder sb = new StringBuilder();
- sb.setLength( 0 );
- while( c >= ' ' && ",:]}/\\\"[{;=#".indexOf( c ) < 0 )
- {
- sb.append( c );
- c = input.next();
- }
- input.back();
- String s = sb.toString().trim();
- if( !"null".equals( s ) )
- {
- input.syntaxError( "Unknown value: '" + s + "'" );
- }
- return null;
- }
- else if( c == '[' )
- {
- q = ']';
- }
- else
- {
- throw input.syntaxError( "A JSONArray text must start with '['" );
- }
- if( input.nextClean() == ']' )
- {
- return collection;
- }
- input.back();
- for(; ; )
- {
- if( input.nextClean() == ',' )
- {
- input.back();
- collection.add( null );
- }
- else
- {
- input.back();
- collection.add( deserializer.apply( input ) );
- }
- c = input.nextClean();
- switch( c )
- {
- case ';':
- case ',':
- if( input.nextClean() == ']' )
- {
- return collection;
- }
- input.back();
- break;
- case ']':
- case ')':
- if( q != c )
- {
- throw input.syntaxError( "Expected a '" + Character.valueOf( q ) + "'" );
- }
- return collection;
- default:
- throw input.syntaxError( "Expected a ',' or ']'" );
- }
- }
- }
-
- @Override
- protected <K, V> Map<K, V> readMapInMap( ModuleDescriptor module,
- JSONTokener input,
- Function<JSONTokener, K> keyDeserializer,
- Function<JSONTokener, V> valueDeserializer,
- Map<K, V> map
- )
- throws Exception
- {
- char c = input.nextClean();
- char q;
- if( c == 'n' ) // null?
- {
- /*
- * Handle unquoted text. This could be the values true, false, or
- * null, or it can be a number. An implementation (such as this one)
- * is allowed to also accept non-standard forms.
- *
- * Accumulate characters until we reach the end of the text or a
- * formatting character.
- */
- StringBuilder sb = new StringBuilder();
- sb.setLength( 0 );
- while( c >= ' ' && ",:]}/\\\"[{;=#".indexOf( c ) < 0 )
- {
- sb.append( c );
- c = input.next();
- }
- input.back();
- String s = sb.toString().trim();
- if( !"null".equals( s ) )
- {
- input.syntaxError( "Unknown value: '" + s + "'" );
- }
- return null;
- }
- else if( c == '[' )
- {
- q = ']';
- }
- else
- {
- throw input.syntaxError( "A JSONArray text must start with '['" );
- }
- if( input.nextClean() == ']' )
- {
- return map;
- }
- input.back();
-
- for(; ; )
- {
- if( input.nextClean() == ',' )
- {
- input.back();
- }
- else
- {
- input.back();
- // Map entry!
- if( input.nextClean() != '{' )
- {
- throw input.syntaxError( "A JSONObject text must begin with '{'" );
- }
-
- String objectKey;
- K key = null;
- V value = null;
-
- boolean breakIteration = false;
- while( !breakIteration )
- {
- c = input.nextClean();
- switch( c )
- {
- case 0:
- throw input.syntaxError( "A JSONObject text must end with '}'" );
- case '}':
- breakIteration = true;
- continue;
- default:
- input.back();
- objectKey = input.nextValue().toString();
- }
-
- /*
- * The key is followed by ':'. We will also tolerate '=' or '=>'.
- */
- c = input.nextClean();
- if( c == '=' )
- {
- if( input.next() != '>' )
- {
- input.back();
- }
- }
- else if( c != ':' )
- {
- throw input.syntaxError( "Expected a ':' after a key" );
- }
-
- if( "key".equals( objectKey ) )
- {
- key = keyDeserializer.apply( input );
- }
- else if( "value".equals( objectKey ) )
- {
- value = valueDeserializer.apply( input );
- }
- else
- {
- input.nextValue();
- }
-
- /*
- * Pairs are separated by ','. We will also tolerate ';'.
- */
- switch( input.nextClean() )
- {
- case ';':
- case ',':
- if( input.nextClean() == '}' )
- {
- breakIteration = true;
- continue;
- }
- input.back();
- continue;
- case '}':
- breakIteration = true;
- continue;
- default:
- throw input.syntaxError( "Expected a ',' or '}'" );
- }
- }
- if( key != null )
- {
- map.put( key, value );
- }
- }
- c = input.nextClean();
- switch( c )
- {
- case ';':
- case ',':
- if( input.nextClean() == ']' )
- {
- return map;
- }
- input.back();
- break;
- case ']':
- case ')':
- if( q != c )
- {
- throw input.syntaxError( "Expected a '" + Character.valueOf( q ) + "'" );
- }
- return map;
- default:
- throw input.syntaxError( "Expected a ',' or ']'" );
- }
- }
- }
-
- //
- // Deserialization - Tree parsing
- //
- @Override
- protected JSONObject readObjectTree( ModuleDescriptor module,
- JSONTokener input
- )
- throws Exception
- {
- Object objectTree = input.nextValue();
- if( JSONObject.NULL.equals( objectTree ) )
- {
- return null;
- }
- return (JSONObject) objectTree;
- }
-
- @Override
- protected Object asSimpleValue( ModuleDescriptor module, Object inputNode )
- throws Exception
- {
- if( JSONObject.NULL.equals( inputNode ) )
- {
- return null;
- }
- if( inputNode instanceof JSONObject || inputNode instanceof JSONArray )
- {
- throw new ValueSerializationException( "Expected a simple value but got " + inputNode );
- }
- return inputNode;
- }
-
- @Override
- protected boolean isObjectValue( ModuleDescriptor module, Object inputNode )
- throws Exception
- {
- if( JSONObject.NULL.equals( inputNode ) )
- {
- return false;
- }
- return inputNode instanceof JSONObject;
- }
-
- @Override
- protected boolean objectHasField( ModuleDescriptor module, Object inputNode, String key )
- throws Exception
- {
- if( JSONObject.NULL.equals( inputNode ) )
- {
- return false;
- }
- if( !( inputNode instanceof JSONObject ) )
- {
- throw new ValueSerializationException( "Expected an object but got " + inputNode );
- }
- JSONObject json = (JSONObject) inputNode;
- return json.has( key );
- }
-
- @Override
- protected <T> T getObjectFieldValue( ModuleDescriptor module,
- Object inputNode,
- String key,
- Function<Object, T> valueDeserializer
- )
- throws Exception
- {
- JSONObject json = (JSONObject) inputNode;
- Object valueNode = json.opt( key );
- if( JSONObject.NULL.equals( valueNode ) )
- {
- return null;
- }
- T value = valueDeserializer.apply( valueNode );
- return value;
- }
-
- @Override
- protected <T> void putArrayNodeInCollection( ModuleDescriptor module,
- Object inputNode,
- Function<Object, T> deserializer,
- Collection<T> collection
- )
- throws Exception
- {
- if( JSONObject.NULL.equals( inputNode ) )
- {
- return;
- }
- if( !( inputNode instanceof JSONArray ) )
- {
- throw new ValueSerializationException( "Expected an array but got " + inputNode );
- }
- JSONArray array = (JSONArray) inputNode;
- for( int idx = 0; idx < array.length(); idx++ )
- {
- Object item = array.get( idx );
- T value = deserializer.apply( item );
- collection.add( value );
- }
- }
-
- @Override
- protected <K, V> void putArrayNodeInMap( ModuleDescriptor module,
- Object inputNode,
- Function<Object, K> keyDeserializer,
- Function<Object, V> valueDeserializer,
- Map<K, V> map
- )
- throws Exception
- {
- if( JSONObject.NULL.equals( inputNode ) )
- {
- return;
- }
- if( !( inputNode instanceof JSONArray ) )
- {
- throw new ValueSerializationException( "Expected an array but got " + inputNode );
- }
- JSONArray array = (JSONArray) inputNode;
- for( int idx = 0; idx < array.length(); idx++ )
- {
- Object item = array.get( idx );
- if( !( item instanceof JSONObject ) )
- {
- throw new ValueSerializationException( "Expected an object but got " + inputNode );
- }
- JSONObject object = (JSONObject) item;
- Object keyNode = object.get( "key" );
- Object valueNode = object.get( "value" );
- K key = keyDeserializer.apply( keyNode );
- V value = valueDeserializer.apply( valueNode );
- if( key != null )
- {
- map.put( key, value );
- }
- }
- }
-
- @Override
- protected <V> void putObjectNodeInMap( ModuleDescriptor module,
- Object inputNode,
- Function<Object, V> valueDeserializer,
- Map<String, V> map
- )
- throws Exception
- {
- if( JSONObject.NULL.equals( inputNode ) )
- {
- return;
- }
- if( !( inputNode instanceof JSONObject ) )
- {
- throw new ValueSerializationException( "Expected an object but got " + inputNode );
- }
- JSONObject object = (JSONObject) inputNode;
-
- @SuppressWarnings( "unchecked" )
- Iterator<String> it = object.keys();
- while( it.hasNext() )
- {
- String key = it.next();
- Object item = object.get( key );
- V valueValue = valueDeserializer.apply( item );
- if( key != null )
- {
- map.put( key, valueValue );
- }
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/core/spi/src/main/java/org/apache/polygene/valueserialization/orgjson/OrgJsonValueSerializationService.java
----------------------------------------------------------------------
diff --git a/core/spi/src/main/java/org/apache/polygene/valueserialization/orgjson/OrgJsonValueSerializationService.java b/core/spi/src/main/java/org/apache/polygene/valueserialization/orgjson/OrgJsonValueSerializationService.java
deleted file mode 100644
index 5bf3544..0000000
--- a/core/spi/src/main/java/org/apache/polygene/valueserialization/orgjson/OrgJsonValueSerializationService.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- *
- */
-package org.apache.polygene.valueserialization.orgjson;
-
-import org.apache.polygene.api.mixin.Mixins;
-import org.apache.polygene.api.value.ValueSerialization;
-
-/**
- * ValueSerialization Service producing and consuming JSON documents using org.json.
- */
-@Mixins( { OrgJsonValueSerializer.class, OrgJsonValueDeserializer.class } )
-public interface OrgJsonValueSerializationService
- extends ValueSerialization
-{
-}