74
74
import java .util .HashMap ;
75
75
import java .util .HashSet ;
76
76
import java .util .LinkedHashMap ;
77
- import java .util .LinkedHashSet ;
78
77
import java .util .List ;
79
78
import java .util .Map ;
80
79
import java .util .Map .Entry ;
84
83
import java .util .TreeMap ;
85
84
import java .util .function .Consumer ;
86
85
import java .util .function .Function ;
86
+ import java .util .function .Supplier ;
87
87
import java .util .stream .Collectors ;
88
88
import java .util .stream .Stream ;
89
89
@@ -170,7 +170,7 @@ private T resolveRoot(Class<?> definition) {
170
170
private <A extends Annotation > T mapAnnotation (A annotation ,
171
171
Function <A , T > mapper ) {
172
172
if (annotation != null ) {
173
- return mapper .apply (annotation );
173
+ return mapper .apply (annotation );
174
174
}
175
175
return null ;
176
176
}
@@ -419,8 +419,8 @@ private Optional<Long> findMaxInSizeAnnotation(BeanProperty beanProperty) {
419
419
420
420
private T resolveObject (LinkedHashMap <String , String > visited , InternalSchemaSwaps schemaSwaps , JsonSchema jacksonSchema ,
421
421
String ... ignore ) {
422
- Set <String > ignores = ignore .length > 0 ? new LinkedHashSet <>(Arrays .asList (ignore )) : Collections .emptySet ();
423
422
423
+ Set <String > ignores = Set .of (ignore );
424
424
schemaSwaps = schemaSwaps .branchAnnotations ();
425
425
final InternalSchemaSwaps swaps = schemaSwaps ;
426
426
@@ -434,8 +434,11 @@ private T resolveObject(LinkedHashMap<String, String> visited, InternalSchemaSwa
434
434
Class <?> rawClass = gos .javaType .getRawClass ();
435
435
collectDependentClasses (rawClass );
436
436
437
- JSONSchema schemaAnnotation = resolvingContext .ignoreJSONSchemaAnnotation ? null : rawClass .getDeclaredAnnotation (JSONSchema .class );
438
- T classSchema = mapAnnotation (schemaAnnotation , schema -> fromAnnotation (rawClass , true , schema ));
437
+ T classSchema = resolveSchemaAnnotation (
438
+ rawClass .getDeclaredAnnotation (JSONSchema .class ),
439
+ rawClass ,
440
+ true ,
441
+ resolvingContext .ignoreJSONSchemaAnnotation );
439
442
440
443
if (classSchema != null ) {
441
444
return classSchema ;
@@ -451,17 +454,16 @@ private T resolveObject(LinkedHashMap<String, String> visited, InternalSchemaSwa
451
454
List <String > required = new ArrayList <>();
452
455
final T objectSchema = singleProperty ("object" );
453
456
454
- for (Map .Entry <String , JsonSchema > property : new TreeMap <> (gos .getProperties ()).entrySet ()) {
457
+ for (Map .Entry <String , JsonSchema > property : visibleProperties (gos .getProperties (), ignores ).entrySet ()) {
455
458
String name = property .getKey ();
456
- if (ignores .contains (name )) {
457
- continue ;
458
- }
459
459
BeanProperty beanProperty = gos .beanProperties .get (property .getKey ());
460
460
Utils .checkNotNull (beanProperty , "CRD generation works only with bean properties" );
461
461
462
- Class <?> propRawClass = beanProperty .getType ().getRawClass ();
463
- JSONSchema propSchemaAnnotation = beanProperty .getAnnotation (JSONSchema .class );
464
- T propSchema = mapAnnotation (propSchemaAnnotation , schema -> fromAnnotation (propRawClass , false , schema ));
462
+ T propSchema = resolveSchemaAnnotation (
463
+ beanProperty .getAnnotation (JSONSchema .class ),
464
+ beanProperty .getType ().getRawClass (),
465
+ false ,
466
+ false );
465
467
466
468
if (propSchema != null ) {
467
469
addProperty (name , objectSchema , propSchema );
@@ -525,6 +527,20 @@ private T resolveObject(LinkedHashMap<String, String> visited, InternalSchemaSwa
525
527
return objectSchema ;
526
528
}
527
529
530
+ private T resolveSchemaAnnotation (JSONSchema annotation , Class <?> rawClass , boolean isTargetType , boolean ignoreAnnotation ) {
531
+ if (annotation != null && !ignoreAnnotation ) {
532
+ return fromAnnotation (rawClass , isTargetType , annotation );
533
+ }
534
+ return null ;
535
+ }
536
+
537
+ private static Map <String , JsonSchema > visibleProperties (Map <String , JsonSchema > properties , Set <String > ignores ) {
538
+ return new TreeMap <>(
539
+ properties .entrySet ().stream ()
540
+ .filter (e -> !ignores .contains (e .getKey ()))
541
+ .collect (Collectors .toMap (Map .Entry ::getKey , Map .Entry ::getValue )));
542
+ }
543
+
528
544
private void collectDependentClasses (Class <?> rawClass ) {
529
545
if (rawClass != null && !rawClass .getName ().startsWith ("java." ) && dependentClasses .add (rawClass .getName ())) {
530
546
Stream .of (rawClass .getInterfaces ()).forEach (this ::collectDependentClasses );
@@ -706,77 +722,68 @@ private Set<String> findIgnoredEnumConstants(JavaType type) {
706
722
}
707
723
708
724
protected T fromAnnotation (Class <?> rawClass , boolean isTargetType , JSONSchema schema ) {
709
- T result = mapImplementation (schema .implementation (), isTargetType );
725
+ T result = mapImplementation (schema .implementation (), isTargetType );
710
726
711
- if (result == null ) {
712
- result = singleProperty (mapDefined ( schema . type ()) );
713
- }
727
+ if (result == null ) {
728
+ result = singleProperty (null );
729
+ }
714
730
715
- setIfDefined (mapDefined ( schema .defaultValue (), rawClass ), result ::setDefault );
716
- setIfDefined (mapDefined ( schema .description () ), result ::setDescription );
717
- setIfDefined (mapBoolean ( schema .exclusiveMaximum ()) , result ::setExclusiveMaximum );
718
- setIfDefined (mapBoolean ( schema .exclusiveMinimum ()) , result ::setExclusiveMinimum );
719
- setIfDefined (mapDefined ( schema .format () ), result ::setFormat );
720
- setIfDefined (mapDefined ( schema .maximum () ), result ::setMaximum );
721
- setIfDefined (mapDefined ( schema .maxItems () ), result ::setMaxItems );
722
- setIfDefined (mapDefined ( schema .maxLength () ), result ::setMaxLength );
723
- setIfDefined (mapDefined ( schema .maxProperties () ), result ::setMaxProperties );
724
- setIfDefined (mapDefined ( schema .minimum () ), result ::setMinimum );
725
- setIfDefined (mapDefined ( schema .minItems () ), result ::setMinItems );
726
- setIfDefined (mapDefined ( schema .minLength () ), result ::setMinLength );
727
- setIfDefined (mapDefined ( schema .minProperties () ), result ::setMinProperties );
728
- setIfDefined (mapBoolean ( schema .nullable ()) , result ::setNullable );
729
- setIfDefined (mapDefined ( schema .pattern () ), result ::setPattern );
730
- setIfDefined (mapDefined ( schema .required ()) , result ::setRequired );
731
- setIfDefined (mapBoolean ( schema .xKubernetesPreserveUnknownFields ()) , result ::setXKubernetesPreserveUnknownFields );
732
- return result ;
731
+ setIfDefined (schema .defaultValue (), v -> parseJson ( v , rawClass ), result ::setDefault );
732
+ setIfDefined (schema .description (), result ::setDescription );
733
+ setIfDefined (schema .exclusiveMaximum (), this :: mapBoolean , result ::setExclusiveMaximum );
734
+ setIfDefined (schema .exclusiveMinimum (), this :: mapBoolean , result ::setExclusiveMinimum );
735
+ setIfDefined (schema .format (), result ::setFormat );
736
+ setIfDefined (schema .maximum (), result ::setMaximum );
737
+ setIfDefined (schema .maxItems (), result ::setMaxItems );
738
+ setIfDefined (schema .maxLength (), result ::setMaxLength );
739
+ setIfDefined (schema .maxProperties (), result ::setMaxProperties );
740
+ setIfDefined (schema .minimum (), result ::setMinimum );
741
+ setIfDefined (schema .minItems (), result ::setMinItems );
742
+ setIfDefined (schema .minLength (), result ::setMinLength );
743
+ setIfDefined (schema .minProperties (), result ::setMinProperties );
744
+ setIfDefined (schema .nullable (), this :: mapBoolean , result ::setNullable );
745
+ setIfDefined (schema .pattern (), result ::setPattern );
746
+ setIfDefined (schema .required (), ArrayList :: new , Arrays :: asList , result ::setRequired );
747
+ setIfDefined (schema .xKubernetesPreserveUnknownFields (), this :: mapBoolean , result ::setXKubernetesPreserveUnknownFields );
748
+ return result ;
733
749
}
734
750
735
- protected static <P > void setIfDefined (P value , Consumer <P > mutator ) {
736
- if (value != null ) {
737
- mutator .accept (value );
738
- }
751
+ protected static <A , M > void setIfDefined (A value , Function <A , M > transformer , Consumer <M > mutator ) {
752
+ setIfDefined (value , () -> null , transformer , mutator );
739
753
}
740
754
741
- protected JsonNode mapDefined (String value , Class <?> targetType ) {
742
- if ((value = mapDefined (value )) == null ) {
743
- return null ;
755
+ protected static <A > void setIfDefined (A value , Consumer <A > mutator ) {
756
+ setIfDefined (value , () -> null , Function .identity (), mutator );
757
+ }
758
+
759
+ protected static <A , M > void setIfDefined (A value , Supplier <M > defaultValue , Function <A , M > transformer ,
760
+ Consumer <M > mutator ) {
761
+ if (JSONSchema .Undefined .isUndefined (value )) {
762
+ // Not defined in the annotation (the default), don't touch the model.
763
+ } else if (JSONSchema .Suppressed .isSuppressed (value )) {
764
+ // Suppressed in the annotation, return the model back to the default value.
765
+ mutator .accept (defaultValue .get ());
766
+ } else {
767
+ mutator .accept (transformer .apply (value ));
744
768
}
769
+ }
745
770
771
+ protected JsonNode parseJson (String value , Class <?> targetType ) {
746
772
Optional <Class <?>> rawType = Optional .ofNullable (targetType );
747
773
748
774
try {
749
775
Object typedValue = resolvingContext .kubernetesSerialization .unmarshal (value , rawType .orElse (Object .class ));
750
776
return resolvingContext .kubernetesSerialization .convertValue (typedValue , JsonNode .class );
751
777
} catch (Exception e ) {
752
- if (value .isEmpty ()) {
753
- LOGGER .warn ("Cannot parse value '{}' from JSONSchema annotation as valid YAML or JSON, no value will be used." , value );
754
- return null ;
755
- }
756
778
throw new IllegalArgumentException ("Cannot parse value '" + value + "' as valid YAML or JSON." , e );
757
779
}
758
780
}
759
781
760
- protected static String mapDefined (String value ) {
761
- return JSONSchema .Undefined .STRING .equals (value ) ? null : value ;
762
- }
763
-
764
- protected static List <String > mapDefined (String [] values ) {
765
- return values .length == 0 ? null : List .of (values );
766
- }
767
-
768
- protected static Double mapDefined (double value ) {
769
- return JSONSchema .Undefined .DOUBLE == value ? null : value ;
782
+ protected List <JsonNode > parseJson (String [] values , Class <?> targetType ) {
783
+ return Arrays .stream (values ).map (value -> parseJson (value , targetType )).collect (Collectors .toList ());
770
784
}
771
785
772
- protected static Long mapDefined (long value ) {
773
- return JSONSchema .Undefined .LONG == value ? null : value ;
774
- }
775
-
776
- protected static <A extends JSONSchema .Boolean > Boolean mapBoolean (Class <A > value ) {
777
- if (value == JSONSchema .Undefined .class ) {
778
- return null ; // NOSONAR
779
- }
786
+ protected <A extends JSONSchema .Boolean > Boolean mapBoolean (Class <A > value ) {
780
787
return value == JSONSchema .True .class ? Boolean .TRUE : Boolean .FALSE ;
781
788
}
782
789
0 commit comments