1 package com.fasterxml.jackson.databind.introspect; 2 3 import java.util.*; 4 5 import com.fasterxml.jackson.annotation.JsonInclude; 6 import com.fasterxml.jackson.annotation.JsonProperty; 7 import com.fasterxml.jackson.annotation.JsonSetter; 8 import com.fasterxml.jackson.annotation.Nulls; 9 10 import com.fasterxml.jackson.databind.*; 11 import com.fasterxml.jackson.databind.cfg.ConfigOverride; 12 import com.fasterxml.jackson.databind.cfg.MapperConfig; 13 import com.fasterxml.jackson.databind.type.TypeFactory; 14 import com.fasterxml.jackson.databind.util.ClassUtil; 15 16 /** 17 * Helper class used for aggregating information about a single 18 * potential POJO property. 19 */ 20 public class POJOPropertyBuilder 21 extends BeanPropertyDefinition 22 implements Comparable<POJOPropertyBuilder> 23 { 24 /** 25 * Marker value used to denote that no reference-property information found for 26 * this property 27 * 28 * @since 2.9 29 */ 30 private final static AnnotationIntrospector.ReferenceProperty NOT_REFEFERENCE_PROP = 31 AnnotationIntrospector.ReferenceProperty.managed(""); 32 33 /** 34 * Whether property is being composed for serialization 35 * (true) or deserialization (false) 36 */ 37 protected final boolean _forSerialization; 38 39 protected final MapperConfig<?> _config; 40 41 protected final AnnotationIntrospector _annotationIntrospector; 42 43 /** 44 * External name of logical property; may change with 45 * renaming (by new instance being constructed using 46 * a new name) 47 */ 48 protected final PropertyName _name; 49 50 /** 51 * Original internal name, derived from accessor, of this 52 * property. Will not be changed by renaming. 53 */ 54 protected final PropertyName _internalName; 55 56 protected Linked<AnnotatedField> _fields; 57 58 protected Linked<AnnotatedParameter> _ctorParameters; 59 60 protected Linked<AnnotatedMethod> _getters; 61 62 protected Linked<AnnotatedMethod> _setters; 63 64 protected transient PropertyMetadata _metadata; 65 66 /** 67 * Lazily accessed information about this property iff it is a forward or 68 * back reference. 69 * 70 * @since 2.9 71 */ 72 protected transient AnnotationIntrospector.ReferenceProperty _referenceInfo; 73 POJOPropertyBuilder(MapperConfig<?> config, AnnotationIntrospector ai, boolean forSerialization, PropertyName internalName)74 public POJOPropertyBuilder(MapperConfig<?> config, AnnotationIntrospector ai, 75 boolean forSerialization, PropertyName internalName) { 76 this(config, ai, forSerialization, internalName, internalName); 77 } 78 POJOPropertyBuilder(MapperConfig<?> config, AnnotationIntrospector ai, boolean forSerialization, PropertyName internalName, PropertyName name)79 protected POJOPropertyBuilder(MapperConfig<?> config, AnnotationIntrospector ai, 80 boolean forSerialization, PropertyName internalName, PropertyName name) 81 { 82 _config = config; 83 _annotationIntrospector = ai; 84 _internalName = internalName; 85 _name = name; 86 _forSerialization = forSerialization; 87 } 88 89 // protected since 2.9 (was public before) POJOPropertyBuilder(POJOPropertyBuilder src, PropertyName newName)90 protected POJOPropertyBuilder(POJOPropertyBuilder src, PropertyName newName) 91 { 92 _config = src._config; 93 _annotationIntrospector = src._annotationIntrospector; 94 _internalName = src._internalName; 95 _name = newName; 96 _fields = src._fields; 97 _ctorParameters = src._ctorParameters; 98 _getters = src._getters; 99 _setters = src._setters; 100 _forSerialization = src._forSerialization; 101 } 102 103 /* 104 /********************************************************** 105 /* Mutant factory methods 106 /********************************************************** 107 */ 108 109 @Override withName(PropertyName newName)110 public POJOPropertyBuilder withName(PropertyName newName) { 111 return new POJOPropertyBuilder(this, newName); 112 } 113 114 @Override withSimpleName(String newSimpleName)115 public POJOPropertyBuilder withSimpleName(String newSimpleName) 116 { 117 PropertyName newName = _name.withSimpleName(newSimpleName); 118 return (newName == _name) ? this : new POJOPropertyBuilder(this, newName); 119 } 120 121 /* 122 /********************************************************** 123 /* Comparable implementation: sort alphabetically, except 124 /* that properties with constructor parameters sorted 125 /* before other properties 126 /********************************************************** 127 */ 128 129 @Override compareTo(POJOPropertyBuilder other)130 public int compareTo(POJOPropertyBuilder other) 131 { 132 // first, if one has ctor params, that should come first: 133 if (_ctorParameters != null) { 134 if (other._ctorParameters == null) { 135 return -1; 136 } 137 } else if (other._ctorParameters != null) { 138 return 1; 139 } 140 /* otherwise sort by external name (including sorting of 141 * ctor parameters) 142 */ 143 return getName().compareTo(other.getName()); 144 } 145 146 /* 147 /********************************************************** 148 /* BeanPropertyDefinition implementation, name/type 149 /********************************************************** 150 */ 151 152 @Override getName()153 public String getName() { 154 return (_name == null) ? null : _name.getSimpleName(); 155 } 156 157 @Override getFullName()158 public PropertyName getFullName() { 159 return _name; 160 } 161 162 @Override hasName(PropertyName name)163 public boolean hasName(PropertyName name) { 164 return _name.equals(name); 165 } 166 167 @Override getInternalName()168 public String getInternalName() { return _internalName.getSimpleName(); } 169 170 @Override getWrapperName()171 public PropertyName getWrapperName() { 172 /* 13-Mar-2013, tatu: Accessing via primary member SHOULD work, 173 * due to annotation merging. However, I have seen some problems 174 * with this access (for other annotations)... so if this should 175 * occur, try commenting out full traversal code 176 */ 177 AnnotatedMember member = getPrimaryMember(); 178 return (member == null || _annotationIntrospector == null) ? null 179 : _annotationIntrospector.findWrapperName(member); 180 /* 181 return fromMemberAnnotations(new WithMember<PropertyName>() { 182 @Override 183 public PropertyName withMember(AnnotatedMember member) { 184 return _annotationIntrospector.findWrapperName(member); 185 } 186 }); 187 */ 188 } 189 190 @Override isExplicitlyIncluded()191 public boolean isExplicitlyIncluded() { 192 return _anyExplicits(_fields) 193 || _anyExplicits(_getters) 194 || _anyExplicits(_setters) 195 // 16-Jan-2016, tatu: Creator names are special, in that name should exist too; 196 // reason for this is [databind#1317]. Let's hope this works well, may need 197 // to tweak further if this lowers visibility 198 // || _anyExplicits(_ctorParameters) 199 || _anyExplicitNames(_ctorParameters) 200 ; 201 } 202 203 @Override isExplicitlyNamed()204 public boolean isExplicitlyNamed() { 205 return _anyExplicitNames(_fields) 206 || _anyExplicitNames(_getters) 207 || _anyExplicitNames(_setters) 208 || _anyExplicitNames(_ctorParameters) 209 ; 210 } 211 212 /* 213 /********************************************************** 214 /* Simple metadata 215 /********************************************************** 216 */ 217 218 @Override getMetadata()219 public PropertyMetadata getMetadata() 220 { 221 if (_metadata == null) { 222 // 20-Jun-2020, tatu: Unfortunately strict checks lead to [databind#2757] 223 // so we will need to try to avoid them at this point 224 final AnnotatedMember prim = getPrimaryMemberUnchecked(); 225 226 if (prim == null) { 227 _metadata = PropertyMetadata.STD_REQUIRED_OR_OPTIONAL; 228 } else { 229 final Boolean b = _annotationIntrospector.hasRequiredMarker(prim); 230 final String desc = _annotationIntrospector.findPropertyDescription(prim); 231 final Integer idx = _annotationIntrospector.findPropertyIndex(prim); 232 final String def = _annotationIntrospector.findPropertyDefaultValue(prim); 233 234 if (b == null && idx == null && def == null) { 235 _metadata = (desc == null) ? PropertyMetadata.STD_REQUIRED_OR_OPTIONAL 236 : PropertyMetadata.STD_REQUIRED_OR_OPTIONAL.withDescription(desc); 237 } else { 238 _metadata = PropertyMetadata.construct(b, desc, idx, def); 239 } 240 if (!_forSerialization) { 241 _metadata = _getSetterInfo(_metadata, prim); 242 } 243 } 244 } 245 return _metadata; 246 } 247 248 /** 249 * Helper method that contains logic for accessing and merging all setter 250 * information that we needed, regarding things like possible merging 251 * of property value, and handling of incoming nulls. 252 * Only called for deserialization purposes. 253 */ _getSetterInfo(PropertyMetadata metadata, AnnotatedMember primary)254 protected PropertyMetadata _getSetterInfo(PropertyMetadata metadata, 255 AnnotatedMember primary) 256 { 257 boolean needMerge = true; 258 Nulls valueNulls = null; 259 Nulls contentNulls = null; 260 261 // Slightly confusing: first, annotations should be accessed via primary member 262 // (mutator); but accessor is needed for actual merge operation. So 263 264 AnnotatedMember acc = getAccessor(); 265 266 if (primary != null) { 267 // Ok, first: does property itself have something to say? 268 if (_annotationIntrospector != null) { 269 if (acc != null) { 270 Boolean b = _annotationIntrospector.findMergeInfo(primary); 271 if (b != null) { 272 needMerge = false; 273 if (b.booleanValue()) { 274 metadata = metadata.withMergeInfo(PropertyMetadata.MergeInfo.createForPropertyOverride(acc)); 275 } 276 } 277 } 278 JsonSetter.Value setterInfo = _annotationIntrospector.findSetterInfo(primary); 279 if (setterInfo != null) { 280 valueNulls = setterInfo.nonDefaultValueNulls(); 281 contentNulls = setterInfo.nonDefaultContentNulls(); 282 } 283 } 284 // If not, config override? 285 // 25-Oct-2016, tatu: Either this, or type of accessor... 286 if (needMerge || (valueNulls == null) || (contentNulls == null)) { 287 // 20-Jun-2020, tatu: Related to [databind#2757], need to find type 288 // but keeping mind that type for setters is trickier; and that 289 // generic typing gets tricky as well. 290 Class<?> rawType = _rawTypeOf(primary); 291 ConfigOverride co = _config.getConfigOverride(rawType); 292 JsonSetter.Value setterInfo = co.getSetterInfo(); 293 if (setterInfo != null) { 294 if (valueNulls == null) { 295 valueNulls = setterInfo.nonDefaultValueNulls(); 296 } 297 if (contentNulls == null) { 298 contentNulls = setterInfo.nonDefaultContentNulls(); 299 } 300 } 301 if (needMerge && (acc != null)) { 302 Boolean b = co.getMergeable(); 303 if (b != null) { 304 needMerge = false; 305 if (b.booleanValue()) { 306 metadata = metadata.withMergeInfo(PropertyMetadata.MergeInfo.createForTypeOverride(acc)); 307 } 308 } 309 } 310 } 311 } 312 if (needMerge || (valueNulls == null) || (contentNulls == null)) { 313 JsonSetter.Value setterInfo = _config.getDefaultSetterInfo(); 314 if (valueNulls == null) { 315 valueNulls = setterInfo.nonDefaultValueNulls(); 316 } 317 if (contentNulls == null) { 318 contentNulls = setterInfo.nonDefaultContentNulls(); 319 } 320 if (needMerge) { 321 Boolean b = _config.getDefaultMergeable(); 322 if (Boolean.TRUE.equals(b) && (acc != null)) { 323 metadata = metadata.withMergeInfo(PropertyMetadata.MergeInfo.createForDefaults(acc)); 324 } 325 } 326 } 327 if ((valueNulls != null) || (contentNulls != null)) { 328 metadata = metadata.withNulls(valueNulls, contentNulls); 329 } 330 return metadata; 331 } 332 333 /** 334 * Type determined from the primary member for the property being built, 335 * considering precedence according to whether we are processing serialization 336 * or deserialization. 337 */ 338 @Override getPrimaryType()339 public JavaType getPrimaryType() { 340 if (_forSerialization) { 341 AnnotatedMember m = getGetter(); 342 if (m == null) { 343 m = getField(); 344 if (m == null) { 345 // 09-Feb-2017, tatu: Not sure if this or `null` but... 346 return TypeFactory.unknownType(); 347 } 348 } 349 return m.getType(); 350 } 351 AnnotatedMember m = getConstructorParameter(); 352 if (m == null) { 353 m = getSetter(); 354 // Important: can't try direct type access for setter; what we need is 355 // type of the first parameter 356 if (m != null) { 357 return ((AnnotatedMethod) m).getParameterType(0); 358 } 359 m = getField(); 360 } 361 // for setterless properties, however, can further try getter 362 if (m == null) { 363 m = getGetter(); 364 if (m == null) { 365 return TypeFactory.unknownType(); 366 } 367 } 368 return m.getType(); 369 } 370 371 @Override getRawPrimaryType()372 public Class<?> getRawPrimaryType() { 373 return getPrimaryType().getRawClass(); 374 } 375 376 /* 377 /********************************************************** 378 /* BeanPropertyDefinition implementation, accessor access 379 /********************************************************** 380 */ 381 382 @Override hasGetter()383 public boolean hasGetter() { return _getters != null; } 384 385 @Override hasSetter()386 public boolean hasSetter() { return _setters != null; } 387 388 @Override hasField()389 public boolean hasField() { return _fields != null; } 390 391 @Override hasConstructorParameter()392 public boolean hasConstructorParameter() { return _ctorParameters != null; } 393 394 @Override couldDeserialize()395 public boolean couldDeserialize() { 396 return (_ctorParameters != null) || (_setters != null) || (_fields != null); 397 } 398 399 @Override couldSerialize()400 public boolean couldSerialize() { 401 return (_getters != null) || (_fields != null); 402 } 403 404 @Override getGetter()405 public AnnotatedMethod getGetter() 406 { 407 // Easy with zero or one getters... 408 Linked<AnnotatedMethod> curr = _getters; 409 if (curr == null) { 410 return null; 411 } 412 Linked<AnnotatedMethod> next = curr.next; 413 if (next == null) { 414 return curr.value; 415 } 416 // But if multiple, verify that they do not conflict... 417 for (; next != null; next = next.next) { 418 /* [JACKSON-255] Allow masking, i.e. do not report exception if one 419 * is in super-class from the other 420 */ 421 Class<?> currClass = curr.value.getDeclaringClass(); 422 Class<?> nextClass = next.value.getDeclaringClass(); 423 if (currClass != nextClass) { 424 if (currClass.isAssignableFrom(nextClass)) { // next is more specific 425 curr = next; 426 continue; 427 } 428 if (nextClass.isAssignableFrom(currClass)) { // current more specific 429 continue; 430 } 431 } 432 /* 30-May-2014, tatu: Three levels of precedence: 433 * 434 * 1. Regular getters ("getX") 435 * 2. Is-getters ("isX") 436 * 3. Implicit, possible getters ("x") 437 */ 438 int priNext = _getterPriority(next.value); 439 int priCurr = _getterPriority(curr.value); 440 441 if (priNext != priCurr) { 442 if (priNext < priCurr) { 443 curr = next; 444 } 445 continue; 446 } 447 throw new IllegalArgumentException("Conflicting getter definitions for property \""+getName()+"\": " 448 +curr.value.getFullName()+" vs "+next.value.getFullName()); 449 } 450 // One more thing; to avoid having to do it again... 451 _getters = curr.withoutNext(); 452 return curr.value; 453 } 454 455 @Override getSetter()456 public AnnotatedMethod getSetter() 457 { 458 // Easy with zero or one setters... 459 Linked<AnnotatedMethod> curr = _setters; 460 if (curr == null) { 461 return null; 462 } 463 Linked<AnnotatedMethod> next = curr.next; 464 if (next == null) { 465 return curr.value; 466 } 467 // But if multiple, verify that they do not conflict... 468 for (; next != null; next = next.next) { 469 // Allow masking, i.e. do not fail if one is in super-class from the other 470 Class<?> currClass = curr.value.getDeclaringClass(); 471 Class<?> nextClass = next.value.getDeclaringClass(); 472 if (currClass != nextClass) { 473 if (currClass.isAssignableFrom(nextClass)) { // next is more specific 474 curr = next; 475 continue; 476 } 477 if (nextClass.isAssignableFrom(currClass)) { // current more specific 478 continue; 479 } 480 } 481 AnnotatedMethod nextM = next.value; 482 AnnotatedMethod currM = curr.value; 483 484 /* 30-May-2014, tatu: Two levels of precedence: 485 * 486 * 1. Regular setters ("setX(...)") 487 * 2. Implicit, possible setters ("x(...)") 488 */ 489 int priNext = _setterPriority(nextM); 490 int priCurr = _setterPriority(currM); 491 492 if (priNext != priCurr) { 493 if (priNext < priCurr) { 494 curr = next; 495 } 496 continue; 497 } 498 // 11-Dec-2015, tatu: As per [databind#1033] allow pluggable conflict resolution 499 if (_annotationIntrospector != null) { 500 AnnotatedMethod pref = _annotationIntrospector.resolveSetterConflict(_config, 501 currM, nextM); 502 503 // note: should be one of nextM/currM; but no need to check 504 if (pref == currM) { 505 continue; 506 } 507 if (pref == nextM) { 508 curr = next; 509 continue; 510 } 511 } 512 throw new IllegalArgumentException(String.format( 513 "Conflicting setter definitions for property \"%s\": %s vs %s", 514 getName(), curr.value.getFullName(), next.value.getFullName())); 515 } 516 // One more thing; to avoid having to do it again... 517 _setters = curr.withoutNext(); 518 return curr.value; 519 } 520 521 @Override getField()522 public AnnotatedField getField() 523 { 524 if (_fields == null) { 525 return null; 526 } 527 // If multiple, verify that they do not conflict... 528 AnnotatedField field = _fields.value; 529 Linked<AnnotatedField> next = _fields.next; 530 for (; next != null; next = next.next) { 531 AnnotatedField nextField = next.value; 532 Class<?> fieldClass = field.getDeclaringClass(); 533 Class<?> nextClass = nextField.getDeclaringClass(); 534 if (fieldClass != nextClass) { 535 if (fieldClass.isAssignableFrom(nextClass)) { // next is more specific 536 field = nextField; 537 continue; 538 } 539 if (nextClass.isAssignableFrom(fieldClass)) { // getter more specific 540 continue; 541 } 542 } 543 throw new IllegalArgumentException("Multiple fields representing property \""+getName()+"\": " 544 +field.getFullName()+" vs "+nextField.getFullName()); 545 } 546 return field; 547 } 548 549 @Override getConstructorParameter()550 public AnnotatedParameter getConstructorParameter() 551 { 552 if (_ctorParameters == null) { 553 return null; 554 } 555 /* Hmmh. Checking for constructor parameters is trickier; for one, 556 * we must allow creator and factory method annotations. 557 * If this is the case, constructor parameter has the precedence. 558 * 559 * So, for now, just try finding the first constructor parameter; 560 * if none, first factory method. And don't check for dups, if we must, 561 * can start checking for them later on. 562 */ 563 Linked<AnnotatedParameter> curr = _ctorParameters; 564 do { 565 if (curr.value.getOwner() instanceof AnnotatedConstructor) { 566 return curr.value; 567 } 568 curr = curr.next; 569 } while (curr != null); 570 return _ctorParameters.value; 571 } 572 573 @Override getConstructorParameters()574 public Iterator<AnnotatedParameter> getConstructorParameters() { 575 if (_ctorParameters == null) { 576 return ClassUtil.emptyIterator(); 577 } 578 return new MemberIterator<AnnotatedParameter>(_ctorParameters); 579 } 580 581 @Override getPrimaryMember()582 public AnnotatedMember getPrimaryMember() { 583 if (_forSerialization) { 584 return getAccessor(); 585 } 586 AnnotatedMember m = getMutator(); 587 // for setterless properties, however... 588 if (m == null) { 589 m = getAccessor(); 590 } 591 return m; 592 } 593 594 // Sometimes we need to actually by-pass failures related to conflicting 595 // getters or setters (see [databind#2757] for specific example); if so, 596 // this method is to be used instead of `getPrimaryMember()` 597 // @since 2.11.1 getPrimaryMemberUnchecked()598 protected AnnotatedMember getPrimaryMemberUnchecked() { 599 if (_forSerialization) { // Inlined `getAccessor()` logic: 600 // Inlined `getGetter()`: 601 if (_getters != null) { 602 return _getters.value; 603 } 604 // Inlined `getField()`: 605 if (_fields != null) { 606 return _fields.value; 607 } 608 return null; 609 } 610 611 // Otherwise, inlined `getMutator()` logic: 612 613 // Inlined `getConstructorParameter()`: 614 if (_ctorParameters != null) { 615 return _ctorParameters.value; 616 } 617 // Inlined `getSetter()`: 618 if (_setters != null) { 619 return _setters.value; 620 } 621 // Inlined `getField()`: 622 if (_fields != null) { 623 return _fields.value; 624 } 625 // but to support setterless-properties, also include part of 626 // `getAccessor()` not yet covered, `getGetter()`: 627 if (_getters != null) { 628 return _getters.value; 629 } 630 return null; 631 } 632 _getterPriority(AnnotatedMethod m)633 protected int _getterPriority(AnnotatedMethod m) 634 { 635 final String name = m.getName(); 636 // [databind#238]: Also, regular getters have precedence over "is-getters" 637 if (name.startsWith("get") && name.length() > 3) { 638 // should we check capitalization? 639 return 1; 640 } 641 if (name.startsWith("is") && name.length() > 2) { 642 return 2; 643 } 644 return 3; 645 } 646 _setterPriority(AnnotatedMethod m)647 protected int _setterPriority(AnnotatedMethod m) 648 { 649 final String name = m.getName(); 650 if (name.startsWith("set") && name.length() > 3) { 651 // should we check capitalization? 652 return 1; 653 } 654 return 2; 655 } 656 657 /* 658 /********************************************************** 659 /* Implementations of refinement accessors 660 /********************************************************** 661 */ 662 663 @Override findViews()664 public Class<?>[] findViews() { 665 return fromMemberAnnotations(new WithMember<Class<?>[]>() { 666 @Override 667 public Class<?>[] withMember(AnnotatedMember member) { 668 return _annotationIntrospector.findViews(member); 669 } 670 }); 671 } 672 673 @Override 674 public AnnotationIntrospector.ReferenceProperty findReferenceType() { 675 // 30-Mar-2017, tatu: Access lazily but retain information since it needs 676 // to be accessed multiple times during processing. 677 AnnotationIntrospector.ReferenceProperty result = _referenceInfo; 678 if (result != null) { 679 if (result == NOT_REFEFERENCE_PROP) { 680 return null; 681 } 682 return result; 683 } 684 result = fromMemberAnnotations(new WithMember<AnnotationIntrospector.ReferenceProperty>() { 685 @Override 686 public AnnotationIntrospector.ReferenceProperty withMember(AnnotatedMember member) { 687 return _annotationIntrospector.findReferenceType(member); 688 } 689 }); 690 _referenceInfo = (result == null) ? NOT_REFEFERENCE_PROP : result; 691 return result; 692 } 693 694 @Override 695 public boolean isTypeId() { 696 Boolean b = fromMemberAnnotations(new WithMember<Boolean>() { 697 @Override 698 public Boolean withMember(AnnotatedMember member) { 699 return _annotationIntrospector.isTypeId(member); 700 } 701 }); 702 return (b != null) && b.booleanValue(); 703 } 704 705 @Override 706 public ObjectIdInfo findObjectIdInfo() { 707 return fromMemberAnnotations(new WithMember<ObjectIdInfo>() { 708 @Override 709 public ObjectIdInfo withMember(AnnotatedMember member) { 710 ObjectIdInfo info = _annotationIntrospector.findObjectIdInfo(member); 711 if (info != null) { 712 info = _annotationIntrospector.findObjectReferenceInfo(member, info); 713 } 714 return info; 715 } 716 }); 717 } 718 719 @Override 720 public JsonInclude.Value findInclusion() { 721 AnnotatedMember a = getAccessor(); 722 // 16-Apr-2106, tatu: Let's include per-type default inclusion too 723 // 17-Aug-2016, tatu: Do NOT include global, or per-type defaults, because 724 // not all of this information (specifically, enclosing type's settings) 725 // is available here 726 JsonInclude.Value v = (_annotationIntrospector == null) ? 727 null : _annotationIntrospector.findPropertyInclusion(a); 728 return (v == null) ? JsonInclude.Value.empty() : v; 729 } 730 731 public JsonProperty.Access findAccess() { 732 return fromMemberAnnotationsExcept(new WithMember<JsonProperty.Access>() { 733 @Override 734 public JsonProperty.Access withMember(AnnotatedMember member) { 735 return _annotationIntrospector.findPropertyAccess(member); 736 } 737 }, JsonProperty.Access.AUTO); 738 } 739 740 /* 741 /********************************************************** 742 /* Data aggregation 743 /********************************************************** 744 */ 745 746 public void addField(AnnotatedField a, PropertyName name, boolean explName, boolean visible, boolean ignored) { 747 _fields = new Linked<AnnotatedField>(a, _fields, name, explName, visible, ignored); 748 } 749 750 public void addCtor(AnnotatedParameter a, PropertyName name, boolean explName, boolean visible, boolean ignored) { 751 _ctorParameters = new Linked<AnnotatedParameter>(a, _ctorParameters, name, explName, visible, ignored); 752 } 753 754 public void addGetter(AnnotatedMethod a, PropertyName name, boolean explName, boolean visible, boolean ignored) { 755 _getters = new Linked<AnnotatedMethod>(a, _getters, name, explName, visible, ignored); 756 } 757 758 public void addSetter(AnnotatedMethod a, PropertyName name, boolean explName, boolean visible, boolean ignored) { 759 _setters = new Linked<AnnotatedMethod>(a, _setters, name, explName, visible, ignored); 760 } 761 762 /** 763 * Method for adding all property members from specified collector into 764 * this collector. 765 */ 766 public void addAll(POJOPropertyBuilder src) 767 { 768 _fields = merge(_fields, src._fields); 769 _ctorParameters = merge(_ctorParameters, src._ctorParameters); 770 _getters= merge(_getters, src._getters); 771 _setters = merge(_setters, src._setters); 772 } 773 774 private static <T> Linked<T> merge(Linked<T> chain1, Linked<T> chain2) 775 { 776 if (chain1 == null) { 777 return chain2; 778 } 779 if (chain2 == null) { 780 return chain1; 781 } 782 return chain1.append(chain2); 783 } 784 785 /* 786 /********************************************************** 787 /* Modifications 788 /********************************************************** 789 */ 790 791 /** 792 * Method called to remove all entries that are marked as 793 * ignored. 794 */ 795 public void removeIgnored() 796 { 797 _fields = _removeIgnored(_fields); 798 _getters = _removeIgnored(_getters); 799 _setters = _removeIgnored(_setters); 800 _ctorParameters = _removeIgnored(_ctorParameters); 801 } 802 803 @Deprecated // since 2.12 804 public JsonProperty.Access removeNonVisible(boolean inferMutators) { 805 return removeNonVisible(inferMutators, null); 806 } 807 808 /** 809 * @param inferMutators Whether mutators can be "pulled in" by visible 810 * accessors or not. 811 * 812 * @since 2.12 (earlier had different signature) 813 */ 814 public JsonProperty.Access removeNonVisible(boolean inferMutators, 815 POJOPropertiesCollector parent) 816 { 817 /* 07-Jun-2015, tatu: With 2.6, we will allow optional definition 818 * of explicit access type for property; if not "AUTO", it will 819 * dictate how visibility checks are applied. 820 */ 821 JsonProperty.Access acc = findAccess(); 822 if (acc == null) { 823 acc = JsonProperty.Access.AUTO; 824 } 825 switch (acc) { 826 case READ_ONLY: 827 // [databind#2719]: Need to add ignorals, first, keeping in mind 828 // we have not yet resolved explicit names, so include implicit 829 // and possible explicit names 830 if (parent != null) { 831 parent._collectIgnorals(getName()); 832 for (PropertyName pn : findExplicitNames()) { 833 parent._collectIgnorals(pn.getSimpleName()); 834 } 835 } 836 // Remove setters, creators for sure, but fields too if deserializing 837 _setters = null; 838 _ctorParameters = null; 839 if (!_forSerialization) { 840 _fields = null; 841 } 842 break; 843 case READ_WRITE: 844 // no trimming whatsoever? 845 break; 846 case WRITE_ONLY: 847 // remove getters, definitely, but also fields if serializing 848 _getters = null; 849 if (_forSerialization) { 850 _fields = null; 851 } 852 break; 853 default: 854 case AUTO: // the default case: base it on visibility 855 _getters = _removeNonVisible(_getters); 856 _ctorParameters = _removeNonVisible(_ctorParameters); 857 858 if (!inferMutators || (_getters == null)) { 859 _fields = _removeNonVisible(_fields); 860 _setters = _removeNonVisible(_setters); 861 } 862 } 863 return acc; 864 } 865 866 /** 867 * Mutator that will simply drop any constructor parameters property may have. 868 * 869 * @since 2.5 870 */ 871 public void removeConstructors() { 872 _ctorParameters = null; 873 } 874 875 /** 876 * Method called to trim unnecessary entries, such as implicit 877 * getter if there is an explict one available. This is important 878 * for later stages, to avoid unnecessary conflicts. 879 */ 880 public void trimByVisibility() 881 { 882 _fields = _trimByVisibility(_fields); 883 _getters = _trimByVisibility(_getters); 884 _setters = _trimByVisibility(_setters); 885 _ctorParameters = _trimByVisibility(_ctorParameters); 886 } 887 888 @SuppressWarnings("unchecked") 889 public void mergeAnnotations(boolean forSerialization) 890 { 891 if (forSerialization) { 892 if (_getters != null) { 893 AnnotationMap ann = _mergeAnnotations(0, _getters, _fields, _ctorParameters, _setters); 894 _getters = _applyAnnotations(_getters, ann); 895 } else if (_fields != null) { 896 AnnotationMap ann = _mergeAnnotations(0, _fields, _ctorParameters, _setters); 897 _fields = _applyAnnotations(_fields, ann); 898 } 899 } else { // for deserialization 900 if (_ctorParameters != null) { 901 AnnotationMap ann = _mergeAnnotations(0, _ctorParameters, _setters, _fields, _getters); 902 _ctorParameters = _applyAnnotations(_ctorParameters, ann); 903 } else if (_setters != null) { 904 AnnotationMap ann = _mergeAnnotations(0, _setters, _fields, _getters); 905 _setters = _applyAnnotations(_setters, ann); 906 } else if (_fields != null) { 907 AnnotationMap ann = _mergeAnnotations(0, _fields, _getters); 908 _fields = _applyAnnotations(_fields, ann); 909 } 910 } 911 } 912 913 private AnnotationMap _mergeAnnotations(int index, 914 Linked<? extends AnnotatedMember>... nodes) 915 { 916 AnnotationMap ann = _getAllAnnotations(nodes[index]); 917 while (++index < nodes.length) { 918 if (nodes[index] != null) { 919 return AnnotationMap.merge(ann, _mergeAnnotations(index, nodes)); 920 } 921 } 922 return ann; 923 } 924 925 /** 926 * Replacement, as per [databind#868], of simple access to annotations, which 927 * does "deep merge" if an as necessary. 928 *<pre> 929 * nodes[index].value.getAllAnnotations() 930 *</pre> 931 * 932 * @since 2.6 933 */ 934 private <T extends AnnotatedMember> AnnotationMap _getAllAnnotations(Linked<T> node) { 935 AnnotationMap ann = node.value.getAllAnnotations(); 936 if (node.next != null) { 937 ann = AnnotationMap.merge(ann, _getAllAnnotations(node.next)); 938 } 939 return ann; 940 } 941 942 /** 943 * Helper method to handle recursive merging of annotations within accessor class, 944 * to ensure no annotations are accidentally dropped within chain when non-visible 945 * and secondary accessors are pruned later on. 946 *<p> 947 * See [databind#868] for more information. 948 * 949 * @since 2.6 950 */ 951 private <T extends AnnotatedMember> Linked<T> _applyAnnotations(Linked<T> node, AnnotationMap ann) { 952 @SuppressWarnings("unchecked") 953 T value = (T) node.value.withAnnotations(ann); 954 if (node.next != null) { 955 node = node.withNext(_applyAnnotations(node.next, ann)); 956 } 957 return node.withValue(value); 958 } 959 960 private <T> Linked<T> _removeIgnored(Linked<T> node) 961 { 962 if (node == null) { 963 return node; 964 } 965 return node.withoutIgnored(); 966 } 967 968 private <T> Linked<T> _removeNonVisible(Linked<T> node) 969 { 970 if (node == null) { 971 return node; 972 } 973 return node.withoutNonVisible(); 974 } 975 976 private <T> Linked<T> _trimByVisibility(Linked<T> node) 977 { 978 if (node == null) { 979 return node; 980 } 981 return node.trimByVisibility(); 982 } 983 984 /* 985 /********************************************************** 986 /* Accessors for aggregate information 987 /********************************************************** 988 */ 989 990 private <T> boolean _anyExplicits(Linked<T> n) 991 { 992 for (; n != null; n = n.next) { 993 if (n.name != null && n.name.hasSimpleName()) { 994 return true; 995 } 996 } 997 return false; 998 } 999 1000 private <T> boolean _anyExplicitNames(Linked<T> n) 1001 { 1002 for (; n != null; n = n.next) { 1003 if (n.name != null && n.isNameExplicit) { 1004 return true; 1005 } 1006 } 1007 return false; 1008 } 1009 1010 public boolean anyVisible() { 1011 return _anyVisible(_fields) 1012 || _anyVisible(_getters) 1013 || _anyVisible(_setters) 1014 || _anyVisible(_ctorParameters) 1015 ; 1016 } 1017 1018 private <T> boolean _anyVisible(Linked<T> n) 1019 { 1020 for (; n != null; n = n.next) { 1021 if (n.isVisible) { 1022 return true; 1023 } 1024 } 1025 return false; 1026 } 1027 1028 public boolean anyIgnorals() { 1029 return _anyIgnorals(_fields) 1030 || _anyIgnorals(_getters) 1031 || _anyIgnorals(_setters) 1032 || _anyIgnorals(_ctorParameters) 1033 ; 1034 } 1035 1036 private <T> boolean _anyIgnorals(Linked<T> n) 1037 { 1038 for (; n != null; n = n.next) { 1039 if (n.isMarkedIgnored) { 1040 return true; 1041 } 1042 } 1043 return false; 1044 } 1045 1046 /** 1047 * Method called to find out set of explicit names for accessors 1048 * bound together due to implicit name. 1049 * 1050 * @since 2.4 1051 */ 1052 public Set<PropertyName> findExplicitNames() 1053 { 1054 Set<PropertyName> renamed = null; 1055 renamed = _findExplicitNames(_fields, renamed); 1056 renamed = _findExplicitNames(_getters, renamed); 1057 renamed = _findExplicitNames(_setters, renamed); 1058 renamed = _findExplicitNames(_ctorParameters, renamed); 1059 if (renamed == null) { 1060 return Collections.emptySet(); 1061 } 1062 return renamed; 1063 } 1064 1065 /** 1066 * Method called when a previous call to {@link #findExplicitNames} found 1067 * multiple distinct explicit names, and the property this builder represents 1068 * basically needs to be broken apart and replaced by a set of more than 1069 * one properties. 1070 * 1071 * @since 2.4 1072 */ 1073 public Collection<POJOPropertyBuilder> explode(Collection<PropertyName> newNames) 1074 { 1075 HashMap<PropertyName,POJOPropertyBuilder> props = new HashMap<PropertyName,POJOPropertyBuilder>(); 1076 _explode(newNames, props, _fields); 1077 _explode(newNames, props, _getters); 1078 _explode(newNames, props, _setters); 1079 _explode(newNames, props, _ctorParameters); 1080 return props.values(); 1081 } 1082 1083 @SuppressWarnings("unchecked") 1084 private void _explode(Collection<PropertyName> newNames, 1085 Map<PropertyName,POJOPropertyBuilder> props, 1086 Linked<?> accessors) 1087 { 1088 final Linked<?> firstAcc = accessors; // clumsy, part 1 1089 for (Linked<?> node = accessors; node != null; node = node.next) { 1090 PropertyName name = node.name; 1091 if (!node.isNameExplicit || name == null) { // no explicit name -- problem! 1092 // [databind#541] ... but only as long as it's visible 1093 if (!node.isVisible) { 1094 continue; 1095 } 1096 1097 throw new IllegalStateException("Conflicting/ambiguous property name definitions (implicit name '" 1098 +_name+"'): found multiple explicit names: " 1099 +newNames+", but also implicit accessor: "+node); 1100 } 1101 POJOPropertyBuilder prop = props.get(name); 1102 if (prop == null) { 1103 prop = new POJOPropertyBuilder(_config, _annotationIntrospector, _forSerialization, 1104 _internalName, name); 1105 props.put(name, prop); 1106 } 1107 // ultra-clumsy, part 2 -- lambdas would be nice here 1108 if (firstAcc == _fields) { 1109 Linked<AnnotatedField> n2 = (Linked<AnnotatedField>) node; 1110 prop._fields = n2.withNext(prop._fields); 1111 } else if (firstAcc == _getters) { 1112 Linked<AnnotatedMethod> n2 = (Linked<AnnotatedMethod>) node; 1113 prop._getters = n2.withNext(prop._getters); 1114 } else if (firstAcc == _setters) { 1115 Linked<AnnotatedMethod> n2 = (Linked<AnnotatedMethod>) node; 1116 prop._setters = n2.withNext(prop._setters); 1117 } else if (firstAcc == _ctorParameters) { 1118 Linked<AnnotatedParameter> n2 = (Linked<AnnotatedParameter>) node; 1119 prop._ctorParameters = n2.withNext(prop._ctorParameters); 1120 } else { 1121 throw new IllegalStateException("Internal error: mismatched accessors, property: "+this); 1122 } 1123 } 1124 } 1125 1126 private Set<PropertyName> _findExplicitNames(Linked<? extends AnnotatedMember> node, 1127 Set<PropertyName> renamed) 1128 { 1129 for (; node != null; node = node.next) { 1130 /* 30-Mar-2014, tatu: Second check should not be needed, but seems like 1131 * removing it can cause nasty exceptions with certain version 1132 * combinations (2.4 databind, an older module). 1133 * So leaving it in for now until this is resolved 1134 * (or version beyond 2.4) 1135 */ 1136 if (!node.isNameExplicit || node.name == null) { 1137 continue; 1138 } 1139 if (renamed == null) { 1140 renamed = new HashSet<PropertyName>(); 1141 } 1142 renamed.add(node.name); 1143 } 1144 return renamed; 1145 } 1146 1147 // For trouble-shooting 1148 @Override 1149 public String toString() 1150 { 1151 StringBuilder sb = new StringBuilder(); 1152 sb.append("[Property '").append(_name) 1153 .append("'; ctors: ").append(_ctorParameters) 1154 .append(", field(s): ").append(_fields) 1155 .append(", getter(s): ").append(_getters) 1156 .append(", setter(s): ").append(_setters) 1157 ; 1158 sb.append("]"); 1159 return sb.toString(); 1160 } 1161 1162 /* 1163 /********************************************************** 1164 /* Helper methods 1165 /********************************************************** 1166 */ 1167 1168 /** 1169 * Helper method used for finding annotation values, from accessors 1170 * relevant to current usage (deserialization, serialization) 1171 */ 1172 protected <T> T fromMemberAnnotations(WithMember<T> func) 1173 { 1174 T result = null; 1175 if (_annotationIntrospector != null) { 1176 if (_forSerialization) { 1177 if (_getters != null) { 1178 result = func.withMember(_getters.value); 1179 } 1180 } else { 1181 if (_ctorParameters != null) { 1182 result = func.withMember(_ctorParameters.value); 1183 } 1184 if (result == null && _setters != null) { 1185 result = func.withMember(_setters.value); 1186 } 1187 } 1188 if (result == null && _fields != null) { 1189 result = func.withMember(_fields.value); 1190 } 1191 } 1192 return result; 1193 } 1194 1195 protected <T> T fromMemberAnnotationsExcept(WithMember<T> func, T defaultValue) 1196 { 1197 if (_annotationIntrospector == null) { 1198 return null; 1199 } 1200 1201 // NOTE: here we must ask ALL accessors, but the order varies between 1202 // serialization, deserialization 1203 if (_forSerialization) { 1204 if (_getters != null) { 1205 T result = func.withMember(_getters.value); 1206 if ((result != null) && (result != defaultValue)) { 1207 return result; 1208 } 1209 } 1210 if (_fields != null) { 1211 T result = func.withMember(_fields.value); 1212 if ((result != null) && (result != defaultValue)) { 1213 return result; 1214 } 1215 } 1216 if (_ctorParameters != null) { 1217 T result = func.withMember(_ctorParameters.value); 1218 if ((result != null) && (result != defaultValue)) { 1219 return result; 1220 } 1221 } 1222 if (_setters != null) { 1223 T result = func.withMember(_setters.value); 1224 if ((result != null) && (result != defaultValue)) { 1225 return result; 1226 } 1227 } 1228 return null; 1229 } 1230 if (_ctorParameters != null) { 1231 T result = func.withMember(_ctorParameters.value); 1232 if ((result != null) && (result != defaultValue)) { 1233 return result; 1234 } 1235 } 1236 if (_setters != null) { 1237 T result = func.withMember(_setters.value); 1238 if ((result != null) && (result != defaultValue)) { 1239 return result; 1240 } 1241 } 1242 if (_fields != null) { 1243 T result = func.withMember(_fields.value); 1244 if ((result != null) && (result != defaultValue)) { 1245 return result; 1246 } 1247 } 1248 if (_getters != null) { 1249 T result = func.withMember(_getters.value); 1250 if ((result != null) && (result != defaultValue)) { 1251 return result; 1252 } 1253 } 1254 return null; 1255 } 1256 1257 // Helper method needed to work around oddity in type access for 1258 // `AnnotatedMethod`. 1259 // 1260 // @since 2.11.1 1261 protected Class<?> _rawTypeOf(AnnotatedMember m) { 1262 // AnnotatedMethod always returns return type, but for setters we 1263 // actually need argument type 1264 if (m instanceof AnnotatedMethod) { 1265 AnnotatedMethod meh = (AnnotatedMethod) m; 1266 if (meh.getParameterCount() > 0) { 1267 // note: get raw type FROM full type since only that resolves 1268 // generic types 1269 return meh.getParameterType(0).getRawClass(); 1270 } 1271 } 1272 // same as above, must get fully resolved type to handled generic typing 1273 // of fields etc. 1274 return m.getType().getRawClass(); 1275 } 1276 1277 /* 1278 /********************************************************** 1279 /* Helper classes 1280 /********************************************************** 1281 */ 1282 1283 private interface WithMember<T> { 1284 public T withMember(AnnotatedMember member); 1285 } 1286 1287 /** 1288 * @since 2.5 1289 */ 1290 protected static class MemberIterator<T extends AnnotatedMember> 1291 implements Iterator<T> 1292 { 1293 private Linked<T> next; 1294 1295 public MemberIterator(Linked<T> first) { 1296 next = first; 1297 } 1298 1299 @Override 1300 public boolean hasNext() { 1301 return (next != null); 1302 } 1303 1304 @Override 1305 public T next() { 1306 if (next == null) throw new NoSuchElementException(); 1307 T result = next.value; 1308 next = next.next; 1309 return result; 1310 } 1311 1312 @Override 1313 public void remove() { 1314 throw new UnsupportedOperationException(); 1315 } 1316 1317 } 1318 1319 /** 1320 * Node used for creating simple linked lists to efficiently store small sets 1321 * of things. 1322 */ 1323 protected final static class Linked<T> 1324 { 1325 public final T value; 1326 public final Linked<T> next; 1327 1328 public final PropertyName name; 1329 public final boolean isNameExplicit; 1330 public final boolean isVisible; 1331 public final boolean isMarkedIgnored; 1332 1333 public Linked(T v, Linked<T> n, 1334 PropertyName name, boolean explName, boolean visible, boolean ignored) 1335 { 1336 value = v; 1337 next = n; 1338 // ensure that we'll never have missing names 1339 this.name = (name == null || name.isEmpty()) ? null : name; 1340 1341 if (explName) { 1342 if (this.name == null) { // sanity check to catch internal problems 1343 throw new IllegalArgumentException("Cannot pass true for 'explName' if name is null/empty"); 1344 } 1345 // 03-Apr-2014, tatu: But how about name-space only override? 1346 // Probably should not be explicit? Or, need to merge somehow? 1347 if (!name.hasSimpleName()) { 1348 explName = false; 1349 } 1350 } 1351 1352 isNameExplicit = explName; 1353 isVisible = visible; 1354 isMarkedIgnored = ignored; 1355 } 1356 1357 public Linked<T> withoutNext() { 1358 if (next == null) { 1359 return this; 1360 } 1361 return new Linked<T>(value, null, name, isNameExplicit, isVisible, isMarkedIgnored); 1362 } 1363 1364 public Linked<T> withValue(T newValue) { 1365 if (newValue == value) { 1366 return this; 1367 } 1368 return new Linked<T>(newValue, next, name, isNameExplicit, isVisible, isMarkedIgnored); 1369 } 1370 1371 public Linked<T> withNext(Linked<T> newNext) { 1372 if (newNext == next) { 1373 return this; 1374 } 1375 return new Linked<T>(value, newNext, name, isNameExplicit, isVisible, isMarkedIgnored); 1376 } 1377 1378 public Linked<T> withoutIgnored() { 1379 if (isMarkedIgnored) { 1380 return (next == null) ? null : next.withoutIgnored(); 1381 } 1382 if (next != null) { 1383 Linked<T> newNext = next.withoutIgnored(); 1384 if (newNext != next) { 1385 return withNext(newNext); 1386 } 1387 } 1388 return this; 1389 } 1390 1391 public Linked<T> withoutNonVisible() { 1392 Linked<T> newNext = (next == null) ? null : next.withoutNonVisible(); 1393 return isVisible ? withNext(newNext) : newNext; 1394 } 1395 1396 /** 1397 * Method called to append given node(s) at the end of this 1398 * node chain. 1399 */ 1400 protected Linked<T> append(Linked<T> appendable) { 1401 if (next == null) { 1402 return withNext(appendable); 1403 } 1404 return withNext(next.append(appendable)); 1405 } 1406 1407 public Linked<T> trimByVisibility() { 1408 if (next == null) { 1409 return this; 1410 } 1411 Linked<T> newNext = next.trimByVisibility(); 1412 if (name != null) { // this already has highest; how about next one? 1413 if (newNext.name == null) { // next one not, drop it 1414 return withNext(null); 1415 } 1416 // both have it, keep 1417 return withNext(newNext); 1418 } 1419 if (newNext.name != null) { // next one has higher, return it... 1420 return newNext; 1421 } 1422 // neither has explicit name; how about visibility? 1423 if (isVisible == newNext.isVisible) { // same; keep both in current order 1424 return withNext(newNext); 1425 } 1426 return isVisible ? withNext(null) : newNext; 1427 } 1428 1429 @Override 1430 public String toString() { 1431 String msg = String.format("%s[visible=%b,ignore=%b,explicitName=%b]", 1432 value.toString(), isVisible, isMarkedIgnored, isNameExplicit); 1433 if (next != null) { 1434 msg = msg + ", "+next.toString(); 1435 } 1436 return msg; 1437 } 1438 } 1439 } 1440