1 package com.fasterxml.jackson.databind.util;
2 
3 import java.util.Collection;
4 import java.util.Collections;
5 import java.util.HashSet;
6 import java.util.Set;
7 
8 /**
9  * @since 2.12
10  */
11 public class IgnorePropertiesUtil
12 {
13     /**
14      * Decide if we need to ignore a property or not, given a set of field to ignore and a set of field to include.
15      */
shouldIgnore(Object value, Collection<String> toIgnore, Collection<String> toInclude)16     public static boolean shouldIgnore(Object value, Collection<String> toIgnore, Collection<String> toInclude) {
17         if (toIgnore == null && toInclude ==null) {
18             return false;
19         }
20 
21         if (toInclude == null) {
22             return toIgnore.contains(value);
23         }
24 
25         if (toIgnore == null) {
26             return !toInclude.contains(value);
27         }
28 
29         // NOTE: conflict between both, JsonIncludeProperties will take priority.
30         return !toInclude.contains(value) || toIgnore.contains(value);
31     }
32 
33     /**
34      * Factory method for creating and return a {@link Checker} instance if (and only if)
35      * one needed.
36      *
37      * @param toIgnore Set of property names to ignore (may be null)
38      * @param toInclude Set of only property names to include (if null, undefined)
39      *
40      * @return Checker, if validity checks are needed; {@code null} otherwise
41      */
buildCheckerIfNeeded(Set<String> toIgnore, Set<String> toInclude)42     public static Checker buildCheckerIfNeeded(Set<String> toIgnore, Set<String> toInclude) {
43         // First: no-op case
44         if ((toInclude == null) && ((toIgnore == null) || toIgnore.isEmpty())) {
45             return null;
46         }
47         return Checker.construct(toIgnore, toInclude);
48     }
49 
50     /**
51      * Helper that encapsulates logic for combining two sets of "included names":
52      * default logic is to do intersection (name must be in both to be included
53      * in result)
54      *
55      * @param prevToInclude Existing set of names to include, if defined; null means "not defined"
56      * @param newToInclude New set of names to included, if defined; null means "not defined"
57      *
58      * @return Resulting set of names, using intersection if neither {@code null}; or the
59      *    non-null one (if only one is {@code null}); or {@code null} if both arguments {@code null}.
60      */
combineNamesToInclude(Set<String> prevToInclude, Set<String> newToInclude)61     public static Set<String> combineNamesToInclude(Set<String> prevToInclude,
62             Set<String> newToInclude) {
63         if (prevToInclude == null) {
64             return newToInclude;
65         }
66         if (newToInclude == null) {
67             return prevToInclude;
68         }
69         final Set<String> result = new HashSet<>();
70 
71         // Make the intersection with the previously included properties
72         for (String prop : newToInclude) {
73             if (prevToInclude.contains(prop)) {
74                 result.add(prop);
75             }
76         }
77         return result;
78     }
79 
80     /**
81      * Helper class to encapsulate logic from static {@code shouldIgnore} method
82      * of util class.
83      */
84     public final static class Checker
85         implements java.io.Serializable
86     {
87         private static final long serialVersionUID = 1L;
88 
89         private final Set<String> _toIgnore;
90         private final Set<String> _toInclude;
91 
Checker(Set<String> toIgnore, Set<String> toInclude)92         private Checker(Set<String> toIgnore, Set<String> toInclude) {
93             if (toIgnore == null) {
94                 toIgnore = Collections.emptySet();
95             }
96             _toIgnore = toIgnore;
97             _toInclude = toInclude;
98         }
99 
construct(Set<String> toIgnore, Set<String> toInclude)100         public static Checker construct(Set<String> toIgnore, Set<String> toInclude) {
101             return new Checker(toIgnore, toInclude);
102         }
103 
104         // May seem odd but during serialization key is not cast up to String:
shouldIgnore(Object propertyName)105         public boolean shouldIgnore(Object propertyName) {
106             return ((_toInclude != null) && !_toInclude.contains(propertyName))
107                     || _toIgnore.contains(propertyName);
108         }
109     }
110 }
111