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 2018/07/03 08:25:08 UTC

johnzon git commit: JOHNZON-176 adding a FieldFilteringStrategy for ignored fields

Repository: johnzon
Updated Branches:
  refs/heads/master 07a04d383 -> a2cbd4375


JOHNZON-176 adding a FieldFilteringStrategy for ignored fields


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

Branch: refs/heads/master
Commit: a2cbd4375fcb361a8805e598e51656f34134dfad
Parents: 07a04d3
Author: Romain Manni-Bucau <rm...@gmail.com>
Authored: Tue Jul 3 10:24:11 2018 +0200
Committer: Romain Manni-Bucau <rm...@gmail.com>
Committed: Tue Jul 3 10:24:11 2018 +0200

----------------------------------------------------------------------
 .../jaxrs/ConfigurableJohnzonProvider.java      |  9 +++
 .../WildcardConfigurableJohnzonProvider.java    |  9 +++
 .../apache/johnzon/mapper/MapperBuilder.java    | 43 ++++++++++--
 .../johnzon/mapper/access/BaseAccessMode.java   | 70 +++++++++++++++-----
 .../org/apache/johnzon/mapper/MapperTest.java   | 27 ++++++++
 5 files changed, 135 insertions(+), 23 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/johnzon/blob/a2cbd437/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/ConfigurableJohnzonProvider.java
----------------------------------------------------------------------
diff --git a/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/ConfigurableJohnzonProvider.java b/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/ConfigurableJohnzonProvider.java
index 18e6466..30a452d 100644
--- a/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/ConfigurableJohnzonProvider.java
+++ b/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/ConfigurableJohnzonProvider.java
@@ -21,6 +21,7 @@ package org.apache.johnzon.jaxrs;
 import org.apache.johnzon.mapper.MapperBuilder;
 import org.apache.johnzon.mapper.SerializeValueFilter;
 import org.apache.johnzon.mapper.access.AccessMode;
+import org.apache.johnzon.mapper.access.BaseAccessMode;
 
 import javax.json.JsonReaderFactory;
 import javax.json.stream.JsonGeneratorFactory;
@@ -150,6 +151,14 @@ public class ConfigurableJohnzonProvider<T> implements MessageBodyWriter<T>, Mes
         builder.setAccessModeName(mode);
     }
 
+    public void setAccessModeFieldFilteringStrategy(final BaseAccessMode.FieldFilteringStrategy strategy) {
+        builder.setAccessModeFieldFilteringStrategy(strategy);
+    }
+
+    public void setAccessModeFieldFilteringStrategyName(final String mode) {
+        builder.setAccessModeFieldFilteringStrategyName(mode);
+    }
+
     public void setSupportHiddenAccess(final boolean supportHiddenAccess) {
         builder.setSupportHiddenAccess(supportHiddenAccess);
     }

http://git-wip-us.apache.org/repos/asf/johnzon/blob/a2cbd437/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/WildcardConfigurableJohnzonProvider.java
----------------------------------------------------------------------
diff --git a/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/WildcardConfigurableJohnzonProvider.java b/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/WildcardConfigurableJohnzonProvider.java
index 34bc456..aa71150 100644
--- a/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/WildcardConfigurableJohnzonProvider.java
+++ b/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/WildcardConfigurableJohnzonProvider.java
@@ -21,6 +21,7 @@ package org.apache.johnzon.jaxrs;
 import org.apache.johnzon.mapper.MapperBuilder;
 import org.apache.johnzon.mapper.SerializeValueFilter;
 import org.apache.johnzon.mapper.access.AccessMode;
+import org.apache.johnzon.mapper.access.BaseAccessMode;
 
 import javax.json.JsonReaderFactory;
 import javax.json.stream.JsonGeneratorFactory;
@@ -158,6 +159,14 @@ public class WildcardConfigurableJohnzonProvider<T> implements MessageBodyWriter
         builder.setAccessModeName(mode);
     }
 
+    public void setAccessModeFieldFilteringStrategy(final BaseAccessMode.FieldFilteringStrategy strategy) {
+        builder.setAccessModeFieldFilteringStrategy(strategy);
+    }
+
+    public void setAccessModeFieldFilteringStrategyName(final String mode) {
+        builder.setAccessModeFieldFilteringStrategyName(mode);
+    }
+
     public void setSupportHiddenAccess(final boolean supportHiddenAccess) {
         builder.setSupportHiddenAccess(supportHiddenAccess);
     }

http://git-wip-us.apache.org/repos/asf/johnzon/blob/a2cbd437/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperBuilder.java
----------------------------------------------------------------------
diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperBuilder.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperBuilder.java
index 387f3e6..126ff0a 100644
--- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperBuilder.java
+++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperBuilder.java
@@ -18,6 +18,9 @@
  */
 package org.apache.johnzon.mapper;
 
+import static java.util.Arrays.asList;
+import static java.util.Locale.ROOT;
+
 import org.apache.johnzon.core.JsonParserFactoryImpl;
 import org.apache.johnzon.mapper.access.AccessMode;
 import org.apache.johnzon.mapper.access.BaseAccessMode;
@@ -129,6 +132,7 @@ public class MapperBuilder {
     private Map<Class<?>, ObjectConverter.Reader<?>> objectConverterReaders = new HashMap<Class<?>, ObjectConverter.Reader<?>>();
     private Map<Class<?>, ObjectConverter.Writer<?>> objectConverterWriters = new HashMap<Class<?>, ObjectConverter.Writer<?>>();
     private Map<Class<?>, String[]> ignoredForFields = new HashMap<Class<?>, String[]>();
+    private BaseAccessMode.FieldFilteringStrategy fieldFilteringStrategy = null;
     private boolean primitiveConverters;
     private boolean failOnUnknownProperties;
     private SerializeValueFilter serializeValueFilter;
@@ -181,15 +185,26 @@ public class MapperBuilder {
                 throw new IllegalArgumentException("Unsupported access mode: " + accessModeName);
             }
         }
+        if (fieldFilteringStrategy != null) {
+            if (!BaseAccessMode.class.isInstance(accessMode)) {
+                throw new IllegalArgumentException("fieldFilteringStrategy can't be set with this access mode: " + accessMode);
+            }
+            BaseAccessMode.class.cast(accessMode).setFieldFilteringStrategy(fieldFilteringStrategy);
+        }
         if (!ignoredForFields.isEmpty()) {
             if (BaseAccessMode.class.isInstance(accessMode)) {
                 final BaseAccessMode baseAccessMode = BaseAccessMode.class.cast(accessMode);
-                for (final Map.Entry<Class<?>, String[]> ignored : ignoredForFields.entrySet()) {
-                    final String[] fields = ignored.getValue();
-                    if (fields == null || fields.length == 0) {
-                        baseAccessMode.getFieldsToRemove().remove(ignored.getKey());
-                    } else {
-                        baseAccessMode.getFieldsToRemove().put(ignored.getKey(), fields);
+                final BaseAccessMode.FieldFilteringStrategy strategy = baseAccessMode.getFieldFilteringStrategy();
+                if (BaseAccessMode.ConfiguredFieldFilteringStrategy.class.isInstance(strategy)) {
+                    final BaseAccessMode.ConfiguredFieldFilteringStrategy filteringStrategy =
+                            BaseAccessMode.ConfiguredFieldFilteringStrategy.class.cast(strategy);
+                    for (final Map.Entry<Class<?>, String[]> ignored : ignoredForFields.entrySet()) {
+                        final String[] fields = ignored.getValue();
+                        if (fields == null || fields.length == 0) {
+                            filteringStrategy.getFieldsToRemove().remove(ignored.getKey());
+                        } else {
+                            filteringStrategy.getFieldsToRemove().put(ignored.getKey(), asList(fields));
+                        }
                     }
                 }
             } else {
@@ -287,6 +302,22 @@ public class MapperBuilder {
         return this;
     }
 
+    public MapperBuilder setAccessModeFieldFilteringStrategy(final BaseAccessMode.FieldFilteringStrategy strategy) {
+        this.fieldFilteringStrategy = strategy;
+        return this;
+    }
+
+    public MapperBuilder setAccessModeFieldFilteringStrategyName(final String mode) {
+        switch (mode.toLowerCase(ROOT)) {
+            case "all":
+                return setAccessModeFieldFilteringStrategy(new BaseAccessMode.AllEntriesFieldFilteringStrategy());
+            case "single":
+                return setAccessModeFieldFilteringStrategy(new BaseAccessMode.SingleEntryFieldFilteringStrategy());
+            default:
+                throw new IllegalArgumentException("Unknown field filter strategy: " + mode);
+        }
+    }
+
     public MapperBuilder setSupportHiddenAccess(final boolean supportHiddenAccess) {
         this.supportHiddenAccess = supportHiddenAccess;
         return this;

http://git-wip-us.apache.org/repos/asf/johnzon/blob/a2cbd437/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/BaseAccessMode.java
----------------------------------------------------------------------
diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/BaseAccessMode.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/BaseAccessMode.java
index 5661ee2..0eba849 100644
--- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/BaseAccessMode.java
+++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/BaseAccessMode.java
@@ -18,6 +18,9 @@
  */
 package org.apache.johnzon.mapper.access;
 
+import static java.util.Arrays.asList;
+import static java.util.Collections.emptySet;
+import static java.util.stream.Collectors.toSet;
 import static org.apache.johnzon.mapper.reflection.Converters.matches;
 
 import java.beans.ConstructorProperties;
@@ -27,8 +30,9 @@ import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.lang.reflect.Type;
+import java.util.Collection;
 import java.util.Comparator;
-import java.util.HashMap;
+import java.util.LinkedHashMap;
 import java.util.Map;
 
 import org.apache.johnzon.mapper.Adapter;
@@ -43,16 +47,13 @@ import org.apache.johnzon.mapper.internal.ConverterAdapter;
 public abstract class BaseAccessMode implements AccessMode {
     private static final Type[] NO_PARAMS = new Type[0];
 
-    private final Map<Class<?>, String[]> fieldsToRemove = new HashMap<Class<?>, String[]>();
+    private FieldFilteringStrategy fieldFilteringStrategy = new SingleEntryFieldFilteringStrategy();
     private final boolean acceptHiddenConstructor;
     private final boolean useConstructor;
 
     protected BaseAccessMode(final boolean useConstructor, final boolean acceptHiddenConstructor) {
         this.useConstructor = useConstructor;
         this.acceptHiddenConstructor = acceptHiddenConstructor;
-
-        // mainly built it in the JVM types == user cant handle them
-        fieldsToRemove.put(Throwable.class, new String[]{"suppressedExceptions", "cause"});
     }
 
     protected abstract Map<String,Reader> doFindReaders(Class<?> clazz);
@@ -73,9 +74,12 @@ public abstract class BaseAccessMode implements AccessMode {
         return sanitize(clazz, doFindWriters(clazz));
     }
 
-    // editable during builder time, dont do it at runtime or you get no guarantee
-    public Map<Class<?>, String[]> getFieldsToRemove() {
-        return fieldsToRemove;
+    public void setFieldFilteringStrategy(final FieldFilteringStrategy fieldFilteringStrategy) {
+        this.fieldFilteringStrategy = fieldFilteringStrategy;
+    }
+
+    public FieldFilteringStrategy getFieldFilteringStrategy() {
+        return fieldFilteringStrategy;
     }
 
     @Override
@@ -182,9 +186,7 @@ public abstract class BaseAccessMode implements AccessMode {
                 }
                 try {
                     return params == null ? cons.newInstance() : cons.newInstance(params);
-                } catch (final InstantiationException e) {
-                    throw new IllegalStateException(e);
-                } catch (final IllegalAccessException e) {
+                } catch (final InstantiationException | IllegalAccessException e) {
                     throw new IllegalStateException(e);
                 } catch (final InvocationTargetException e) {
                     throw new IllegalStateException(e.getCause());
@@ -255,14 +257,48 @@ public abstract class BaseAccessMode implements AccessMode {
     }
 
     private <T> Map<String, T> sanitize(final Class<?> type, final Map<String, T> delegate) {
-        for (final Map.Entry<Class<?>, String[]> entry : fieldsToRemove.entrySet()) {
-            if (entry.getKey().isAssignableFrom(type)) {
-                for (final String field : entry.getValue()) {
-                    delegate.remove(field);
+        for (final String field : fieldFilteringStrategy.select(type)) {
+            delegate.remove(field);
+        }
+        return delegate;
+    }
+
+    public interface FieldFilteringStrategy {
+        Collection<String> select(final Class<?> type);
+    }
+
+    public static abstract class ConfiguredFieldFilteringStrategy implements FieldFilteringStrategy {
+        private final Map<Class<?>, Collection<String>> fieldsToRemove = new LinkedHashMap<>();
+
+        public ConfiguredFieldFilteringStrategy() {
+            // mainly built it in the JVM types == user cant handle them
+            fieldsToRemove.put(Throwable.class, asList("suppressedExceptions", "cause"));
+        }
+
+        public Map<Class<?>, Collection<String>> getFieldsToRemove() {
+            return fieldsToRemove;
+        }
+    }
+
+    public static class SingleEntryFieldFilteringStrategy extends ConfiguredFieldFilteringStrategy {
+        @Override
+        public Collection<String> select(final Class<?> type) {
+            for (final Map.Entry<Class<?>, Collection<String>> entry : getFieldsToRemove().entrySet()) {
+                if (entry.getKey().isAssignableFrom(type)) {
+                    return entry.getValue();
                 }
-                return delegate;
             }
+            return emptySet();
+        }
+    }
+
+    public static class AllEntriesFieldFilteringStrategy extends ConfiguredFieldFilteringStrategy {
+        @Override
+        public Collection<String> select(final Class<?> type) {
+            return getFieldsToRemove().entrySet().stream()
+                    .filter(entry -> entry.getKey().isAssignableFrom(type))
+                    .flatMap(entry -> entry.getValue().stream())
+                    .collect(toSet());
         }
-        return delegate;
     }
 }

http://git-wip-us.apache.org/repos/asf/johnzon/blob/a2cbd437/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/MapperTest.java
----------------------------------------------------------------------
diff --git a/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/MapperTest.java b/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/MapperTest.java
index c3d90cf..3582460 100644
--- a/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/MapperTest.java
+++ b/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/MapperTest.java
@@ -32,6 +32,7 @@ import java.lang.reflect.ParameterizedType;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashMap;
 import java.util.LinkedHashMap;
@@ -59,6 +60,22 @@ public class MapperTest {
             + "\"primitives\":[1,2,3,4,5]," + "\"collectionWrapper\":[1,2,3,4,5]," + "\"map\":{\"uno\":true,\"duos\":false}" + "}";
 
     @Test
+    public void ignoreAllStrategy() {
+        final StringWriter writer = new StringWriter();
+        final Child object = new Child();
+        object.children = Collections.singletonList("first");
+        object.a = 5;
+        object.b = 6;
+        object.c = 7;
+        new MapperBuilder().setAccessModeFieldFilteringStrategyName("all")
+                           .setIgnoreFieldsForType(Child.class, "children")
+                           .setIgnoreFieldsForType(Parent.class, "a", "b")
+                           .build()
+                           .writeObject(object, writer);
+        assertEquals("{\"c\":7}", writer.toString());
+    }
+
+    @Test
     public void writeEmptyObject() {
         final StringWriter writer = new StringWriter();
         new MapperBuilder().build().writeObject(null, writer);
@@ -1098,4 +1115,14 @@ public class MapperTest {
     public static class PrimitiveObject {
         public Object bool;
     }
+
+    public static class Parent {
+        public int a;
+        public int b;
+        public int c;
+    }
+
+    public static class Child extends Parent {
+        public List<String> children;
+    }
 }