Skip to content

Commit 09960de

Browse files
committed
Minor refactoring to (try to) defer resolution/introspection later, to avoid reporting irrelevant issues
1 parent f38d38f commit 09960de

File tree

1 file changed

+83
-60
lines changed

1 file changed

+83
-60
lines changed

src/main/java/com/fasterxml/jackson/databind/introspect/POJOPropertiesCollector.java

+83-60
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,13 @@ public class POJOPropertiesCollector
6464
*/
6565

6666
/**
67-
* Set of logical property information collected so far
67+
* Set of logical property information collected so far.
68+
*<p>
69+
* Since 2.6, this has been constructed (more) lazily, to defer
70+
* throwing of exceptions for potential conflicts in cases where
71+
* this may not be an actual problem.
6872
*/
69-
protected final LinkedHashMap<String, POJOPropertyBuilder> _properties
70-
= new LinkedHashMap<String, POJOPropertyBuilder>();
73+
protected LinkedHashMap<String, POJOPropertyBuilder> _properties;
7174

7275
protected LinkedList<POJOPropertyBuilder> _creatorProperties = null;
7376

@@ -143,7 +146,8 @@ public AnnotationIntrospector getAnnotationIntrospector() {
143146

144147
public List<BeanPropertyDefinition> getProperties() {
145148
// make sure we return a copy, so caller can remove entries if need be:
146-
return new ArrayList<BeanPropertyDefinition>(_properties.values());
149+
Map<String, POJOPropertyBuilder> props = getPropertyMap();
150+
return new ArrayList<BeanPropertyDefinition>(props.values());
147151
}
148152

149153
public Map<Object, AnnotatedMember> getInjectables() {
@@ -222,7 +226,11 @@ public Class<?> findPOJOBuilderClass()
222226

223227
// for unit tests:
224228
protected Map<String, POJOPropertyBuilder> getPropertyMap() {
225-
return _properties;
229+
Map<String, POJOPropertyBuilder> props = _properties;
230+
if (props == null) {
231+
props = collectProperties();
232+
}
233+
return props;
226234
}
227235

228236
/*
@@ -234,51 +242,59 @@ protected Map<String, POJOPropertyBuilder> getPropertyMap() {
234242
/**
235243
* Method that orchestrates collection activities, and needs to be called
236244
* after creating the instance.
245+
*<p>
246+
* Since 2.6 has become a no-op and actual collection is done more lazily
247+
* at point where properties are actually needed.
237248
*/
238249
public POJOPropertiesCollector collect()
239250
{
240-
_properties.clear();
251+
return this;
252+
}
253+
254+
protected Map<String, POJOPropertyBuilder> collectProperties()
255+
{
256+
LinkedHashMap<String, POJOPropertyBuilder> props = new LinkedHashMap<String, POJOPropertyBuilder>();
241257

242258
// First: gather basic data
243-
_addFields();
244-
_addMethods();
245-
_addCreators();
246-
_addInjectables();
259+
_addFields(props);
260+
_addMethods(props);
261+
_addCreators(props);
262+
_addInjectables(props);
247263

248264
// Remove ignored properties, individual entries
249-
_removeUnwantedProperties();
265+
_removeUnwantedProperties(props);
250266

251267
// Rename remaining properties
252-
_renameProperties();
268+
_renameProperties(props);
253269
// And use custom naming strategy, if applicable...
254270
PropertyNamingStrategy naming = _findNamingStrategy();
255271
if (naming != null) {
256-
_renameUsing(naming);
272+
_renameUsing(props, naming);
257273
}
258274

259275
/* Sort by visibility (explicit over implicit); drop all but first
260276
* of member type (getter, setter etc) if there is visibility
261277
* difference
262278
*/
263-
for (POJOPropertyBuilder property : _properties.values()) {
279+
for (POJOPropertyBuilder property : props.values()) {
264280
property.trimByVisibility();
265281
}
266282

267283
// and then "merge" annotations
268-
for (POJOPropertyBuilder property : _properties.values()) {
284+
for (POJOPropertyBuilder property : props.values()) {
269285
property.mergeAnnotations(_forSerialization);
270286
}
271287

272288
/* and, if required, apply wrapper name: note, MUST be done after
273289
* annotations are merged.
274290
*/
275291
if (_config.isEnabled(MapperFeature.USE_WRAPPER_NAME_AS_PROPERTY_NAME)) {
276-
_renameWithWrappers();
292+
_renameWithWrappers(props);
277293
}
278294

279295
// well, almost last: there's still ordering...
280-
_sortProperties();
281-
return this;
296+
_sortProperties(props);
297+
return props;
282298
}
283299

284300
/*
@@ -290,7 +306,7 @@ public POJOPropertiesCollector collect()
290306
/**
291307
* Method for collecting basic information on all fields found
292308
*/
293-
protected void _addFields()
309+
protected void _addFields(Map<String, POJOPropertyBuilder> props)
294310
{
295311
final AnnotationIntrospector ai = _annotationIntrospector;
296312
/* 28-Mar-2013, tatu: For deserialization we may also want to remove
@@ -349,14 +365,14 @@ protected void _addFields()
349365
if (pruneFinalFields && (pn == null) && !ignored && Modifier.isFinal(f.getModifiers())) {
350366
continue;
351367
}
352-
_property(implName).addField(f, pn, nameExplicit, visible, ignored);
368+
_property(props, implName).addField(f, pn, nameExplicit, visible, ignored);
353369
}
354370
}
355371

356372
/**
357373
* Method for collecting basic information on constructor(s) found
358374
*/
359-
protected void _addCreators()
375+
protected void _addCreators(Map<String, POJOPropertyBuilder> props)
360376
{
361377
// can be null if annotation processing is disabled...
362378
if (_annotationIntrospector != null) {
@@ -365,15 +381,15 @@ protected void _addCreators()
365381
_creatorProperties = new LinkedList<POJOPropertyBuilder>();
366382
}
367383
for (int i = 0, len = ctor.getParameterCount(); i < len; ++i) {
368-
_addCreatorParam(ctor.getParameter(i));
384+
_addCreatorParam(props, ctor.getParameter(i));
369385
}
370386
}
371387
for (AnnotatedMethod factory : _classDef.getStaticMethods()) {
372388
if (_creatorProperties == null) {
373389
_creatorProperties = new LinkedList<POJOPropertyBuilder>();
374390
}
375391
for (int i = 0, len = factory.getParameterCount(); i < len; ++i) {
376-
_addCreatorParam(factory.getParameter(i));
392+
_addCreatorParam(props, factory.getParameter(i));
377393
}
378394
}
379395
}
@@ -382,7 +398,8 @@ protected void _addCreators()
382398
/**
383399
* @since 2.4
384400
*/
385-
protected void _addCreatorParam(AnnotatedParameter param)
401+
protected void _addCreatorParam(Map<String, POJOPropertyBuilder> props,
402+
AnnotatedParameter param)
386403
{
387404
// JDK 8, paranamer, Scala can give implicit name
388405
String impl = _annotationIntrospector.findImplicitPropertyName(param);
@@ -413,15 +430,16 @@ protected void _addCreatorParam(AnnotatedParameter param)
413430
* fields and methods work; but unlike those, we don't necessarily have
414431
* implicit name to use (pre-Java8 at least). So:
415432
*/
416-
POJOPropertyBuilder prop = (expl && impl.isEmpty()) ? _property(pn) : _property(impl);
433+
POJOPropertyBuilder prop = (expl && impl.isEmpty())
434+
? _property(props, pn) : _property(props, impl);
417435
prop.addCtor(param, pn, expl, true, false);
418436
_creatorProperties.add(prop);
419437
}
420438

421439
/**
422440
* Method for collecting basic information on all fields found
423441
*/
424-
protected void _addMethods()
442+
protected void _addMethods(Map<String, POJOPropertyBuilder> props)
425443
{
426444
final AnnotationIntrospector ai = _annotationIntrospector;
427445

@@ -433,9 +451,9 @@ protected void _addMethods()
433451
*/
434452
int argCount = m.getParameterCount();
435453
if (argCount == 0) { // getters (including 'any getter')
436-
_addGetterMethod(m, ai);
454+
_addGetterMethod(props, m, ai);
437455
} else if (argCount == 1) { // setters
438-
_addSetterMethod(m, ai);
456+
_addSetterMethod(props, m, ai);
439457
} else if (argCount == 2) { // any getter?
440458
if (ai != null && ai.hasAnySetterAnnotation(m)) {
441459
if (_anySetters == null) {
@@ -447,7 +465,8 @@ protected void _addMethods()
447465
}
448466
}
449467

450-
protected void _addGetterMethod(AnnotatedMethod m, AnnotationIntrospector ai)
468+
protected void _addGetterMethod(Map<String, POJOPropertyBuilder> props,
469+
AnnotatedMethod m, AnnotationIntrospector ai)
451470
{
452471
// Very first thing: skip if not returning any value
453472
if (!m.hasReturnType()) {
@@ -510,10 +529,11 @@ protected void _addGetterMethod(AnnotatedMethod m, AnnotationIntrospector ai)
510529
visible = true;
511530
}
512531
boolean ignore = (ai == null) ? false : ai.hasIgnoreMarker(m);
513-
_property(implName).addGetter(m, pn, nameExplicit, visible, ignore);
532+
_property(props, implName).addGetter(m, pn, nameExplicit, visible, ignore);
514533
}
515-
516-
protected void _addSetterMethod(AnnotatedMethod m, AnnotationIntrospector ai)
534+
535+
protected void _addSetterMethod(Map<String, POJOPropertyBuilder> props,
536+
AnnotatedMethod m, AnnotationIntrospector ai)
517537
{
518538
String implName; // from naming convention
519539
boolean visible;
@@ -546,10 +566,10 @@ protected void _addSetterMethod(AnnotatedMethod m, AnnotationIntrospector ai)
546566
visible = true;
547567
}
548568
boolean ignore = (ai == null) ? false : ai.hasIgnoreMarker(m);
549-
_property(implName).addSetter(m, pn, nameExplicit, visible, ignore);
569+
_property(props, implName).addSetter(m, pn, nameExplicit, visible, ignore);
550570
}
551571

552-
protected void _addInjectables()
572+
protected void _addInjectables(Map<String, POJOPropertyBuilder> props)
553573
{
554574
final AnnotationIntrospector ai = _annotationIntrospector;
555575
if (ai == null) {
@@ -602,9 +622,9 @@ private PropertyName _propNameFromSimple(String simpleName) {
602622
* Method called to get rid of candidate properties that are marked
603623
* as ignored, or that are not visible.
604624
*/
605-
protected void _removeUnwantedProperties()
625+
protected void _removeUnwantedProperties(Map<String, POJOPropertyBuilder> props)
606626
{
607-
Iterator<Map.Entry<String,POJOPropertyBuilder>> it = _properties.entrySet().iterator();
627+
Iterator<Map.Entry<String,POJOPropertyBuilder>> it = props.entrySet().iterator();
608628
final boolean forceNonVisibleRemoval = !_config.isEnabled(MapperFeature.INFER_PROPERTY_MUTATORS);
609629

610630
while (it.hasNext()) {
@@ -651,10 +671,10 @@ private void _addIgnored(String name)
651671
/**********************************************************
652672
*/
653673

654-
protected void _renameProperties()
674+
protected void _renameProperties(Map<String, POJOPropertyBuilder> props)
655675
{
656676
// With renaming need to do in phases: first, find properties to rename
657-
Iterator<Map.Entry<String,POJOPropertyBuilder>> it = _properties.entrySet().iterator();
677+
Iterator<Map.Entry<String,POJOPropertyBuilder>> it = props.entrySet().iterator();
658678
LinkedList<POJOPropertyBuilder> renamed = null;
659679
while (it.hasNext()) {
660680
Map.Entry<String, POJOPropertyBuilder> entry = it.next();
@@ -696,9 +716,9 @@ protected void _renameProperties()
696716
if (renamed != null) {
697717
for (POJOPropertyBuilder prop : renamed) {
698718
String name = prop.getName();
699-
POJOPropertyBuilder old = _properties.get(name);
719+
POJOPropertyBuilder old = props.get(name);
700720
if (old == null) {
701-
_properties.put(name, prop);
721+
props.put(name, prop);
702722
} else {
703723
old.addAll(prop);
704724
}
@@ -708,10 +728,11 @@ protected void _renameProperties()
708728
}
709729
}
710730

711-
protected void _renameUsing(PropertyNamingStrategy naming)
731+
protected void _renameUsing(Map<String, POJOPropertyBuilder> propMap,
732+
PropertyNamingStrategy naming)
712733
{
713-
POJOPropertyBuilder[] props = _properties.values().toArray(new POJOPropertyBuilder[_properties.size()]);
714-
_properties.clear();
734+
POJOPropertyBuilder[] props = propMap.values().toArray(new POJOPropertyBuilder[propMap.size()]);
735+
propMap.clear();
715736
for (POJOPropertyBuilder prop : props) {
716737
PropertyName fullName = prop.getFullName();
717738
String rename = null;
@@ -749,9 +770,9 @@ protected void _renameUsing(PropertyNamingStrategy naming)
749770
/* As per [JACKSON-687], need to consider case where there may already be
750771
* something in there...
751772
*/
752-
POJOPropertyBuilder old = _properties.get(simpleName);
773+
POJOPropertyBuilder old = propMap.get(simpleName);
753774
if (old == null) {
754-
_properties.put(simpleName, prop);
775+
propMap.put(simpleName, prop);
755776
} else {
756777
old.addAll(prop);
757778
}
@@ -760,12 +781,12 @@ protected void _renameUsing(PropertyNamingStrategy naming)
760781
}
761782
}
762783

763-
protected void _renameWithWrappers()
784+
protected void _renameWithWrappers(Map<String, POJOPropertyBuilder> props)
764785
{
765786
/* 11-Sep-2012, tatu: To support 'MapperFeature.USE_WRAPPER_NAME_AS_PROPERTY_NAME',
766787
* need another round of renaming...
767788
*/
768-
Iterator<Map.Entry<String,POJOPropertyBuilder>> it = _properties.entrySet().iterator();
789+
Iterator<Map.Entry<String,POJOPropertyBuilder>> it = props.entrySet().iterator();
769790
LinkedList<POJOPropertyBuilder> renamed = null;
770791
while (it.hasNext()) {
771792
Map.Entry<String, POJOPropertyBuilder> entry = it.next();
@@ -794,9 +815,9 @@ protected void _renameWithWrappers()
794815
if (renamed != null) {
795816
for (POJOPropertyBuilder prop : renamed) {
796817
String name = prop.getName();
797-
POJOPropertyBuilder old = _properties.get(name);
818+
POJOPropertyBuilder old = props.get(name);
798819
if (old == null) {
799-
_properties.put(name, prop);
820+
props.put(name, prop);
800821
} else {
801822
old.addAll(prop);
802823
}
@@ -813,7 +834,7 @@ protected void _renameWithWrappers()
813834
/* First, order by [JACKSON-90] (explicit ordering and/or alphabetic)
814835
* and then for [JACKSON-170] (implicitly order creator properties before others)
815836
*/
816-
protected void _sortProperties()
837+
protected void _sortProperties(Map<String, POJOPropertyBuilder> props)
817838
{
818839
// Then how about explicit ordering?
819840
AnnotationIntrospector intr = _annotationIntrospector;
@@ -831,7 +852,7 @@ protected void _sortProperties()
831852
if (!sort && (_creatorProperties == null) && (propertyOrder == null)) {
832853
return;
833854
}
834-
int size = _properties.size();
855+
int size = props.size();
835856
Map<String, POJOPropertyBuilder> all;
836857
// Need to (re)sort alphabetically?
837858
if (sort) {
@@ -840,7 +861,7 @@ protected void _sortProperties()
840861
all = new LinkedHashMap<String,POJOPropertyBuilder>(size+size);
841862
}
842863

843-
for (POJOPropertyBuilder prop : _properties.values()) {
864+
for (POJOPropertyBuilder prop : props.values()) {
844865
all.put(prop.getName(), prop);
845866
}
846867
Map<String,POJOPropertyBuilder> ordered = new LinkedHashMap<String,POJOPropertyBuilder>(size+size);
@@ -849,7 +870,7 @@ protected void _sortProperties()
849870
for (String name : propertyOrder) {
850871
POJOPropertyBuilder w = all.get(name);
851872
if (w == null) { // also, as per [JACKSON-268], we will allow use of "implicit" names
852-
for (POJOPropertyBuilder prop : _properties.values()) {
873+
for (POJOPropertyBuilder prop : props.values()) {
853874
if (name.equals(prop.getInternalName())) {
854875
w = prop;
855876
// plus re-map to external name, to avoid dups:
@@ -888,8 +909,8 @@ protected void _sortProperties()
888909
// And finally whatever is left (trying to put again will not change ordering)
889910
ordered.putAll(all);
890911

891-
_properties.clear();
892-
_properties.putAll(ordered);
912+
props.clear();
913+
props.putAll(ordered);
893914
}
894915

895916
/*
@@ -902,18 +923,20 @@ protected void reportProblem(String msg) {
902923
throw new IllegalArgumentException("Problem with definition of "+_classDef+": "+msg);
903924
}
904925

905-
protected POJOPropertyBuilder _property(PropertyName name) {
906-
return _property(name.getSimpleName());
926+
protected POJOPropertyBuilder _property(Map<String, POJOPropertyBuilder> props,
927+
PropertyName name) {
928+
return _property(props, name.getSimpleName());
907929
}
908930

909931
// !!! TODO: deprecate, require use of PropertyName
910-
protected POJOPropertyBuilder _property(String implName)
932+
protected POJOPropertyBuilder _property(Map<String, POJOPropertyBuilder> props,
933+
String implName)
911934
{
912-
POJOPropertyBuilder prop = _properties.get(implName);
935+
POJOPropertyBuilder prop = props.get(implName);
913936
if (prop == null) {
914937
prop = new POJOPropertyBuilder(PropertyName.construct(implName),
915938
_annotationIntrospector, _forSerialization);
916-
_properties.put(implName, prop);
939+
props.put(implName, prop);
917940
}
918941
return prop;
919942
}

0 commit comments

Comments
 (0)