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             nullnullnullnullnullnull);
21
22     public final static PropertyMetadata STD_OPTIONAL = new PropertyMetadata(Boolean.FALSE,
23             nullnullnullnullnullnull);
24
25     public final static PropertyMetadata STD_REQUIRED_OR_OPTIONAL = new PropertyMetadata(null,
26             nullnullnullnullnullnull);
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
46         protected MergeInfo(AnnotatedMember getter, boolean fromDefaults) {
47             this.getter = getter;
48             this.fromDefaults = fromDefaults;
49         }
50
51         public static MergeInfo createForDefaults(AnnotatedMember getter) {
52             return new MergeInfo(getter, true);
53         }
54
55         public static MergeInfo createForTypeOverride(AnnotatedMember getter) {
56             return new MergeInfo(getter, false);
57         }
58
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      */

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      */

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                     nullnullnull);
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
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                     nullnullnull);
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      */

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
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      */

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      */

190     public PropertyMetadata withNulls(Nulls valueNulls,
191             Nulls contentNulls) {
192         return new PropertyMetadata(_required, _description, _index, _defaultValue,
193                 _mergeInfo, valueNulls, contentNulls);
194     }
195
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     
209     public PropertyMetadata withIndex(Integer index) {
210         return new PropertyMetadata(_required, _description, index, _defaultValue,
211                 _mergeInfo, _valueNulls, _contentNulls);
212     }
213     
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
232     public String getDescription() { return _description; }
233
234     /**
235      * @since 2.5
236      */

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      */

245     public boolean hasDefaultValue() { return (_defaultValue != null); }
246
247     public boolean isRequired() { return (_required != null) && _required.booleanValue(); }
248
249     public Boolean getRequired() { return _required; }
250
251     /**
252      * @since 2.4
253      */

254     public Integer getIndex() { return _index; }
255
256     /**
257      * @since 2.4
258      */

259     public boolean hasIndex() { return _index != null; }
260
261     /**
262      * @since 2.9
263      */

264     public MergeInfo getMergeInfo() { return _mergeInfo; }
265
266     /**
267      * @since 2.9
268      */

269     public Nulls getValueNulls() { return _valueNulls; }
270
271     /**
272      * @since 2.9
273      */

274     public Nulls getContentNulls() { return _contentNulls; }
275 }
276