• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.fasterxml.jackson.databind;
2 
3 import com.fasterxml.jackson.annotation.Nulls;
4 import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
5 
6 /**
7  * Simple container class used for storing "additional" metadata about
8  * properties. Carved out to reduce number of distinct properties that
9  * actual property implementations and place holders need to store;
10  * since instances are immutable, they can be freely shared.
11  *
12  * @since 2.3
13  */
14 public class PropertyMetadata
15     implements java.io.Serializable
16 {
17     private static final long serialVersionUID = -1;
18 
19     public final static PropertyMetadata STD_REQUIRED = new PropertyMetadata(Boolean.TRUE,
20             null, null, null, null, null, null);
21 
22     public final static PropertyMetadata STD_OPTIONAL = new PropertyMetadata(Boolean.FALSE,
23             null, null, null, null, null, null);
24 
25     public final static PropertyMetadata STD_REQUIRED_OR_OPTIONAL = new PropertyMetadata(null,
26             null, null, null, null, null, null);
27 
28     /**
29      * Helper class used for containing information about expected merge
30      * information for this property, if merging is expected.
31      *
32      * @since 2.9
33      */
34     public final static class MergeInfo
35     // NOTE: need not be Serializable, not persisted
36     {
37         public final AnnotatedMember getter;
38 
39         /**
40          * Flag that is set if the information came from global defaults,
41          * and not from explicit per-property annotations or per-type
42          * config overrides.
43          */
44         public final boolean fromDefaults;
45 
MergeInfo(AnnotatedMember getter, boolean fromDefaults)46         protected MergeInfo(AnnotatedMember getter, boolean fromDefaults) {
47             this.getter = getter;
48             this.fromDefaults = fromDefaults;
49         }
50 
createForDefaults(AnnotatedMember getter)51         public static MergeInfo createForDefaults(AnnotatedMember getter) {
52             return new MergeInfo(getter, true);
53         }
54 
createForTypeOverride(AnnotatedMember getter)55         public static MergeInfo createForTypeOverride(AnnotatedMember getter) {
56             return new MergeInfo(getter, false);
57         }
58 
createForPropertyOverride(AnnotatedMember getter)59         public static MergeInfo createForPropertyOverride(AnnotatedMember getter) {
60             return new MergeInfo(getter, false);
61         }
62     }
63 
64     /**
65      * Three states: required, not required and unknown; unknown represented
66      * as null.
67      */
68     protected final Boolean _required;
69 
70     /**
71      * Optional human-readable description associated with the property.
72      */
73     protected final String _description;
74 
75     /**
76      * Optional index of the property within containing Object.
77      *
78      * @since 2.4
79      */
80     protected final Integer _index;
81 
82     /**
83      * Optional default value, as String, for property; not used for
84      * any functionality by core databind, offered as metadata for
85      * extensions.
86      */
87     protected final String _defaultValue;
88 
89     /**
90      * Settings regarding merging, if property is determined to possibly
91      * be mergeable (possibly since global settings may be omitted for
92      * non-mergeable types).
93      *<p>
94      * NOTE: transient since it is assumed that this information is only
95      * relevant during initial setup and not needed after full initialization.
96      * May be changed if this proves necessary.
97      *
98      * @since 2.9
99      */
100     protected final transient MergeInfo _mergeInfo;
101 
102     /**
103      * Settings regarding handling of incoming `null`s, both for value itself
104      * and, for structured types, content values (array/Collection elements,
105      * Map values).
106      *
107      * @since 2.9
108      */
109     protected Nulls _valueNulls, _contentNulls;
110 
111     /*
112     /**********************************************************
113     /* Construction, configuration
114     /**********************************************************
115      */
116 
117     /**
118      * @since 2.9
119      */
PropertyMetadata(Boolean req, String desc, Integer index, String def, MergeInfo mergeInfo, Nulls valueNulls, Nulls contentNulls)120     protected PropertyMetadata(Boolean req, String desc, Integer index, String def,
121             MergeInfo mergeInfo, Nulls valueNulls, Nulls contentNulls)
122     {
123         _required = req;
124         _description = desc;
125         _index = index;
126         _defaultValue = (def == null || def.isEmpty()) ? null : def;
127         _mergeInfo = mergeInfo;
128         _valueNulls = valueNulls;
129         _contentNulls = contentNulls;
130     }
131 
132     /**
133      * @since 2.8.8
134      */
construct(Boolean req, String desc, Integer index, String defaultValue)135     public static PropertyMetadata construct(Boolean req, String desc, Integer index,
136             String defaultValue) {
137         if ((desc != null) || (index != null) || (defaultValue != null)) {
138             return new PropertyMetadata(req, desc, index, defaultValue,
139                     null, null, null);
140         }
141         if (req == null) {
142             return STD_REQUIRED_OR_OPTIONAL;
143         }
144         return req ? STD_REQUIRED : STD_OPTIONAL;
145     }
146 
147     @Deprecated // since 2.8.8
construct(boolean req, String desc, Integer index, String defaultValue)148     public static PropertyMetadata construct(boolean req, String desc, Integer index,
149             String defaultValue) {
150         if (desc != null || index != null || defaultValue != null) {
151             return new PropertyMetadata(req, desc, index, defaultValue,
152                     null, null, null);
153         }
154         return req ? STD_REQUIRED : STD_OPTIONAL;
155     }
156 
157     /**
158      * Minor optimization: let's canonicalize back to placeholders in cases
159      * where there is no real data to consider
160      */
readResolve()161     protected Object readResolve()
162     {
163         if ((_description == null) && (_index == null) && (_defaultValue == null)
164                 && (_mergeInfo == null)
165                 && (_valueNulls == null) && (_contentNulls == null)) {
166             if (_required == null) {
167                 return STD_REQUIRED_OR_OPTIONAL;
168             }
169             return _required.booleanValue() ? STD_REQUIRED : STD_OPTIONAL;
170         }
171         return this;
172     }
173 
withDescription(String desc)174     public PropertyMetadata withDescription(String desc) {
175         return new PropertyMetadata(_required, desc, _index, _defaultValue,
176                 _mergeInfo, _valueNulls, _contentNulls);
177     }
178 
179     /**
180      * @since 2.9
181      */
withMergeInfo(MergeInfo mergeInfo)182     public PropertyMetadata withMergeInfo(MergeInfo mergeInfo) {
183         return new PropertyMetadata(_required, _description, _index, _defaultValue,
184                 mergeInfo, _valueNulls, _contentNulls);
185     }
186 
187     /**
188      * @since 2.9
189      */
withNulls(Nulls valueNulls, Nulls contentNulls)190     public PropertyMetadata withNulls(Nulls valueNulls,
191             Nulls contentNulls) {
192         return new PropertyMetadata(_required, _description, _index, _defaultValue,
193                 _mergeInfo, valueNulls, contentNulls);
194     }
195 
withDefaultValue(String def)196     public PropertyMetadata withDefaultValue(String def) {
197         if ((def == null) || def.isEmpty()) {
198             if (_defaultValue == null) {
199                 return this;
200             }
201             def = null;
202         } else if (def.equals(_defaultValue)) {
203             return this;
204         }
205         return new PropertyMetadata(_required, _description, _index, def,
206                 _mergeInfo, _valueNulls, _contentNulls);
207     }
208 
withIndex(Integer index)209     public PropertyMetadata withIndex(Integer index) {
210         return new PropertyMetadata(_required, _description, index, _defaultValue,
211                 _mergeInfo, _valueNulls, _contentNulls);
212     }
213 
withRequired(Boolean b)214     public PropertyMetadata withRequired(Boolean b) {
215         if (b == null) {
216             if (_required == null) {
217                 return this;
218             }
219         } else if (b.equals(_required)) {
220             return this;
221         }
222         return new PropertyMetadata(b, _description, _index, _defaultValue,
223                 _mergeInfo, _valueNulls, _contentNulls);
224     }
225 
226     /*
227     /**********************************************************
228     /* Accessors
229     /**********************************************************
230      */
231 
getDescription()232     public String getDescription() { return _description; }
233 
234     /**
235      * @since 2.5
236      */
getDefaultValue()237     public String getDefaultValue() { return _defaultValue; }
238 
239     /**
240      * Accessor for determining whether property has declared "default value",
241      * which may be used by extension modules.
242      *
243      * @since 2.6
244      */
hasDefaultValue()245     public boolean hasDefaultValue() { return (_defaultValue != null); }
246 
isRequired()247     public boolean isRequired() { return (_required != null) && _required.booleanValue(); }
248 
getRequired()249     public Boolean getRequired() { return _required; }
250 
251     /**
252      * @since 2.4
253      */
getIndex()254     public Integer getIndex() { return _index; }
255 
256     /**
257      * @since 2.4
258      */
hasIndex()259     public boolean hasIndex() { return _index != null; }
260 
261     /**
262      * @since 2.9
263      */
getMergeInfo()264     public MergeInfo getMergeInfo() { return _mergeInfo; }
265 
266     /**
267      * @since 2.9
268      */
getValueNulls()269     public Nulls getValueNulls() { return _valueNulls; }
270 
271     /**
272      * @since 2.9
273      */
getContentNulls()274     public Nulls getContentNulls() { return _contentNulls; }
275 }
276