You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@johnzon.apache.org by rm...@apache.org on 2019/09/09 07:38:20 UTC

[johnzon] branch master updated: JOHNZON-275 ensure Adapter types can be extracted when inheritance is used

This is an automated email from the ASF dual-hosted git repository.

rmannibucau pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/johnzon.git


The following commit(s) were added to refs/heads/master by this push:
     new 940715e  JOHNZON-275 ensure Adapter types can be extracted when inheritance is used
940715e is described below

commit 940715e055bcd1c2a5db16c0872e1c49762ef3ca
Author: Romain Manni-Bucau <rm...@gmail.com>
AuthorDate: Mon Sep 9 09:38:06 2019 +0200

    JOHNZON-275 ensure Adapter types can be extracted when inheritance is used
---
 .../apache/johnzon/mapper/MappingParserImpl.java   | 28 +++++----
 .../apache/johnzon/mapper/IndirectAdapterTest.java | 69 ++++++++++++++++++++++
 2 files changed, 85 insertions(+), 12 deletions(-)

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 a2f388f..6c16b72 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
@@ -453,7 +453,7 @@ public class MappingParserImpl implements MappingParser {
         final JsonValue.ValueType valueType = jsonValue != null ? jsonValue.getValueType() : null;
 
         final AdapterKey key = getAdapterKey(converter);
-        if (JsonValue.class == key.getTo()) {
+        if (key != null && JsonValue.class == key.getTo()) {
             return converter.to(jsonValue);
         }
 
@@ -538,18 +538,22 @@ public class MappingParserImpl implements MappingParser {
                 config.getReverseAdapters().putIfAbsent(converter, adapterKey);
 
             } else {
-                final Type[] types = converter.getClass().getGenericInterfaces();
-                for (final Type t : types) {
-                    if (!ParameterizedType.class.isInstance(t)) {
-                        continue;
-                    }
-                    final ParameterizedType pt = ParameterizedType.class.cast(t);
-                    if (Adapter.class == pt.getRawType()) {
-                        final Type[] actualTypeArguments = pt.getActualTypeArguments();
-                        adapterKey = new AdapterKey(actualTypeArguments[0], actualTypeArguments[1]);
-                        config.getReverseAdapters().putIfAbsent(converter, adapterKey);
-                        break;
+                Class<?> current = converter.getClass();
+                while (current != null && current != Object.class) {
+                    final Type[] types = current.getGenericInterfaces();
+                    for (final Type t : types) {
+                        if (!ParameterizedType.class.isInstance(t)) {
+                            continue;
+                        }
+                        final ParameterizedType pt = ParameterizedType.class.cast(t);
+                        if (Adapter.class == pt.getRawType()) {
+                            final Type[] actualTypeArguments = pt.getActualTypeArguments();
+                            adapterKey = new AdapterKey(actualTypeArguments[0], actualTypeArguments[1]);
+                            config.getReverseAdapters().putIfAbsent(converter, adapterKey);
+                            return adapterKey;
+                        }
                     }
+                    current = current.getSuperclass();
                 }
             }
         }
diff --git a/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/IndirectAdapterTest.java b/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/IndirectAdapterTest.java
new file mode 100644
index 0000000..d8409bd
--- /dev/null
+++ b/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/IndirectAdapterTest.java
@@ -0,0 +1,69 @@
+/*
+ * 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.johnzon.mapper;
+
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.time.temporal.TemporalAccessor;
+import java.time.temporal.TemporalQuery;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class IndirectAdapterTest {
+    protected abstract static class GenericTimeAdapter<T extends TemporalAccessor> implements Adapter<T, String> {
+        private final DateTimeFormatter formatter;
+        private final TemporalQuery<T> query;
+
+        private GenericTimeAdapter(final DateTimeFormatter formatter, final TemporalQuery<T> query) {
+            this.formatter = formatter;
+            this.query = query;
+        }
+
+        @Override
+        public T to(final String b) {
+            return formatter.parse(b, query);
+        }
+
+        @Override
+        public String from(final T a) {
+            return formatter.format(a);
+        }
+    }
+
+    public static final class LocalDateAdapter extends GenericTimeAdapter<LocalDate> {
+        public LocalDateAdapter() {
+            super(DateTimeFormatter.ISO_DATE, LocalDate::from);
+        }
+    }
+
+
+    public static class BeanType {
+        @JohnzonConverter(LocalDateAdapter.class)
+        public LocalDate date;
+    }
+
+    @Test
+    public void testIndirectAdapter() {
+        try (final Mapper mapper = new MapperBuilder().build()) {
+            final BeanType content = mapper.readObject("{\"date\":\"2019-09-09\"}", BeanType.class);
+            Assert.assertEquals(LocalDate.of(2019, 9, 9), content.date);
+        }
+    }
+}