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

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

commit 23b49f3d517a07e3d51f1ea1d32cf94a474cd7d4
Author: Mark Struberg <strub...@apache.org>
AuthorDate: Tue Apr 12 10:03:36 2022 +0200

    JOHNZON-364 use reflection to avoid caches.
---
 .../org/apache/johnzon/core/util/ClassUtil.java    | 32 ++++++++++++++++++
 .../org/apache/johnzon/core/ClassUtilTest.java     | 38 ++++++++++++++++++++++
 .../jsonb/DefaultPropertyVisibilityStrategy.java   | 23 +++++++++----
 3 files changed, 87 insertions(+), 6 deletions(-)

diff --git 
a/johnzon-core/src/main/java/org/apache/johnzon/core/util/ClassUtil.java 
b/johnzon-core/src/main/java/org/apache/johnzon/core/util/ClassUtil.java
index 1dc189b..1eebe6f 100644
--- a/johnzon-core/src/main/java/org/apache/johnzon/core/util/ClassUtil.java
+++ b/johnzon-core/src/main/java/org/apache/johnzon/core/util/ClassUtil.java
@@ -58,4 +58,36 @@ public final class ClassUtil {
         }
     }
 
+    /**
+     * Calculate the name of a getter based on the name of it's field and the 
type
+     *
+     * @param fieldName
+     * @param type      of the field
+     * @return "get" or "is" method name for the field
+     */
+    public static String getterName(String fieldName, Class<?> type) {
+        StringBuilder sb = new StringBuilder(50);
+        sb.append(type == Boolean.class || type == boolean.class ? "is" : 
"get");
+        
sb.append(Character.toUpperCase(fieldName.charAt(0))).append(fieldName.substring(1));
+        return sb.toString();
+    }
+
+    /**
+     * Calculate the name of a setter based on the name of it's field
+     *
+     * @param fieldName
+     * @return "set" method name for the field
+     */
+    public static String setterName(String fieldName) {
+        StringBuilder sb = new StringBuilder(50);
+        sb.append("set");
+        
sb.append(Character.toUpperCase(fieldName.charAt(0))).append(fieldName.substring(1));
+        return sb.toString();
+    }
+
+    public static String capitalizeName(String fieldName) {
+        StringBuilder sb = new StringBuilder(50);
+        
sb.append(Character.toUpperCase(fieldName.charAt(0))).append(fieldName.substring(1));
+        return sb.toString();
+    }
 }
\ No newline at end of file
diff --git 
a/johnzon-core/src/test/java/org/apache/johnzon/core/ClassUtilTest.java 
b/johnzon-core/src/test/java/org/apache/johnzon/core/ClassUtilTest.java
new file mode 100644
index 0000000..299d146
--- /dev/null
+++ b/johnzon-core/src/test/java/org/apache/johnzon/core/ClassUtilTest.java
@@ -0,0 +1,38 @@
+/*
+ * 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.core;
+
+import org.apache.johnzon.core.util.ClassUtil;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class ClassUtilTest {
+
+    @Test
+    public void testGetterNames() {
+        assertEquals("getMyName", ClassUtil.getterName("myName", 
Integer.class));
+        assertEquals("isEnabled", ClassUtil.getterName("enabled", 
Boolean.class));
+        assertEquals("isEnabled", ClassUtil.getterName("enabled", 
boolean.class));
+    }
+
+    @Test
+    public void testSetterNames() {
+        assertEquals("setMyName", ClassUtil.setterName("myName"));
+        assertEquals("setEnabled", ClassUtil.setterName("enabled"));
+    }
+}
diff --git 
a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/DefaultPropertyVisibilityStrategy.java
 
b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/DefaultPropertyVisibilityStrategy.java
index fe4d449..33e0be5 100644
--- 
a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/DefaultPropertyVisibilityStrategy.java
+++ 
b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/DefaultPropertyVisibilityStrategy.java
@@ -18,6 +18,7 @@
  */
 package org.apache.johnzon.jsonb;
 
+import org.apache.johnzon.core.util.ClassUtil;
 import org.apache.johnzon.mapper.Cleanable;
 
 import javax.json.bind.annotation.JsonbProperty;
@@ -36,8 +37,6 @@ import static java.util.Optional.ofNullable;
 
 class DefaultPropertyVisibilityStrategy implements 
javax.json.bind.config.PropertyVisibilityStrategy, Cleanable<Class<?>> {
     private final ConcurrentMap<Class<?>, PropertyVisibilityStrategy> 
strategies = new ConcurrentHashMap<>();
-    private final ConcurrentMap<Class<?>, Map<String, Boolean>> getters = new 
ConcurrentHashMap<>();
-    private final ConcurrentMap<Class<?>, Map<String, Boolean>> setters = new 
ConcurrentHashMap<>();
 
     private volatile boolean skipGetpackage;
 
@@ -61,9 +60,23 @@ class DefaultPropertyVisibilityStrategy implements 
javax.json.bind.config.Proper
         // 3.7.1. Scope and Field access strategy
         // note: we should bind the class since a field of a parent class can 
have a getter in a child
         if (!useGetter) {
-            return setters.computeIfAbsent(root, 
this::calculateSetters).getOrDefault(field.getName(), true);
+            return !hasMethod(root, ClassUtil.setterName(field.getName()));
+        }
+        final String capitalizedName = 
ClassUtil.capitalizeName(field.getName());
+        return !hasMethod(root, "get" + capitalizedName) ||  hasMethod(root, 
"is" + capitalizedName);
+    }
+
+    private boolean hasMethod(Class<?> clazz, String methodName, Class<?>... 
paramTypes) {
+        try {
+            clazz.getDeclaredMethod(methodName, paramTypes);
+            return true;
+        } catch (NoSuchMethodException e) {
+            final Class<?> superclass = clazz.getSuperclass();
+            if (superclass == Object.class) {
+                return false;
+            }
+            return hasMethod(superclass, methodName, paramTypes);
         }
-        return getters.computeIfAbsent(root, 
this::calculateGetters).getOrDefault(field.getName(), true);
     }
 
     /**
@@ -165,8 +178,6 @@ class DefaultPropertyVisibilityStrategy implements 
javax.json.bind.config.Proper
 
     @Override
     public void clean(final Class<?> clazz) {
-        getters.remove(clazz);
-        setters.remove(clazz);
         strategies.remove(clazz);
     }
 }

Reply via email to