Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
import java.util.*;

import static com.predic8.membrane.annot.generator.kubernetes.model.SchemaFactory.*;
import static com.predic8.membrane.annot.generator.kubernetes.model.SchemaFactory.ref;
import static com.predic8.membrane.annot.generator.util.SchemaGeneratorUtil.*;
import static javax.tools.StandardLocation.*;

Expand All @@ -40,7 +39,7 @@
*/
public class JsonSchemaGenerator extends AbstractK8sGenerator {

private final Map<String,Boolean> topLevelAdded = new HashMap<>();
private final Map<String, Boolean> topLevelAdded = new HashMap<>();

public JsonSchemaGenerator(ProcessingEnvironment processingEnv) {
super(processingEnv);
Expand Down Expand Up @@ -86,12 +85,12 @@ private void assemble(Model m, MainInfo main) throws IOException {

private void addTopLevelProperties() {
schema.additionalProperties(false)
.property(string("apiVersion"))
.property( string("kind").enumeration(List.of("api")))
.property( ref("spec").ref("#/$defs/com.predic8.membrane.core.config.spring.ApiParser").required(true))
.property(object("metadata")
.additionalProperties(true)
.property(string("name")));
.property(string("apiVersion"))
.property(string("kind").enumeration(List.of("api")))
.property(ref("spec").ref("#/$defs/com_predic8_membrane_core_config_spring_ApiParser").required(true))
.property(object("metadata")
.additionalProperties(true)
.property(string("name")));
}

private void addParserDefinitions(Model m, MainInfo main) {
Expand All @@ -118,7 +117,7 @@ private SchemaObject createParser(Model m, MainInfo main, ElementInfo elementInf
ChildElementInfo child = elementInfo.getChildElementSpecs().getFirst();
var childName = child.getPropertyName();

if (!topLevelAdded.containsKey(childName) && !shouldGenerateParserType(child) ) {
if (!topLevelAdded.containsKey(childName) && !shouldGenerateParserType(child)) {
SchemaArray array = array(childName + "Parser");
processMCChilds(m, main, child.getEi(), array);
schema.definition(array);
Expand All @@ -129,8 +128,8 @@ private SchemaObject createParser(Model m, MainInfo main, ElementInfo elementInf
}

SchemaObject parser = object(parserName)
.additionalProperties( false)
.description( getDescriptionContent(elementInfo));
.additionalProperties(false)
.description(getDescriptionContent(elementInfo));
collectProperties(m, main, elementInfo, parser);
return parser;
}
Expand Down Expand Up @@ -161,12 +160,24 @@ private FileObject createFile(MainInfo main) throws IOException {
private void processMCAttributes(ElementInfo i, SchemaObject so) {
i.getAis().stream()
.filter(ai -> !ai.getXMLName().equals("id"))
.forEach(ai -> so.property(object(ai.getXMLName())
.description(getDescriptionContent(ai))
.type(ai.getSchemaType(processingEnv.getTypeUtils()))
.required(ai.isRequired())));
.forEach(ai -> so.property(createProperty(ai)));
}

private AbstractSchema<?> createProperty(AttributeInfo ai) {
String type = ai.getSchemaType(processingEnv.getTypeUtils());
AbstractSchema<?> s = SchemaFactory.from(type)
.name(ai.getXMLName())
.description(getDescriptionContent(ai))
.type(type)
.required(ai.isRequired());
// Add enum values if the type is an enum. If it is an enum for a boolean value, rely on the "boolean" type.
if (ai.isEnum(processingEnv.getTypeUtils()) && !"boolean".equals(type)) {
s.enumValues(ai.enumsAsLowerCaseList(processingEnv.getTypeUtils()));
}
return s;
}


private void collectProperties(Model m, MainInfo main, ElementInfo i, SchemaObject schema) {
processMCAttributes(i, schema);
collectTextContent(i, schema);
Expand All @@ -177,16 +188,16 @@ private void collectTextContent(ElementInfo i, SchemaObject so) {
if (i.getTci() == null)
return;

SchemaObject sop = string(i.getTci().getPropertyName());
var sop = string(i.getTci().getPropertyName());
// sop.addAttribute("description", getDescriptionAsText(i));
// sop.addAttribute("x-intellij-html-description", getDescriptionAsHtml(i));
so.property(sop);
}

private void processMCChilds(Model m, MainInfo main, ElementInfo i, AbstractSchema so) {
private void processMCChilds(Model m, MainInfo main, ElementInfo i, AbstractSchema<?> so) {
for (ChildElementInfo cei : i.getChildElementSpecs()) {

AbstractSchema parent2 = so;
AbstractSchema<?> parent2 = so;

if (cei.isList()) {
if (shouldGenerateParserType(cei)) {
Expand Down Expand Up @@ -221,7 +232,7 @@ boolean isFlowFromWebSocket(ChildElementInfo cei) {
return "com.predic8.membrane.core.transport.ws.WebSocketInterceptorInterface".equals(cei.getTypeDeclaration().getQualifiedName().toString());
}

private AbstractSchema processList(ElementInfo i, AbstractSchema so, ChildElementInfo cei, ArrayList<SchemaObject> sos) {
private AbstractSchema<?> processList(ElementInfo i, AbstractSchema<?> so, ChildElementInfo cei, ArrayList<SchemaObject> sos) {

SchemaObject items = object("items");

Expand All @@ -243,9 +254,9 @@ private AbstractSchema processList(ElementInfo i, AbstractSchema so, ChildElemen
return items;
}

private void addFlowParserRef(AbstractSchema so, List<SchemaObject> sos) {
private void addFlowParserRef(AbstractSchema<?> so, List<SchemaObject> sos) {
if (!flowDefCreated) {
schema.definition( array("flowParser").items( anyOf(sos)));
schema.definition(array("flowParser").items(anyOf(sos)));
flowDefCreated = true;
}
SchemaRef ref = ref("flow").ref("#/$defs/flowParser");
Expand All @@ -259,9 +270,9 @@ private void addFlowParserRef(AbstractSchema so, List<SchemaObject> sos) {
private void addChildsAsProperties(Model m, MainInfo main, ChildElementInfo cei, SchemaObject parent2) {
for (ElementInfo ei : getChildElementDeclarationInfo(main, cei).getElementInfo()) {
parent2.property(ref(ei.getAnnotation().name())
.ref("#/$defs/" + ei.getXSDTypeName(m)))
.description(getDescriptionContent(ei))
.required(cei.isRequired());
.ref("#/$defs/" + ei.getXSDTypeName(m)))
.description(getDescriptionContent(ei))
.required(cei.isRequired());

}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
import java.util.*;

import static com.predic8.membrane.annot.generator.kubernetes.model.SchemaFactory.*;
import static com.predic8.membrane.annot.generator.kubernetes.model.SchemaFactory.schema;

/**
* Generates JSON Schema (draft 2019-09/2020-12) to validate Kubernetes CustomResourceDefinitions.
Expand Down Expand Up @@ -69,21 +68,21 @@ private void assembleBase(Model m, Writer w, MainInfo main, ElementInfo i) throw
collectDefinitions(m, main, i, schema);
collectProperties(m, main, i, schema);

w.append( writer.writeValueAsString(schema.json(JsonNodeFactory.instance.objectNode())));
w.append(writer.writeValueAsString(schema.json(JsonNodeFactory.instance.objectNode())));
}

private void collectAttributes(ElementInfo i, SchemaObject so) {
i.getAis().stream()
.filter(ai -> !ai.getXMLName().equals("id"))
.forEach(ai -> {
SchemaObject sop = object(ai.getXMLName());
sop.type(ai.getSchemaType(processingEnv.getTypeUtils()));
sop.required(ai.isRequired());
so.property(sop);
AbstractSchema<?> schema = SchemaFactory.from(ai.getSchemaType(processingEnv.getTypeUtils()));
schema.name(ai.getXMLName());
schema.required(ai.isRequired());
so.property(schema);
});
}

private void collectProperties(Model m, MainInfo main, ElementInfo i, AbstractSchema schema) {
private void collectProperties(Model m, MainInfo main, ElementInfo i, AbstractSchema<?> schema) {
if (schema instanceof SchemaObject sop) {
collectAttributes(i, sop);
collectTextContent(i, sop);
Expand Down Expand Up @@ -113,7 +112,7 @@ private void collectDefinitions(Model m, MainInfo main, ElementInfo i, Schema sc

for (Map.Entry<String, ElementInfo> entry : all.entrySet()) {
boolean noEnvelope = entry.getValue().getAnnotation().noEnvelope();
AbstractSchema as;
AbstractSchema<?> as;
if (noEnvelope) {
as = array(entry.getKey());
} else {
Expand All @@ -132,14 +131,14 @@ private void collectTextContent(ElementInfo i, SchemaObject so) {
so.property(string(i.getTci().getPropertyName()));
}

private void collectChildElements(Model m, MainInfo main, ElementInfo i, AbstractSchema so) {
private void collectChildElements(Model m, MainInfo main, ElementInfo i, AbstractSchema<?> so) {
for (ChildElementInfo cei : i.getChildElementSpecs()) {
boolean isList = cei.isList();

AbstractSchema parent2 = so;
AbstractSchema<?> parent2 = so;

if (isList) {
SchemaObject items = object("items").additionalProperties( cei.getAnnotation().allowForeign());
SchemaObject items = object("items").additionalProperties(cei.getAnnotation().allowForeign());

if (i.getAnnotation().noEnvelope()) {
if (so instanceof SchemaArray sa)
Expand Down Expand Up @@ -171,7 +170,7 @@ private void collectChildElements(Model m, MainInfo main, ElementInfo i, Abstrac
//sop.setRequired(cei.isRequired());
// TODO only one is required, not all
sop.ref("#/$defs/" + ei.getXSDTypeName(m));
((SchemaObject)parent2).property(sop);
((SchemaObject) parent2).property(sop);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,20 @@

import com.fasterxml.jackson.databind.node.*;

import java.util.*;

public abstract class AbstractSchema<T extends AbstractSchema<T>> implements ISchema {

protected static final JsonNodeFactory jnf = JsonNodeFactory.instance;

protected String name;
protected String type;
protected String description;
private List<String> enumValues;

protected boolean required = false;

public AbstractSchema() {
}
public AbstractSchema() {}

public AbstractSchema(String name) {
this.name = name;
Expand All @@ -29,6 +31,10 @@ public String getName() {
return name;
}

public List<String> getEnumValues() {
return enumValues;
}

public T description(String description) {
this.description = description;
return self();
Expand All @@ -53,6 +59,11 @@ public T type(String type) {
return self();
}

public T enumValues(List<String> enumValues) {
this.enumValues = enumValues;
return self();
}

public boolean isObject() {
return "object".equals(type);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.predic8.membrane.annot.generator.kubernetes.model;

public class BasicSchema extends AbstractSchema<BasicSchema> {

public BasicSchema(String name) {
super(name);
}

public BasicSchema() {
super();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@

public class SchemaArray extends AbstractSchema<SchemaArray> {

SchemaObject items;
AbstractSchema items;

SchemaArray(String name) {
super(name);
type(ARRAY);
}

public SchemaArray items(SchemaObject items) {
public SchemaArray items(AbstractSchema items) {
this.items = items;
return this;
}
Expand All @@ -26,4 +26,9 @@ public ObjectNode json(ObjectNode node) {
}
return node;
}

@Override
public boolean isObject() {
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,26 @@ public static SchemaObject object(String name) {
return new SchemaObject(name);
}

public static BasicSchema basic(String name) {
return new BasicSchema(name);
}

public static AbstractSchema from(String type) {
if ("object".equals(type)) {
return object();
}
if ("array".equals(type)) {
return array();
}
BasicSchema bs = new BasicSchema();
bs.type = type;
return bs;
}

public static SchemaArray array() {
return array(null);
}

public static SchemaArray array(String name) {
return new SchemaArray(name);
}
Expand Down
Loading