blob: 9e562edff2bfe43db7c049e31e557b6c1d4e07ee [file] [log] [blame]
Tatu Salorantae4f23bb2011-12-23 00:31:35 -08001package com.fasterxml.jackson.databind.introspect;
2
Tatu Saloranta19624102014-04-14 20:07:31 -07003import java.util.*;
Tatu Salorantaa00cdd82014-03-30 19:22:49 -07004
Tatu Saloranta80674fe2014-12-03 22:17:21 -08005import com.fasterxml.jackson.annotation.JsonInclude;
Cowtowncoder04413c72015-06-02 17:46:11 -07006import com.fasterxml.jackson.annotation.JsonProperty;
Tatu Saloranta2a41afc2014-05-30 22:58:41 -07007import com.fasterxml.jackson.databind.*;
Cowtowncoderc717c2f2014-09-25 16:52:30 -07008import com.fasterxml.jackson.databind.util.EmptyIterator;
Tatu Salorantae4f23bb2011-12-23 00:31:35 -08009
10/**
11 * Helper class used for aggregating information about a single
12 * potential POJO property.
Tatu Salorantae4f23bb2011-12-23 00:31:35 -080013 */
14public class POJOPropertyBuilder
15 extends BeanPropertyDefinition
16 implements Comparable<POJOPropertyBuilder>
17{
18 /**
Tatu Salorantae40a7692012-01-25 17:36:36 -080019 * Whether property is being composed for serialization
20 * (true) or deserialization (false)
21 */
22 protected final boolean _forSerialization;
23
24 protected final AnnotationIntrospector _annotationIntrospector;
Tatu97d03f62014-05-15 14:23:11 -070025
Tatu Salorantae40a7692012-01-25 17:36:36 -080026 /**
Tatu Salorantae4f23bb2011-12-23 00:31:35 -080027 * External name of logical property; may change with
28 * renaming (by new instance being constructed using
29 * a new name)
30 */
Tatu Saloranta1488cef2013-07-26 14:42:17 -070031 protected final PropertyName _name;
Tatu Salorantae4f23bb2011-12-23 00:31:35 -080032
33 /**
34 * Original internal name, derived from accessor, of this
35 * property. Will not be changed by renaming.
36 */
Tatu Saloranta1488cef2013-07-26 14:42:17 -070037 protected final PropertyName _internalName;
Tatu Salorantae4f23bb2011-12-23 00:31:35 -080038
Tatu Saloranta65c410c2012-01-27 20:44:45 -080039 protected Linked<AnnotatedField> _fields;
Tatu Salorantae4f23bb2011-12-23 00:31:35 -080040
Tatu Saloranta65c410c2012-01-27 20:44:45 -080041 protected Linked<AnnotatedParameter> _ctorParameters;
Tatu Salorantae4f23bb2011-12-23 00:31:35 -080042
Tatu Saloranta65c410c2012-01-27 20:44:45 -080043 protected Linked<AnnotatedMethod> _getters;
Tatu Salorantae4f23bb2011-12-23 00:31:35 -080044
Tatu Saloranta65c410c2012-01-27 20:44:45 -080045 protected Linked<AnnotatedMethod> _setters;
Tatu Saloranta1488cef2013-07-26 14:42:17 -070046
Tatu Saloranta80674fe2014-12-03 22:17:21 -080047 public POJOPropertyBuilder(PropertyName internalName, AnnotationIntrospector ai,
48 boolean forSerialization) {
Tatu Saloranta19624102014-04-14 20:07:31 -070049 this(internalName, internalName, ai, forSerialization);
50 }
51
52 protected POJOPropertyBuilder(PropertyName internalName, PropertyName name,
Tatu Saloranta2fd4ffd2012-02-17 22:40:13 -080053 AnnotationIntrospector annotationIntrospector, boolean forSerialization)
Tatu Salorantae4f23bb2011-12-23 00:31:35 -080054 {
55 _internalName = internalName;
Tatu Saloranta19624102014-04-14 20:07:31 -070056 _name = name;
Tatu Salorantae40a7692012-01-25 17:36:36 -080057 _annotationIntrospector = annotationIntrospector;
58 _forSerialization = forSerialization;
Tatu Salorantae4f23bb2011-12-23 00:31:35 -080059 }
Tatu Saloranta19624102014-04-14 20:07:31 -070060
Tatu Saloranta1488cef2013-07-26 14:42:17 -070061 public POJOPropertyBuilder(POJOPropertyBuilder src, PropertyName newName)
Tatu Salorantae4f23bb2011-12-23 00:31:35 -080062 {
63 _internalName = src._internalName;
64 _name = newName;
Tatu Salorantae40a7692012-01-25 17:36:36 -080065 _annotationIntrospector = src._annotationIntrospector;
Tatu Salorantae4f23bb2011-12-23 00:31:35 -080066 _fields = src._fields;
67 _ctorParameters = src._ctorParameters;
68 _getters = src._getters;
69 _setters = src._setters;
Tatu Salorantae40a7692012-01-25 17:36:36 -080070 _forSerialization = src._forSerialization;
Tatu Salorantae4f23bb2011-12-23 00:31:35 -080071 }
Tatu Salorantafbd795b2012-01-26 22:02:30 -080072
73 /*
74 /**********************************************************
75 /* Fluent factory methods
76 /**********************************************************
Tatu Salorantae4f23bb2011-12-23 00:31:35 -080077 */
Tatu Salorantafbd795b2012-01-26 22:02:30 -080078
79 @Override
Tatu Saloranta1488cef2013-07-26 14:42:17 -070080 public POJOPropertyBuilder withName(PropertyName newName) {
Tatu Salorantae4f23bb2011-12-23 00:31:35 -080081 return new POJOPropertyBuilder(this, newName);
82 }
Tatu Saloranta1488cef2013-07-26 14:42:17 -070083
84 @Override
85 public POJOPropertyBuilder withSimpleName(String newSimpleName)
86 {
87 PropertyName newName = _name.withSimpleName(newSimpleName);
88 return (newName == _name) ? this : new POJOPropertyBuilder(this, newName);
89 }
Tatu Salorantae4f23bb2011-12-23 00:31:35 -080090
91 /*
92 /**********************************************************
93 /* Comparable implementation: sort alphabetically, except
94 /* that properties with constructor parameters sorted
95 /* before other properties
96 /**********************************************************
97 */
98
Tatu Saloranta9439a312013-03-02 13:13:09 -080099 @Override
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800100 public int compareTo(POJOPropertyBuilder other)
101 {
102 // first, if one has ctor params, that should come first:
103 if (_ctorParameters != null) {
104 if (other._ctorParameters == null) {
105 return -1;
106 }
107 } else if (other._ctorParameters != null) {
108 return 1;
109 }
110 /* otherwise sort by external name (including sorting of
111 * ctor parameters)
112 */
113 return getName().compareTo(other.getName());
114 }
Tatu Saloranta69d9c102013-03-13 15:20:18 -0700115
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800116 /*
117 /**********************************************************
Tatu Saloranta69d9c102013-03-13 15:20:18 -0700118 /* BeanPropertyDefinition implementation, name/type
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800119 /**********************************************************
120 */
121
122 @Override
Tatu Saloranta1488cef2013-07-26 14:42:17 -0700123 public String getName() {
124 return (_name == null) ? null : _name.getSimpleName();
125 }
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800126
127 @Override
Tatu Saloranta1488cef2013-07-26 14:42:17 -0700128 public PropertyName getFullName() {
129 return _name;
130 }
Tatu Salorantaa6943ec2015-03-15 20:00:58 -0700131
132 @Override
133 public boolean hasName(PropertyName name) {
134 return _name.equals(name);
135 }
136
Tatu Saloranta1488cef2013-07-26 14:42:17 -0700137 @Override
138 public String getInternalName() { return _internalName.getSimpleName(); }
Tatu Salorantad8e52fa2012-03-12 23:17:45 -0700139
140 @Override
Tatu Saloranta69d9c102013-03-13 15:20:18 -0700141 public PropertyName getWrapperName() {
Tatu Saloranta8d53c222013-03-13 15:56:09 -0700142 /* 13-Mar-2013, tatu: Accessing via primary member SHOULD work,
143 * due to annotation merging. However, I have seen some problems
Tatu Saloranta1488cef2013-07-26 14:42:17 -0700144 * with this access (for other annotations)... so if this should
145 * occur, try commenting out full traversal code
Tatu Saloranta8d53c222013-03-13 15:56:09 -0700146 */
147 AnnotatedMember member = getPrimaryMember();
148 return (member == null || _annotationIntrospector == null) ? null
149 : _annotationIntrospector.findWrapperName(member);
Tatu Saloranta69d9c102013-03-13 15:20:18 -0700150 /*
151 return fromMemberAnnotations(new WithMember<PropertyName>() {
152 @Override
153 public PropertyName withMember(AnnotatedMember member) {
154 return _annotationIntrospector.findWrapperName(member);
155 }
156 });
157 */
158 }
159
160 @Override
Tatu Salorantad8e52fa2012-03-12 23:17:45 -0700161 public boolean isExplicitlyIncluded() {
Tatu365c29b2014-03-28 15:51:00 -0700162 return _anyExplicits(_fields)
163 || _anyExplicits(_getters)
164 || _anyExplicits(_setters)
165 || _anyExplicits(_ctorParameters)
166 ;
167 }
168
169 @Override
170 public boolean isExplicitlyNamed() {
Tatu Salorantad8e52fa2012-03-12 23:17:45 -0700171 return _anyExplicitNames(_fields)
172 || _anyExplicitNames(_getters)
173 || _anyExplicitNames(_setters)
174 || _anyExplicitNames(_ctorParameters)
175 ;
176 }
Tatu365c29b2014-03-28 15:51:00 -0700177
Tatu Saloranta69d9c102013-03-13 15:20:18 -0700178 /*
179 /**********************************************************
180 /* BeanPropertyDefinition implementation, accessor access
181 /**********************************************************
182 */
Tatu70034622014-05-21 14:41:45 -0700183
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800184 @Override
185 public boolean hasGetter() { return _getters != null; }
186
187 @Override
188 public boolean hasSetter() { return _setters != null; }
189
190 @Override
191 public boolean hasField() { return _fields != null; }
192
193 @Override
194 public boolean hasConstructorParameter() { return _ctorParameters != null; }
195
196 @Override
Tatu70034622014-05-21 14:41:45 -0700197 public boolean couldDeserialize() {
198 return (_ctorParameters != null) || (_setters != null) || (_fields != null);
199 }
200
201 @Override
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800202 public boolean couldSerialize() {
203 return (_getters != null) || (_fields != null);
204 }
205
206 @Override
207 public AnnotatedMethod getGetter()
208 {
Tatu Salorantaf52059d2014-05-30 23:07:58 -0700209 // Easy with zero or one getters...
Tatu Saloranta2a41afc2014-05-30 22:58:41 -0700210 Linked<AnnotatedMethod> curr = _getters;
Tatu Saloranta2a41afc2014-05-30 22:58:41 -0700211 if (curr == null) {
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800212 return null;
213 }
Tatu Saloranta2a41afc2014-05-30 22:58:41 -0700214 Linked<AnnotatedMethod> next = curr.next;
Tatu Saloranta2a41afc2014-05-30 22:58:41 -0700215 if (next == null) {
216 return curr.value;
217 }
Tatu Saloranta2a41afc2014-05-30 22:58:41 -0700218 // But if multiple, verify that they do not conflict...
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800219 for (; next != null; next = next.next) {
Tatu Saloranta2a41afc2014-05-30 22:58:41 -0700220 /* [JACKSON-255] Allow masking, i.e. do not report exception if one
221 * is in super-class from the other
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800222 */
Tatu Salorantaf52059d2014-05-30 23:07:58 -0700223 Class<?> currClass = curr.value.getDeclaringClass();
Tatu Saloranta2a41afc2014-05-30 22:58:41 -0700224 Class<?> nextClass = next.value.getDeclaringClass();
Tatu Salorantaf52059d2014-05-30 23:07:58 -0700225 if (currClass != nextClass) {
226 if (currClass.isAssignableFrom(nextClass)) { // next is more specific
Tatu Saloranta2a41afc2014-05-30 22:58:41 -0700227 curr = next;
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800228 continue;
229 }
Tatu Salorantaf52059d2014-05-30 23:07:58 -0700230 if (nextClass.isAssignableFrom(currClass)) { // current more specific
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800231 continue;
232 }
233 }
Tatu Saloranta2a41afc2014-05-30 22:58:41 -0700234 /* 30-May-2014, tatu: Three levels of precedence:
235 *
236 * 1. Regular getters ("getX")
237 * 2. Is-getters ("isX")
238 * 3. Implicit, possible getters ("x")
Tatu Saloranta833680a2013-07-10 19:37:14 -0700239 */
Tatu Saloranta2a41afc2014-05-30 22:58:41 -0700240 int priNext = _getterPriority(next.value);
241 int priCurr = _getterPriority(curr.value);
242
243 if (priNext != priCurr) {
244 if (priNext < priCurr) {
245 curr = next;
246 }
Tatu Saloranta833680a2013-07-10 19:37:14 -0700247 continue;
248 }
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800249 throw new IllegalArgumentException("Conflicting getter definitions for property \""+getName()+"\": "
Tatu Saloranta2a41afc2014-05-30 22:58:41 -0700250 +curr.value.getFullName()+" vs "+next.value.getFullName());
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800251 }
Tatu Saloranta2a41afc2014-05-30 22:58:41 -0700252 // One more thing; to avoid having to do it again...
253 _getters = curr.withoutNext();
254 return curr.value;
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800255 }
Tatu Saloranta2a41afc2014-05-30 22:58:41 -0700256
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800257 @Override
258 public AnnotatedMethod getSetter()
259 {
Tatu Salorantaf52059d2014-05-30 23:07:58 -0700260 // Easy with zero or one getters...
261 Linked<AnnotatedMethod> curr = _setters;
262 if (curr == null) {
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800263 return null;
264 }
Tatu Salorantaf52059d2014-05-30 23:07:58 -0700265 Linked<AnnotatedMethod> next = curr.next;
266 if (next == null) {
267 return curr.value;
268 }
269 // But if multiple, verify that they do not conflict...
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800270 for (; next != null; next = next.next) {
Tatu Salorantaf52059d2014-05-30 23:07:58 -0700271 /* [JACKSON-255] Allow masking, i.e. do not report exception if one
272 * is in super-class from the other
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800273 */
Tatu Salorantaf52059d2014-05-30 23:07:58 -0700274 Class<?> currClass = curr.value.getDeclaringClass();
275 Class<?> nextClass = next.value.getDeclaringClass();
276 if (currClass != nextClass) {
277 if (currClass.isAssignableFrom(nextClass)) { // next is more specific
278 curr = next;
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800279 continue;
280 }
Tatu Salorantaf52059d2014-05-30 23:07:58 -0700281 if (nextClass.isAssignableFrom(currClass)) { // current more specific
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800282 continue;
283 }
284 }
Tatu Salorantaf52059d2014-05-30 23:07:58 -0700285 /* 30-May-2014, tatu: Two levels of precedence:
286 *
287 * 1. Regular setters ("setX(...)")
288 * 2. Implicit, possible setters ("x(...)")
289 */
290 int priNext = _setterPriority(next.value);
291 int priCurr = _setterPriority(curr.value);
292
293 if (priNext != priCurr) {
294 if (priNext < priCurr) {
295 curr = next;
296 }
297 continue;
298 }
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800299 throw new IllegalArgumentException("Conflicting setter definitions for property \""+getName()+"\": "
Tatu Salorantaf52059d2014-05-30 23:07:58 -0700300 +curr.value.getFullName()+" vs "+next.value.getFullName());
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800301 }
Tatu Salorantaf52059d2014-05-30 23:07:58 -0700302 // One more thing; to avoid having to do it again...
303 _setters = curr.withoutNext();
304 return curr.value;
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800305 }
306
307 @Override
308 public AnnotatedField getField()
309 {
310 if (_fields == null) {
311 return null;
312 }
313 // If multiple, verify that they do not conflict...
314 AnnotatedField field = _fields.value;
Tatu Saloranta65c410c2012-01-27 20:44:45 -0800315 Linked<AnnotatedField> next = _fields.next;
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800316 for (; next != null; next = next.next) {
317 AnnotatedField nextField = next.value;
318 Class<?> fieldClass = field.getDeclaringClass();
319 Class<?> nextClass = nextField.getDeclaringClass();
320 if (fieldClass != nextClass) {
321 if (fieldClass.isAssignableFrom(nextClass)) { // next is more specific
322 field = nextField;
323 continue;
324 }
325 if (nextClass.isAssignableFrom(fieldClass)) { // getter more specific
326 continue;
327 }
328 }
329 throw new IllegalArgumentException("Multiple fields representing property \""+getName()+"\": "
330 +field.getFullName()+" vs "+nextField.getFullName());
331 }
332 return field;
333 }
334
335 @Override
336 public AnnotatedParameter getConstructorParameter()
337 {
338 if (_ctorParameters == null) {
339 return null;
340 }
341 /* Hmmh. Checking for constructor parameters is trickier; for one,
342 * we must allow creator and factory method annotations.
343 * If this is the case, constructor parameter has the precedence.
344 *
345 * So, for now, just try finding the first constructor parameter;
346 * if none, first factory method. And don't check for dups, if we must,
347 * can start checking for them later on.
348 */
Tatu Saloranta65c410c2012-01-27 20:44:45 -0800349 Linked<AnnotatedParameter> curr = _ctorParameters;
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800350 do {
351 if (curr.value.getOwner() instanceof AnnotatedConstructor) {
352 return curr.value;
353 }
354 curr = curr.next;
355 } while (curr != null);
356 return _ctorParameters.value;
357 }
Cowtowncoderc717c2f2014-09-25 16:52:30 -0700358
359 @Override
360 public Iterator<AnnotatedParameter> getConstructorParameters() {
361 if (_ctorParameters == null) {
362 return EmptyIterator.instance();
363 }
364 return new MemberIterator<AnnotatedParameter>(_ctorParameters);
365 }
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800366
Tatu Salorantae40a7692012-01-25 17:36:36 -0800367 @Override
368 public AnnotatedMember getAccessor()
369 {
370 AnnotatedMember m = getGetter();
371 if (m == null) {
372 m = getField();
373 }
374 return m;
375 }
376
377 @Override
378 public AnnotatedMember getMutator()
379 {
380 AnnotatedMember m = getConstructorParameter();
381 if (m == null) {
382 m = getSetter();
383 if (m == null) {
384 m = getField();
385 }
386 }
387 return m;
388 }
Tatu Salorantab0091942013-10-18 23:52:30 -0700389
390 @Override
391 public AnnotatedMember getNonConstructorMutator() {
392 AnnotatedMember m = getSetter();
393 if (m == null) {
394 m = getField();
395 }
396 return m;
397 }
398
Tatu Salorantaf412e852012-09-11 22:05:51 -0700399 @Override
400 public AnnotatedMember getPrimaryMember() {
401 if (_forSerialization) {
402 return getAccessor();
403 }
404 return getMutator();
405 }
Tatu Salorantae40a7692012-01-25 17:36:36 -0800406
Tatu Salorantaf52059d2014-05-30 23:07:58 -0700407 protected int _getterPriority(AnnotatedMethod m)
408 {
409 final String name = m.getName();
410 // [#238]: Also, regular getters have precedence over "is-getters"
411 if (name.startsWith("get") && name.length() > 3) {
412 // should we check capitalization?
413 return 1;
414 }
415 if (name.startsWith("is") && name.length() > 2) {
416 return 2;
417 }
418 return 3;
419 }
420
421 protected int _setterPriority(AnnotatedMethod m)
422 {
423 final String name = m.getName();
424 if (name.startsWith("set") && name.length() > 3) {
425 // should we check capitalization?
426 return 1;
427 }
428 return 2;
429 }
430
Tatu9550e092012-02-03 17:20:13 -0800431 /*
Tatu Salorantaf412e852012-09-11 22:05:51 -0700432 /**********************************************************
Tatu9550e092012-02-03 17:20:13 -0800433 /* Implementations of refinement accessors
Tatu Salorantaf412e852012-09-11 22:05:51 -0700434 /**********************************************************
Tatu Salorantae40a7692012-01-25 17:36:36 -0800435 */
Tatu Saloranta9439a312013-03-02 13:13:09 -0800436
Tatu Saloranta65c410c2012-01-27 20:44:45 -0800437 @Override
438 public Class<?>[] findViews() {
Tatu Salorantaf412e852012-09-11 22:05:51 -0700439 return fromMemberAnnotations(new WithMember<Class<?>[]>() {
Tatu Saloranta9439a312013-03-02 13:13:09 -0800440 @Override
Tatu Salorantaf1c79d42012-04-17 07:57:41 -0700441 public Class<?>[] withMember(AnnotatedMember member) {
Tatu Saloranta65c410c2012-01-27 20:44:45 -0800442 return _annotationIntrospector.findViews(member);
Tatu Saloranta19ab5802012-01-26 22:26:18 -0800443 }
Tatu Saloranta65c410c2012-01-27 20:44:45 -0800444 });
445 }
446
447 @Override
448 public AnnotationIntrospector.ReferenceProperty findReferenceType() {
Tatu Salorantaf412e852012-09-11 22:05:51 -0700449 return fromMemberAnnotations(new WithMember<AnnotationIntrospector.ReferenceProperty>() {
Tatu Saloranta9439a312013-03-02 13:13:09 -0800450 @Override
Tatu Salorantaf1c79d42012-04-17 07:57:41 -0700451 public AnnotationIntrospector.ReferenceProperty withMember(AnnotatedMember member) {
Tatu Saloranta65c410c2012-01-27 20:44:45 -0800452 return _annotationIntrospector.findReferenceType(member);
Tatu Saloranta19ab5802012-01-26 22:26:18 -0800453 }
Tatu Saloranta65c410c2012-01-27 20:44:45 -0800454 });
Tatu Salorantae40a7692012-01-25 17:36:36 -0800455 }
Tatu9550e092012-02-03 17:20:13 -0800456
Tatu Salorantaeffb8fd2012-02-04 19:20:10 -0800457 @Override
Tatu9550e092012-02-03 17:20:13 -0800458 public boolean isTypeId() {
Tatu Salorantaf412e852012-09-11 22:05:51 -0700459 Boolean b = fromMemberAnnotations(new WithMember<Boolean>() {
Tatu Saloranta9439a312013-03-02 13:13:09 -0800460 @Override
Tatu Salorantaf1c79d42012-04-17 07:57:41 -0700461 public Boolean withMember(AnnotatedMember member) {
Tatu9550e092012-02-03 17:20:13 -0800462 return _annotationIntrospector.isTypeId(member);
463 }
464 });
465 return (b != null) && b.booleanValue();
466 }
Tatu Salorantaeffb8fd2012-02-04 19:20:10 -0800467
468 @Override
Tatu Saloranta8bdd49b2013-07-26 16:18:32 -0700469 public PropertyMetadata getMetadata() {
Tatu Saloranta105c58a2013-07-26 16:33:43 -0700470 final Boolean b = _findRequired();
471 final String desc = _findDescription();
Tatu Salorantaab53ab42014-04-12 12:57:43 -0700472 final Integer idx = _findIndex();
Tatu Saloranta2b917fc2014-12-23 21:45:43 -0800473 final String def = _findDefaultValue();
474 if (b == null && idx == null && def == null) {
Tatu Saloranta105c58a2013-07-26 16:33:43 -0700475 return (desc == null) ? PropertyMetadata.STD_REQUIRED_OR_OPTIONAL
476 : PropertyMetadata.STD_REQUIRED_OR_OPTIONAL.withDescription(desc);
477 }
Tatu Saloranta2b917fc2014-12-23 21:45:43 -0800478 return PropertyMetadata.construct(b.booleanValue(), desc, idx, def);
Tatu Saloranta8bdd49b2013-07-26 16:18:32 -0700479 }
480
Tatu Saloranta105c58a2013-07-26 16:33:43 -0700481 protected Boolean _findRequired() {
Tatu Salorantaf412e852012-09-11 22:05:51 -0700482 Boolean b = fromMemberAnnotations(new WithMember<Boolean>() {
Tatu Saloranta9439a312013-03-02 13:13:09 -0800483 @Override
Tatu Salorantaf1c79d42012-04-17 07:57:41 -0700484 public Boolean withMember(AnnotatedMember member) {
Tatu Saloranta2fd4ffd2012-02-17 22:40:13 -0800485 return _annotationIntrospector.hasRequiredMarker(member);
486 }
487 });
Tatu Saloranta105c58a2013-07-26 16:33:43 -0700488 return b;
Tatu Saloranta2fd4ffd2012-02-17 22:40:13 -0800489 }
Tatu Saloranta8bdd49b2013-07-26 16:18:32 -0700490
491 protected String _findDescription() {
492 return fromMemberAnnotations(new WithMember<String>() {
493 @Override
494 public String withMember(AnnotatedMember member) {
495 return _annotationIntrospector.findPropertyDescription(member);
496 }
497 });
498 }
Tatu Salorantaab53ab42014-04-12 12:57:43 -0700499
500 protected Integer _findIndex() {
501 return fromMemberAnnotations(new WithMember<Integer>() {
502 @Override
503 public Integer withMember(AnnotatedMember member) {
504 return _annotationIntrospector.findPropertyIndex(member);
505 }
506 });
507 }
Tatu Saloranta2b917fc2014-12-23 21:45:43 -0800508
509 protected String _findDefaultValue() {
510 return fromMemberAnnotations(new WithMember<String>() {
511 @Override
512 public String withMember(AnnotatedMember member) {
513 return _annotationIntrospector.findPropertyDefaultValue(member);
514 }
515 });
516 }
Tatu Saloranta8bdd49b2013-07-26 16:18:32 -0700517
Tatu Saloranta2fd4ffd2012-02-17 22:40:13 -0800518 @Override
Tatu Salorantad4531822012-02-06 22:44:40 -0800519 public ObjectIdInfo findObjectIdInfo() {
Tatu Salorantaf412e852012-09-11 22:05:51 -0700520 return fromMemberAnnotations(new WithMember<ObjectIdInfo>() {
Tatu Saloranta9439a312013-03-02 13:13:09 -0800521 @Override
Tatu Salorantaf1c79d42012-04-17 07:57:41 -0700522 public ObjectIdInfo withMember(AnnotatedMember member) {
Tatu Saloranta88040e22012-08-24 13:33:00 -0700523 ObjectIdInfo info = _annotationIntrospector.findObjectIdInfo(member);
524 if (info != null) {
525 info = _annotationIntrospector.findObjectReferenceInfo(member, info);
526 }
527 return info;
Tatu Salorantaeffb8fd2012-02-04 19:20:10 -0800528 }
529 });
Tatu Salorantaeffb8fd2012-02-04 19:20:10 -0800530 }
Tatu Saloranta80674fe2014-12-03 22:17:21 -0800531
532 @Override
533 public JsonInclude.Include findInclusion() {
534 if (_annotationIntrospector == null) {
535 return null;
536 }
537 AnnotatedMember am = getAccessor();
538 return _annotationIntrospector.findSerializationInclusion(am, null);
539 }
540
Cowtowncoder04413c72015-06-02 17:46:11 -0700541 public JsonProperty.Access findAccess() {
542 return fromMemberAnnotationsExcept(new WithMember<JsonProperty.Access>() {
543 @Override
544 public JsonProperty.Access withMember(AnnotatedMember member) {
545 return _annotationIntrospector.findPropertyAccess(member);
546 }
547 }, JsonProperty.Access.AUTO);
548 }
549
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800550 /*
551 /**********************************************************
552 /* Data aggregation
553 /**********************************************************
554 */
555
Tatu Saloranta26a052b2014-03-30 20:48:56 -0700556 public void addField(AnnotatedField a, PropertyName name, boolean explName, boolean visible, boolean ignored) {
Tatu365c29b2014-03-28 15:51:00 -0700557 _fields = new Linked<AnnotatedField>(a, _fields, name, explName, visible, ignored);
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800558 }
559
Tatu Saloranta26a052b2014-03-30 20:48:56 -0700560 public void addCtor(AnnotatedParameter a, PropertyName name, boolean explName, boolean visible, boolean ignored) {
Tatu365c29b2014-03-28 15:51:00 -0700561 _ctorParameters = new Linked<AnnotatedParameter>(a, _ctorParameters, name, explName, visible, ignored);
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800562 }
563
Tatu Saloranta26a052b2014-03-30 20:48:56 -0700564 public void addGetter(AnnotatedMethod a, PropertyName name, boolean explName, boolean visible, boolean ignored) {
Tatu365c29b2014-03-28 15:51:00 -0700565 _getters = new Linked<AnnotatedMethod>(a, _getters, name, explName, visible, ignored);
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800566 }
567
Tatu Saloranta26a052b2014-03-30 20:48:56 -0700568 public void addSetter(AnnotatedMethod a, PropertyName name, boolean explName, boolean visible, boolean ignored) {
Tatu365c29b2014-03-28 15:51:00 -0700569 _setters = new Linked<AnnotatedMethod>(a, _setters, name, explName, visible, ignored);
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800570 }
571
572 /**
573 * Method for adding all property members from specified collector into
574 * this collector.
575 */
576 public void addAll(POJOPropertyBuilder src)
577 {
578 _fields = merge(_fields, src._fields);
579 _ctorParameters = merge(_ctorParameters, src._ctorParameters);
580 _getters= merge(_getters, src._getters);
581 _setters = merge(_setters, src._setters);
582 }
583
Tatu Saloranta65c410c2012-01-27 20:44:45 -0800584 private static <T> Linked<T> merge(Linked<T> chain1, Linked<T> chain2)
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800585 {
586 if (chain1 == null) {
587 return chain2;
588 }
589 if (chain2 == null) {
590 return chain1;
591 }
592 return chain1.append(chain2);
593 }
Tatu Salorantaa00cdd82014-03-30 19:22:49 -0700594
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800595 /*
596 /**********************************************************
597 /* Modifications
598 /**********************************************************
599 */
600
601 /**
602 * Method called to remove all entries that are marked as
603 * ignored.
604 */
605 public void removeIgnored()
606 {
607 _fields = _removeIgnored(_fields);
608 _getters = _removeIgnored(_getters);
609 _setters = _removeIgnored(_setters);
610 _ctorParameters = _removeIgnored(_ctorParameters);
611 }
612
Tatu Salorantafbb1c3b2015-06-07 22:50:50 -0700613 /**
614 * @param inferMutators Whether mutators can be "pulled in" by visible
615 * accessors or not.
616 */
617 public void removeNonVisible(boolean inferMutators)
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800618 {
Tatu Salorantafbb1c3b2015-06-07 22:50:50 -0700619 /* 07-Jun-2015, tatu: With 2.6, we will allow optional definition
620 * of explicit access type for property; if not "AUTO", it will
621 * dictate how visibility checks are applied.
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800622 */
Tatu Salorantafbb1c3b2015-06-07 22:50:50 -0700623 JsonProperty.Access acc = findAccess();
624 if (acc == null) {
625 acc = JsonProperty.Access.AUTO;
626 }
627 switch (acc) {
628 case READ_ONLY:
629 // Remove setters, creators for sure, but fields too if deserializing
630 _setters = null;
631 _ctorParameters = null;
632 if (!_forSerialization) {
633 _fields = null;
634 }
635 break;
636 case READ_WRITE:
637 // no trimming whatsoever?
638 break;
639 case WRITE_ONLY:
640 // remove getters, definitely, but also fields if serializing
641 _getters = null;
642 if (_forSerialization) {
643 _fields = null;
644 }
645 break;
646 default:
647 case AUTO: // the default case: base it imply on visibility
648 _getters = _removeNonVisible(_getters);
649 _ctorParameters = _removeNonVisible(_ctorParameters);
650
651 if (!inferMutators || (_getters == null)) {
652 _fields = _removeNonVisible(_fields);
653 _setters = _removeNonVisible(_setters);
654 }
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800655 }
656 }
657
658 /**
Tatu Salorantaa56270a2014-11-16 23:05:18 -0800659 * Mutator that will simply drop any constructor parameters property may have.
660 *
661 * @since 2.5
662 */
663 public void removeConstructors() {
664 _ctorParameters = null;
665 }
666
667 /**
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800668 * Method called to trim unnecessary entries, such as implicit
669 * getter if there is an explict one available. This is important
670 * for later stages, to avoid unnecessary conflicts.
671 */
672 public void trimByVisibility()
673 {
674 _fields = _trimByVisibility(_fields);
675 _getters = _trimByVisibility(_getters);
676 _setters = _trimByVisibility(_setters);
677 _ctorParameters = _trimByVisibility(_ctorParameters);
678 }
679
680 @SuppressWarnings("unchecked")
681 public void mergeAnnotations(boolean forSerialization)
682 {
683 if (forSerialization) {
684 if (_getters != null) {
685 AnnotationMap ann = _mergeAnnotations(0, _getters, _fields, _ctorParameters, _setters);
Christopher Currie6cf2bb52015-07-16 23:48:05 -0700686 _getters = _applyAnnotations(_getters, ann);
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800687 } else if (_fields != null) {
688 AnnotationMap ann = _mergeAnnotations(0, _fields, _ctorParameters, _setters);
Christopher Currie6cf2bb52015-07-16 23:48:05 -0700689 _fields = _applyAnnotations(_fields, ann);
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800690 }
Tatu Salorantab0091942013-10-18 23:52:30 -0700691 } else { // for deserialization
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800692 if (_ctorParameters != null) {
693 AnnotationMap ann = _mergeAnnotations(0, _ctorParameters, _setters, _fields, _getters);
Christopher Currie6cf2bb52015-07-16 23:48:05 -0700694 _ctorParameters = _applyAnnotations(_ctorParameters, ann);
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800695 } else if (_setters != null) {
696 AnnotationMap ann = _mergeAnnotations(0, _setters, _fields, _getters);
Christopher Currie6cf2bb52015-07-16 23:48:05 -0700697 _setters = _applyAnnotations(_setters, ann);
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800698 } else if (_fields != null) {
699 AnnotationMap ann = _mergeAnnotations(0, _fields, _getters);
Christopher Currie6cf2bb52015-07-16 23:48:05 -0700700 _fields = _applyAnnotations(_fields, ann);
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800701 }
702 }
703 }
704
Tatu Saloranta65c410c2012-01-27 20:44:45 -0800705 private AnnotationMap _mergeAnnotations(int index, Linked<? extends AnnotatedMember>... nodes)
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800706 {
Christopher Currie6cf2bb52015-07-16 23:48:05 -0700707 AnnotationMap ann = _getAllAnnotations(nodes[index]);
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800708 ++index;
709 for (; index < nodes.length; ++index) {
710 if (nodes[index] != null) {
711 return AnnotationMap.merge(ann, _mergeAnnotations(index, nodes));
712 }
713 }
714 return ann;
715 }
Christopher Currie6cf2bb52015-07-16 23:48:05 -0700716
Cowtowncodera23ff9f2015-07-17 11:53:06 -0700717 /**
718 * Replacement, as per [databind#868], of simple access to annotations, which
719 * does "deep merge" if an as necessary.
720 *<pre>
721 * nodes[index].value.getAllAnnotations()
722 *</pre>
723 *
724 * @since 2.6
725 */
Christopher Currie6cf2bb52015-07-16 23:48:05 -0700726 private <T extends AnnotatedMember> AnnotationMap _getAllAnnotations(Linked<T> node) {
727 AnnotationMap ann = node.value.getAllAnnotations();
728 if (node.next != null) {
729 ann = AnnotationMap.merge(ann, _getAllAnnotations(node.next));
730 }
731 return ann;
732 }
733
Cowtowncodera23ff9f2015-07-17 11:53:06 -0700734 /**
735 * Helper method to handle recursive merging of annotations within accessor class,
736 * to ensure no annotations are accidentally dropped within chain when non-visible
737 * and secondary accessors are pruned later on.
738 *<p>
739 * See [databind#868] for more information.
740 *
741 * @since 2.6
742 */
Christopher Currie6cf2bb52015-07-16 23:48:05 -0700743 private <T extends AnnotatedMember> Linked<T> _applyAnnotations(Linked<T> node, AnnotationMap ann) {
Cowtowncodera23ff9f2015-07-17 11:53:06 -0700744 @SuppressWarnings("unchecked")
Christopher Currie6cf2bb52015-07-16 23:48:05 -0700745 T value = (T) node.value.withAnnotations(ann);
746 if (node.next != null) {
747 node = node.withNext(_applyAnnotations(node.next, ann));
748 }
749 return node.withValue(value);
750 }
751
Tatu Saloranta65c410c2012-01-27 20:44:45 -0800752 private <T> Linked<T> _removeIgnored(Linked<T> node)
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800753 {
754 if (node == null) {
755 return node;
756 }
757 return node.withoutIgnored();
758 }
759
Tatu Saloranta65c410c2012-01-27 20:44:45 -0800760 private <T> Linked<T> _removeNonVisible(Linked<T> node)
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800761 {
762 if (node == null) {
763 return node;
764 }
765 return node.withoutNonVisible();
766 }
767
Tatu Saloranta65c410c2012-01-27 20:44:45 -0800768 private <T> Linked<T> _trimByVisibility(Linked<T> node)
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800769 {
770 if (node == null) {
771 return node;
772 }
773 return node.trimByVisibility();
774 }
775
776 /*
777 /**********************************************************
778 /* Accessors for aggregate information
779 /**********************************************************
780 */
781
Tatu365c29b2014-03-28 15:51:00 -0700782 private <T> boolean _anyExplicits(Linked<T> n)
783 {
784 for (; n != null; n = n.next) {
Tatu Saloranta26a052b2014-03-30 20:48:56 -0700785 if (n.name != null && n.name.hasSimpleName()) {
Tatu365c29b2014-03-28 15:51:00 -0700786 return true;
787 }
788 }
789 return false;
790 }
791
Tatu Saloranta65c410c2012-01-27 20:44:45 -0800792 private <T> boolean _anyExplicitNames(Linked<T> n)
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800793 {
794 for (; n != null; n = n.next) {
Tatu365c29b2014-03-28 15:51:00 -0700795 if (n.name != null && n.isNameExplicit) {
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800796 return true;
797 }
798 }
799 return false;
800 }
801
802 public boolean anyVisible() {
803 return _anyVisible(_fields)
804 || _anyVisible(_getters)
805 || _anyVisible(_setters)
806 || _anyVisible(_ctorParameters)
807 ;
808 }
809
Tatu Saloranta65c410c2012-01-27 20:44:45 -0800810 private <T> boolean _anyVisible(Linked<T> n)
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800811 {
812 for (; n != null; n = n.next) {
813 if (n.isVisible) {
814 return true;
815 }
816 }
817 return false;
818 }
819
820 public boolean anyIgnorals() {
821 return _anyIgnorals(_fields)
822 || _anyIgnorals(_getters)
823 || _anyIgnorals(_setters)
824 || _anyIgnorals(_ctorParameters)
825 ;
826 }
827
Tatu Saloranta65c410c2012-01-27 20:44:45 -0800828 private <T> boolean _anyIgnorals(Linked<T> n)
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800829 {
830 for (; n != null; n = n.next) {
831 if (n.isMarkedIgnored) {
832 return true;
833 }
834 }
835 return false;
836 }
837
838 /**
Tatu Saloranta19624102014-04-14 20:07:31 -0700839 * Method called to find out set of explicit names for accessors
840 * bound together due to implicit name.
841 *
842 * @since 2.4
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800843 */
Tatu Saloranta19624102014-04-14 20:07:31 -0700844 public Set<PropertyName> findExplicitNames()
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800845 {
Tatu Saloranta19624102014-04-14 20:07:31 -0700846 Set<PropertyName> renamed = null;
847 renamed = _findExplicitNames(_fields, renamed);
848 renamed = _findExplicitNames(_getters, renamed);
849 renamed = _findExplicitNames(_setters, renamed);
850 renamed = _findExplicitNames(_ctorParameters, renamed);
851 if (renamed == null) {
852 return Collections.emptySet();
853 }
854 return renamed;
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800855 }
856
Tatu Saloranta19624102014-04-14 20:07:31 -0700857 /**
858 * Method called when a previous call to {@link #findExplicitNames} found
859 * multiple distinct explicit names, and the property this builder represents
860 * basically needs to be broken apart and replaced by a set of more than
861 * one properties.
862 *
863 * @since 2.4
864 */
865 public Collection<POJOPropertyBuilder> explode(Collection<PropertyName> newNames)
866 {
867 HashMap<PropertyName,POJOPropertyBuilder> props = new HashMap<PropertyName,POJOPropertyBuilder>();
868 _explode(newNames, props, _fields);
869 _explode(newNames, props, _getters);
870 _explode(newNames, props, _setters);
871 _explode(newNames, props, _ctorParameters);
872 return props.values();
873 }
874
875 @SuppressWarnings("unchecked")
876 private void _explode(Collection<PropertyName> newNames,
877 Map<PropertyName,POJOPropertyBuilder> props,
878 Linked<?> accessors)
879 {
880 final Linked<?> firstAcc = accessors; // clumsy, part 1
881 for (Linked<?> node = accessors; node != null; node = node.next) {
882 PropertyName name = node.name;
883 if (!node.isNameExplicit || name == null) { // no explicit name -- problem!
Cowtowncoderf95a9272014-09-16 16:40:43 -0700884 // [Issue#541] ... but only as long as it's visible
885 if (!node.isVisible) {
886 continue;
887 }
888
Tatu Saloranta19624102014-04-14 20:07:31 -0700889 throw new IllegalStateException("Conflicting/ambiguous property name definitions (implicit name '"
890 +_name+"'): found multiple explicit names: "
891 +newNames+", but also implicit accessor: "+node);
892 }
893 POJOPropertyBuilder prop = props.get(name);
894 if (prop == null) {
895 prop = new POJOPropertyBuilder(_internalName, name, _annotationIntrospector, _forSerialization);
896 props.put(name, prop);
897 }
898 // ultra-clumsy, part 2 -- lambdas would be nice here
899 if (firstAcc == _fields) {
900 Linked<AnnotatedField> n2 = (Linked<AnnotatedField>) node;
901 prop._fields = n2.withNext(prop._fields);
902 } else if (firstAcc == _getters) {
903 Linked<AnnotatedMethod> n2 = (Linked<AnnotatedMethod>) node;
904 prop._getters = n2.withNext(prop._getters);
905 } else if (firstAcc == _setters) {
906 Linked<AnnotatedMethod> n2 = (Linked<AnnotatedMethod>) node;
907 prop._setters = n2.withNext(prop._setters);
908 } else if (firstAcc == _ctorParameters) {
909 Linked<AnnotatedParameter> n2 = (Linked<AnnotatedParameter>) node;
910 prop._ctorParameters = n2.withNext(prop._ctorParameters);
911 } else {
912 throw new IllegalStateException("Internal error: mismatched accessors, property: "+this);
913 }
914 }
915 }
916
917 private Set<PropertyName> _findExplicitNames(Linked<? extends AnnotatedMember> node,
918 Set<PropertyName> renamed)
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800919 {
920 for (; node != null; node = node.next) {
Tatu Saloranta19624102014-04-14 20:07:31 -0700921 /* 30-Mar-2014, tatu: Second check should not be needed, but seems like
Tatu Saloranta2bd58f52014-03-30 21:11:06 -0700922 * removing it can cause nasty exceptions with certain version
923 * combinations (2.4 databind, an older module).
924 * So leaving it in for now until this is resolved
925 * (or version beyond 2.4)
926 */
927 if (!node.isNameExplicit || node.name == null) {
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800928 continue;
929 }
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800930 if (renamed == null) {
Tatu Saloranta19624102014-04-14 20:07:31 -0700931 renamed = new HashSet<PropertyName>();
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800932 }
Tatu Saloranta19624102014-04-14 20:07:31 -0700933 renamed.add(node.name);
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800934 }
935 return renamed;
936 }
Tatu Salorantaa1e496f2012-09-11 20:25:12 -0700937
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800938 // For trouble-shooting
939 @Override
940 public String toString()
941 {
942 StringBuilder sb = new StringBuilder();
943 sb.append("[Property '").append(_name)
944 .append("'; ctors: ").append(_ctorParameters)
945 .append(", field(s): ").append(_fields)
946 .append(", getter(s): ").append(_getters)
947 .append(", setter(s): ").append(_setters)
948 ;
949 sb.append("]");
950 return sb.toString();
951 }
952
953 /*
954 /**********************************************************
Tatu Saloranta65c410c2012-01-27 20:44:45 -0800955 /* Helper methods
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800956 /**********************************************************
957 */
958
959 /**
Tatu Salorantaf412e852012-09-11 22:05:51 -0700960 * Helper method used for finding annotation values, from accessors
961 * relevant to current usage (deserialization, serialization)
Tatu Saloranta65c410c2012-01-27 20:44:45 -0800962 */
Tatu Salorantaf412e852012-09-11 22:05:51 -0700963 protected <T> T fromMemberAnnotations(WithMember<T> func)
Tatu Saloranta65c410c2012-01-27 20:44:45 -0800964 {
965 T result = null;
966 if (_annotationIntrospector != null) {
967 if (_forSerialization) {
968 if (_getters != null) {
969 result = func.withMember(_getters.value);
970 }
971 } else {
972 if (_ctorParameters != null) {
973 result = func.withMember(_ctorParameters.value);
974 }
975 if (result == null && _setters != null) {
976 result = func.withMember(_setters.value);
977 }
978 }
979 if (result == null && _fields != null) {
980 result = func.withMember(_fields.value);
981 }
982 }
983 return result;
984 }
Cowtowncoder04413c72015-06-02 17:46:11 -0700985
986 protected <T> T fromMemberAnnotationsExcept(WithMember<T> func, T defaultValue)
987 {
Tatu Salorantafbb1c3b2015-06-07 22:50:50 -0700988 if (_annotationIntrospector == null) {
989 return null;
990 }
991
992 // NOTE: here we must ask ALL accessors, but the order varies between
993 // serialization, deserialization
994 if (_forSerialization) {
995 if (_getters != null) {
996 T result = func.withMember(_getters.value);
997 if ((result != null) && (result != defaultValue)) {
998 return result;
Cowtowncoder04413c72015-06-02 17:46:11 -0700999 }
1000 }
1001 if (_fields != null) {
1002 T result = func.withMember(_fields.value);
1003 if ((result != null) && (result != defaultValue)) {
1004 return result;
1005 }
1006 }
Tatu Salorantafbb1c3b2015-06-07 22:50:50 -07001007 if (_ctorParameters != null) {
1008 T result = func.withMember(_ctorParameters.value);
1009 if ((result != null) && (result != defaultValue)) {
1010 return result;
1011 }
1012 }
1013 if (_setters != null) {
1014 T result = func.withMember(_setters.value);
1015 if ((result != null) && (result != defaultValue)) {
1016 return result;
1017 }
1018 }
1019 return null;
1020 }
1021 if (_ctorParameters != null) {
1022 T result = func.withMember(_ctorParameters.value);
1023 if ((result != null) && (result != defaultValue)) {
1024 return result;
1025 }
1026 }
1027 if (_setters != null) {
1028 T result = func.withMember(_setters.value);
1029 if ((result != null) && (result != defaultValue)) {
1030 return result;
1031 }
1032 }
1033 if (_fields != null) {
1034 T result = func.withMember(_fields.value);
1035 if ((result != null) && (result != defaultValue)) {
1036 return result;
1037 }
1038 }
1039 if (_getters != null) {
1040 T result = func.withMember(_getters.value);
1041 if ((result != null) && (result != defaultValue)) {
1042 return result;
1043 }
Cowtowncoder04413c72015-06-02 17:46:11 -07001044 }
1045 return null;
1046 }
Tatu Saloranta65c410c2012-01-27 20:44:45 -08001047
1048 /*
1049 /**********************************************************
1050 /* Helper classes
1051 /**********************************************************
1052 */
1053
Tatu Saloranta26a052b2014-03-30 20:48:56 -07001054 private interface WithMember<T> {
Tatu Saloranta65c410c2012-01-27 20:44:45 -08001055 public T withMember(AnnotatedMember member);
1056 }
Cowtowncoderc717c2f2014-09-25 16:52:30 -07001057
1058 /**
1059 * @since 2.5
1060 */
1061 protected static class MemberIterator<T extends AnnotatedMember>
1062 implements Iterator<T>
1063 {
1064 private Linked<T> next;
1065
1066 public MemberIterator(Linked<T> first) {
1067 next = first;
1068 }
1069
1070 @Override
1071 public boolean hasNext() {
1072 return (next != null);
1073 }
1074
1075 @Override
1076 public T next() {
1077 if (next == null) throw new NoSuchElementException();
1078 T result = next.value;
1079 next = next.next;
1080 return result;
1081 }
1082
1083 @Override
1084 public void remove() {
1085 throw new UnsupportedOperationException();
1086 }
1087
1088 }
Tatu Saloranta65c410c2012-01-27 20:44:45 -08001089
1090 /**
Tatu Salorantae4f23bb2011-12-23 00:31:35 -08001091 * Node used for creating simple linked lists to efficiently store small sets
1092 * of things.
1093 */
Christopher Currieb6f3f6a2015-07-16 23:17:16 -07001094 protected final static class Linked<T>
Tatu Salorantae4f23bb2011-12-23 00:31:35 -08001095 {
1096 public final T value;
Tatu Saloranta65c410c2012-01-27 20:44:45 -08001097 public final Linked<T> next;
Tatu Salorantae4f23bb2011-12-23 00:31:35 -08001098
Tatu Saloranta26a052b2014-03-30 20:48:56 -07001099 public final PropertyName name;
Tatu365c29b2014-03-28 15:51:00 -07001100 public final boolean isNameExplicit;
Tatu Salorantae4f23bb2011-12-23 00:31:35 -08001101 public final boolean isVisible;
1102 public final boolean isMarkedIgnored;
1103
Tatu Saloranta65c410c2012-01-27 20:44:45 -08001104 public Linked(T v, Linked<T> n,
Tatu Saloranta26a052b2014-03-30 20:48:56 -07001105 PropertyName name, boolean explName, boolean visible, boolean ignored)
Tatu Salorantae4f23bb2011-12-23 00:31:35 -08001106 {
1107 value = v;
1108 next = n;
1109 // ensure that we'll never have missing names
Tatue400d162014-04-03 10:27:43 -07001110 this.name = (name == null || name.isEmpty()) ? null : name;
Tatu Salorantaa7693512014-03-30 21:05:16 -07001111
Tatue400d162014-04-03 10:27:43 -07001112 if (explName) {
1113 if (this.name == null) { // sanity check to catch internal problems
1114 throw new IllegalArgumentException("Can not pass true for 'explName' if name is null/empty");
1115 }
1116 // 03-Apr-2014, tatu: But how about name-space only override?
1117 // Probably should not be explicit? Or, need to merge somehow?
1118 if (!name.hasSimpleName()) {
1119 explName = false;
1120 }
Tatu Salorantaa7693512014-03-30 21:05:16 -07001121 }
Tatu Salorantaa00cdd82014-03-30 19:22:49 -07001122
Tatu365c29b2014-03-28 15:51:00 -07001123 isNameExplicit = explName;
Tatu Salorantae4f23bb2011-12-23 00:31:35 -08001124 isVisible = visible;
1125 isMarkedIgnored = ignored;
1126 }
1127
Tatu Saloranta2a41afc2014-05-30 22:58:41 -07001128 public Linked<T> withoutNext() {
1129 if (next == null) {
1130 return this;
1131 }
1132 return new Linked<T>(value, null, name, isNameExplicit, isVisible, isMarkedIgnored);
1133 }
1134
Tatu365c29b2014-03-28 15:51:00 -07001135 public Linked<T> withValue(T newValue) {
Tatu Salorantae4f23bb2011-12-23 00:31:35 -08001136 if (newValue == value) {
1137 return this;
1138 }
Tatu365c29b2014-03-28 15:51:00 -07001139 return new Linked<T>(newValue, next, name, isNameExplicit, isVisible, isMarkedIgnored);
Tatu Salorantae4f23bb2011-12-23 00:31:35 -08001140 }
1141
Tatu Saloranta65c410c2012-01-27 20:44:45 -08001142 public Linked<T> withNext(Linked<T> newNext) {
Tatu Salorantae4f23bb2011-12-23 00:31:35 -08001143 if (newNext == next) {
1144 return this;
1145 }
Tatu365c29b2014-03-28 15:51:00 -07001146 return new Linked<T>(value, newNext, name, isNameExplicit, isVisible, isMarkedIgnored);
Tatu Salorantae4f23bb2011-12-23 00:31:35 -08001147 }
1148
Tatu Saloranta26a052b2014-03-30 20:48:56 -07001149 public Linked<T> withoutIgnored() {
Tatu Salorantae4f23bb2011-12-23 00:31:35 -08001150 if (isMarkedIgnored) {
1151 return (next == null) ? null : next.withoutIgnored();
1152 }
1153 if (next != null) {
Tatu Saloranta65c410c2012-01-27 20:44:45 -08001154 Linked<T> newNext = next.withoutIgnored();
Tatu Salorantae4f23bb2011-12-23 00:31:35 -08001155 if (newNext != next) {
1156 return withNext(newNext);
1157 }
1158 }
1159 return this;
1160 }
1161
Tatu Saloranta26a052b2014-03-30 20:48:56 -07001162 public Linked<T> withoutNonVisible() {
Tatu Saloranta65c410c2012-01-27 20:44:45 -08001163 Linked<T> newNext = (next == null) ? null : next.withoutNonVisible();
Tatu Salorantae4f23bb2011-12-23 00:31:35 -08001164 return isVisible ? withNext(newNext) : newNext;
1165 }
1166
1167 /**
1168 * Method called to append given node(s) at the end of this
1169 * node chain.
1170 */
Cowtowncoder72de08e2014-11-25 14:58:53 -08001171 protected Linked<T> append(Linked<T> appendable) {
Tatu Salorantae4f23bb2011-12-23 00:31:35 -08001172 if (next == null) {
1173 return withNext(appendable);
1174 }
1175 return withNext(next.append(appendable));
1176 }
Tatu Saloranta26a052b2014-03-30 20:48:56 -07001177
1178 public Linked<T> trimByVisibility() {
Tatu Salorantae4f23bb2011-12-23 00:31:35 -08001179 if (next == null) {
1180 return this;
1181 }
Tatu Saloranta65c410c2012-01-27 20:44:45 -08001182 Linked<T> newNext = next.trimByVisibility();
Tatu365c29b2014-03-28 15:51:00 -07001183 if (name != null) { // this already has highest; how about next one?
1184 if (newNext.name == null) { // next one not, drop it
Tatu Salorantae4f23bb2011-12-23 00:31:35 -08001185 return withNext(null);
1186 }
1187 // both have it, keep
1188 return withNext(newNext);
1189 }
Tatu365c29b2014-03-28 15:51:00 -07001190 if (newNext.name != null) { // next one has higher, return it...
Tatu Salorantae4f23bb2011-12-23 00:31:35 -08001191 return newNext;
1192 }
1193 // neither has explicit name; how about visibility?
1194 if (isVisible == newNext.isVisible) { // same; keep both in current order
1195 return withNext(newNext);
1196 }
1197 return isVisible ? withNext(null) : newNext;
1198 }
1199
1200 @Override
1201 public String toString() {
Tatu Salorantaa00cdd82014-03-30 19:22:49 -07001202 String msg = value.toString()+"[visible="+isVisible+",ignore="+isMarkedIgnored
1203 +",explicitName="+isNameExplicit+"]";
Tatu Salorantae4f23bb2011-12-23 00:31:35 -08001204 if (next != null) {
1205 msg = msg + ", "+next.toString();
1206 }
1207 return msg;
1208 }
1209 }
1210}