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