diff --git a/crd-generator/api/src/main/java/io/fabric8/crd/generator/visitor/AdditionalPrinterColumnDetector.java b/crd-generator/api/src/main/java/io/fabric8/crd/generator/visitor/AdditionalPrinterColumnDetector.java index 6f87a176bc6..754efe32bd2 100644 --- a/crd-generator/api/src/main/java/io/fabric8/crd/generator/visitor/AdditionalPrinterColumnDetector.java +++ b/crd-generator/api/src/main/java/io/fabric8/crd/generator/visitor/AdditionalPrinterColumnDetector.java @@ -25,7 +25,7 @@ public AdditionalPrinterColumnDetector() { } public AdditionalPrinterColumnDetector(String prefix) { - super(prefix, PrinterColumn.class.getSimpleName(), new ArrayList<>()); + super(prefix, PrinterColumn.class.getSimpleName()); } } diff --git a/crd-generator/api/src/main/java/io/fabric8/crd/generator/visitor/AnnotatedMultiPropertyPathDetector.java b/crd-generator/api/src/main/java/io/fabric8/crd/generator/visitor/AnnotatedMultiPropertyPathDetector.java index b821017f703..387353a7dfa 100644 --- a/crd-generator/api/src/main/java/io/fabric8/crd/generator/visitor/AnnotatedMultiPropertyPathDetector.java +++ b/crd-generator/api/src/main/java/io/fabric8/crd/generator/visitor/AnnotatedMultiPropertyPathDetector.java @@ -21,13 +21,18 @@ import io.sundr.model.Property; import io.sundr.model.TypeDef; import io.sundr.model.TypeDefBuilder; + +import java.util.ArrayDeque; import java.util.ArrayList; +import java.util.Deque; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; +import static io.fabric8.crd.generator.AbstractJsonSchema.ANNOTATION_JSON_IGNORE; + public class AnnotatedMultiPropertyPathDetector extends TypedVisitor { protected static final String DOT = "."; @@ -37,20 +42,24 @@ public class AnnotatedMultiPropertyPathDetector extends TypedVisitor parents; private final Map properties; + private final Deque toRun; public AnnotatedMultiPropertyPathDetector(String prefix, String annotationName) { - this(prefix, annotationName, new ArrayList<>()); - } - - public AnnotatedMultiPropertyPathDetector(String prefix, String annotationName, List parents) { - this(prefix, annotationName, parents, new HashMap<>()); + this(prefix, annotationName, new ArrayList<>(), new HashMap<>(), new ArrayDeque<>()); } - public AnnotatedMultiPropertyPathDetector(String prefix, String annotationName, List parents, Map properties) { + public AnnotatedMultiPropertyPathDetector(String prefix, String annotationName, List parents, + Map properties, Deque toRun) { this.prefix = prefix; this.annotationName = annotationName; this.parents = parents; this.properties = properties; + this.toRun = toRun; + } + + private boolean excludePropertyProcessing(Property p) { + return p.getAnnotations().stream() + .anyMatch(ann -> ann.getClassRef().getFullyQualifiedName().equals(ANNOTATION_JSON_IGNORE)); } @Override @@ -58,33 +67,37 @@ public void visit(TypeDefBuilder builder) { TypeDef type = builder.build(); final List props = type.getProperties(); for (Property p : props) { - if (parents.contains(p)) { - continue; - } + if (parents.contains(p)) { + continue; + } - List newParents = new ArrayList<>(parents); - boolean match = p.getAnnotations().stream().anyMatch(a -> a.getClassRef().getName().equals(annotationName)); - if (match) { - newParents.add(p); - this.properties - .put(newParents.stream().map(Property::getName).collect(Collectors.joining(DOT, prefix, "")), p); - } + List newParents = new ArrayList<>(parents); + boolean match = p.getAnnotations().stream().anyMatch(a -> a.getClassRef().getName().equals(annotationName)); + if (match) { + newParents.add(p); + this.properties + .put(newParents.stream().map(Property::getName).collect(Collectors.joining(DOT, prefix, "")), p); + } } props.stream().filter(p -> p.getTypeRef() instanceof ClassRef).forEach(p -> { - if (!parents.contains(p)) { - ClassRef classRef = (ClassRef) p.getTypeRef(); - TypeDef propertyType = Types.typeDefFrom(classRef); - if (!propertyType.isEnum()) { - List newParents = new ArrayList<>(parents); - newParents.add(p); - new TypeDefBuilder(propertyType) - .accept(new AnnotatedMultiPropertyPathDetector(prefix, annotationName, newParents, - this.properties)) - .build(); - } + if (!parents.contains(p) && !excludePropertyProcessing(p)) { + ClassRef classRef = (ClassRef) p.getTypeRef(); + TypeDef propertyType = Types.typeDefFrom(classRef); + if (!propertyType.isEnum() && !classRef.getPackageName().startsWith("java.")) { + List newParents = new ArrayList<>(parents); + newParents.add(p); + toRun.add(() -> new TypeDefBuilder(propertyType) + .accept(new AnnotatedMultiPropertyPathDetector(prefix, annotationName, newParents, properties, toRun))); } - }); + } + }); + + if (parents.isEmpty()) { + while (!toRun.isEmpty()) { + toRun.pop().run(); + } + } } public Set getPaths() { diff --git a/crd-generator/api/src/main/java/io/fabric8/crd/generator/visitor/AnnotatedPropertyPathDetector.java b/crd-generator/api/src/main/java/io/fabric8/crd/generator/visitor/AnnotatedPropertyPathDetector.java index 4ddfb7b3e5b..be261ccc447 100644 --- a/crd-generator/api/src/main/java/io/fabric8/crd/generator/visitor/AnnotatedPropertyPathDetector.java +++ b/crd-generator/api/src/main/java/io/fabric8/crd/generator/visitor/AnnotatedPropertyPathDetector.java @@ -17,16 +17,22 @@ import io.fabric8.crd.generator.utils.Types; import io.sundr.builder.TypedVisitor; +import io.sundr.model.AnnotationRef; import io.sundr.model.ClassRef; import io.sundr.model.Property; import io.sundr.model.TypeDef; import io.sundr.model.TypeDefBuilder; + +import java.util.ArrayDeque; import java.util.ArrayList; +import java.util.Deque; import java.util.List; import java.util.Optional; import java.util.concurrent.atomic.AtomicReference; import java.util.stream.Collectors; +import static io.fabric8.crd.generator.AbstractJsonSchema.ANNOTATION_JSON_IGNORE; + public class AnnotatedPropertyPathDetector extends TypedVisitor { protected static final String DOT = "."; @@ -35,59 +41,74 @@ public class AnnotatedPropertyPathDetector extends TypedVisitor private final String prefix; private final String annotationName; private final List parents; - private final AtomicReference> reference; + private final AtomicReference reference; + private final Deque toRun; public AnnotatedPropertyPathDetector(String prefix, String annotationName) { - this(prefix, annotationName, new ArrayList<>()); - } - - public AnnotatedPropertyPathDetector(String prefix, String annotationName, List parents) { - this(prefix, annotationName, parents, new AtomicReference<>(Optional.empty())); + this(prefix, annotationName, new ArrayList<>(), new AtomicReference<>(), new ArrayDeque<>()); } - public AnnotatedPropertyPathDetector(String prefix, String annotationName, List parents, AtomicReference> reference) { + public AnnotatedPropertyPathDetector(String prefix, String annotationName, List parents, + AtomicReference reference, Deque toRun) { this.prefix = prefix; this.annotationName = annotationName; this.parents = parents; this.reference = reference; + this.toRun = toRun; + } + + private static boolean excludePropertyProcessing(Property p) { + for (AnnotationRef annotation : p.getAnnotations()) { + if (annotation.getClassRef().getFullyQualifiedName().equals(ANNOTATION_JSON_IGNORE)) { + return true; + } + } + return false; } @Override public void visit(TypeDefBuilder builder) { TypeDef type = builder.build(); final List properties = type.getProperties(); + visitProperties(properties); + } + + private void visitProperties(List properties) { for (Property p : properties) { if (parents.contains(p)) { - continue; - } + continue; + } - List newParents = new ArrayList<>(parents); - boolean match = p.getAnnotations().stream().anyMatch(a -> a.getClassRef().getName().equals(annotationName)); + List newParents = new ArrayList<>(parents); + boolean match = false; + for (AnnotationRef annotation : p.getAnnotations()) { + match = annotation.getClassRef().getName().equals(annotationName); if (match) { newParents.add(p); - reference.set(Optional.of(newParents.stream().map(Property::getName).collect(Collectors.joining(DOT, prefix, "")))); + reference.set(newParents.stream().map(Property::getName).collect(Collectors.joining(DOT, prefix, ""))); return; } - } + } - properties.stream() - .filter(p -> p.getTypeRef() instanceof ClassRef) - .forEach(p -> { - if (!parents.contains(p)) { - ClassRef classRef = (ClassRef) p.getTypeRef(); - TypeDef propertyType = Types.typeDefFrom(classRef); - if (!propertyType.isEnum()) { - List newParents = new ArrayList<>(parents); - newParents.add(p); - new TypeDefBuilder(propertyType) - .accept(new AnnotatedPropertyPathDetector(prefix, annotationName, newParents, reference)) - .build(); - } + if (p.getTypeRef() instanceof ClassRef && !excludePropertyProcessing(p)) { + ClassRef classRef = (ClassRef) p.getTypeRef(); + TypeDef propertyType = Types.typeDefFrom(classRef); + if (!propertyType.isEnum() && !classRef.getPackageName().startsWith("java.")) { + newParents.add(p); + new TypeDefBuilder(propertyType) + .accept(new AnnotatedPropertyPathDetector(prefix, annotationName, newParents, reference, toRun)); } - }); + } + } + + if (parents.isEmpty()) { + while (!toRun.isEmpty() && reference.get() == null) { + toRun.pop().run(); + } + } } public Optional getPath() { - return reference.get(); + return Optional.ofNullable(reference.get()); } } diff --git a/crd-generator/api/src/main/java/io/fabric8/crd/generator/visitor/LabelSelectorPathDetector.java b/crd-generator/api/src/main/java/io/fabric8/crd/generator/visitor/LabelSelectorPathDetector.java index 216854795c2..6fdb308f34f 100644 --- a/crd-generator/api/src/main/java/io/fabric8/crd/generator/visitor/LabelSelectorPathDetector.java +++ b/crd-generator/api/src/main/java/io/fabric8/crd/generator/visitor/LabelSelectorPathDetector.java @@ -25,6 +25,6 @@ public LabelSelectorPathDetector() { } public LabelSelectorPathDetector(String prefix) { - super(prefix, LabelSelector.class.getSimpleName(), new ArrayList<>()); + super(prefix, LabelSelector.class.getSimpleName()); } } diff --git a/crd-generator/api/src/main/java/io/fabric8/crd/generator/visitor/SpecReplicasPathDetector.java b/crd-generator/api/src/main/java/io/fabric8/crd/generator/visitor/SpecReplicasPathDetector.java index 162d944fe6e..0c993a82cc9 100644 --- a/crd-generator/api/src/main/java/io/fabric8/crd/generator/visitor/SpecReplicasPathDetector.java +++ b/crd-generator/api/src/main/java/io/fabric8/crd/generator/visitor/SpecReplicasPathDetector.java @@ -24,6 +24,6 @@ public SpecReplicasPathDetector() { this(DOT); } public SpecReplicasPathDetector(String prefix) { - super(prefix, SpecReplicas.class.getSimpleName(), new ArrayList<>()); + super(prefix, SpecReplicas.class.getSimpleName()); } } diff --git a/crd-generator/api/src/main/java/io/fabric8/crd/generator/visitor/StatusReplicasPathDetector.java b/crd-generator/api/src/main/java/io/fabric8/crd/generator/visitor/StatusReplicasPathDetector.java index c23ee4d0708..5d533d6b408 100644 --- a/crd-generator/api/src/main/java/io/fabric8/crd/generator/visitor/StatusReplicasPathDetector.java +++ b/crd-generator/api/src/main/java/io/fabric8/crd/generator/visitor/StatusReplicasPathDetector.java @@ -21,7 +21,7 @@ public class StatusReplicasPathDetector extends AnnotatedPropertyPathDetector { public StatusReplicasPathDetector(String prefix) { - super(prefix, StatusReplicas.class.getSimpleName(), new ArrayList<>()); + super(prefix, StatusReplicas.class.getSimpleName()); } diff --git a/crd-generator/api/src/test/java/io/fabric8/crd/example/map/ContainingMapsSpec.java b/crd-generator/api/src/test/java/io/fabric8/crd/example/map/ContainingMapsSpec.java index e09a7ee8f02..9d0e66652e5 100644 --- a/crd-generator/api/src/test/java/io/fabric8/crd/example/map/ContainingMapsSpec.java +++ b/crd-generator/api/src/test/java/io/fabric8/crd/example/map/ContainingMapsSpec.java @@ -15,6 +15,7 @@ */ package io.fabric8.crd.example.map; +import java.util.EnumMap; import java.util.List; import java.util.Map; @@ -32,4 +33,10 @@ public Map>> getTest2() { return test2; } + public enum Foo { + BAR + } + + private EnumMap enumToStringMap; + } diff --git a/crd-generator/api/src/test/java/io/fabric8/crd/generator/CRDGeneratorTest.java b/crd-generator/api/src/test/java/io/fabric8/crd/generator/CRDGeneratorTest.java index a1f96364356..accd511b043 100644 --- a/crd-generator/api/src/test/java/io/fabric8/crd/generator/CRDGeneratorTest.java +++ b/crd-generator/api/src/test/java/io/fabric8/crd/generator/CRDGeneratorTest.java @@ -275,7 +275,7 @@ void mapPropertyShouldHaveCorrectValueType() { final Map specProps = version.getSchema().getOpenAPIV3Schema() .getProperties().get("spec").getProperties(); - assertEquals(2, specProps.size()); + assertEquals(3, specProps.size()); checkMapProp(specProps, "test", "array"); String arrayType = specProps.get("test").getAdditionalProperties().getSchema().getItems().getSchema().getType();