aboutsummaryrefslogtreecommitdiffstats
path: root/config-model
diff options
context:
space:
mode:
authorArne H Juul <arnej@yahooinc.com>2022-03-16 07:03:54 +0000
committerArne H Juul <arnej@yahooinc.com>2022-03-16 09:29:51 +0000
commita043188e341fa5a8874288fe0ffcb75b39708a57 (patch)
tree8c36043b733323203330e34f756ba2fbee5e752a /config-model
parentcd7f364094c441c7e2656d0d5efde3bf09914c42 (diff)
pre-resolve struct and annotation inheritance
Diffstat (limited to 'config-model')
-rw-r--r--config-model/src/main/java/com/yahoo/searchdefinition/parser/ConvertSchemaCollection.java95
1 files changed, 95 insertions, 0 deletions
diff --git a/config-model/src/main/java/com/yahoo/searchdefinition/parser/ConvertSchemaCollection.java b/config-model/src/main/java/com/yahoo/searchdefinition/parser/ConvertSchemaCollection.java
index 8ee4a237258..79ad811bd2b 100644
--- a/config-model/src/main/java/com/yahoo/searchdefinition/parser/ConvertSchemaCollection.java
+++ b/config-model/src/main/java/com/yahoo/searchdefinition/parser/ConvertSchemaCollection.java
@@ -125,6 +125,9 @@ public class ConvertSchemaCollection {
}
public List<Schema> convertToSchemas() {
+ resolveStructInheritance();
+ resolveAnnotationInheritance();
+ addMissingAnnotationStructs();
var converter = new ConvertParsedSchemas(orderedInput,
docMan,
applicationPackage,
@@ -136,4 +139,96 @@ public class ConvertSchemaCollection {
return converter.convertToSchemas();
}
+ private void resolveStructInheritance() {
+ List<ParsedStruct> all = new ArrayList();
+ for (var schema : orderedInput) {
+ var doc = schema.getDocument();
+ for (var struct : doc.getStructs()) {
+ for (String inherit : struct.getInherited()) {
+ var parent = doc.findParsedStruct(inherit);
+ if (parent == null) {
+ throw new IllegalArgumentException("Can not find parent for "+struct+" in "+doc);
+ }
+ struct.resolveInherit(inherit, parent);
+ }
+ all.add(struct);
+ }
+ }
+ List<String> seen = new ArrayList<>();
+ for (ParsedStruct struct : all) {
+ inheritanceCycleCheck(struct, seen);
+ }
+ }
+
+ private void resolveAnnotationInheritance() {
+ List<ParsedAnnotation> all = new ArrayList();
+ for (var schema : orderedInput) {
+ var doc = schema.getDocument();
+ for (var annotation : doc.getAnnotations()) {
+ for (String inherit : annotation.getInherited()) {
+ var parent = doc.findParsedAnnotation(inherit);
+ if (parent == null) {
+ throw new IllegalArgumentException("Can not find parent for "+annotation+" in "+doc);
+ }
+ annotation.resolveInherit(inherit, parent);
+ }
+ all.add(annotation);
+ }
+ }
+ List<String> seen = new ArrayList<>();
+ for (ParsedAnnotation annotation : all) {
+ inheritanceCycleCheck(annotation, seen);
+ }
+ }
+
+ private void fixupAnnotationStruct(ParsedAnnotation parsed) {
+ for (var parent : parsed.getResolvedInherits()) {
+ fixupAnnotationStruct(parent);
+ parent.getStruct().ifPresent(ps -> {
+ var myStruct = parsed.ensureStruct();
+ if (! myStruct.getInherited().contains(ps.name())) {
+ myStruct.inherit(ps.name());
+ myStruct.resolveInherit(ps.name(), ps);
+ }
+ });
+ }
+ }
+
+ private void addMissingAnnotationStructs() {
+ for (var schema : orderedInput) {
+ var doc = schema.getDocument();
+ for (var annotation : doc.getAnnotations()) {
+ fixupAnnotationStruct(annotation);
+ }
+ }
+ }
+
+ private void inheritanceCycleCheck(ParsedStruct struct, List<String> seen) {
+ String name = struct.name();
+ if (seen.contains(name)) {
+ seen.add(name);
+ throw new IllegalArgumentException("Inheritance/reference cycle for structs: " +
+ String.join(" -> ", seen));
+ }
+ seen.add(name);
+ for (ParsedStruct parent : struct.getResolvedInherits()) {
+ inheritanceCycleCheck(parent, seen);
+ }
+ seen.remove(name);
+ }
+
+ private void inheritanceCycleCheck(ParsedAnnotation annotation, List<String> seen) {
+ String name = annotation.name();
+ if (seen.contains(name)) {
+ seen.add(name);
+ throw new IllegalArgumentException("Inheritance/reference cycle for annotations: " +
+ String.join(" -> ", seen));
+ }
+ seen.add(name);
+ for (ParsedAnnotation parent : annotation.getResolvedInherits()) {
+ inheritanceCycleCheck(parent, seen);
+ }
+ seen.remove(name);
+ }
+
}