@@ -64,10 +64,13 @@ public class POJOPropertiesCollector
64
64
*/
65
65
66
66
/**
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.
68
72
*/
69
- protected final LinkedHashMap <String , POJOPropertyBuilder > _properties
70
- = new LinkedHashMap <String , POJOPropertyBuilder >();
73
+ protected LinkedHashMap <String , POJOPropertyBuilder > _properties ;
71
74
72
75
protected LinkedList <POJOPropertyBuilder > _creatorProperties = null ;
73
76
@@ -143,7 +146,8 @@ public AnnotationIntrospector getAnnotationIntrospector() {
143
146
144
147
public List <BeanPropertyDefinition > getProperties () {
145
148
// 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 ());
147
151
}
148
152
149
153
public Map <Object , AnnotatedMember > getInjectables () {
@@ -222,7 +226,11 @@ public Class<?> findPOJOBuilderClass()
222
226
223
227
// for unit tests:
224
228
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 ;
226
234
}
227
235
228
236
/*
@@ -234,51 +242,59 @@ protected Map<String, POJOPropertyBuilder> getPropertyMap() {
234
242
/**
235
243
* Method that orchestrates collection activities, and needs to be called
236
244
* 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.
237
248
*/
238
249
public POJOPropertiesCollector collect ()
239
250
{
240
- _properties .clear ();
251
+ return this ;
252
+ }
253
+
254
+ protected Map <String , POJOPropertyBuilder > collectProperties ()
255
+ {
256
+ LinkedHashMap <String , POJOPropertyBuilder > props = new LinkedHashMap <String , POJOPropertyBuilder >();
241
257
242
258
// First: gather basic data
243
- _addFields ();
244
- _addMethods ();
245
- _addCreators ();
246
- _addInjectables ();
259
+ _addFields (props );
260
+ _addMethods (props );
261
+ _addCreators (props );
262
+ _addInjectables (props );
247
263
248
264
// Remove ignored properties, individual entries
249
- _removeUnwantedProperties ();
265
+ _removeUnwantedProperties (props );
250
266
251
267
// Rename remaining properties
252
- _renameProperties ();
268
+ _renameProperties (props );
253
269
// And use custom naming strategy, if applicable...
254
270
PropertyNamingStrategy naming = _findNamingStrategy ();
255
271
if (naming != null ) {
256
- _renameUsing (naming );
272
+ _renameUsing (props , naming );
257
273
}
258
274
259
275
/* Sort by visibility (explicit over implicit); drop all but first
260
276
* of member type (getter, setter etc) if there is visibility
261
277
* difference
262
278
*/
263
- for (POJOPropertyBuilder property : _properties .values ()) {
279
+ for (POJOPropertyBuilder property : props .values ()) {
264
280
property .trimByVisibility ();
265
281
}
266
282
267
283
// and then "merge" annotations
268
- for (POJOPropertyBuilder property : _properties .values ()) {
284
+ for (POJOPropertyBuilder property : props .values ()) {
269
285
property .mergeAnnotations (_forSerialization );
270
286
}
271
287
272
288
/* and, if required, apply wrapper name: note, MUST be done after
273
289
* annotations are merged.
274
290
*/
275
291
if (_config .isEnabled (MapperFeature .USE_WRAPPER_NAME_AS_PROPERTY_NAME )) {
276
- _renameWithWrappers ();
292
+ _renameWithWrappers (props );
277
293
}
278
294
279
295
// well, almost last: there's still ordering...
280
- _sortProperties ();
281
- return this ;
296
+ _sortProperties (props );
297
+ return props ;
282
298
}
283
299
284
300
/*
@@ -290,7 +306,7 @@ public POJOPropertiesCollector collect()
290
306
/**
291
307
* Method for collecting basic information on all fields found
292
308
*/
293
- protected void _addFields ()
309
+ protected void _addFields (Map < String , POJOPropertyBuilder > props )
294
310
{
295
311
final AnnotationIntrospector ai = _annotationIntrospector ;
296
312
/* 28-Mar-2013, tatu: For deserialization we may also want to remove
@@ -349,14 +365,14 @@ protected void _addFields()
349
365
if (pruneFinalFields && (pn == null ) && !ignored && Modifier .isFinal (f .getModifiers ())) {
350
366
continue ;
351
367
}
352
- _property (implName ).addField (f , pn , nameExplicit , visible , ignored );
368
+ _property (props , implName ).addField (f , pn , nameExplicit , visible , ignored );
353
369
}
354
370
}
355
371
356
372
/**
357
373
* Method for collecting basic information on constructor(s) found
358
374
*/
359
- protected void _addCreators ()
375
+ protected void _addCreators (Map < String , POJOPropertyBuilder > props )
360
376
{
361
377
// can be null if annotation processing is disabled...
362
378
if (_annotationIntrospector != null ) {
@@ -365,15 +381,15 @@ protected void _addCreators()
365
381
_creatorProperties = new LinkedList <POJOPropertyBuilder >();
366
382
}
367
383
for (int i = 0 , len = ctor .getParameterCount (); i < len ; ++i ) {
368
- _addCreatorParam (ctor .getParameter (i ));
384
+ _addCreatorParam (props , ctor .getParameter (i ));
369
385
}
370
386
}
371
387
for (AnnotatedMethod factory : _classDef .getStaticMethods ()) {
372
388
if (_creatorProperties == null ) {
373
389
_creatorProperties = new LinkedList <POJOPropertyBuilder >();
374
390
}
375
391
for (int i = 0 , len = factory .getParameterCount (); i < len ; ++i ) {
376
- _addCreatorParam (factory .getParameter (i ));
392
+ _addCreatorParam (props , factory .getParameter (i ));
377
393
}
378
394
}
379
395
}
@@ -382,7 +398,8 @@ protected void _addCreators()
382
398
/**
383
399
* @since 2.4
384
400
*/
385
- protected void _addCreatorParam (AnnotatedParameter param )
401
+ protected void _addCreatorParam (Map <String , POJOPropertyBuilder > props ,
402
+ AnnotatedParameter param )
386
403
{
387
404
// JDK 8, paranamer, Scala can give implicit name
388
405
String impl = _annotationIntrospector .findImplicitPropertyName (param );
@@ -413,15 +430,16 @@ protected void _addCreatorParam(AnnotatedParameter param)
413
430
* fields and methods work; but unlike those, we don't necessarily have
414
431
* implicit name to use (pre-Java8 at least). So:
415
432
*/
416
- POJOPropertyBuilder prop = (expl && impl .isEmpty ()) ? _property (pn ) : _property (impl );
433
+ POJOPropertyBuilder prop = (expl && impl .isEmpty ())
434
+ ? _property (props , pn ) : _property (props , impl );
417
435
prop .addCtor (param , pn , expl , true , false );
418
436
_creatorProperties .add (prop );
419
437
}
420
438
421
439
/**
422
440
* Method for collecting basic information on all fields found
423
441
*/
424
- protected void _addMethods ()
442
+ protected void _addMethods (Map < String , POJOPropertyBuilder > props )
425
443
{
426
444
final AnnotationIntrospector ai = _annotationIntrospector ;
427
445
@@ -433,9 +451,9 @@ protected void _addMethods()
433
451
*/
434
452
int argCount = m .getParameterCount ();
435
453
if (argCount == 0 ) { // getters (including 'any getter')
436
- _addGetterMethod (m , ai );
454
+ _addGetterMethod (props , m , ai );
437
455
} else if (argCount == 1 ) { // setters
438
- _addSetterMethod (m , ai );
456
+ _addSetterMethod (props , m , ai );
439
457
} else if (argCount == 2 ) { // any getter?
440
458
if (ai != null && ai .hasAnySetterAnnotation (m )) {
441
459
if (_anySetters == null ) {
@@ -447,7 +465,8 @@ protected void _addMethods()
447
465
}
448
466
}
449
467
450
- protected void _addGetterMethod (AnnotatedMethod m , AnnotationIntrospector ai )
468
+ protected void _addGetterMethod (Map <String , POJOPropertyBuilder > props ,
469
+ AnnotatedMethod m , AnnotationIntrospector ai )
451
470
{
452
471
// Very first thing: skip if not returning any value
453
472
if (!m .hasReturnType ()) {
@@ -510,10 +529,11 @@ protected void _addGetterMethod(AnnotatedMethod m, AnnotationIntrospector ai)
510
529
visible = true ;
511
530
}
512
531
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 );
514
533
}
515
-
516
- protected void _addSetterMethod (AnnotatedMethod m , AnnotationIntrospector ai )
534
+
535
+ protected void _addSetterMethod (Map <String , POJOPropertyBuilder > props ,
536
+ AnnotatedMethod m , AnnotationIntrospector ai )
517
537
{
518
538
String implName ; // from naming convention
519
539
boolean visible ;
@@ -546,10 +566,10 @@ protected void _addSetterMethod(AnnotatedMethod m, AnnotationIntrospector ai)
546
566
visible = true ;
547
567
}
548
568
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 );
550
570
}
551
571
552
- protected void _addInjectables ()
572
+ protected void _addInjectables (Map < String , POJOPropertyBuilder > props )
553
573
{
554
574
final AnnotationIntrospector ai = _annotationIntrospector ;
555
575
if (ai == null ) {
@@ -602,9 +622,9 @@ private PropertyName _propNameFromSimple(String simpleName) {
602
622
* Method called to get rid of candidate properties that are marked
603
623
* as ignored, or that are not visible.
604
624
*/
605
- protected void _removeUnwantedProperties ()
625
+ protected void _removeUnwantedProperties (Map < String , POJOPropertyBuilder > props )
606
626
{
607
- Iterator <Map .Entry <String ,POJOPropertyBuilder >> it = _properties .entrySet ().iterator ();
627
+ Iterator <Map .Entry <String ,POJOPropertyBuilder >> it = props .entrySet ().iterator ();
608
628
final boolean forceNonVisibleRemoval = !_config .isEnabled (MapperFeature .INFER_PROPERTY_MUTATORS );
609
629
610
630
while (it .hasNext ()) {
@@ -651,10 +671,10 @@ private void _addIgnored(String name)
651
671
/**********************************************************
652
672
*/
653
673
654
- protected void _renameProperties ()
674
+ protected void _renameProperties (Map < String , POJOPropertyBuilder > props )
655
675
{
656
676
// 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 ();
658
678
LinkedList <POJOPropertyBuilder > renamed = null ;
659
679
while (it .hasNext ()) {
660
680
Map .Entry <String , POJOPropertyBuilder > entry = it .next ();
@@ -696,9 +716,9 @@ protected void _renameProperties()
696
716
if (renamed != null ) {
697
717
for (POJOPropertyBuilder prop : renamed ) {
698
718
String name = prop .getName ();
699
- POJOPropertyBuilder old = _properties .get (name );
719
+ POJOPropertyBuilder old = props .get (name );
700
720
if (old == null ) {
701
- _properties .put (name , prop );
721
+ props .put (name , prop );
702
722
} else {
703
723
old .addAll (prop );
704
724
}
@@ -708,10 +728,11 @@ protected void _renameProperties()
708
728
}
709
729
}
710
730
711
- protected void _renameUsing (PropertyNamingStrategy naming )
731
+ protected void _renameUsing (Map <String , POJOPropertyBuilder > propMap ,
732
+ PropertyNamingStrategy naming )
712
733
{
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 ();
715
736
for (POJOPropertyBuilder prop : props ) {
716
737
PropertyName fullName = prop .getFullName ();
717
738
String rename = null ;
@@ -749,9 +770,9 @@ protected void _renameUsing(PropertyNamingStrategy naming)
749
770
/* As per [JACKSON-687], need to consider case where there may already be
750
771
* something in there...
751
772
*/
752
- POJOPropertyBuilder old = _properties .get (simpleName );
773
+ POJOPropertyBuilder old = propMap .get (simpleName );
753
774
if (old == null ) {
754
- _properties .put (simpleName , prop );
775
+ propMap .put (simpleName , prop );
755
776
} else {
756
777
old .addAll (prop );
757
778
}
@@ -760,12 +781,12 @@ protected void _renameUsing(PropertyNamingStrategy naming)
760
781
}
761
782
}
762
783
763
- protected void _renameWithWrappers ()
784
+ protected void _renameWithWrappers (Map < String , POJOPropertyBuilder > props )
764
785
{
765
786
/* 11-Sep-2012, tatu: To support 'MapperFeature.USE_WRAPPER_NAME_AS_PROPERTY_NAME',
766
787
* need another round of renaming...
767
788
*/
768
- Iterator <Map .Entry <String ,POJOPropertyBuilder >> it = _properties .entrySet ().iterator ();
789
+ Iterator <Map .Entry <String ,POJOPropertyBuilder >> it = props .entrySet ().iterator ();
769
790
LinkedList <POJOPropertyBuilder > renamed = null ;
770
791
while (it .hasNext ()) {
771
792
Map .Entry <String , POJOPropertyBuilder > entry = it .next ();
@@ -794,9 +815,9 @@ protected void _renameWithWrappers()
794
815
if (renamed != null ) {
795
816
for (POJOPropertyBuilder prop : renamed ) {
796
817
String name = prop .getName ();
797
- POJOPropertyBuilder old = _properties .get (name );
818
+ POJOPropertyBuilder old = props .get (name );
798
819
if (old == null ) {
799
- _properties .put (name , prop );
820
+ props .put (name , prop );
800
821
} else {
801
822
old .addAll (prop );
802
823
}
@@ -813,7 +834,7 @@ protected void _renameWithWrappers()
813
834
/* First, order by [JACKSON-90] (explicit ordering and/or alphabetic)
814
835
* and then for [JACKSON-170] (implicitly order creator properties before others)
815
836
*/
816
- protected void _sortProperties ()
837
+ protected void _sortProperties (Map < String , POJOPropertyBuilder > props )
817
838
{
818
839
// Then how about explicit ordering?
819
840
AnnotationIntrospector intr = _annotationIntrospector ;
@@ -831,7 +852,7 @@ protected void _sortProperties()
831
852
if (!sort && (_creatorProperties == null ) && (propertyOrder == null )) {
832
853
return ;
833
854
}
834
- int size = _properties .size ();
855
+ int size = props .size ();
835
856
Map <String , POJOPropertyBuilder > all ;
836
857
// Need to (re)sort alphabetically?
837
858
if (sort ) {
@@ -840,7 +861,7 @@ protected void _sortProperties()
840
861
all = new LinkedHashMap <String ,POJOPropertyBuilder >(size +size );
841
862
}
842
863
843
- for (POJOPropertyBuilder prop : _properties .values ()) {
864
+ for (POJOPropertyBuilder prop : props .values ()) {
844
865
all .put (prop .getName (), prop );
845
866
}
846
867
Map <String ,POJOPropertyBuilder > ordered = new LinkedHashMap <String ,POJOPropertyBuilder >(size +size );
@@ -849,7 +870,7 @@ protected void _sortProperties()
849
870
for (String name : propertyOrder ) {
850
871
POJOPropertyBuilder w = all .get (name );
851
872
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 ()) {
853
874
if (name .equals (prop .getInternalName ())) {
854
875
w = prop ;
855
876
// plus re-map to external name, to avoid dups:
@@ -888,8 +909,8 @@ protected void _sortProperties()
888
909
// And finally whatever is left (trying to put again will not change ordering)
889
910
ordered .putAll (all );
890
911
891
- _properties .clear ();
892
- _properties .putAll (ordered );
912
+ props .clear ();
913
+ props .putAll (ordered );
893
914
}
894
915
895
916
/*
@@ -902,18 +923,20 @@ protected void reportProblem(String msg) {
902
923
throw new IllegalArgumentException ("Problem with definition of " +_classDef +": " +msg );
903
924
}
904
925
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 ());
907
929
}
908
930
909
931
// !!! TODO: deprecate, require use of PropertyName
910
- protected POJOPropertyBuilder _property (String implName )
932
+ protected POJOPropertyBuilder _property (Map <String , POJOPropertyBuilder > props ,
933
+ String implName )
911
934
{
912
- POJOPropertyBuilder prop = _properties .get (implName );
935
+ POJOPropertyBuilder prop = props .get (implName );
913
936
if (prop == null ) {
914
937
prop = new POJOPropertyBuilder (PropertyName .construct (implName ),
915
938
_annotationIntrospector , _forSerialization );
916
- _properties .put (implName , prop );
939
+ props .put (implName , prop );
917
940
}
918
941
return prop ;
919
942
}
0 commit comments