103
103
*/
104
104
public String timezone () default DEFAULT_TIMEZONE ;
105
105
106
+ /**
107
+ * Property that indicates whether "lenient" handling should be enabled or
108
+ * disabled. This is relevant mostly for deserialization of some textual
109
+ * datatypes, especially date/time types.
110
+ *
111
+ * @since 2.9
112
+ */
113
+ public OptBoolean lenient () default OptBoolean .DEFAULT ;
114
+
106
115
/**
107
116
* Set of {@link JsonFormat.Feature}s to explicitly enable with respect
108
117
* to handling of annotated property. This will have precedence over possible
@@ -397,6 +406,11 @@ public static class Value
397
406
398
407
private final String _timezoneStr ;
399
408
409
+ /**
410
+ * @since 2.9
411
+ */
412
+ private final Boolean _lenient ;
413
+
400
414
/**
401
415
* @since 2.6
402
416
*/
@@ -406,77 +420,72 @@ public static class Value
406
420
private transient TimeZone _timezone ;
407
421
408
422
public Value () {
409
- this ("" , Shape .ANY , "" , "" , Features .empty ());
423
+ this ("" , Shape .ANY , "" , "" , Features .empty (), null );
410
424
}
411
425
412
426
public Value (JsonFormat ann ) {
413
427
this (ann .pattern (), ann .shape (), ann .locale (), ann .timezone (),
414
- Features .construct (ann ));
428
+ Features .construct (ann ), ann . lenient (). asBoolean () );
415
429
}
416
430
417
431
/**
418
- * @since 2.6
432
+ * @since 2.9
419
433
*/
420
- public Value (String p , Shape sh , String localeStr , String tzStr , Features f )
434
+ public Value (String p , Shape sh , String localeStr , String tzStr , Features f ,
435
+ Boolean lenient )
421
436
{
422
437
this (p , sh ,
423
438
(localeStr == null || localeStr .length () == 0 || DEFAULT_LOCALE .equals (localeStr )) ?
424
439
null : new Locale (localeStr ),
425
440
(tzStr == null || tzStr .length () == 0 || DEFAULT_TIMEZONE .equals (tzStr )) ?
426
441
null : tzStr ,
427
- null , f );
442
+ null , f , lenient );
428
443
}
429
444
430
445
/**
431
- * @since 2.6
446
+ * @since 2.9
432
447
*/
433
- public Value (String p , Shape sh , Locale l , TimeZone tz , Features f )
448
+ public Value (String p , Shape sh , Locale l , TimeZone tz , Features f ,
449
+ Boolean lenient )
434
450
{
435
451
_pattern = p ;
436
452
_shape = (sh == null ) ? Shape .ANY : sh ;
437
453
_locale = l ;
438
454
_timezone = tz ;
439
455
_timezoneStr = null ;
440
456
_features = (f == null ) ? Features .empty () : f ;
457
+ _lenient = lenient ;
441
458
}
442
459
443
460
/**
444
- * @since 2.6
461
+ * @since 2.9
445
462
*/
446
- public Value (String p , Shape sh , Locale l , String tzStr , TimeZone tz , Features f )
463
+ public Value (String p , Shape sh , Locale l , String tzStr , TimeZone tz , Features f ,
464
+ Boolean lenient )
447
465
{
448
466
_pattern = p ;
449
467
_shape = (sh == null ) ? Shape .ANY : sh ;
450
468
_locale = l ;
451
469
_timezone = tz ;
452
470
_timezoneStr = tzStr ;
453
471
_features = (f == null ) ? Features .empty () : f ;
472
+ _lenient = lenient ;
454
473
}
455
474
456
- /**
457
- * @deprecated since 2.6
458
- */
459
- @ Deprecated
460
- public Value (String p , Shape sh , Locale l , TimeZone tz ) {
461
- this (p , sh , l , tz , Features .empty ());
462
- }
463
-
464
- /**
465
- * @deprecated since 2.6
466
- */
467
- @ Deprecated
468
- public Value (String p , Shape sh , String localeStr , String tzStr ) {
469
- this (p , sh , localeStr , tzStr , Features .empty ());
475
+ @ Deprecated // since 2.9
476
+ public Value (String p , Shape sh , Locale l , String tzStr , TimeZone tz , Features f ) {
477
+ this (p , sh , l , tzStr , tz , f , null );
470
478
}
471
479
472
- /**
473
- * @deprecated since 2.6
474
- */
475
- @ Deprecated
476
- public Value (String p , Shape sh , Locale l , String tzStr , TimeZone tz ) {
477
- this (p , sh , l , tzStr , tz , Features .empty ());
480
+ @ Deprecated // since 2.9
481
+ public Value (String p , Shape sh , String localeStr , String tzStr , Features f ) {
482
+ this (p , sh , localeStr , tzStr , f , null );
478
483
}
479
-
484
+ @ Deprecated // since 2.9
485
+ public Value (String p , Shape sh , Locale l , TimeZone tz , Features f ) {
486
+ this (p , sh , l , tz , f , null );
487
+ }
488
+
480
489
/**
481
490
* @since 2.7
482
491
*/
@@ -526,7 +535,7 @@ public final static Value from(JsonFormat ann) {
526
535
* @since 2.7
527
536
*/
528
537
public final Value withOverrides (Value overrides ) {
529
- if ((overrides == null ) || (overrides == EMPTY )) {
538
+ if ((overrides == null ) || (overrides == EMPTY ) || ( overrides == this ) ) {
530
539
return this ;
531
540
}
532
541
if (this == EMPTY ) { // cheesy, but probably common enough
@@ -550,6 +559,10 @@ public final Value withOverrides(Value overrides) {
550
559
} else {
551
560
f = f .withOverrides (overrides ._features );
552
561
}
562
+ Boolean lenient = overrides ._lenient ;
563
+ if (lenient == null ) {
564
+ lenient = _lenient ;
565
+ }
553
566
554
567
// timezone not merged, just choose one
555
568
String tzStr = overrides ._timezoneStr ;
@@ -561,49 +574,75 @@ public final Value withOverrides(Value overrides) {
561
574
} else {
562
575
tz = overrides ._timezone ;
563
576
}
564
- return new Value (p , sh , l , tzStr , tz , f );
577
+ return new Value (p , sh , l , tzStr , tz , f , lenient );
565
578
}
566
579
567
580
/**
568
581
* @since 2.6
569
582
*/
570
583
public static Value forPattern (String p ) {
571
- return new Value (p , null , null , null , null , Features .empty ());
584
+ return new Value (p , null , null , null , null , Features .empty (), null );
572
585
}
573
586
574
587
/**
575
588
* @since 2.7
576
589
*/
577
590
public static Value forShape (Shape sh ) {
578
- return new Value (null , sh , null , null , null , Features .empty ());
591
+ return new Value (null , sh , null , null , null , Features .empty (), null );
579
592
}
580
593
594
+ /**
595
+ * @since 2.9
596
+ */
597
+ public static Value forLeniency (boolean lenient ) {
598
+ return new Value (null , null , null , null , null , Features .empty (),
599
+ Boolean .valueOf (lenient ));
600
+ }
601
+
581
602
/**
582
603
* @since 2.1
583
604
*/
584
605
public Value withPattern (String p ) {
585
- return new Value (p , _shape , _locale , _timezoneStr , _timezone , _features );
606
+ return new Value (p , _shape , _locale , _timezoneStr , _timezone ,
607
+ _features , _lenient );
586
608
}
587
609
588
610
/**
589
611
* @since 2.1
590
612
*/
591
613
public Value withShape (Shape s ) {
592
- return new Value (_pattern , s , _locale , _timezoneStr , _timezone , _features );
614
+ if (s == _shape ) {
615
+ return this ;
616
+ }
617
+ return new Value (_pattern , s , _locale , _timezoneStr , _timezone ,
618
+ _features , _lenient );
593
619
}
594
620
595
621
/**
596
622
* @since 2.1
597
623
*/
598
624
public Value withLocale (Locale l ) {
599
- return new Value (_pattern , _shape , l , _timezoneStr , _timezone , _features );
625
+ return new Value (_pattern , _shape , l , _timezoneStr , _timezone ,
626
+ _features , _lenient );
600
627
}
601
628
602
629
/**
603
630
* @since 2.1
604
631
*/
605
632
public Value withTimeZone (TimeZone tz ) {
606
- return new Value (_pattern , _shape , _locale , null , tz , _features );
633
+ return new Value (_pattern , _shape , _locale , null , tz ,
634
+ _features , _lenient );
635
+ }
636
+
637
+ /**
638
+ * @since 2.9
639
+ */
640
+ public Value withLenient (Boolean lenient ) {
641
+ if (lenient == _lenient ) {
642
+ return this ;
643
+ }
644
+ return new Value (_pattern , _shape , _locale , _timezoneStr , _timezone ,
645
+ _features , lenient );
607
646
}
608
647
609
648
/**
@@ -612,7 +651,8 @@ public Value withTimeZone(TimeZone tz) {
612
651
public Value withFeature (JsonFormat .Feature f ) {
613
652
Features newFeats = _features .with (f );
614
653
return (newFeats == _features ) ? this :
615
- new Value (_pattern , _shape , _locale , _timezoneStr , _timezone , newFeats );
654
+ new Value (_pattern , _shape , _locale , _timezoneStr , _timezone ,
655
+ newFeats , _lenient );
616
656
}
617
657
618
658
/**
@@ -621,7 +661,8 @@ public Value withFeature(JsonFormat.Feature f) {
621
661
public Value withoutFeature (JsonFormat .Feature f ) {
622
662
Features newFeats = _features .without (f );
623
663
return (newFeats == _features ) ? this :
624
- new Value (_pattern , _shape , _locale , _timezoneStr , _timezone , newFeats );
664
+ new Value (_pattern , _shape , _locale , _timezoneStr , _timezone ,
665
+ newFeats , _lenient );
625
666
}
626
667
627
668
@ Override
@@ -633,6 +674,19 @@ public Class<JsonFormat> valueFor() {
633
674
public Shape getShape () { return _shape ; }
634
675
public Locale getLocale () { return _locale ; }
635
676
677
+ /**
678
+ * @since 2.9
679
+ */
680
+ public Boolean getLenient () {
681
+ return _lenient ;
682
+ }
683
+ /**
684
+ * @since 2.9
685
+ */
686
+ public boolean isLenient () {
687
+ return Boolean .TRUE .equals (_lenient );
688
+ }
689
+
636
690
/**
637
691
* Alternate access (compared to {@link #getTimeZone()}) which is useful
638
692
* when caller just wants time zone id to convert, but not as JDK
@@ -683,6 +737,17 @@ public boolean hasTimeZone() {
683
737
return (_timezone != null ) || (_timezoneStr != null && !_timezoneStr .isEmpty ());
684
738
}
685
739
740
+ /**
741
+ * Accessor for checking whether there is a setting for leniency.
742
+ * NOTE: does NOT mean that `lenient` is `true` necessarily; just that
743
+ * it has been set.
744
+ *
745
+ * @since 2.9
746
+ */
747
+ public boolean hasLenient () {
748
+ return _lenient != null ;
749
+ }
750
+
686
751
/**
687
752
* Accessor for checking whether this format value has specific setting for
688
753
* given feature. Result is 3-valued with either `null`, {@link Boolean#TRUE} or
@@ -708,8 +773,8 @@ public Features getFeatures() {
708
773
@ Override
709
774
public String toString () {
710
775
// !!! TODO: Features?
711
- return String .format ("[ pattern=%s,shape=%s,locale=%s,timezone=%s] " ,
712
- _pattern , _shape , _locale , _timezoneStr );
776
+ return String .format ("JsonFormat.Value( pattern=%s,shape=%s,lenient=%s, locale=%s,timezone=%s) " ,
777
+ _pattern , _shape , _lenient , _locale , _timezoneStr );
713
778
}
714
779
715
780
@ Override
@@ -719,10 +784,13 @@ public int hashCode() {
719
784
hash ^= _pattern .hashCode ();
720
785
}
721
786
hash += _shape .hashCode ();
787
+ if (_lenient != null ) {
788
+ hash ^= _lenient .hashCode ();
789
+ }
722
790
if (_locale != null ) {
723
- hash ^ = _locale .hashCode ();
791
+ hash + = _locale .hashCode ();
724
792
}
725
- hash + = _features .hashCode ();
793
+ hash ^ = _features .hashCode ();
726
794
return hash ;
727
795
}
728
796
@@ -737,7 +805,8 @@ public boolean equals(Object o) {
737
805
|| !_features .equals (other ._features )) {
738
806
return false ;
739
807
}
740
- return _equal (_timezoneStr , other ._timezoneStr )
808
+ return _equal (_lenient , other ._lenient )
809
+ && _equal (_timezoneStr , other ._timezoneStr )
741
810
&& _equal (_pattern , other ._pattern )
742
811
&& _equal (_timezone , other ._timezone )
743
812
&& _equal (_locale , other ._locale );
@@ -747,7 +816,8 @@ private static <T> boolean _equal(T value1, T value2)
747
816
{
748
817
if (value1 == null ) {
749
818
return (value2 == null );
750
- } else if (value2 == null ) {
819
+ }
820
+ if (value2 == null ) {
751
821
return false ;
752
822
}
753
823
return value1 .equals (value2 );
0 commit comments