http://git-wip-us.apache.org/repos/asf/polygene-java/blob/e4cca11e/extensions/serialization-msgpack/src/main/java/org/apache/polygene/serialization/msgpack/MessagePackDeserializer.java ---------------------------------------------------------------------- diff --git a/extensions/serialization-msgpack/src/main/java/org/apache/polygene/serialization/msgpack/MessagePackDeserializer.java b/extensions/serialization-msgpack/src/main/java/org/apache/polygene/serialization/msgpack/MessagePackDeserializer.java new file mode 100644 index 0000000..f6b8b3a --- /dev/null +++ b/extensions/serialization-msgpack/src/main/java/org/apache/polygene/serialization/msgpack/MessagePackDeserializer.java @@ -0,0 +1,295 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.polygene.serialization.msgpack; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectInputStream; +import java.util.AbstractMap; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Stream; +import org.apache.polygene.api.association.AssociationDescriptor; +import org.apache.polygene.api.entity.EntityReference; +import org.apache.polygene.api.injection.scope.This; +import org.apache.polygene.api.mixin.Mixins; +import org.apache.polygene.api.property.PropertyDescriptor; +import org.apache.polygene.api.serialization.Deserializer; +import org.apache.polygene.api.serialization.SerializationException; +import org.apache.polygene.api.structure.ModuleDescriptor; +import org.apache.polygene.api.type.CollectionType; +import org.apache.polygene.api.type.EnumType; +import org.apache.polygene.api.type.MapType; +import org.apache.polygene.api.type.ValueCompositeType; +import org.apache.polygene.api.type.ValueType; +import org.apache.polygene.api.value.ValueBuilder; +import org.apache.polygene.api.value.ValueDescriptor; +import org.apache.polygene.spi.serialization.AbstractBinaryDeserializer; +import org.msgpack.core.MessagePack; +import org.msgpack.core.MessageUnpacker; +import org.msgpack.value.ArrayValue; +import org.msgpack.value.BinaryValue; +import org.msgpack.value.ImmutableValue; +import org.msgpack.value.MapValue; +import org.msgpack.value.Value; + +import static java.util.Collections.unmodifiableList; +import static java.util.Collections.unmodifiableMap; +import static java.util.Collections.unmodifiableSet; +import static org.apache.polygene.api.util.Collectors.toMap; + +// TODO Test all deserializations for: missing & spurious entries +@Mixins( MessagePackDeserializer.Mixin.class ) +public interface MessagePackDeserializer extends Deserializer +{ + class Mixin extends AbstractBinaryDeserializer + { + @This + private MessagePackAdapters adapters; + + @Override + public <T> T deserialize( ModuleDescriptor module, ValueType valueType, InputStream state ) + { + MessageUnpacker unpacker = MessagePack.newDefaultUnpacker( state ); + try + { + if( !unpacker.hasNext() ) + { + return null; + } + ImmutableValue value = unpacker.unpackValue(); + return doDeserialize( module, valueType, value ); + } + catch( IOException e ) + { + throw new SerializationException( "Unable to deserialize " + valueType ); + } + } + + @SuppressWarnings( "unchecked" ) + private <T> T doDeserialize( ModuleDescriptor module, ValueType valueType, Value value ) + { + try + { + if( value.isNilValue() ) + { + return null; + } + MessagePackAdapter<?> adapter = adapters.adapterFor( valueType ); + if( adapter != null ) + { + return (T) adapter.deserialize( value, ( val, type ) -> doDeserialize( module, valueType, val ) ); + } + if( EnumType.class.isAssignableFrom( valueType.getClass() ) ) + { + return (T) Enum.valueOf( (Class) valueType.primaryType(), value.asStringValue().asString() ); + } + if( CollectionType.class.isAssignableFrom( valueType.getClass() ) ) + { + return (T) deserializeCollection( module, (CollectionType) valueType, value.asArrayValue() ); + } + if( MapType.class.isAssignableFrom( valueType.getClass() ) ) + { + return (T) deserializeMap( module, (MapType) valueType, value.asMapValue() ); + } + if( ValueCompositeType.class.isAssignableFrom( valueType.getClass() ) ) + { + return (T) deserializeValueComposite( module, (ValueCompositeType) valueType, value.asMapValue() ); + } + return (T) doGuessDeserialize( module, valueType, value ); + } + catch( IOException | ClassNotFoundException ex ) + { + throw new SerializationException( "Unable to deserialize " + valueType + " from: " + value ); + } + } + + private Collection<?> deserializeCollection( ModuleDescriptor module, CollectionType collectionType, + ArrayValue value ) throws IOException + { + Collection<?> collection = collectionType.isSet() ? new LinkedHashSet( value.size() ) + : new ArrayList( value.size() ); + for( Value element : value.list() ) + { + collection.add( doDeserialize( module, collectionType.collectedType(), element ) ); + } + return collection; + } + + private Map<Object, Object> deserializeMap( ModuleDescriptor module, MapType mapType, MapValue value ) + throws IOException + { + Map<Object, Object> map = new LinkedHashMap<>( value.size() ); + for( Map.Entry<Value, Value> entry : value.entrySet() ) + { + Object key = doDeserialize( module, mapType.keyType(), entry.getKey() ); + Object val = doDeserialize( module, mapType.valueType(), entry.getValue() ); + map.put( key, val ); + } + return map; + } + + private Object deserializeValueComposite( ModuleDescriptor module, ValueCompositeType valueType, + MapValue value ) throws IOException + { + Map<String, Value> namedValues = value.map().entrySet().stream().map( + entry -> + { + String key = doDeserialize( module, ValueType.STRING, entry.getKey() ); + return new AbstractMap.SimpleImmutableEntry<>( key, entry.getValue() ); + } + ).collect( toMap( HashMap::new ) ); + + String typeInfo = null; + if( namedValues.containsKey( "_type" ) ) + { + typeInfo = doDeserialize( module, ValueType.STRING, namedValues.get( "_type" ) ); + } + if( typeInfo != null ) + { + ValueDescriptor descriptor = module.valueDescriptor( typeInfo ); + if( descriptor == null ) + { + throw new SerializationException( + "_type: " + typeInfo + " could not be resolved while deserializing " + value ); + } + valueType = descriptor.valueType(); + } + + ValueBuilder builder = module.instance().newValueBuilderWithState( + valueType.primaryType(), + propertyFunction( module, namedValues ), + associationFunction( module, namedValues ), + manyAssociationFunction( module, namedValues ), + namedAssociationFunction( module, namedValues ) ); + return builder.newInstance(); + } + + private Function<PropertyDescriptor, Object> propertyFunction( ModuleDescriptor module, + Map<String, Value> namedValues ) + { + return property -> + { + Value value = namedValues.get( property.qualifiedName().name() ); + if( value != null ) + { + Object propertyValue = doDeserialize( module, property.valueType(), value ); + if( property.isImmutable() ) + { + if( propertyValue instanceof Set ) + { + return unmodifiableSet( (Set<?>) propertyValue ); + } + else if( propertyValue instanceof List ) + { + return unmodifiableList( (List<?>) propertyValue ); + } + else if( propertyValue instanceof Map ) + { + return unmodifiableMap( (Map<?, ?>) propertyValue ); + } + } + return propertyValue; + } + return property.initialValue( module ); + }; + } + + private Function<AssociationDescriptor, EntityReference> associationFunction( ModuleDescriptor module, + Map<String, Value> namedValues ) + { + return association -> doDeserialize( module, ValueType.ENTITY_REFERENCE, + namedValues.get( association.qualifiedName().name() ) ); + } + + private Function<AssociationDescriptor, Stream<EntityReference>> manyAssociationFunction( + ModuleDescriptor module, Map<String, Value> namedValues ) + { + return association -> + { + List list = doDeserialize( module, ENTITY_REF_LIST_VALUE_TYPE, + namedValues.get( association.qualifiedName().name() ) ); + return list == null ? Stream.empty() : list.stream(); + }; + } + + private Function<AssociationDescriptor, Stream<Map.Entry<String, EntityReference>>> namedAssociationFunction( + ModuleDescriptor module, Map<String, Value> namedValues ) + { + return association -> + { + Map map = doDeserialize( module, ENTITY_REF_MAP_VALUE_TYPE, + namedValues.get( association.qualifiedName().name() ) ); + return map == null ? Stream.empty() : map.entrySet().stream(); + }; + } + + private Object doGuessDeserialize( ModuleDescriptor module, ValueType valueType, Value value ) + throws IOException, ClassNotFoundException + { + switch( value.getValueType() ) + { + case BINARY: + return deserializeJava( value.asBinaryValue() ); + case MAP: + MapValue mapValue = value.asMapValue(); + Optional<String> typeInfo = mapValue + .entrySet().stream() + .filter( entry -> entry.getKey().isStringValue() ) + .map( entry -> + { + String key = doDeserialize( module, ValueType.STRING, entry.getKey() ); + return new AbstractMap.SimpleImmutableEntry<>( key, entry.getValue() ); + } ) + .filter( entry -> "_type".equals( entry.getKey() ) ) + .findFirst() + .map( entry -> doDeserialize( module, ValueType.STRING, entry.getValue() ) ); + if( typeInfo.isPresent() ) + { + ValueDescriptor valueDescriptor = module.valueDescriptor( typeInfo.get() ); + if( valueDescriptor != null ) + { + return deserializeValueComposite( module, valueDescriptor.valueType(), mapValue ); + } + } + default: + throw new SerializationException( "Don't know how to deserialize " + valueType + " from " + value + + " (" + value.getValueType() + ")" ); + } + } + + private Object deserializeJava( BinaryValue value ) + throws IOException, ClassNotFoundException + { + byte[] bytes = value.asByteArray(); + try( ObjectInputStream oin = new ObjectInputStream( new ByteArrayInputStream( bytes ) ) ) + { + return oin.readObject(); + } + } + } +}
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/e4cca11e/extensions/serialization-msgpack/src/main/java/org/apache/polygene/serialization/msgpack/MessagePackSerialization.java ---------------------------------------------------------------------- diff --git a/extensions/serialization-msgpack/src/main/java/org/apache/polygene/serialization/msgpack/MessagePackSerialization.java b/extensions/serialization-msgpack/src/main/java/org/apache/polygene/serialization/msgpack/MessagePackSerialization.java new file mode 100644 index 0000000..d24d597 --- /dev/null +++ b/extensions/serialization-msgpack/src/main/java/org/apache/polygene/serialization/msgpack/MessagePackSerialization.java @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.polygene.serialization.msgpack; + +public interface MessagePackSerialization extends MessagePackSerializer, MessagePackDeserializer +{ +} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/e4cca11e/extensions/serialization-msgpack/src/main/java/org/apache/polygene/serialization/msgpack/MessagePackSerializationAssembler.java ---------------------------------------------------------------------- diff --git a/extensions/serialization-msgpack/src/main/java/org/apache/polygene/serialization/msgpack/MessagePackSerializationAssembler.java b/extensions/serialization-msgpack/src/main/java/org/apache/polygene/serialization/msgpack/MessagePackSerializationAssembler.java new file mode 100644 index 0000000..63536cc --- /dev/null +++ b/extensions/serialization-msgpack/src/main/java/org/apache/polygene/serialization/msgpack/MessagePackSerializationAssembler.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.polygene.serialization.msgpack; + +import org.apache.polygene.api.serialization.Deserializer; +import org.apache.polygene.api.serialization.Serialization; +import org.apache.polygene.api.serialization.Serializer; +import org.apache.polygene.bootstrap.Assemblers; +import org.apache.polygene.bootstrap.ModuleAssembly; +import org.apache.polygene.bootstrap.ServiceDeclaration; + +public class MessagePackSerializationAssembler extends Assemblers.VisibilityIdentity<MessagePackSerializationAssembler> +{ + private MessagePackSettings settings; + + public MessagePackSerializationAssembler withMessagePackSettings( MessagePackSettings settings ) + { + this.settings = settings; + return this; + } + + @Override + public void assemble( ModuleAssembly module ) + { + ServiceDeclaration declaration = module.services( MessagePackSerializationService.class ) + .withTypes( Serialization.class, Serializer.class, Deserializer.class ) + .visibleIn( visibility() ); + if( hasIdentity() ) + { + declaration.identifiedBy( identity() ); + } + if( settings != null ) + { + declaration.setMetaInfo( settings ); + } + } +} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/e4cca11e/extensions/serialization-msgpack/src/main/java/org/apache/polygene/serialization/msgpack/MessagePackSerializationService.java ---------------------------------------------------------------------- diff --git a/extensions/serialization-msgpack/src/main/java/org/apache/polygene/serialization/msgpack/MessagePackSerializationService.java b/extensions/serialization-msgpack/src/main/java/org/apache/polygene/serialization/msgpack/MessagePackSerializationService.java new file mode 100644 index 0000000..4cd23b7 --- /dev/null +++ b/extensions/serialization-msgpack/src/main/java/org/apache/polygene/serialization/msgpack/MessagePackSerializationService.java @@ -0,0 +1,414 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.polygene.serialization.msgpack; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.time.Duration; +import java.time.Instant; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.OffsetDateTime; +import java.time.Period; +import java.time.ZonedDateTime; +import java.util.function.BiFunction; +import java.util.function.Function; +import org.apache.polygene.api.entity.EntityReference; +import org.apache.polygene.api.identity.Identity; +import org.apache.polygene.api.identity.StringIdentity; +import org.apache.polygene.api.injection.scope.This; +import org.apache.polygene.api.injection.scope.Uses; +import org.apache.polygene.api.mixin.Mixins; +import org.apache.polygene.api.service.ServiceActivation; +import org.apache.polygene.api.service.ServiceDescriptor; +import org.apache.polygene.api.type.ValueType; +import org.msgpack.value.Value; +import org.msgpack.value.ValueFactory; + +@Mixins( MessagePackSerializationService.Activation.class ) +public interface MessagePackSerializationService extends MessagePackSerialization, ServiceActivation +{ + class Activation implements ServiceActivation + { + @Uses + private ServiceDescriptor descriptor; + + @This + private MessagePackAdapters adapters; + + private boolean registrationDone = false; + + @Override + public void activateService() + { + if( !registrationDone ) + { + registerCustomAdapters(); + registerBaseAdapters(); + registrationDone = true; + } + } + + @Override + public void passivateService() {} + + private void registerCustomAdapters() + { + MessagePackSettings.orDefault( descriptor.metaInfo( MessagePackSettings.class ) ) + .getAdapters() + .forEach( ( valueType, adapter ) -> adapters.registerAdapter( valueType, adapter ) ); + } + + private void registerBaseAdapters() + { + // Primitive Value types + adapters.registerAdapter( ValueType.STRING, new StringAdapter() ); + adapters.registerAdapter( ValueType.CHARACTER, new CharacterAdapter() ); + adapters.registerAdapter( ValueType.BOOLEAN, new BooleanAdapter() ); + adapters.registerAdapter( ValueType.INTEGER, new IntegerAdapter() ); + adapters.registerAdapter( ValueType.LONG, new LongAdapter() ); + adapters.registerAdapter( ValueType.SHORT, new ShortAdapter() ); + adapters.registerAdapter( ValueType.BYTE, new ByteAdapter() ); + adapters.registerAdapter( ValueType.FLOAT, new FloatAdapter() ); + adapters.registerAdapter( ValueType.DOUBLE, new DoubleAdapter() ); + + // Number types + adapters.registerAdapter( ValueType.BIG_DECIMAL, new BigDecimalAdapter() ); + adapters.registerAdapter( ValueType.BIG_INTEGER, new BigIntegerAdapter() ); + + // Date types + adapters.registerAdapter( ValueType.INSTANT, new InstantAdapter() ); + adapters.registerAdapter( ValueType.ZONED_DATE_TIME, new ZonedDateTimeAdapter() ); + adapters.registerAdapter( ValueType.OFFSET_DATE_TIME, new OffsetDateTimeAdapter() ); + adapters.registerAdapter( ValueType.LOCAL_DATE_TIME, new LocalDateTimeAdapter() ); + adapters.registerAdapter( ValueType.LOCAL_DATE, new LocalDateAdapter() ); + adapters.registerAdapter( ValueType.LOCAL_TIME, new LocalTimeAdapter() ); + adapters.registerAdapter( ValueType.DURATION, new DurationAdapter() ); + adapters.registerAdapter( ValueType.PERIOD, new PeriodAdapter() ); + + // Other supported types + adapters.registerAdapter( ValueType.IDENTITY, new IdentityAdapter() ); + adapters.registerAdapter( ValueType.ENTITY_REFERENCE, new EntityReferenceAdapter() ); + } + + private static abstract class ToStringAdapter<T> implements MessagePackAdapter<T> + { + @Override + public Value serialize( Object object, Function<Object, Value> serializeFunction ) + { + return ValueFactory.newString( object.toString() ); + } + } + + private static class StringAdapter extends ToStringAdapter<String> + { + @Override + public Class<String> type() { return String.class; } + + @Override + public String deserialize( Value value, BiFunction<Value, ValueType, Object> deserializeFunction ) + { + return value.asStringValue().asString(); + } + } + + private static class CharacterAdapter extends ToStringAdapter<Character> + { + @Override + public Class<Character> type() { return Character.class; } + + @Override + public Character deserialize( Value value, BiFunction<Value, ValueType, Object> deserializeFunction ) + { + String string = value.asStringValue().asString(); + return string.isEmpty() ? null : string.charAt( 0 ); + } + } + + private static class BooleanAdapter implements MessagePackAdapter<Boolean> + { + @Override + public Class<Boolean> type() { return Boolean.class; } + + @Override + public Value serialize( Object object, Function<Object, Value> serializeFunction ) + { + return ValueFactory.newBoolean( (Boolean) object ); + } + + @Override + public Boolean deserialize( Value value, BiFunction<Value, ValueType, Object> deserializeFunction ) + { + return value.asBooleanValue().getBoolean(); + } + } + + private static class IntegerAdapter implements MessagePackAdapter<Integer> + { + @Override + public Class<Integer> type() { return Integer.class; } + + @Override + public Value serialize( Object object, Function<Object, Value> serializeFunction ) + { + return ValueFactory.newInteger( (Integer) object ); + } + + @Override + public Integer deserialize( Value value, BiFunction<Value, ValueType, Object> deserializeFunction ) + { + return value.asIntegerValue().asInt(); + } + } + + private static class LongAdapter implements MessagePackAdapter<Long> + { + @Override + public Class<Long> type() { return Long.class; } + + @Override + public Value serialize( Object object, Function<Object, Value> serializeFunction ) + { + return ValueFactory.newInteger( (Long) object ); + } + + @Override + public Long deserialize( Value value, BiFunction<Value, ValueType, Object> deserializeFunction ) + { + return value.asIntegerValue().asLong(); + } + } + + private static class ShortAdapter implements MessagePackAdapter<Short> + { + @Override + public Class<Short> type() { return Short.class; } + + @Override + public Value serialize( Object object, Function<Object, Value> serializeFunction ) + { + return ValueFactory.newInteger( (Short) object ); + } + + @Override + public Short deserialize( Value value, BiFunction<Value, ValueType, Object> deserializeFunction ) + { + return value.asIntegerValue().asShort(); + } + } + + private static class ByteAdapter implements MessagePackAdapter<Byte> + { + @Override + public Class<Byte> type() { return Byte.class; } + + @Override + public Value serialize( Object object, Function<Object, Value> serializeFunction ) + { + return ValueFactory.newInteger( (Byte) object ); + } + + @Override + public Byte deserialize( Value value, BiFunction<Value, ValueType, Object> deserializeFunction ) + { + return value.asIntegerValue().asByte(); + } + } + + private static class FloatAdapter implements MessagePackAdapter<Float> + { + @Override + public Class<Float> type() { return Float.class; } + + @Override + public Value serialize( Object object, Function<Object, Value> serializeFunction ) + { + return ValueFactory.newFloat( (Float) object ); + } + + @Override + public Float deserialize( Value value, BiFunction<Value, ValueType, Object> deserializeFunction ) + { + return value.asFloatValue().toFloat(); + } + } + + private static class DoubleAdapter implements MessagePackAdapter<Double> + { + @Override + public Class<Double> type() { return Double.class; } + + @Override + public Value serialize( Object object, Function<Object, Value> serializeFunction ) + { + return ValueFactory.newFloat( (Double) object ); + } + + @Override + public Double deserialize( Value value, BiFunction<Value, ValueType, Object> deserializeFunction ) + { + return value.asFloatValue().toDouble(); + } + } + + private static class BigDecimalAdapter extends ToStringAdapter<BigDecimal> + { + @Override + public Class<BigDecimal> type() { return BigDecimal.class; } + + @Override + public BigDecimal deserialize( Value value, BiFunction<Value, ValueType, Object> deserializeFunction ) + { + return new BigDecimal( value.asStringValue().asString() ); + } + } + + private static class BigIntegerAdapter extends ToStringAdapter<BigInteger> + { + @Override + public Class<BigInteger> type() { return BigInteger.class; } + + @Override + public BigInteger deserialize( Value value, BiFunction<Value, ValueType, Object> deserializeFunction ) + { + return new BigInteger( value.asStringValue().asString() ); + } + } + + private static class InstantAdapter extends ToStringAdapter<Instant> + { + @Override + public Class<Instant> type() { return Instant.class; } + + @Override + public Instant deserialize( Value value, BiFunction<Value, ValueType, Object> deserializeFunction ) + { + return Instant.parse( value.asStringValue().asString() ); + } + } + + private static class ZonedDateTimeAdapter extends ToStringAdapter<ZonedDateTime> + { + @Override + public Class<ZonedDateTime> type() { return ZonedDateTime.class; } + + @Override + public ZonedDateTime deserialize( Value value, BiFunction<Value, ValueType, Object> deserializeFunction ) + { + return ZonedDateTime.parse( value.asStringValue().asString() ); + } + } + + private static class OffsetDateTimeAdapter extends ToStringAdapter<OffsetDateTime> + { + @Override + public Class<OffsetDateTime> type() { return OffsetDateTime.class; } + + @Override + public OffsetDateTime deserialize( Value value, BiFunction<Value, ValueType, Object> deserializeFunction ) + { + return OffsetDateTime.parse( value.asStringValue().asString() ); + } + } + + private static class LocalDateTimeAdapter extends ToStringAdapter<LocalDateTime> + { + @Override + public Class<LocalDateTime> type() { return LocalDateTime.class; } + + @Override + public LocalDateTime deserialize( Value value, BiFunction<Value, ValueType, Object> deserializeFunction ) + { + return LocalDateTime.parse( value.asStringValue().asString() ); + } + } + + private static class LocalDateAdapter extends ToStringAdapter<LocalDate> + { + @Override + public Class<LocalDate> type() { return LocalDate.class; } + + @Override + public LocalDate deserialize( Value value, BiFunction<Value, ValueType, Object> deserializeFunction ) + { + return LocalDate.parse( value.asStringValue().asString() ); + } + } + + private static class LocalTimeAdapter extends ToStringAdapter<LocalTime> + { + @Override + public Class<LocalTime> type() { return LocalTime.class; } + + @Override + public LocalTime deserialize( Value value, BiFunction<Value, ValueType, Object> deserializeFunction ) + { + return LocalTime.parse( value.asStringValue().asString() ); + } + } + + private static class DurationAdapter extends ToStringAdapter<Duration> + { + @Override + public Class<Duration> type() { return Duration.class; } + + @Override + public Duration deserialize( Value value, BiFunction<Value, ValueType, Object> deserializeFunction ) + { + return Duration.parse( value.asStringValue().asString() ); + } + } + + private static class PeriodAdapter extends ToStringAdapter<Period> + { + @Override + public Class<Period> type() { return Period.class; } + + @Override + public Period deserialize( Value value, BiFunction<Value, ValueType, Object> deserializeFunction ) + { + return Period.parse( value.asStringValue().asString() ); + } + } + + private static class IdentityAdapter extends ToStringAdapter<Identity> + { + @Override + public Class<Identity> type() { return Identity.class; } + + @Override + public Identity deserialize( Value value, BiFunction<Value, ValueType, Object> deserializeFunction ) + { + return StringIdentity.fromString( value.asStringValue().asString() ); + } + } + + private static class EntityReferenceAdapter extends ToStringAdapter<EntityReference> + { + @Override + public Class<EntityReference> type() { return EntityReference.class; } + + @Override + public EntityReference deserialize( Value value, BiFunction<Value, ValueType, Object> deserializeFunction ) + { + return EntityReference.parseEntityReference( value.asStringValue().asString() ); + } + } + } +} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/e4cca11e/extensions/serialization-msgpack/src/main/java/org/apache/polygene/serialization/msgpack/MessagePackSerializer.java ---------------------------------------------------------------------- diff --git a/extensions/serialization-msgpack/src/main/java/org/apache/polygene/serialization/msgpack/MessagePackSerializer.java b/extensions/serialization-msgpack/src/main/java/org/apache/polygene/serialization/msgpack/MessagePackSerializer.java new file mode 100644 index 0000000..7321e6d --- /dev/null +++ b/extensions/serialization-msgpack/src/main/java/org/apache/polygene/serialization/msgpack/MessagePackSerializer.java @@ -0,0 +1,187 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.polygene.serialization.msgpack; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectOutputStream; +import java.io.OutputStream; +import java.util.Map; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; +import org.apache.polygene.api.PolygeneAPI; +import org.apache.polygene.api.association.AssociationStateHolder; +import org.apache.polygene.api.common.Optional; +import org.apache.polygene.api.composite.CompositeInstance; +import org.apache.polygene.api.injection.scope.This; +import org.apache.polygene.api.mixin.Mixins; +import org.apache.polygene.api.serialization.SerializationException; +import org.apache.polygene.api.serialization.Serializer; +import org.apache.polygene.api.type.EnumType; +import org.apache.polygene.api.type.MapType; +import org.apache.polygene.api.type.ValueCompositeType; +import org.apache.polygene.api.value.ValueComposite; +import org.apache.polygene.api.value.ValueDescriptor; +import org.apache.polygene.spi.serialization.AbstractBinarySerializer; +import org.msgpack.core.MessagePack; +import org.msgpack.core.MessagePacker; +import org.msgpack.value.ArrayValue; +import org.msgpack.value.BinaryValue; +import org.msgpack.value.MapValue; +import org.msgpack.value.Value; +import org.msgpack.value.ValueFactory; + +import static java.util.stream.Collectors.toList; +import static org.apache.polygene.api.util.Collectors.toMap; + +@Mixins( MessagePackSerializer.Mixin.class ) +public interface MessagePackSerializer extends Serializer +{ + class Mixin extends AbstractBinarySerializer + { + @This + private MessagePackAdapters adapters; + + @Override + public void serialize( Options options, OutputStream output, @Optional Object object ) + { + MessagePacker packer = MessagePack.newDefaultPacker( output ); + Value value = doSerialize( options, object, true ); + try + { + packer.packValue( value ); + packer.flush(); + } + catch( IOException ex ) + { + throw new SerializationException( "Unable to serialize " + object, ex ); + } + } + + private Value doSerialize( Options options, Object object, boolean root ) + { + try + { + if( object == null ) + { + return ValueFactory.newNil(); + } + Class<?> objectClass = object.getClass(); + MessagePackAdapter<?> adapter = adapters.adapterFor( objectClass ); + if( adapter != null ) + { + return adapter.serialize( object, obj -> doSerialize( options, obj, false ) ); + } + if( EnumType.isEnum( objectClass ) ) + { + return ValueFactory.newString( object.toString() ); + } + if( ValueCompositeType.isValueComposite( objectClass ) ) + { + return serializeValueComposite( options, object, root ); + } + if( MapType.isMap( objectClass ) ) + { + return serializeMap( options, (Map<?, ?>) object ); + } + if( Iterable.class.isAssignableFrom( objectClass ) ) + { + return serializeIterable( options, (Iterable<?>) object ); + } + if( Stream.class.isAssignableFrom( objectClass ) ) + { + return serializeStream( options, (Stream<?>) object ); + } + // Fallback to Java Serialization + // Include all arrays! + return serializeJava( object ); + } + catch( IOException ex ) + { + throw new SerializationException( "Unable to serialize " + object, ex ); + } + } + + private MapValue serializeValueComposite( Options options, Object composite, boolean root ) + { + CompositeInstance instance = PolygeneAPI.FUNCTION_COMPOSITE_INSTANCE_OF.apply( (ValueComposite) composite ); + ValueDescriptor descriptor = (ValueDescriptor) instance.descriptor(); + AssociationStateHolder state = (AssociationStateHolder) instance.state(); + ValueCompositeType valueType = descriptor.valueType(); + + ValueFactory.MapBuilder builder = ValueFactory.newMapBuilder(); + valueType.properties().forEach( + property -> builder.put( + ValueFactory.newString( property.qualifiedName().name() ), + doSerialize( options, state.propertyFor( property.accessor() ).get(), false ) ) ); + valueType.associations().forEach( + association -> builder.put( + ValueFactory.newString( association.qualifiedName().name() ), + doSerialize( options, state.associationFor( association.accessor() ).reference(), false ) ) ); + valueType.manyAssociations().forEach( + association -> builder.put( + ValueFactory.newString( association.qualifiedName().name() ), + doSerialize( options, + state.manyAssociationFor( association.accessor() ).references().collect( toList() ), + false ) ) ); + valueType.namedAssociations().forEach( + association -> builder.put( + ValueFactory.newString( association.qualifiedName().name() ), + doSerialize( options, + state.namedAssociationFor( association.accessor() ).references().collect( toMap() ), + false ) ) ); + + if( !root && options.includeTypeInfo() ) + { + builder.put( ValueFactory.newString( "_type" ), + ValueFactory.newString( valueType.primaryType().getName() ) ); + } + return builder.build(); + } + + private MapValue serializeMap( Options options, Map<?, ?> map ) + { + ValueFactory.MapBuilder builder = ValueFactory.newMapBuilder(); + map.forEach( ( key, value ) -> builder.put( doSerialize( options, key, false ), + doSerialize( options, value, false ) ) ); + return builder.build(); + } + + private ArrayValue serializeIterable( Options options, Iterable<?> iterable ) + { + return serializeStream( options, StreamSupport.stream( iterable.spliterator(), false ) ); + } + + private ArrayValue serializeStream( Options options, Stream<?> stream ) + { + return ValueFactory.newArray( stream.map( element -> doSerialize( options, element, false ) ) + .collect( toList() ) ); + } + + private BinaryValue serializeJava( Object object ) throws IOException + { + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + try( ObjectOutputStream out = new ObjectOutputStream( bout ) ) + { + out.writeUnshared( object ); + byte[] bytes = bout.toByteArray(); + return ValueFactory.newBinary( bytes ); + } + } + } +} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/e4cca11e/extensions/serialization-msgpack/src/main/java/org/apache/polygene/serialization/msgpack/MessagePackSettings.java ---------------------------------------------------------------------- diff --git a/extensions/serialization-msgpack/src/main/java/org/apache/polygene/serialization/msgpack/MessagePackSettings.java b/extensions/serialization-msgpack/src/main/java/org/apache/polygene/serialization/msgpack/MessagePackSettings.java new file mode 100644 index 0000000..8080d94 --- /dev/null +++ b/extensions/serialization-msgpack/src/main/java/org/apache/polygene/serialization/msgpack/MessagePackSettings.java @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.polygene.serialization.msgpack; + +import java.util.LinkedHashMap; +import java.util.Map; +import org.apache.polygene.api.type.ValueType; + +public class MessagePackSettings +{ + public static final MessagePackSettings DEFAULT = new MessagePackSettings(); + + public static MessagePackSettings orDefault( MessagePackSettings settings ) + { + return settings != null ? settings : DEFAULT; + } + + private Map<ValueType, MessagePackAdapter<?>> adapters; + + public MessagePackSettings() + { + adapters = new LinkedHashMap<>(); + } + + public Map<ValueType, MessagePackAdapter<?>> getAdapters() + { + return adapters; + } +} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/e4cca11e/extensions/serialization-msgpack/src/main/java/org/apache/polygene/serialization/msgpack/package.html ---------------------------------------------------------------------- diff --git a/extensions/serialization-msgpack/src/main/java/org/apache/polygene/serialization/msgpack/package.html b/extensions/serialization-msgpack/src/main/java/org/apache/polygene/serialization/msgpack/package.html new file mode 100644 index 0000000..16c905a --- /dev/null +++ b/extensions/serialization-msgpack/src/main/java/org/apache/polygene/serialization/msgpack/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>MessagePack Serialization.</h2> + </body> +</html> http://git-wip-us.apache.org/repos/asf/polygene-java/blob/e4cca11e/extensions/serialization-msgpack/src/test/java/org/apache/polygene/serialization/msgpack/MessagePackCollectionSerializationTest.java ---------------------------------------------------------------------- diff --git a/extensions/serialization-msgpack/src/test/java/org/apache/polygene/serialization/msgpack/MessagePackCollectionSerializationTest.java b/extensions/serialization-msgpack/src/test/java/org/apache/polygene/serialization/msgpack/MessagePackCollectionSerializationTest.java new file mode 100644 index 0000000..6ade37f --- /dev/null +++ b/extensions/serialization-msgpack/src/test/java/org/apache/polygene/serialization/msgpack/MessagePackCollectionSerializationTest.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.msgpack; + +import org.apache.polygene.bootstrap.ModuleAssembly; +import org.apache.polygene.test.serialization.AbstractCollectionSerializationTest; + +public class MessagePackCollectionSerializationTest extends AbstractCollectionSerializationTest +{ + @Override + public void assemble( ModuleAssembly module ) + { + new MessagePackSerializationAssembler().assemble( module ); + super.assemble( module ); + } +} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/e4cca11e/extensions/serialization-msgpack/src/test/java/org/apache/polygene/serialization/msgpack/MessagePackDateFormatSerializationTest.java ---------------------------------------------------------------------- diff --git a/extensions/serialization-msgpack/src/test/java/org/apache/polygene/serialization/msgpack/MessagePackDateFormatSerializationTest.java b/extensions/serialization-msgpack/src/test/java/org/apache/polygene/serialization/msgpack/MessagePackDateFormatSerializationTest.java new file mode 100644 index 0000000..083d418 --- /dev/null +++ b/extensions/serialization-msgpack/src/test/java/org/apache/polygene/serialization/msgpack/MessagePackDateFormatSerializationTest.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.msgpack; + +import org.apache.polygene.bootstrap.ModuleAssembly; +import org.apache.polygene.test.serialization.AbstractDateFormatSerializationTest; +import org.junit.Ignore; + +@Ignore( "Super test assume text" ) +public class MessagePackDateFormatSerializationTest extends AbstractDateFormatSerializationTest +{ + @Override + public void assemble( ModuleAssembly module ) + { + new MessagePackSerializationAssembler().assemble( module ); + super.assemble( module ); + } +} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/e4cca11e/extensions/serialization-msgpack/src/test/java/org/apache/polygene/serialization/msgpack/MessagePackPlainValueSerializationTest.java ---------------------------------------------------------------------- diff --git a/extensions/serialization-msgpack/src/test/java/org/apache/polygene/serialization/msgpack/MessagePackPlainValueSerializationTest.java b/extensions/serialization-msgpack/src/test/java/org/apache/polygene/serialization/msgpack/MessagePackPlainValueSerializationTest.java new file mode 100644 index 0000000..3940b64 --- /dev/null +++ b/extensions/serialization-msgpack/src/test/java/org/apache/polygene/serialization/msgpack/MessagePackPlainValueSerializationTest.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.msgpack; + +import org.apache.polygene.bootstrap.ModuleAssembly; +import org.apache.polygene.test.serialization.AbstractPlainValueSerializationTest; +import org.junit.Ignore; + +@Ignore( "Super test assume text" ) +public class MessagePackPlainValueSerializationTest extends AbstractPlainValueSerializationTest +{ + @Override + public void assemble( ModuleAssembly module ) + { + new MessagePackSerializationAssembler().assemble( module ); + super.assemble( module ); + } +} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/e4cca11e/extensions/serialization-msgpack/src/test/java/org/apache/polygene/serialization/msgpack/MessagePackValueCompositeSerializationTest.java ---------------------------------------------------------------------- diff --git a/extensions/serialization-msgpack/src/test/java/org/apache/polygene/serialization/msgpack/MessagePackValueCompositeSerializationTest.java b/extensions/serialization-msgpack/src/test/java/org/apache/polygene/serialization/msgpack/MessagePackValueCompositeSerializationTest.java new file mode 100644 index 0000000..204f991 --- /dev/null +++ b/extensions/serialization-msgpack/src/test/java/org/apache/polygene/serialization/msgpack/MessagePackValueCompositeSerializationTest.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.msgpack; + +import org.apache.polygene.bootstrap.ModuleAssembly; +import org.apache.polygene.test.serialization.AbstractValueCompositeSerializationTest; + +public class MessagePackValueCompositeSerializationTest extends AbstractValueCompositeSerializationTest +{ + @Override + public void assemble( ModuleAssembly module ) + { + new MessagePackSerializationAssembler().assemble( module ); + super.assemble( module ); + } +} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/e4cca11e/extensions/valueserialization-jackson/build.gradle ---------------------------------------------------------------------- diff --git a/extensions/valueserialization-jackson/build.gradle b/extensions/valueserialization-jackson/build.gradle deleted file mode 100644 index 17ac4b5..0000000 --- a/extensions/valueserialization-jackson/build.gradle +++ /dev/null @@ -1,37 +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. - * - * - */ - -apply plugin: 'polygene-extension' - -description = "Apache Polygene⢠Jackson ValueSerialization Extension" - -jar { manifest { name = "Apache Polygene⢠Extension - ValueSerialization - Jackson" } } - -dependencies { - compile polygene.core.bootstrap - compile libraries.jackson_mapper - - runtime polygene.core.runtime - - testCompile polygene.core.testsupport - - testRuntime libraries.logback -} - http://git-wip-us.apache.org/repos/asf/polygene-java/blob/e4cca11e/extensions/valueserialization-jackson/dev-status.xml ---------------------------------------------------------------------- diff --git a/extensions/valueserialization-jackson/dev-status.xml b/extensions/valueserialization-jackson/dev-status.xml deleted file mode 100644 index 7fa50ff..0000000 --- a/extensions/valueserialization-jackson/dev-status.xml +++ /dev/null @@ -1,36 +0,0 @@ -<?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> - <codebase>beta</codebase> - <!--none,early,beta,stable,mature--> - <documentation>good</documentation> - <!-- none, brief, good, complete --> - <unittests>complete</unittests> - <!-- none, some, good, complete --> - </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/valueserialization-jackson/src/docs/vs-jackson.txt ---------------------------------------------------------------------- diff --git a/extensions/valueserialization-jackson/src/docs/vs-jackson.txt b/extensions/valueserialization-jackson/src/docs/vs-jackson.txt deleted file mode 100644 index 8605125..0000000 --- a/extensions/valueserialization-jackson/src/docs/vs-jackson.txt +++ /dev/null @@ -1,43 +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. -/////////////////////////////////////////////////////////////// - -[[extension-vs-jackson, Jackson ValueSerialization]] -= Jackson ValueSerialization = - -[devstatus] --------------- -source=extensions/valueserialization-jackson/dev-status.xml --------------- - -ValueSerialization Service backed by http://wiki.fasterxml.com/JacksonHome[Jackson]. - -include::../../build/docs/buildinfo/artifact.txt[] - -== Assembly == - -Assembly is done as follows: - -[snippet,java] ----- -source=extensions/valueserialization-jackson/src/test/java/org/apache/polygene/valueserialization/jackson/JacksonPlainValueSerializationTest.java -tag=assembly ----- - -See the ValueSerialization <<core-api-value,API>> and <<core-spi-valueserialization,SPI>> documentation for details and -usage. http://git-wip-us.apache.org/repos/asf/polygene-java/blob/e4cca11e/extensions/valueserialization-jackson/src/main/java/org/apache/polygene/valueserialization/jackson/JacksonValueDeserializer.java ---------------------------------------------------------------------- diff --git a/extensions/valueserialization-jackson/src/main/java/org/apache/polygene/valueserialization/jackson/JacksonValueDeserializer.java b/extensions/valueserialization-jackson/src/main/java/org/apache/polygene/valueserialization/jackson/JacksonValueDeserializer.java deleted file mode 100644 index 256cbe7..0000000 --- a/extensions/valueserialization-jackson/src/main/java/org/apache/polygene/valueserialization/jackson/JacksonValueDeserializer.java +++ /dev/null @@ -1,379 +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.jackson; - -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.JsonToken; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.MappingJsonFactory; -import com.fasterxml.jackson.databind.node.ArrayNode; -import com.fasterxml.jackson.databind.node.ObjectNode; -import java.io.InputStream; -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.type.ValueType; -import org.apache.polygene.api.value.ValueSerializationException; -import org.apache.polygene.spi.value.ValueDeserializerAdapter; - -/** - * ValueDeserializer reading Values from JSON documents using Jackson. - */ -public class JacksonValueDeserializer - extends ValueDeserializerAdapter<JsonParser, JsonNode> -{ - - private final JsonFactory jsonFactory = new MappingJsonFactory(); - - @Override - protected JsonParser adaptInput( ModuleDescriptor module, InputStream input ) - throws Exception - { - return jsonFactory.createParser( input ); - } - - @Override - protected void onDeserializationEnd( ModuleDescriptor module, ValueType valueType, JsonParser input ) - throws Exception - { - input.close(); - } - - @Override - protected Object readPlainValue( ModuleDescriptor module, JsonParser input ) - throws Exception - { - JsonNode jsonNode = input.readValueAsTree(); - if( jsonNode.isArray() || jsonNode.isObject() ) - { - throw new ValueSerializationException( "Asked for a Value but found an Object or an Array at " - + input.getCurrentLocation().toString() ); - } - if( jsonNode.isDouble() ) - { - return jsonNode.asDouble(); - } - if( jsonNode.isLong() ) - { - return jsonNode.asLong(); - } - if( jsonNode.isInt() ) - { - return jsonNode.asInt(); - } - if( jsonNode.isBoolean() ) - { - return jsonNode.asBoolean(); - } - if( jsonNode.isNull() ) - { - return null; - } - return jsonNode.asText(); - } - - @Override - protected <T> Collection<T> readArrayInCollection( ModuleDescriptor module, - JsonParser input, - Function<JsonParser, T> deserializer, - Collection<T> collection - ) - throws Exception - { - JsonToken token = input.getCurrentToken(); - if( token == JsonToken.VALUE_NULL ) - { - return null; - } - if( token != JsonToken.START_ARRAY ) - { - token = input.nextToken(); - } - if( token == JsonToken.VALUE_NULL ) - { - return null; - } - if( token != JsonToken.START_ARRAY ) - { - throw new ValueSerializationException( "Expected an array start at " - + input.getCurrentLocation().toString() ); - } - while( input.nextToken() != JsonToken.END_ARRAY ) - { - T element = deserializer.apply( input ); - collection.add( element ); - } - return collection; - } - - @Override - protected <K, V> Map<K, V> readMapInMap( ModuleDescriptor module, - JsonParser input, - Function<JsonParser, K> keyDeserializer, - Function<JsonParser, V> valueDeserializer, - Map<K, V> map - ) - throws Exception - { - JsonToken token = input.getCurrentToken(); - if( token == JsonToken.VALUE_NULL ) - { - return null; - } - if( token != JsonToken.START_ARRAY ) - { - token = input.nextToken(); - } - if( token == JsonToken.VALUE_NULL ) - { - return null; - } - if( token != JsonToken.START_ARRAY ) - { - throw new ValueSerializationException( "Expected an array start at " - + input.getCurrentLocation().toString() ); - } - JsonToken currentToken = input.nextToken(); - while( currentToken != JsonToken.END_ARRAY ) - { - if( currentToken != JsonToken.START_OBJECT ) - { - throw new ValueSerializationException( "Expected an object start at " - + input.getCurrentLocation().toString() ); - } - currentToken = input.nextToken(); - K key = null; - V value = null; - while( currentToken != JsonToken.END_OBJECT ) - { - String objectKey = input.getCurrentName(); - input.nextToken(); - if( "key".equals( objectKey ) ) - { - key = keyDeserializer.apply( input ); - } - else if( "value".equals( objectKey ) ) - { - value = valueDeserializer.apply( input ); - } - else - { - //input.nextToken(); - input.skipChildren(); - } - currentToken = input.nextToken(); - } - if( key != null ) - { - map.put( key, value ); - } - currentToken = input.nextToken(); - } - return map; - } - - @Override - protected ObjectNode readObjectTree( ModuleDescriptor module, JsonParser input ) - throws Exception - { - JsonToken token = input.getCurrentToken(); - if( token == JsonToken.VALUE_NULL ) - { - return null; - } - if( token != JsonToken.START_OBJECT ) - { - token = input.nextToken(); - } - if( token != JsonToken.START_OBJECT ) - { - String message = "Expected an object start at " + input.getCurrentLocation().toString(); - throw new ValueSerializationException( message ); - } - return (ObjectNode) input.readValueAsTree(); - } - - @Override - protected Object asSimpleValue( ModuleDescriptor module, JsonNode inputNode ) - throws Exception - { - if( isNullOrMissing( inputNode ) ) - { - return null; - } - if( !inputNode.isValueNode() ) - { - throw new ValueSerializationException( "Expected a value node but got a container node " + inputNode ); - } - if( inputNode.isDouble() ) - { - return inputNode.asDouble(); - } - if( inputNode.isLong() ) - { - return inputNode.asLong(); - } - if( inputNode.isInt() ) - { - return inputNode.asInt(); - } - if( inputNode.isBoolean() ) - { - return inputNode.asBoolean(); - } - return inputNode.asText(); - } - - @Override - @SuppressWarnings( "SimplifiableIfStatement" ) - protected boolean isObjectValue( ModuleDescriptor module, JsonNode inputNode ) - throws Exception - { - if( isNullOrMissing( inputNode ) ) - { - return false; - } - return inputNode.isObject(); - } - - @Override - protected boolean objectHasField( ModuleDescriptor module, JsonNode inputNode, String key ) - throws Exception - { - if( isNullOrMissing( inputNode ) ) - { - return false; - } - if( !inputNode.isObject() ) - { - throw new ValueSerializationException( "Expected an object but got " + inputNode ); - } - return inputNode.has( key ); - } - - @Override - protected <T> T getObjectFieldValue( ModuleDescriptor module, - JsonNode inputNode, - String key, - Function<JsonNode, T> valueDeserializer - ) - throws Exception - { - JsonNode valueNode = inputNode.get( key ); - if( isNullOrMissing( valueNode ) ) - { - return null; - } - return valueDeserializer.apply( valueNode ); - } - - @Override - protected <T> void putArrayNodeInCollection( ModuleDescriptor module, - JsonNode inputNode, - Function<JsonNode, T> deserializer, - Collection<T> collection - ) - throws Exception - { - if( isNullOrMissing( inputNode ) ) - { - return; - } - if( !inputNode.isArray() ) - { - throw new ValueSerializationException( "Expected an array but got " + inputNode ); - } - ArrayNode array = (ArrayNode) inputNode; - for( JsonNode item : array ) - { - T value = deserializer.apply( item ); - collection.add( value ); - } - } - - @Override - protected <K, V> void putArrayNodeInMap( ModuleDescriptor module, - JsonNode inputNode, - Function<JsonNode, K> keyDeserializer, - Function<JsonNode, V> valueDeserializer, - Map<K, V> map - ) - throws Exception - { - if( isNullOrMissing( inputNode ) ) - { - return; - } - if( !inputNode.isArray() ) - { - throw new ValueSerializationException( "Expected an array but got " + inputNode ); - } - ArrayNode array = (ArrayNode) inputNode; - for( JsonNode item : array ) - { - if( !item.isObject() ) - { - throw new ValueSerializationException( "Expected an object but got " + inputNode ); - } - JsonNode keyNode = item.get( "key" ); - JsonNode valueNode = item.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, - JsonNode inputNode, - Function<JsonNode, V> valueDeserializer, - Map<String, V> map - ) - throws Exception - { - if( isNullOrMissing( inputNode ) ) - { - return; - } - if( !inputNode.isObject() ) - { - throw new ValueSerializationException( "Expected an object but got " + inputNode ); - } - ObjectNode object = (ObjectNode) inputNode; - Iterator<Map.Entry<String, JsonNode>> fields = object.fields(); - while( fields.hasNext() ) - { - Map.Entry<String, JsonNode> entry = fields.next(); - V value = valueDeserializer.apply( entry.getValue() ); - map.put( entry.getKey(), value ); - } - } - - private static boolean isNullOrMissing( JsonNode inputNode ) - { - return inputNode == null || inputNode.isNull() || inputNode.isMissingNode(); - } -} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/e4cca11e/extensions/valueserialization-jackson/src/main/java/org/apache/polygene/valueserialization/jackson/JacksonValueSerializationAssembler.java ---------------------------------------------------------------------- diff --git a/extensions/valueserialization-jackson/src/main/java/org/apache/polygene/valueserialization/jackson/JacksonValueSerializationAssembler.java b/extensions/valueserialization-jackson/src/main/java/org/apache/polygene/valueserialization/jackson/JacksonValueSerializationAssembler.java deleted file mode 100644 index 8f6421d..0000000 --- a/extensions/valueserialization-jackson/src/main/java/org/apache/polygene/valueserialization/jackson/JacksonValueSerializationAssembler.java +++ /dev/null @@ -1,41 +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.jackson; - -import org.apache.polygene.api.value.ValueSerialization; -import org.apache.polygene.bootstrap.Assemblers; -import org.apache.polygene.bootstrap.AssemblyException; -import org.apache.polygene.bootstrap.ModuleAssembly; - -/** - * Assemble a ValueSerialization Service producing and consuming JSON documents. - */ -public class JacksonValueSerializationAssembler - extends Assemblers.Visibility<JacksonValueSerializationAssembler> -{ - @Override - public void assemble( ModuleAssembly module ) - throws AssemblyException - { - module.services( JacksonValueSerializationService.class ). - visibleIn( visibility() ). - taggedWith( ValueSerialization.Formats.JSON ); - } -} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/e4cca11e/extensions/valueserialization-jackson/src/main/java/org/apache/polygene/valueserialization/jackson/JacksonValueSerializationService.java ---------------------------------------------------------------------- diff --git a/extensions/valueserialization-jackson/src/main/java/org/apache/polygene/valueserialization/jackson/JacksonValueSerializationService.java b/extensions/valueserialization-jackson/src/main/java/org/apache/polygene/valueserialization/jackson/JacksonValueSerializationService.java deleted file mode 100644 index b05c7d9..0000000 --- a/extensions/valueserialization-jackson/src/main/java/org/apache/polygene/valueserialization/jackson/JacksonValueSerializationService.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.jackson; - -import org.apache.polygene.api.mixin.Mixins; -import org.apache.polygene.api.value.ValueSerialization; - -/** - * ValueSerialization Service producing and consuming JSON documents using Jackson. - */ -@Mixins( { JacksonValueSerializer.class, JacksonValueDeserializer.class } ) -public interface JacksonValueSerializationService - extends ValueSerialization -{ -} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/e4cca11e/extensions/valueserialization-jackson/src/main/java/org/apache/polygene/valueserialization/jackson/JacksonValueSerializer.java ---------------------------------------------------------------------- diff --git a/extensions/valueserialization-jackson/src/main/java/org/apache/polygene/valueserialization/jackson/JacksonValueSerializer.java b/extensions/valueserialization-jackson/src/main/java/org/apache/polygene/valueserialization/jackson/JacksonValueSerializer.java deleted file mode 100644 index a52b030..0000000 --- a/extensions/valueserialization-jackson/src/main/java/org/apache/polygene/valueserialization/jackson/JacksonValueSerializer.java +++ /dev/null @@ -1,92 +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.jackson; - -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.databind.MappingJsonFactory; -import java.io.OutputStream; -import org.apache.polygene.spi.value.ValueSerializerAdapter; - -/** - * ValueSerializer producing Values state as JSON documents using Jackson. - */ -public class JacksonValueSerializer - extends ValueSerializerAdapter<JsonGenerator> -{ - - private final JsonFactory jsonFactory = new MappingJsonFactory(); - - @Override - protected JsonGenerator adaptOutput( OutputStream output ) - throws Exception - { - return jsonFactory.createGenerator( output ); - } - - @Override - protected void onSerializationEnd( Object object, JsonGenerator output ) - throws Exception - { - output.close(); - } - - @Override - protected void onArrayStart( JsonGenerator output ) - throws Exception - { - output.writeStartArray(); - } - - @Override - protected void onArrayEnd( JsonGenerator output ) - throws Exception - { - output.writeEndArray(); - } - - @Override - protected void onObjectStart( JsonGenerator output ) - throws Exception - { - output.writeStartObject(); - } - - @Override - protected void onObjectEnd( JsonGenerator output ) - throws Exception - { - output.writeEndObject(); - } - - @Override - protected void onFieldStart( JsonGenerator output, String fieldName ) - throws Exception - { - output.writeFieldName( fieldName ); - } - - @Override - protected void onValue( JsonGenerator output, Object value ) - throws Exception - { - output.writeObject( value ); - } -} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/e4cca11e/extensions/valueserialization-jackson/src/main/java/org/apache/polygene/valueserialization/jackson/package.html ---------------------------------------------------------------------- diff --git a/extensions/valueserialization-jackson/src/main/java/org/apache/polygene/valueserialization/jackson/package.html b/extensions/valueserialization-jackson/src/main/java/org/apache/polygene/valueserialization/jackson/package.html deleted file mode 100644 index d229040..0000000 --- a/extensions/valueserialization-jackson/src/main/java/org/apache/polygene/valueserialization/jackson/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>Jackson Value Serializer.</h2> - </body> -</html> http://git-wip-us.apache.org/repos/asf/polygene-java/blob/e4cca11e/extensions/valueserialization-jackson/src/test/java/org/apache/polygene/valueserialization/jackson/JacksonCollectionSerializationTest.java ---------------------------------------------------------------------- diff --git a/extensions/valueserialization-jackson/src/test/java/org/apache/polygene/valueserialization/jackson/JacksonCollectionSerializationTest.java b/extensions/valueserialization-jackson/src/test/java/org/apache/polygene/valueserialization/jackson/JacksonCollectionSerializationTest.java deleted file mode 100644 index 8160c55..0000000 --- a/extensions/valueserialization-jackson/src/test/java/org/apache/polygene/valueserialization/jackson/JacksonCollectionSerializationTest.java +++ /dev/null @@ -1,37 +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.jackson; - -import org.apache.polygene.bootstrap.AssemblyException; -import org.apache.polygene.bootstrap.ModuleAssembly; -import org.apache.polygene.test.value.AbstractCollectionSerializationTest; - -public class JacksonCollectionSerializationTest - extends AbstractCollectionSerializationTest -{ - - @Override - public void assemble( ModuleAssembly module ) - throws AssemblyException - { - super.assemble( module ); - new JacksonValueSerializationAssembler().assemble( module ); - } -}
