Repository: johnzon
Updated Branches:
  refs/heads/master fb5d8b7a9 -> eb93b91a5


JAX-RS MessageWriter/MessagerReader with Priority (so that user can define and 
provide his own)
JsonbConfig injectable via Jax-RS API
Better support for generics types
Support for JsonbDeserializers/JsonbSerializers defined in interfaces or 
abstract classes
Support for default deserialization from string to enum
Fix to dateformatting (date format was not properly used in deserialization)

Project: http://git-wip-us.apache.org/repos/asf/johnzon/repo
Commit: http://git-wip-us.apache.org/repos/asf/johnzon/commit/028a1644
Tree: http://git-wip-us.apache.org/repos/asf/johnzon/tree/028a1644
Diff: http://git-wip-us.apache.org/repos/asf/johnzon/diff/028a1644

Branch: refs/heads/master
Commit: 028a1644aac2e565fbed007ba85e8f0bede9061f
Parents: fb5d8b7
Author: amoscatelli <dragonide001>
Authored: Mon Mar 26 16:02:31 2018 +0200
Committer: amoscatelli <dragonide001>
Committed: Mon Mar 26 16:02:31 2018 +0200

----------------------------------------------------------------------
 johnzon-jsonb/pom.xml                           |  15 ++
 .../jaxrs/jsonb/jaxrs/JsonbJaxrsProvider.java   |  99 ++++-------
 .../apache/johnzon/jsonb/JohnzonBuilder.java    | 167 +++++++++----------
 .../johnzon/mapper/MappingParserImpl.java       |  90 ++++++----
 4 files changed, 181 insertions(+), 190 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/johnzon/blob/028a1644/johnzon-jsonb/pom.xml
----------------------------------------------------------------------
diff --git a/johnzon-jsonb/pom.xml b/johnzon-jsonb/pom.xml
index d63250e..30585b0 100644
--- a/johnzon-jsonb/pom.xml
+++ b/johnzon-jsonb/pom.xml
@@ -35,6 +35,14 @@
   </properties>
 
   <dependencies>
+      
+    <!-- FOR PRIORITY ANNOTATION NOT FOUND IN GERONIMO (??) -->
+    <dependency>
+        <groupId>javax.annotation</groupId>
+        <artifactId>javax.annotation-api</artifactId>
+        <version>1.3.2</version>
+    </dependency>
+      
     <dependency>
       <groupId>org.apache.geronimo.specs</groupId>
       <artifactId>geronimo-jaxrs_2.0_spec</artifactId>
@@ -62,6 +70,13 @@
       <version>${project.version}</version>
     </dependency>
 
+    <!-- FOR GENERICS DISCOVERY -->
+    <dependency>
+        <groupId>com.googlecode.gentyref</groupId>
+        <artifactId>gentyref</artifactId>
+        <version>1.2.0</version>
+    </dependency>
+
     <dependency>
       <groupId>org.apache.cxf</groupId>
       <artifactId>cxf-rt-rs-client</artifactId>

http://git-wip-us.apache.org/repos/asf/johnzon/blob/028a1644/johnzon-jsonb/src/main/java/org/apache/johnzon/jaxrs/jsonb/jaxrs/JsonbJaxrsProvider.java
----------------------------------------------------------------------
diff --git 
a/johnzon-jsonb/src/main/java/org/apache/johnzon/jaxrs/jsonb/jaxrs/JsonbJaxrsProvider.java
 
b/johnzon-jsonb/src/main/java/org/apache/johnzon/jaxrs/jsonb/jaxrs/JsonbJaxrsProvider.java
index 49cd334..f5b2de8 100644
--- 
a/johnzon-jsonb/src/main/java/org/apache/johnzon/jaxrs/jsonb/jaxrs/JsonbJaxrsProvider.java
+++ 
b/johnzon-jsonb/src/main/java/org/apache/johnzon/jaxrs/jsonb/jaxrs/JsonbJaxrsProvider.java
@@ -21,7 +21,6 @@ package org.apache.johnzon.jaxrs.jsonb.jaxrs;
 import javax.json.JsonStructure;
 import javax.json.bind.Jsonb;
 import javax.json.bind.JsonbBuilder;
-import javax.json.bind.JsonbConfig;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.Produces;
 import javax.ws.rs.WebApplicationException;
@@ -36,22 +35,29 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.Reader;
-import java.io.StringReader;
 import java.io.Writer;
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Type;
 import java.util.Collection;
-import java.util.Properties;
 import java.util.concurrent.atomic.AtomicReference;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.ext.ContextResolver;
+import javax.ws.rs.ext.Providers;
+import javax.annotation.Priority;
+import javax.ws.rs.Priorities;
 
 // here while we dont compile in java 8 jaxrs module, when migrated we'll 
merge it with IgnorableTypes hierarchy at least
 @Provider
-@Produces("application/json")
-@Consumes("application/json")
+@Priority(value = Priorities.USER-100)
+@Produces(MediaType.APPLICATION_JSON)
+@Consumes(MediaType.APPLICATION_JSON)
 public class JsonbJaxrsProvider<T> implements MessageBodyWriter<T>, 
MessageBodyReader<T> {
+
     protected final Collection<String> ignores;
     protected final AtomicReference<Jsonb> delegate = new AtomicReference<>();
-    protected final JsonbConfig config = new JsonbConfig();
+
+    @Context
+    private Providers providers;
 
     public JsonbJaxrsProvider() {
         this(null);
@@ -61,60 +67,11 @@ public class JsonbJaxrsProvider<T> implements 
MessageBodyWriter<T>, MessageBodyR
         this.ignores = ignores;
     }
 
-    protected Jsonb createJsonb() {
-        return JsonbBuilder.create(config);
-    }
-
     private boolean isIgnored(final Class<?> type) {
         return ignores != null && ignores.contains(type.getName());
     }
 
-    // config - main containers support the configuration of providers this way
-    public void setFailOnUnknownProperties(final boolean active) {
-        config.setProperty("johnzon.fail-on-unknown-properties", active);
-    }
-
-    public void setOtherProperties(final String others) {
-        final Properties properties = new Properties() {{
-            try {
-                load(new StringReader(others));
-            } catch (final IOException e) {
-                throw new IllegalArgumentException(e);
-            }
-        }};
-        properties.stringPropertyNames().forEach(k -> config.setProperty(k, 
properties.getProperty(k)));
-    }
-
-    public void setIJson(final boolean active) {
-        config.withStrictIJSON(active);
-    }
-
-    public void setEncoding(final String encoding) {
-        config.withEncoding(encoding);
-    }
-
-    public void setBinaryDataStrategy(final String binaryDataStrategy) {
-        config.withBinaryDataStrategy(binaryDataStrategy);
-    }
-
-    public void setPropertyNamingStrategy(final String propertyNamingStrategy) 
{
-        config.withPropertyNamingStrategy(propertyNamingStrategy);
-    }
-
-    public void setPropertyOrderStrategy(final String propertyOrderStrategy) {
-        config.withPropertyOrderStrategy(propertyOrderStrategy);
-    }
-
-    public void setNullValues(final boolean nulls) {
-        config.withNullValues(nulls);
-    }
-
-    public void setPretty(final boolean pretty) {
-        config.withFormatting(pretty);
-    }
-
     // actual impl
-
     @Override
     public boolean isReadable(final Class<?> type, final Type genericType, 
final Annotation[] annotations, final MediaType mediaType) {
         return !isIgnored(type)
@@ -144,26 +101,30 @@ public class JsonbJaxrsProvider<T> implements 
MessageBodyWriter<T>, MessageBodyR
 
     @Override
     public T readFrom(final Class<T> type, final Type genericType, final 
Annotation[] annotations, final MediaType mediaType,
-                      final MultivaluedMap<String, String> httpHeaders, final 
InputStream entityStream) throws IOException, WebApplicationException {
-        return delegate().fromJson(entityStream, genericType);
+            final MultivaluedMap<String, String> httpHeaders, final 
InputStream entityStream) throws IOException, WebApplicationException {
+        return delegate(type).fromJson(entityStream, genericType);
     }
 
     @Override
     public void writeTo(final T t, final Class<?> type, final Type 
genericType, final Annotation[] annotations, final MediaType mediaType,
-                        final MultivaluedMap<String, Object> httpHeaders, 
final OutputStream entityStream) throws IOException, WebApplicationException {
-        delegate().toJson(t, entityStream);
+            final MultivaluedMap<String, Object> httpHeaders, final 
OutputStream entityStream) throws IOException, WebApplicationException {
+        delegate(type).toJson(t, entityStream);
     }
 
-    private Jsonb delegate() {
-        Jsonb jsonb = delegate.get();
-        if (jsonb == null) {
-            final Jsonb newJsonb = createJsonb();
-            if (delegate.compareAndSet(null, newJsonb)) {
-                jsonb = newJsonb;
-            } else {
-                jsonb = delegate.get();
-            }
+    protected Jsonb getJsonb(Class<?> type) {
+        ContextResolver<Jsonb> contextResolver = 
providers.getContextResolver(Jsonb.class, MediaType.APPLICATION_JSON_TYPE);
+        if (contextResolver != null) {
+            return contextResolver.getContext(type);
+        } else {
+            return JsonbBuilder.create();
         }
-        return jsonb;
     }
+    
+    private Jsonb delegate(Class<?> type) {
+        if (delegate.get() == null) {
+            delegate.compareAndSet(null, getJsonb(type));
+        }
+        return delegate.get();
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/johnzon/blob/028a1644/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonBuilder.java
----------------------------------------------------------------------
diff --git 
a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonBuilder.java 
b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonBuilder.java
index 1ae554a..eb834b2 100644
--- a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonBuilder.java
+++ b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonBuilder.java
@@ -18,6 +18,7 @@
  */
 package org.apache.johnzon.jsonb;
 
+import com.googlecode.gentyref.GenericTypeReflector;
 import org.apache.johnzon.core.AbstractJsonFactory;
 import org.apache.johnzon.core.JsonGeneratorFactoryImpl;
 import org.apache.johnzon.core.JsonParserFactoryImpl;
@@ -96,6 +97,7 @@ import static 
javax.json.bind.config.PropertyNamingStrategy.IDENTITY;
 import static javax.json.bind.config.PropertyOrderStrategy.LEXICOGRAPHICAL;
 
 public class JohnzonBuilder implements JsonbBuilder {
+
     private static final Object NO_BM = new Object();
 
     private final MapperBuilder builder = new MapperBuilder();
@@ -141,52 +143,52 @@ public class JohnzonBuilder implements JsonbBuilder {
         final String orderValue = 
config.getProperty(JsonbConfig.PROPERTY_ORDER_STRATEGY).map(String::valueOf).orElse(LEXICOGRAPHICAL);
         final PropertyVisibilityStrategy visibilityStrategy = 
config.getProperty(JsonbConfig.PROPERTY_VISIBILITY_STRATEGY)
                 .map(PropertyVisibilityStrategy.class::cast).orElse(new 
PropertyVisibilityStrategy() {
-                    private final ConcurrentMap<Class<?>, 
PropertyVisibilityStrategy> strategies = new ConcurrentHashMap<>();
+            private final ConcurrentMap<Class<?>, PropertyVisibilityStrategy> 
strategies = new ConcurrentHashMap<>();
 
-                    @Override
-                    public boolean isVisible(final Field field) {
-                        if (field.getAnnotation(JsonbProperty.class) != null) {
-                            return true;
-                        }
-                        final PropertyVisibilityStrategy strategy = 
strategies.computeIfAbsent(field.getDeclaringClass(), this::visibilityStrategy);
-                        return strategy == this ? 
Modifier.isPublic(field.getModifiers()) : strategy.isVisible(field);
-                    }
+            @Override
+            public boolean isVisible(final Field field) {
+                if (field.getAnnotation(JsonbProperty.class) != null) {
+                    return true;
+                }
+                final PropertyVisibilityStrategy strategy = 
strategies.computeIfAbsent(field.getDeclaringClass(), this::visibilityStrategy);
+                return strategy == this ? 
Modifier.isPublic(field.getModifiers()) : strategy.isVisible(field);
+            }
 
-                    @Override
-                    public boolean isVisible(final Method method) {
-                        final PropertyVisibilityStrategy strategy = 
strategies.computeIfAbsent(method.getDeclaringClass(), 
this::visibilityStrategy);
-                        return strategy == this ? 
Modifier.isPublic(method.getModifiers()) : strategy.isVisible(method);
-                    }
+            @Override
+            public boolean isVisible(final Method method) {
+                final PropertyVisibilityStrategy strategy = 
strategies.computeIfAbsent(method.getDeclaringClass(), 
this::visibilityStrategy);
+                return strategy == this ? 
Modifier.isPublic(method.getModifiers()) : strategy.isVisible(method);
+            }
 
-                    private PropertyVisibilityStrategy 
visibilityStrategy(final Class<?> type) { // can be cached
-                        JsonbVisibility visibility = 
type.getAnnotation(JsonbVisibility.class);
-                        if (visibility != null) {
-                            try {
-                                return visibility.value().newInstance();
-                            } catch (final InstantiationException | 
IllegalAccessException e) {
-                                throw new IllegalArgumentException(e);
-                            }
-                        }
-                        Package p = type.getPackage();
-                        while (p != null) {
-                            visibility = 
p.getAnnotation(JsonbVisibility.class);
-                            if (visibility != null) {
-                                try {
-                                    return visibility.value().newInstance();
-                                } catch (final InstantiationException | 
IllegalAccessException e) {
-                                    throw new IllegalArgumentException(e);
-                                }
-                            }
-                            final String name = p.getName();
-                            final int end = name.lastIndexOf('.');
-                            if (end < 0) {
-                                break;
-                            }
-                            p = Package.getPackage(name.substring(0, end));
+            private PropertyVisibilityStrategy visibilityStrategy(final 
Class<?> type) { // can be cached
+                JsonbVisibility visibility = 
type.getAnnotation(JsonbVisibility.class);
+                if (visibility != null) {
+                    try {
+                        return visibility.value().newInstance();
+                    } catch (final InstantiationException | 
IllegalAccessException e) {
+                        throw new IllegalArgumentException(e);
+                    }
+                }
+                Package p = type.getPackage();
+                while (p != null) {
+                    visibility = p.getAnnotation(JsonbVisibility.class);
+                    if (visibility != null) {
+                        try {
+                            return visibility.value().newInstance();
+                        } catch (final InstantiationException | 
IllegalAccessException e) {
+                            throw new IllegalArgumentException(e);
                         }
-                        return this;
                     }
-                });
+                    final String name = p.getName();
+                    final int end = name.lastIndexOf('.');
+                    if (end < 0) {
+                        break;
+                    }
+                    p = Package.getPackage(name.substring(0, end));
+                }
+                return this;
+            }
+        });
 
         config.getProperty("johnzon.attributeOrder").ifPresent(comp -> 
builder.setAttributeOrder(Comparator.class.cast(comp)));
         config.getProperty("johnzon.enforceQuoteString")
@@ -227,16 +229,15 @@ public class JohnzonBuilder implements JsonbBuilder {
         final AccessMode accessMode = config.getProperty("johnzon.accessMode")
                 .map(this::toAccessMode)
                 .orElseGet(() -> new JsonbAccessMode(
-                        propertyNamingStrategy, orderValue, visibilityStrategy,
-                        
!namingStrategyValue.orElse("").equals(PropertyNamingStrategy.CASE_INSENSITIVE),
-                        defaultConverters,
-                        factory, parserFactoryProvider,
-                        config.getProperty("johnzon.accessModeDelegate")
-                                .map(this::toAccessMode)
-                                .orElseGet(() -> new 
FieldAndMethodAccessMode(true, true, false))));
+                propertyNamingStrategy, orderValue, visibilityStrategy,
+                
!namingStrategyValue.orElse("").equals(PropertyNamingStrategy.CASE_INSENSITIVE),
+                defaultConverters,
+                factory, parserFactoryProvider,
+                config.getProperty("johnzon.accessModeDelegate")
+                        .map(this::toAccessMode)
+                        .orElseGet(() -> new FieldAndMethodAccessMode(true, 
true, false))));
         builder.setAccessMode(accessMode);
 
-
         // user adapters
         config.getProperty(JsonbConfig.ADAPTERS).ifPresent(adapters -> 
Stream.of(JsonbAdapter[].class.cast(adapters)).forEach(adapter -> {
             final ParameterizedType pt = ParameterizedType.class.cast(
@@ -306,35 +307,34 @@ public class JohnzonBuilder implements JsonbBuilder {
 
         
config.getProperty(JsonbConfig.SERIALIZERS).map(JsonbSerializer[].class::cast).ifPresent(serializers
 -> {
             Stream.of(serializers).forEach(s -> {
-                final ParameterizedType pt = findPT(s, JsonbSerializer.class);
-                if (pt == null) {
-                    throw new IllegalArgumentException(s + " doesn't implement 
JsonbSerializer");
-                }
-                final Type[] args = pt.getActualTypeArguments();
-                // TODO: support PT in ObjectConverter (list)
-                if (args.length != 1 || !Class.class.isInstance(args[0])) {
-                    throw new IllegalArgumentException("We only support 
serializer on Class for now");
+                Type typeParameter = 
GenericTypeReflector.getTypeParameter(s.getClass(), 
JsonbDeserializer.class.getTypeParameters()[0]);
+                if (typeParameter instanceof Class) {
+                    builder.addObjectConverter(
+                            Class.class.cast(typeParameter),
+                            (ObjectConverter.Writer) (instance, jsonbGenerator)
+                            -> s.serialize(instance, 
jsonbGenerator.getJsonGenerator(), new 
JohnzonSerializationContext(jsonbGenerator)));
+                } else if (typeParameter instanceof ParameterizedType) {
+                    builder.addObjectConverter(
+                            
Class.class.cast(ParameterizedType.class.cast(typeParameter).getRawType()),
+                            (ObjectConverter.Writer) (instance, jsonbGenerator)
+                            -> s.serialize(instance, 
jsonbGenerator.getJsonGenerator(), new 
JohnzonSerializationContext(jsonbGenerator)));
                 }
-                builder.addObjectConverter(
-                        Class.class.cast(args[0]), (ObjectConverter.Writer)
-                                (instance, jsonbGenerator) -> 
s.serialize(instance, jsonbGenerator.getJsonGenerator(), new 
JohnzonSerializationContext(jsonbGenerator)));
+
             });
         });
         
config.getProperty(JsonbConfig.DESERIALIZERS).map(JsonbDeserializer[].class::cast).ifPresent(deserializers
 -> {
             Stream.of(deserializers).forEach(d -> {
-                final ParameterizedType pt = findPT(d, 
JsonbDeserializer.class);
-                if (pt == null) {
-                    throw new IllegalArgumentException(d + " doesn't implement 
JsonbDeserializer");
-                }
-                final Type[] args = pt.getActualTypeArguments();
-                if (args.length != 1 || !Class.class.isInstance(args[0])) {
-                    throw new IllegalArgumentException("We only support 
deserializer on Class for now");
-                }
+                Type typeParameter = 
GenericTypeReflector.getTypeParameter(d.getClass(), 
JsonbDeserializer.class.getTypeParameters()[0]);
                 // TODO: support PT in ObjectConverter (list)
-                builder.addObjectConverter(
-                        Class.class.cast(args[0]), (ObjectConverter.Reader)
-                                (jsonObject, targetType, parser) -> 
d.deserialize(
-                                        
parserFactoryProvider.get().createParser(jsonObject), new 
JohnzonDeserializationContext(parser), targetType));
+                if (typeParameter instanceof Class) {
+                    builder.addObjectConverter(
+                            Class.class.cast(typeParameter), 
(ObjectConverter.Reader) (jsonObject, targetType, parser) -> d.deserialize(
+                            
parserFactoryProvider.get().createParser(jsonObject), new 
JohnzonDeserializationContext(parser), targetType));
+                } else if (typeParameter instanceof ParameterizedType) {
+                    builder.addObjectConverter(
+                            
Class.class.cast(ParameterizedType.class.cast(typeParameter).getRawType()), 
(ObjectConverter.Reader) (jsonObject, targetType, parser) -> d.deserialize(
+                            
parserFactoryProvider.get().createParser(jsonObject), new 
JohnzonDeserializationContext(parser), targetType));
+                }
             });
         });
 
@@ -398,13 +398,6 @@ public class JohnzonBuilder implements JsonbBuilder {
         };
     }
 
-    private ParameterizedType findPT(final Object s, final Class<?> type) {
-        return ParameterizedType.class.cast(
-                Stream.of(s.getClass().getGenericInterfaces())
-                        .filter(i -> ParameterizedType.class.isInstance(i) && 
ParameterizedType.class.cast(i).getRawType() == type)
-                        .findFirst().orElse(null));
-    }
-
     private Object getBeanManager() {
         if (beanManager == null) {
             try { // don't trigger CDI is not there
@@ -619,7 +612,6 @@ public class JohnzonBuilder implements JsonbBuilder {
         }));
         addDateFormatConfigConverters(converters, zoneIDUTC);
 
-
         converters.forEach((k, v) -> builder.addAdapter(k.getFrom(), 
k.getTo(), v));
         return converters;
     }
@@ -632,25 +624,16 @@ public class JohnzonBuilder implements JsonbBuilder {
 
             // Note: we try and fallback in the parsing cause we don't know if 
the date format provided is
             // for date, datetime, time
-
             converters.put(new AdapterKey(Date.class, String.class), new 
ConverterAdapter<>(new Converter<Date>() {
-                private volatile boolean useFormatter = true;
 
                 @Override
                 public String toString(final Date instance) {
-                    return LocalDateTime.ofInstant(instance.toInstant(), 
zoneIDUTC).toString();
+                    return 
formatter.format(ZonedDateTime.ofInstant(instance.toInstant(), zoneIDUTC));
                 }
 
                 @Override
                 public Date fromString(final String text) {
-                    if (useFormatter) {
-                        try {
-                            return Date.from(LocalDateTime.parse(text, 
formatter).toInstant(ZoneOffset.UTC));
-                        } catch (final DateTimeParseException dpe) {
-                            useFormatter = false;
-                        }
-                    }
-                    return 
Date.from(LocalDateTime.parse(text).toInstant(ZoneOffset.UTC));
+                    return Date.from(Instant.from(formatter.parse(text)));
                 }
             }));
             converters.put(new AdapterKey(LocalDateTime.class, String.class), 
new ConverterAdapter<>(new Converter<LocalDateTime>() {
@@ -721,7 +704,7 @@ public class JohnzonBuilder implements JsonbBuilder {
         if (text.length() == 3) { // don't fail but log it
             
Logger.getLogger(JohnzonBuilder.class.getName()).severe("Deprecated timezone: " 
+ text);
         }
-        */
+         */
     }
 
     private Map<String, ?> generatorConfig() {

http://git-wip-us.apache.org/repos/asf/johnzon/blob/028a1644/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingParserImpl.java
----------------------------------------------------------------------
diff --git 
a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingParserImpl.java 
b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingParserImpl.java
index 8e74e3c..35b303a 100644
--- 
a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingParserImpl.java
+++ 
b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingParserImpl.java
@@ -18,6 +18,7 @@
  */
 package org.apache.johnzon.mapper;
 
+import java.lang.reflect.AnnotatedType;
 import org.apache.johnzon.mapper.access.AccessMode;
 import org.apache.johnzon.mapper.converter.CharacterConverter;
 import org.apache.johnzon.mapper.converter.EnumConverter;
@@ -40,10 +41,12 @@ import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.lang.reflect.ParameterizedType;
 import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
 import java.math.BigDecimal;
 import java.math.BigInteger;
 import java.util.ArrayDeque;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Base64;
 import java.util.Collection;
 import java.util.Collections;
@@ -70,9 +73,12 @@ import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 
 import static java.util.Arrays.asList;
+import java.util.Date;
+import java.util.Optional;
 import static javax.json.JsonValue.ValueType.FALSE;
 import static javax.json.JsonValue.ValueType.NULL;
 import static javax.json.JsonValue.ValueType.NUMBER;
+import static javax.json.JsonValue.ValueType.STRING;
 import static javax.json.JsonValue.ValueType.TRUE;
 
 /**
@@ -93,13 +99,11 @@ public class MappingParserImpl implements MappingParser {
     private final JsonReader jsonReader;
 
     /**
-     * Used for de-referencing JsonPointers during deserialisation.
-     * key: JsonPointer
-     * value: already deserialised Object
+     * Used for de-referencing JsonPointers during deserialisation. key:
+     * JsonPointer value: already deserialised Object
      */
     private Map<String, Object> jsonPointers;
 
-
     public MappingParserImpl(MapperConfig config, Mappings mappings, 
JsonReader jsonReader, boolean isDeduplicateObjects) {
         this.config = config;
         this.mappings = mappings;
@@ -108,7 +112,6 @@ public class MappingParserImpl implements MappingParser {
 
         reverseAdaptersRegistry = new 
ConcurrentHashMap<>(config.getAdapters().size());
 
-
         this.isDeduplicateObjects = isDeduplicateObjects;
 
         if (isDeduplicateObjects) {
@@ -118,7 +121,6 @@ public class MappingParserImpl implements MappingParser {
         }
     }
 
-
     @Override
     public <T> T readObject(Type targetType) {
         try {
@@ -143,6 +145,12 @@ public class MappingParserImpl implements MappingParser {
         if (JsonString.class.isInstance(jsonValue) && (targetType == 
String.class || targetType == Object.class)) {
             return (T) JsonString.class.cast(jsonValue).getString();
         }
+        if (JsonString.class.isInstance(jsonValue) && targetType instanceof 
Class && Class.class.cast(targetType).isEnum()) {
+            return (T) Enum.valueOf(Class.class.cast(targetType), 
JsonString.class.cast(jsonValue).getString());
+        }
+        if (JsonString.class.isInstance(jsonValue) && targetType instanceof 
Class && Date.class.isAssignableFrom(Class.class.cast(targetType))) {
+            return (T) convertTo(config.findAdapter(targetType), jsonValue, 
null);
+        }
         if (JsonNumber.class.isInstance(jsonValue)) {
             final JsonNumber number = JsonNumber.class.cast(jsonValue);
             if (targetType == int.class || targetType == Integer.class) {
@@ -199,7 +207,6 @@ public class MappingParserImpl implements MappingParser {
         throw new IllegalArgumentException("Unsupported " + jsonValue + " for 
type " + targetType);
     }
 
-
     private Object buildObject(final Type inType, final JsonObject object, 
final boolean applyObjectConverter, JsonPointerTracker jsonPointer) {
         Type type = inType;
         if (inType == Object.class) {
@@ -264,7 +271,29 @@ public class MappingParserImpl implements MappingParser {
                         }
                         return map;
                     }
+                } else {
+                
+                    // if a specific mapping has not been declared, let's try 
finding and using one without generics
+                    ObjectConverter.Reader objectConverter = 
config.findObjectConverterReader((Class) aType.getRawType());
+                
+                    if (objectConverter != null) {
+                        return objectConverter.fromJson(object, type, new 
SuppressConversionMappingParser(this, object));
+                    }
+                    
+                }
+            } else if (TypeVariable.class.isInstance(type)) {
+                
+                TypeVariable vType = TypeVariable.class.cast(type);
+                
+                Optional<AnnotatedType> findFirst = 
Arrays.asList(vType.getAnnotatedBounds()).stream().findFirst();
+
+                if (findFirst.isPresent()) {
+                    ObjectConverter.Reader objectConverter = 
config.findObjectConverterReader((Class) findFirst.get().getType());
+                    if (objectConverter != null) {
+                        return objectConverter.fromJson(object, type, new 
SuppressConversionMappingParser(this, object));
+                    }
                 }
+
             } else if (Map.class == type || HashMap.class == type || 
LinkedHashMap.class == type) {
                 final LinkedHashMap<String, Object> map = new 
LinkedHashMap<String, Object>();
                 for (final Map.Entry<String, JsonValue> value : 
object.entrySet()) {
@@ -284,7 +313,7 @@ public class MappingParserImpl implements MappingParser {
         if (classMapping.adapter != null) {
             return classMapping.adapter.from(t);
         }
-        */
+         */
 
         if (classMapping.factory == null) {
             throw new MapperException(classMapping.clazz + " not 
instantiable");
@@ -292,9 +321,11 @@ public class MappingParserImpl implements MappingParser {
 
         if (config.isFailOnUnknown()) {
             if (!classMapping.setters.keySet().containsAll(object.keySet())) {
-                throw new MapperException("(fail on unknown properties): " + 
new HashSet<String>(object.keySet()) {{
-                    removeAll(classMapping.setters.keySet());
-                }});
+                throw new MapperException("(fail on unknown properties): " + 
new HashSet<String>(object.keySet()) {
+                    {
+                        removeAll(classMapping.setters.keySet());
+                    }
+                });
             }
         }
 
@@ -426,6 +457,9 @@ public class MappingParserImpl implements MappingParser {
                 }
             }
         }
+        if (STRING.equals(valueType)) {
+            return converter.to(JsonString.class.cast(jsonValue).getString());
+        }
         return converter.to(jsonValue.toString());
 
     }
@@ -459,10 +493,9 @@ public class MappingParserImpl implements MappingParser {
         return adapterKey;
     }
 
-
     private Object toObject(final Object baseInstance, final JsonValue 
jsonValue,
-                            final Type type, final Adapter itemConverter, 
final JsonPointerTracker jsonPointer,
-                            final Type rootType) {
+            final Type type, final Adapter itemConverter, final 
JsonPointerTracker jsonPointer,
+            final Type rootType) {
         if (jsonValue == null || JsonValue.NULL.equals(jsonValue)) {
             return null;
         }
@@ -506,8 +539,7 @@ public class MappingParserImpl implements MappingParser {
             }
             final boolean typedAdapter = 
TypeAwareAdapter.class.isInstance(itemConverter);
             final Object object = buildObject(
-                    baseInstance != null ? baseInstance.getClass() : (
-                            typedAdapter ? 
TypeAwareAdapter.class.cast(itemConverter).getTo() : type),
+                    baseInstance != null ? baseInstance.getClass() : 
(typedAdapter ? TypeAwareAdapter.class.cast(itemConverter).getTo() : type),
                     JsonObject.class.cast(jsonValue), type instanceof Class,
                     jsonPointer);
             return typedAdapter ? itemConverter.to(object) : object;
@@ -578,8 +610,8 @@ public class MappingParserImpl implements MappingParser {
     }
 
     private Object buildArray(final Type type, final JsonArray jsonArray, 
final Adapter itemConverter,
-                              final ObjectConverter.Reader objectConverter,
-                              final JsonPointerTracker jsonPointer, final Type 
rootType) {
+            final ObjectConverter.Reader objectConverter,
+            final JsonPointerTracker jsonPointer, final Type rootType) {
         if (Class.class.isInstance(type)) {
             final Class clazz = Class.class.cast(type);
             if (clazz.isArray()) {
@@ -603,7 +635,7 @@ public class MappingParserImpl implements MappingParser {
     }
 
     private Object buildArrayWithComponentType(final JsonArray jsonArray, 
final Class<?> componentType, final Adapter itemConverter,
-                                               final JsonPointerTracker 
jsonPointer, final Type rootType) {
+            final JsonPointerTracker jsonPointer, final Type rootType) {
         final Object array = Array.newInstance(componentType, 
jsonArray.size());
         int i = 0;
         for (final JsonValue value : jsonArray) {
@@ -615,8 +647,8 @@ public class MappingParserImpl implements MappingParser {
     }
 
     private <T> Collection<T> mapCollection(final Mappings.CollectionMapping 
mapping, final JsonArray jsonArray,
-                                            final Adapter itemConverter, 
ObjectConverter.Reader objectConverter,
-                                            final JsonPointerTracker 
jsonPointer, final Type rootType) {
+            final Adapter itemConverter, ObjectConverter.Reader 
objectConverter,
+            final JsonPointerTracker jsonPointer, final Type rootType) {
         final Collection collection;
 
         if (SortedSet.class == mapping.raw || NavigableSet.class == 
mapping.raw || TreeSet.class == mapping.raw) {
@@ -642,7 +674,7 @@ public class MappingParserImpl implements MappingParser {
             collection.add(JsonValue.NULL.equals(value)
                     ? null
                     : toValue(null, value, null, itemConverter, mapping.arg, 
objectConverter,
-                    isDeduplicateObjects ? new JsonPointerTracker(jsonPointer, 
i) : null, rootType));
+                            isDeduplicateObjects ? new 
JsonPointerTracker(jsonPointer, i) : null, rootType));
             i++;
         }
 
@@ -660,7 +692,6 @@ public class MappingParserImpl implements MappingParser {
         return collection;
     }
 
-
     private Object[] createParameters(final Mappings.ClassMapping mapping, 
final JsonObject object, JsonPointerTracker jsonPointer) {
         final int length = mapping.factory.getParameterTypes().length;
         final Object[] objects = new Object[length];
@@ -682,8 +713,8 @@ public class MappingParserImpl implements MappingParser {
     }
 
     private Object toValue(final Object baseInstance, final JsonValue 
jsonValue, final Adapter converter,
-                           final Adapter itemConverter, final Type type, final 
ObjectConverter.Reader objectConverter,
-                           final JsonPointerTracker jsonPointer, final Type 
rootType) {
+            final Adapter itemConverter, final Type type, final 
ObjectConverter.Reader objectConverter,
+            final JsonPointerTracker jsonPointer, final Type rootType) {
 
         if (objectConverter != null) {
 
@@ -701,7 +732,6 @@ public class MappingParserImpl implements MappingParser {
                 : convertTo(converter, jsonValue, jsonPointer);
     }
 
-
     /**
      * @deprecated see MapperConfig
      */
@@ -743,8 +773,8 @@ public class MappingParserImpl implements MappingParser {
             }
         }
         if (converter == null) {
-            throw new MapperException("Missing a Converter for type " + aClass 
+ " to convert the JSON String '" +
-                    text + "' . Please register a custom converter for it.");
+            throw new MapperException("Missing a Converter for type " + aClass 
+ " to convert the JSON String '"
+                    + text + "' . Please register a custom converter for it.");
         }
         return converter.to(text);
     }
@@ -770,9 +800,11 @@ public class MappingParserImpl implements MappingParser {
 
     /**
      * Internal class to suppress {@link ObjectConverter} lookup if and only if
-     * the {@link JsonValue} is the same refernece than the lookup was done 
before.
+     * the {@link JsonValue} is the same refernece than the lookup was done
+     * before.
      */
     private static class SuppressConversionMappingParser implements 
MappingParser {
+
         private final MappingParserImpl delegate;
         private final JsonObject suppressConversionFor;
 

Reply via email to