ZEST-156 - introducing a new Value Serialization system
Project: http://git-wip-us.apache.org/repos/asf/zest-java/repo Commit: http://git-wip-us.apache.org/repos/asf/zest-java/commit/301f837d Tree: http://git-wip-us.apache.org/repos/asf/zest-java/tree/301f837d Diff: http://git-wip-us.apache.org/repos/asf/zest-java/diff/301f837d Branch: refs/heads/ValueSerializationCleaning Commit: 301f837df0e89f6966f56a953870d92816dad87e Parents: 0e78cbc Author: Niclas Hedhman <[email protected]> Authored: Fri Jul 22 18:54:55 2016 +0800 Committer: Niclas Hedhman <[email protected]> Committed: Fri Jul 22 18:54:55 2016 +0800 ---------------------------------------------------------------------- .../java/org/apache/zest/api/type/MapType.java | 1 - .../spi/value/BooleanClassDeserializer.java | 70 +++++ .../java/org/apache/zest/spi/value/Entry.java | 63 ++++ .../value/IllegalDeserializationException.java | 31 ++ .../org/apache/zest/spi/value/ObjectField.java | 63 ++++ .../apache/zest/spi/value/ParserLocation.java | 41 +++ .../apache/zest/spi/value/TypeDeserializer.java | 40 +++ .../value/ValueDeserializationException.java | 33 +++ .../index/rdf/query/RdfQueryParserFactory.java | 8 +- .../rdf/query/internal/RdfQueryParserImpl.java | 4 +- .../jackson/JacksonDeserializer.java | 239 +++++++++++++++ .../jackson/JacksonDeserializerTest.java | 293 +++++++++++++++++++ 12 files changed, 876 insertions(+), 10 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/zest-java/blob/301f837d/core/api/src/main/java/org/apache/zest/api/type/MapType.java ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/apache/zest/api/type/MapType.java b/core/api/src/main/java/org/apache/zest/api/type/MapType.java index c76fd60..ace1fca 100644 --- a/core/api/src/main/java/org/apache/zest/api/type/MapType.java +++ b/core/api/src/main/java/org/apache/zest/api/type/MapType.java @@ -30,7 +30,6 @@ import org.apache.zest.api.util.Classes; public final class MapType extends ValueType { - private ValueType keyType; private ValueType valueType; http://git-wip-us.apache.org/repos/asf/zest-java/blob/301f837d/core/spi/src/main/java/org/apache/zest/spi/value/BooleanClassDeserializer.java ---------------------------------------------------------------------- diff --git a/core/spi/src/main/java/org/apache/zest/spi/value/BooleanClassDeserializer.java b/core/spi/src/main/java/org/apache/zest/spi/value/BooleanClassDeserializer.java new file mode 100644 index 0000000..0420672 --- /dev/null +++ b/core/spi/src/main/java/org/apache/zest/spi/value/BooleanClassDeserializer.java @@ -0,0 +1,70 @@ +/* + * 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.zest.spi.value; + +import java.lang.reflect.Type; +import java.util.List; + +public class BooleanClassDeserializer + implements TypeDeserializer<Boolean> +{ + + @Override + public Boolean deserialize( Class<? extends Boolean> type, VDA parent, Object parser ) + throws Exception + { + Object value = parent.nextValue( parser ); + if( value instanceof String ) + { + return Boolean.valueOf( (String) value ); + } + if( value instanceof Boolean ) + { + return (Boolean) value; + } + throw new IllegalDeserializationException( "Boolean value expected.", parent.location(parser) ); + } + + @Override + public Boolean deserialize( Class<? extends Boolean> type, VDA parent, String stringValue ) + throws Exception + { + return Boolean.valueOf( stringValue ); + } + + @Override + public List<String> fieldNames( Class<?> type ) + { + return null; + } + + @Override + public Class<?> fieldTypeOf( Type parent, String fieldName ) + { + return null; + } + + @Override + public Boolean createObject( Object data ) + { + return null; + } +} http://git-wip-us.apache.org/repos/asf/zest-java/blob/301f837d/core/spi/src/main/java/org/apache/zest/spi/value/Entry.java ---------------------------------------------------------------------- diff --git a/core/spi/src/main/java/org/apache/zest/spi/value/Entry.java b/core/spi/src/main/java/org/apache/zest/spi/value/Entry.java new file mode 100644 index 0000000..0362abd --- /dev/null +++ b/core/spi/src/main/java/org/apache/zest/spi/value/Entry.java @@ -0,0 +1,63 @@ +/* + * 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.zest.spi.value; + +import java.util.Objects; + +public class Entry<K, V> +{ + public final K key; + public final V value; + + public Entry( K key, V value ) + { + this.key = key; + this.value = value; + } + + @Override + public boolean equals( Object o ) + { + if( this == o ) + { + return true; + } + if( !( o instanceof Entry ) ) + { + return false; + } + Entry<?, ?> entry = (Entry<?, ?>) o; + return Objects.equals( key, entry.key ) && + Objects.equals( value, entry.value ); + } + + @Override + public int hashCode() + { + return Objects.hash( key, value ); + } + + @Override + public String toString() + { + return key + ":" + value; + } +} http://git-wip-us.apache.org/repos/asf/zest-java/blob/301f837d/core/spi/src/main/java/org/apache/zest/spi/value/IllegalDeserializationException.java ---------------------------------------------------------------------- diff --git a/core/spi/src/main/java/org/apache/zest/spi/value/IllegalDeserializationException.java b/core/spi/src/main/java/org/apache/zest/spi/value/IllegalDeserializationException.java new file mode 100644 index 0000000..7bd8dc0 --- /dev/null +++ b/core/spi/src/main/java/org/apache/zest/spi/value/IllegalDeserializationException.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.zest.spi.value; + +import org.apache.zest.api.value.ValueSerializationException; + +public class IllegalDeserializationException extends ValueDeserializationException +{ + public IllegalDeserializationException( String message, ParserLocation location ) + { + super( message + " at " + location ); + } +} http://git-wip-us.apache.org/repos/asf/zest-java/blob/301f837d/core/spi/src/main/java/org/apache/zest/spi/value/ObjectField.java ---------------------------------------------------------------------- diff --git a/core/spi/src/main/java/org/apache/zest/spi/value/ObjectField.java b/core/spi/src/main/java/org/apache/zest/spi/value/ObjectField.java new file mode 100644 index 0000000..17ecfe7 --- /dev/null +++ b/core/spi/src/main/java/org/apache/zest/spi/value/ObjectField.java @@ -0,0 +1,63 @@ +/* + * 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.zest.spi.value; + +import java.util.Objects; + +public class ObjectField<V> +{ + public final String name; + public final V value; + + public ObjectField( String name, V value ) + { + this.name = name; + this.value = value; + } + + @Override + public boolean equals( Object o ) + { + if( this == o ) + { + return true; + } + if( !( o instanceof ObjectField ) ) + { + return false; + } + ObjectField<?> field = (ObjectField<?>) o; + return Objects.equals( name, field.name ) && + Objects.equals( value, field.value ); + } + + @Override + public int hashCode() + { + return Objects.hash( name, value ); + } + + @Override + public String toString() + { + return name + ':' + value; + } +} http://git-wip-us.apache.org/repos/asf/zest-java/blob/301f837d/core/spi/src/main/java/org/apache/zest/spi/value/ParserLocation.java ---------------------------------------------------------------------- diff --git a/core/spi/src/main/java/org/apache/zest/spi/value/ParserLocation.java b/core/spi/src/main/java/org/apache/zest/spi/value/ParserLocation.java new file mode 100644 index 0000000..e00483a --- /dev/null +++ b/core/spi/src/main/java/org/apache/zest/spi/value/ParserLocation.java @@ -0,0 +1,41 @@ +/* + * 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.zest.spi.value; + +public class ParserLocation +{ + public final String info; + public final int line; + public final int column; + + public ParserLocation( String info, int line, int column ) + { + this.info = info; + this.line = line; + this.column = column; + } + + @Override + public String toString() + { + return "'" + info + "' " + line + ":" + column; + } +} http://git-wip-us.apache.org/repos/asf/zest-java/blob/301f837d/core/spi/src/main/java/org/apache/zest/spi/value/TypeDeserializer.java ---------------------------------------------------------------------- diff --git a/core/spi/src/main/java/org/apache/zest/spi/value/TypeDeserializer.java b/core/spi/src/main/java/org/apache/zest/spi/value/TypeDeserializer.java new file mode 100644 index 0000000..e9db38f --- /dev/null +++ b/core/spi/src/main/java/org/apache/zest/spi/value/TypeDeserializer.java @@ -0,0 +1,40 @@ +/* + * 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.zest.spi.value; + +import java.lang.reflect.Type; +import java.util.List; +import java.util.Map; + +public interface TypeDeserializer<T> +{ + T deserialize( Class<? extends T> type, VDA parent, Object parser ) + throws Exception; + + T deserialize( Class<? extends T> type, VDA parent, String stringValue ) + throws Exception; + + List<String> fieldNames( Class<?> type ); + + Class<?> fieldTypeOf( Type parent, String fieldName ); + + T createObject( Object data ); +} http://git-wip-us.apache.org/repos/asf/zest-java/blob/301f837d/core/spi/src/main/java/org/apache/zest/spi/value/ValueDeserializationException.java ---------------------------------------------------------------------- diff --git a/core/spi/src/main/java/org/apache/zest/spi/value/ValueDeserializationException.java b/core/spi/src/main/java/org/apache/zest/spi/value/ValueDeserializationException.java new file mode 100644 index 0000000..c4ddf20 --- /dev/null +++ b/core/spi/src/main/java/org/apache/zest/spi/value/ValueDeserializationException.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.zest.spi.value; + +public class ValueDeserializationException extends RuntimeException +{ + public ValueDeserializationException( String message ) + { + super( message ); + } + + public ValueDeserializationException( String message, Exception cause ) + { + } +} http://git-wip-us.apache.org/repos/asf/zest-java/blob/301f837d/extensions/indexing-rdf/src/main/java/org/apache/zest/index/rdf/query/RdfQueryParserFactory.java ---------------------------------------------------------------------- diff --git a/extensions/indexing-rdf/src/main/java/org/apache/zest/index/rdf/query/RdfQueryParserFactory.java b/extensions/indexing-rdf/src/main/java/org/apache/zest/index/rdf/query/RdfQueryParserFactory.java index f89ff68..a3bfc6b 100644 --- a/extensions/indexing-rdf/src/main/java/org/apache/zest/index/rdf/query/RdfQueryParserFactory.java +++ b/extensions/indexing-rdf/src/main/java/org/apache/zest/index/rdf/query/RdfQueryParserFactory.java @@ -20,9 +20,7 @@ package org.apache.zest.index.rdf.query; -import org.openrdf.query.QueryLanguage; import org.apache.zest.api.injection.scope.Service; -import org.apache.zest.api.injection.scope.Structure; import org.apache.zest.api.mixin.Mixins; import org.apache.zest.api.service.ServiceComposite; import org.apache.zest.api.service.qualifier.Tagged; @@ -30,7 +28,7 @@ import org.apache.zest.api.value.ValueSerialization; import org.apache.zest.api.value.ValueSerializer; import org.apache.zest.index.rdf.UnsupportedLanguageException; import org.apache.zest.index.rdf.query.internal.RdfQueryParserImpl; -import org.apache.zest.spi.ZestSPI; +import org.openrdf.query.QueryLanguage; @Mixins( RdfQueryParserFactory.RdfQueryParserFactoryMixin.class ) public interface RdfQueryParserFactory @@ -41,8 +39,6 @@ public interface RdfQueryParserFactory abstract class RdfQueryParserFactoryMixin implements RdfQueryParserFactory { - @Structure - private ZestSPI spi; @Service @Tagged( ValueSerialization.Formats.JSON ) private ValueSerializer valueSerializer; @@ -52,7 +48,7 @@ public interface RdfQueryParserFactory { if( language.equals( QueryLanguage.SPARQL ) ) { - return new RdfQueryParserImpl( spi, valueSerializer ); + return new RdfQueryParserImpl( valueSerializer ); } throw new UnsupportedLanguageException( language ); } http://git-wip-us.apache.org/repos/asf/zest-java/blob/301f837d/extensions/indexing-rdf/src/main/java/org/apache/zest/index/rdf/query/internal/RdfQueryParserImpl.java ---------------------------------------------------------------------- diff --git a/extensions/indexing-rdf/src/main/java/org/apache/zest/index/rdf/query/internal/RdfQueryParserImpl.java b/extensions/indexing-rdf/src/main/java/org/apache/zest/index/rdf/query/internal/RdfQueryParserImpl.java index e79178f..f453d71 100644 --- a/extensions/indexing-rdf/src/main/java/org/apache/zest/index/rdf/query/internal/RdfQueryParserImpl.java +++ b/extensions/indexing-rdf/src/main/java/org/apache/zest/index/rdf/query/internal/RdfQueryParserImpl.java @@ -74,7 +74,6 @@ public class RdfQueryParserImpl private final Namespaces namespaces = new Namespaces(); private final Triples triples = new Triples( namespaces ); - private final ZestSPI spi; private final ValueSerializer valueSerializer; private Map<String, Object> variables; @@ -93,9 +92,8 @@ public class RdfQueryParserImpl ) ); } - public RdfQueryParserImpl( ZestSPI spi, ValueSerializer valueSerializer ) + public RdfQueryParserImpl( ValueSerializer valueSerializer ) { - this.spi = spi; this.valueSerializer = valueSerializer; } http://git-wip-us.apache.org/repos/asf/zest-java/blob/301f837d/extensions/valueserialization-jackson/src/main/java/org/apache/zest/valueserialization/jackson/JacksonDeserializer.java ---------------------------------------------------------------------- diff --git a/extensions/valueserialization-jackson/src/main/java/org/apache/zest/valueserialization/jackson/JacksonDeserializer.java b/extensions/valueserialization-jackson/src/main/java/org/apache/zest/valueserialization/jackson/JacksonDeserializer.java new file mode 100644 index 0000000..08474ab --- /dev/null +++ b/extensions/valueserialization-jackson/src/main/java/org/apache/zest/valueserialization/jackson/JacksonDeserializer.java @@ -0,0 +1,239 @@ +/* + * 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.zest.valueserialization.jackson; + +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonToken; +import java.io.InputStream; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.apache.zest.spi.value.Entry; +import org.apache.zest.spi.value.ObjectField; +import org.apache.zest.spi.value.ParserLocation; +import org.apache.zest.spi.value.VDA; + +public class JacksonDeserializer extends VDA<JsonParser> +{ + private final JsonFactory jsonFactory = new JsonFactory(); + + @Override + protected JsonParser adaptInput( InputStream input ) + throws Exception + { + return jsonFactory.createParser( input ); + } + + @Override + protected <T> T readPlainValue( Class<T> type, JsonParser jsonParser ) + throws Exception + { + JsonToken currentToken = jsonParser.nextValue(); + if( type.equals( Boolean.class ) || type.equals( Boolean.TYPE ) ) + { + if( currentToken == JsonToken.VALUE_TRUE ) + { + return (T) Boolean.TRUE; + } + if( currentToken == JsonToken.VALUE_FALSE ) + { + return (T) Boolean.FALSE; + } + return (T) Boolean.valueOf( (String) jsonParser.getCurrentValue() ); + } + if( type.equals( Byte.class ) || type.equals( Byte.TYPE ) ) + { + if( currentToken == JsonToken.VALUE_NUMBER_INT || + currentToken == JsonToken.VALUE_NUMBER_FLOAT ) + { + return (T) Byte.valueOf( (Byte) jsonParser.getCurrentValue() ); + } + return (T) Byte.valueOf( (String) jsonParser.getCurrentValue() ); + } + if( type.equals( Character.class ) || type.equals( Character.TYPE ) ) + { + return (T) Character.valueOf( ( (String) jsonParser.getCurrentValue() ).charAt( 0 ) ); + } + if( type.equals( Short.class ) || type.equals( Short.TYPE ) ) + { + if( currentToken == JsonToken.VALUE_NUMBER_INT || + currentToken == JsonToken.VALUE_NUMBER_FLOAT ) + { + return (T) Short.valueOf( (Byte) jsonParser.getCurrentValue() ); + } + return (T) Short.valueOf( (String) jsonParser.getCurrentValue() ); + } + if( type.equals( Integer.class ) || type.equals( Integer.TYPE ) ) + { + if( currentToken == JsonToken.VALUE_NUMBER_INT || + currentToken == JsonToken.VALUE_NUMBER_FLOAT ) + { + return (T) Integer.valueOf( (Byte) jsonParser.getCurrentValue() ); + } + return (T) Integer.valueOf( (String) jsonParser.getCurrentValue() ); + } + if( type.equals( Long.class ) || type.equals( Long.TYPE ) ) + { + if( currentToken == JsonToken.VALUE_NUMBER_INT || + currentToken == JsonToken.VALUE_NUMBER_FLOAT ) + { + return (T) Long.valueOf( (Byte) jsonParser.getCurrentValue() ); + } + return (T) Long.valueOf( (String) jsonParser.getCurrentValue() ); + } + if( type.equals( Float.class ) || type.equals( Float.TYPE ) ) + { + if( currentToken == JsonToken.VALUE_NUMBER_INT || + currentToken == JsonToken.VALUE_NUMBER_FLOAT ) + { + return (T) Float.valueOf( (Byte) jsonParser.getCurrentValue() ); + } + return (T) Float.valueOf( (String) jsonParser.getCurrentValue() ); + } + if( type.equals( Double.class ) || type.equals( Double.TYPE ) ) + { + if( currentToken == JsonToken.VALUE_NUMBER_INT || + currentToken == JsonToken.VALUE_NUMBER_FLOAT ) + { + return (T) Double.valueOf( (Byte) jsonParser.getCurrentValue() ); + } + return (T) Double.valueOf( (String) jsonParser.getCurrentValue() ); + } + throw new InternalError( "Please contact [email protected]." ); + } + + protected <T> T readObjectValue( Type tType, JsonParser jsonParser ) + throws Exception + { + JsonToken currentToken = jsonParser.nextToken(); + Map<Object, Object> entries = new HashMap<>(); + if( currentToken == JsonToken.START_OBJECT ) + { + while( currentToken != JsonToken.END_OBJECT ) + { + String fieldName = jsonParser.nextFieldName(); + Class<?> fieldType = fieldTypeOf( tType, fieldName ); + Object fieldValue = readObject( fieldType, jsonParser ); + entries.put( fieldName, fieldValue ); + currentToken = jsonParser.nextToken(); + } + return createObject( tType, entries ); + } + return null; + } + + @Override + protected <T> T readArrayValue( Class<T> type, JsonParser jsonParser ) + throws Exception + { + JsonToken currentToken = jsonParser.nextToken(); + List<Object> entries = new ArrayList<>(); + if( currentToken == JsonToken.START_ARRAY ) + { + while( currentToken != JsonToken.END_ARRAY ) + { + Object fieldValue = readObject( type.getComponentType(), jsonParser ); + entries.add( fieldValue ); + currentToken = jsonParser.nextToken(); + } + return createArray( type, entries ); + } + return null; + } + + @Override + protected <K, V> Map<K, V> readMapValue( Type mapType, JsonParser jsonParser ) + throws Exception + { + Type keyType; + Type valueType; + if( mapType instanceof ParameterizedType ) + { + keyType = ( (ParameterizedType) mapType ).getActualTypeArguments()[ 0 ]; + valueType = ( (ParameterizedType) mapType ).getActualTypeArguments()[ 1 ]; + } + else + { + keyType = Object.class; + valueType = Object.class; + } + + JsonToken currentToken = jsonParser.nextToken(); + Map<Object, Object> entries = new HashMap<>(); + if( currentToken == JsonToken.START_OBJECT ) + { + while( currentToken != JsonToken.END_OBJECT ) + { + Object fieldKey = readObject( keyType, jsonParser ); + Object fieldValue = readObject( valueType, jsonParser ); + entries.put( fieldKey, fieldValue ); + currentToken = jsonParser.nextToken(); + } + return createObject(mapType, entries); + } + return null; + } + + @Override + protected <T> T readListValue( Type listType, JsonParser jsonParser ) + throws Exception + { + return null; + } + + @Override + protected <T> T readEnumValue( Class<T> type, JsonParser jsonParser ) + throws Exception + { + return null; + } + + @Override + protected ObjectField nextField( JsonParser jsonParser ) + throws Exception + { + return null; + } + + @Override + protected Entry nextEntry( JsonParser jsonParser ) + throws Exception + { + return null; + } + + @Override + protected Object nextValue( JsonParser jsonParser ) + throws Exception + { + return null; + } + + @Override + public ParserLocation location( JsonParser jsonParser ) + { + return null; + } +} http://git-wip-us.apache.org/repos/asf/zest-java/blob/301f837d/extensions/valueserialization-jackson/src/test/java/org/apache/zest/valueserialization/jackson/JacksonDeserializerTest.java ---------------------------------------------------------------------- diff --git a/extensions/valueserialization-jackson/src/test/java/org/apache/zest/valueserialization/jackson/JacksonDeserializerTest.java b/extensions/valueserialization-jackson/src/test/java/org/apache/zest/valueserialization/jackson/JacksonDeserializerTest.java new file mode 100644 index 0000000..2943037 --- /dev/null +++ b/extensions/valueserialization-jackson/src/test/java/org/apache/zest/valueserialization/jackson/JacksonDeserializerTest.java @@ -0,0 +1,293 @@ +/* + * 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.zest.valueserialization.jackson; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.OffsetDateTime; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; +import org.apache.zest.api.entity.EntityBuilder; +import org.apache.zest.api.entity.EntityReference; +import org.apache.zest.api.injection.scope.Service; +import org.apache.zest.api.property.Property; +import org.apache.zest.api.unitofwork.UnitOfWork; +import org.apache.zest.api.usecase.UsecaseBuilder; +import org.apache.zest.api.value.ValueBuilder; +import org.apache.zest.api.value.ValueSerialization; +import org.apache.zest.bootstrap.AssemblyException; +import org.apache.zest.bootstrap.ModuleAssembly; +import org.apache.zest.entitystore.memory.MemoryEntityStoreService; +import org.apache.zest.spi.uuid.UuidIdentityGeneratorService; +import org.apache.zest.test.AbstractZestTest; +import org.junit.Test; + +import static org.hamcrest.core.IsEqual.equalTo; +import static org.hamcrest.core.IsNot.not; +import static org.junit.Assert.assertThat; + +public class JacksonDeserializerTest extends AbstractZestTest +{ + + @Service + @SuppressWarnings( "ProtectedField" ) + protected ValueSerialization valueSerialization; + + @Override + public void assemble( ModuleAssembly module ) + throws AssemblyException + { + module.values( Regression142Type.class ); + module.entities( Regression142Type.class ); + + module.services( MemoryEntityStoreService.class ); + module.services( UuidIdentityGeneratorService.class ); + } + + @Test + public void givenCharacterValueWhenSerializingAndDeserializingExpectEquals() + { + String serialized = valueSerialization.serialize( 'q' ); + assertThat( "Serialized", serialized, equalTo( "q" ) ); + + Character deserialized = valueSerialization.deserialize( module, Character.class, serialized ); + assertThat( "Deserialized", deserialized, equalTo( 'q' ) ); + } + + @Test + public void givenEmptyStringValueWhenSerializingAndDeserializingExpectEquals() + { + String serialized = valueSerialization.serialize( "" ); + assertThat( "Serialized", serialized, equalTo( "" ) ); + + String deserialized = valueSerialization.deserialize( module, String.class, serialized ); + assertThat( "Deserialized", deserialized, equalTo( "" ) ); + } + + @Test + public void givenStringValueWhenSerializingAndDeserializingExpectEquals() + { + String serialized = valueSerialization.serialize( "test" ); + assertThat( serialized, equalTo( "test" ) ); + + String deserialized = valueSerialization.deserialize( module, String.class, serialized ); + assertThat( deserialized, equalTo( "test" ) ); + } + + @Test + public void givenBooleanValueWhenSerializingAndDeserializingExpectEquals() + { + String serialized = valueSerialization.serialize( Boolean.TRUE ); + assertThat( serialized, equalTo( "true" ) ); + + Boolean deserialized = valueSerialization.deserialize( module, Boolean.class, serialized ); + assertThat( deserialized, equalTo( Boolean.TRUE ) ); + } + + @Test + public void givenIntegerValueWhenSerializingAndDeserializingExpectEquals() + { + String serialized = valueSerialization.serialize( 42 ); + assertThat( serialized, equalTo( "42" ) ); + Integer deserialized = valueSerialization.deserialize( module, Integer.class, serialized ); + assertThat( deserialized, equalTo( 42 ) ); + } + + @Test + public void givenLongValueWhenSerializingAndDeserializingExpectEquals() + { + String serialized = valueSerialization.serialize( 42L ); + assertThat( serialized, equalTo( "42" ) ); + + Long deserialized = valueSerialization.deserialize( module, Long.class, serialized ); + assertThat( deserialized, equalTo( 42L ) ); + } + + @Test + public void givenShortValueWhenSerializingAndDeserializingExpectEquals() + { + String serialized = valueSerialization.serialize( (short) 42 ); + assertThat( serialized, equalTo( "42" ) ); + + Short deserialized = valueSerialization.deserialize( module, Short.class, serialized ); + assertThat( deserialized, equalTo( (short) 42 ) ); + } + + @Test + public void givenByteValueWhenSerializingAndDeserializingExpectEquals() + { + String serialized = valueSerialization.serialize( (byte) 42 ); + assertThat( serialized, equalTo( "42" ) ); + Byte deserialized = valueSerialization.deserialize( module, Byte.class, serialized ); + assertThat( deserialized, equalTo( (byte) 42 ) ); + } + + @Test + public void givenFloatValueWhenSerializingAndDeserializingExpectEquals() + { + String serialized = valueSerialization.serialize( 42F ); + assertThat( serialized, equalTo( "42.0" ) ); + + Float deserialized = valueSerialization.deserialize( module, Float.class, serialized ); + assertThat( deserialized, equalTo( 42F ) ); + } + + @Test + public void givenDoubleValueWhenSerializingAndDeserializingExpectEquals() + { + String serialized = valueSerialization.serialize( 42D ); + assertThat( serialized, equalTo( "42.0" ) ); + + Double deserialized = valueSerialization.deserialize( module, Double.class, serialized ); + assertThat( deserialized, equalTo( 42D ) ); + } + + @Test + public void givenBigIntegerValueWhenSerializingAndDeserializingExpectEquals() + { + BigInteger bigInteger = new BigInteger( "42424242424242424242424242" ); + assertThat( bigInteger, not( equalTo( BigInteger.valueOf( bigInteger.longValue() ) ) ) ); + + String serialized = valueSerialization.serialize( bigInteger ); + assertThat( serialized, equalTo( "42424242424242424242424242" ) ); + + BigInteger deserialized = valueSerialization.deserialize( module, BigInteger.class, serialized ); + assertThat( deserialized, equalTo( bigInteger ) ); + } + + @Test + public void givenBigDecimalValueWhenSerializingAndDeserializingExpectEquals() + { + BigDecimal bigDecimal = new BigDecimal( "42.2376931348623157e+309" ); + assertThat( bigDecimal.doubleValue(), equalTo( Double.POSITIVE_INFINITY ) ); + + String serialized = valueSerialization.serialize( bigDecimal ); + assertThat( serialized, equalTo( "4.22376931348623157E+310" ) ); + + BigDecimal deserialized = valueSerialization.deserialize( module, BigDecimal.class, serialized ); + assertThat( deserialized, equalTo( bigDecimal ) ); + } + + @Test + public void givenDateTimeValueWhenSerializingAndDeserializingExpectEquals() + { + String serialized = valueSerialization.serialize( OffsetDateTime.of( 2020, 3, 4, 13, 24, 35, 123000000, ZoneOffset + .ofHours( 1 ) ) ); + assertThat( serialized, equalTo( "2020-03-04T13:24:35.123+01:00" ) ); + ZonedDateTime deserialized = valueSerialization.deserialize( module, ZonedDateTime.class, serialized ); + assertThat( deserialized, equalTo( ZonedDateTime.of( 2020, 3, 4, 13, 24, 35, 123000000, ZoneOffset.ofHours( 1 ) ) ) ); + } + + @Test + public void givenLocalDateTimeValueWhenSerializingAndDeserializingExpectEquals() + { + // Serialized without TimeZone + String serialized = valueSerialization.serialize( LocalDateTime.of( 2020, 3, 4, 13, 23, 12 ) ); + assertThat( serialized, equalTo( "2020-03-04T13:23:12" ) ); + + LocalDateTime deserialized = valueSerialization.deserialize( module, LocalDateTime.class, serialized ); + assertThat( deserialized, equalTo( LocalDateTime.of( 2020, 3, 4, 13, 23, 12 ) ) ); + } + + @Test + public void givenLocalDateValueWhenSerializingAndDeserializingExpectEquals() + { + String serialized = valueSerialization.serialize( LocalDate.of( 2020, 3, 4 ) ); + assertThat( serialized, equalTo( "2020-03-04" ) ); + + LocalDate deserialized = valueSerialization.deserialize( module, LocalDate.class, serialized ); + assertThat( deserialized, equalTo( LocalDate.of( 2020,3,4 ) ) ); + } + + @Test + public void givenEntityReferenceValueWhenSerializingAndDeserializingExpectEquals() + { + String serialized = valueSerialization.serialize( EntityReference.parseEntityReference( "ABCD-1234" ) ); + assertThat( serialized, equalTo( "ABCD-1234" ) ); + + EntityReference deserialized = valueSerialization.deserialize( module, EntityReference.class, serialized ); + assertThat( deserialized, equalTo( EntityReference.parseEntityReference( "ABCD-1234" ) ) ); + } + + @Test + public void zest142RegressionTest() + throws Exception + { + if( getClass().getName().equals( "org.apache.zest.valueserialization.stax.StaxPlainValueSerializationTest" ) ) + { + // This test is disabled, as this test expect a JSON capable serializer as it uses + // the JSONMapEntityStoreMixin in MemoryEntityStore. + return; + } + ValueSerialization serialization = serviceFinder.findService( ValueSerialization.class ).get(); + + Regression142Type value; + { + ValueBuilder<Regression142Type> builder = valueBuilderFactory.newValueBuilder( Regression142Type.class ); + builder.prototype().price().set( 23.45 ); + builder.prototype().testenum().set( Regression142Enum.B ); + value = builder.newInstance(); + String serialized = serialization.serialize( value ); + System.out.println( serialized ); // ok + value = serialization.deserialize( module, Regression142Type.class, serialized ); // ok + } + { + String valueId = "abcdefg"; + { + try (UnitOfWork uow = unitOfWorkFactory.newUnitOfWork( UsecaseBuilder.newUsecase( "create" ) )) + { + EntityBuilder<Regression142Type> builder = uow.newEntityBuilder( Regression142Type.class, valueId ); + builder.instance().price().set( 45.67 ); + builder.instance().testenum().set( Regression142Enum.A ); + value = builder.newInstance(); + System.out.println( value.testenum().get() ); + uow.complete(); + } + catch( Exception e_ ) + { + e_.printStackTrace(); + } + } + { + try (UnitOfWork uow = unitOfWorkFactory.newUnitOfWork( UsecaseBuilder.newUsecase( "create" ) )) + { + value = uow.get( Regression142Type.class, valueId ); + System.out.println( value.price().get() ); + System.out.println( value.testenum().get() ); // FAIL + } + } + } + } + + private enum Regression142Enum + { + A, B, C, D + } + + interface Regression142Type + { + Property<Double> price(); + + Property<Regression142Enum> testenum(); + } +}
