diff options
author | Jon Bratseth <bratseth@gmail.com> | 2021-11-10 12:53:31 +0100 |
---|---|---|
committer | Jon Bratseth <bratseth@gmail.com> | 2021-11-10 12:53:31 +0100 |
commit | 77a0e3bdc57cb1ea0a9e4c17da55197c95e18947 (patch) | |
tree | a1c8814aa56871d986f1ebdf2ed9a82d7228fd0b /config-model | |
parent | 4e36629576deded814f9aa59faa05808a37fd2f2 (diff) |
Support struct inheritance
Diffstat (limited to 'config-model')
7 files changed, 103 insertions, 45 deletions
diff --git a/config-model/src/main/java/com/yahoo/documentmodel/NewDocumentType.java b/config-model/src/main/java/com/yahoo/documentmodel/NewDocumentType.java index 08a0f8b9882..d98869e9dd3 100644 --- a/config-model/src/main/java/com/yahoo/documentmodel/NewDocumentType.java +++ b/config-model/src/main/java/com/yahoo/documentmodel/NewDocumentType.java @@ -368,9 +368,9 @@ public final class NewDocumentType extends StructuredDataType implements DataTyp @Override public String toString() { return name; } - public final String getName() { return name; } + public String getName() { return name; } - public final int getId() { return id; } + public int getId() { return id; } @Override public int hashCode() { return name.hashCode(); } diff --git a/config-model/src/main/java/com/yahoo/documentmodel/VespaDocumentType.java b/config-model/src/main/java/com/yahoo/documentmodel/VespaDocumentType.java index 4899029c4b0..b29e4704f62 100644 --- a/config-model/src/main/java/com/yahoo/documentmodel/VespaDocumentType.java +++ b/config-model/src/main/java/com/yahoo/documentmodel/VespaDocumentType.java @@ -16,7 +16,7 @@ public class VespaDocumentType { public static NewDocumentType INSTANCE = newInstance(); - public static DataTypeName NAME = new DataTypeName("document"); + public static final DataTypeName NAME = new DataTypeName("document"); private static NewDocumentType newInstance() { NewDocumentType vespa = new NewDocumentType(new NewDocumentType.Name(8, "document")); diff --git a/config-model/src/main/java/com/yahoo/searchdefinition/SDDocumentTypeOrderer.java b/config-model/src/main/java/com/yahoo/searchdefinition/SDDocumentTypeOrderer.java index 8a6f16586d2..aa43c00f461 100644 --- a/config-model/src/main/java/com/yahoo/searchdefinition/SDDocumentTypeOrderer.java +++ b/config-model/src/main/java/com/yahoo/searchdefinition/SDDocumentTypeOrderer.java @@ -4,6 +4,7 @@ package com.yahoo.searchdefinition; import com.yahoo.config.application.api.DeployLogger; import com.yahoo.document.*; import com.yahoo.document.annotation.AnnotationReferenceDataType; +import com.yahoo.documentmodel.NewDocumentType; import com.yahoo.searchdefinition.document.SDDocumentType; import com.yahoo.searchdefinition.document.TemporarySDDocumentType; @@ -15,10 +16,10 @@ import java.util.logging.Level; */ public class SDDocumentTypeOrderer { - private Map<DataTypeName, SDDocumentType> createdSDTypes = new LinkedHashMap<>(); - private Set<Integer> seenTypes = new LinkedHashSet<>(); + private final Map<DataTypeName, SDDocumentType> createdSDTypes = new LinkedHashMap<>(); + private final Set<Integer> seenTypes = new LinkedHashSet<>(); List<SDDocumentType> processingOrder = new LinkedList<>(); - private DeployLogger deployLogger; + private final DeployLogger deployLogger; public SDDocumentTypeOrderer(List<SDDocumentType> sdTypes, DeployLogger deployLogger) { this.deployLogger = deployLogger; @@ -36,28 +37,12 @@ public class SDDocumentTypeOrderer { public void process() { for (SDDocumentType type : createdSDTypes.values()) { - process(type); + process(type, type); } } - private void process(SDDocumentType type) { - List<DataTypeName> toReplace = new ArrayList<>(); - for (SDDocumentType sdoc : type.getInheritedTypes()) { - if (sdoc instanceof TemporarySDDocumentType) { - toReplace.add(sdoc.getDocumentName()); - } - } - for (DataTypeName name : toReplace) { - SDDocumentType inherited = createdSDTypes.get(name); - if (inherited == null) { - throw new IllegalStateException("Document type '" + name + "' not found."); - } - process(inherited); - type.inherit(inherited); - } - visit(type); - } - private void visit(SDDocumentType docOrStruct) { + private void process(SDDocumentType docOrStruct, SDDocumentType owningDocument) { + resolveAndProcessInheritedTemporaryTypes(docOrStruct, owningDocument); int id; if (docOrStruct.isStruct()) { id = new StructDataType(docOrStruct.getName()).getId(); @@ -71,16 +56,38 @@ public class SDDocumentTypeOrderer { seenTypes.add((new StructDataType(docOrStruct.getName()).getId())); } - for (Field field : docOrStruct.fieldSet()) { if (!seenTypes.contains(field.getDataType().getId())) { //we haven't seen this before, do it - visit(field.getDataType()); + visit(field.getDataType(), owningDocument); } } processingOrder.add(docOrStruct); } + private void resolveAndProcessInheritedTemporaryTypes(SDDocumentType type, SDDocumentType owningDocument) { + List<DataTypeName> toReplace = new ArrayList<>(); + for (SDDocumentType sdoc : type.getInheritedTypes()) { + if (sdoc instanceof TemporarySDDocumentType) { + toReplace.add(sdoc.getDocumentName()); + } + } + for (DataTypeName name : toReplace) { + SDDocumentType inherited; + if (type.isStruct()) { + inherited = owningDocument.allTypes().get(new NewDocumentType.Name(name.getName())); + if (inherited == null) throw new IllegalStateException("Struct '" + name + "' not found in " + owningDocument); + process(inherited, owningDocument); + } + else { + inherited = createdSDTypes.get(name); + if (inherited == null) throw new IllegalStateException("Document type '" + name + "' not found"); + process(inherited, inherited); + } + type.inherit(inherited); + } + } + private SDDocumentType find(String name) { SDDocumentType sdDocType = createdSDTypes.get(new DataTypeName(name)); if (sdDocType != null) { @@ -95,27 +102,28 @@ public class SDDocumentTypeOrderer { } return null; } - private void visit(DataType type) { + + private void visit(DataType type, SDDocumentType owningDocument) { if (type instanceof StructuredDataType) { StructuredDataType structType = (StructuredDataType) type; SDDocumentType sdDocType = find(structType.getName()); if (sdDocType == null) { - throw new IllegalArgumentException("Could not find struct '" + type.getName() + "'."); + throw new IllegalArgumentException("Could not find struct '" + type.getName() + "'"); } - visit(sdDocType); + process(sdDocType, owningDocument); return; } if (type instanceof MapDataType) { MapDataType mType = (MapDataType) type; - visit(mType.getValueType()); - visit(mType.getKeyType()); + visit(mType.getValueType(), owningDocument); + visit(mType.getKeyType(), owningDocument); } else if (type instanceof WeightedSetDataType) { WeightedSetDataType wType = (WeightedSetDataType) type; - visit(wType.getNestedType()); + visit(wType.getNestedType(), owningDocument); } else if (type instanceof CollectionDataType) { CollectionDataType cType = (CollectionDataType) type; - visit(cType.getNestedType()); + visit(cType.getNestedType(), owningDocument); } else if (type instanceof AnnotationReferenceDataType) { //do nothing } else if (type instanceof PrimitiveDataType) { @@ -128,4 +136,5 @@ public class SDDocumentTypeOrderer { deployLogger.logApplicationPackage(Level.WARNING, "Unknown type : " + type); } } + } diff --git a/config-model/src/main/java/com/yahoo/searchdefinition/document/SDDocumentType.java b/config-model/src/main/java/com/yahoo/searchdefinition/document/SDDocumentType.java index 6424db1c2dd..de9a39ea75d 100644 --- a/config-model/src/main/java/com/yahoo/searchdefinition/document/SDDocumentType.java +++ b/config-model/src/main/java/com/yahoo/searchdefinition/document/SDDocumentType.java @@ -127,6 +127,14 @@ public class SDDocumentType implements Cloneable, Serializable { return list; } + public Map<NewDocumentType.Name, SDDocumentType> allTypes() { + Map<NewDocumentType.Name, SDDocumentType> map = new LinkedHashMap<>(); + for (SDDocumentType inherited : inheritedTypes.values()) + map.putAll(inherited.allTypes()); + map.putAll(ownedTypes); + return map; + } + /** * Creates a new document type. * The document type id will be generated as a hash from the document type name. @@ -145,10 +153,9 @@ public class SDDocumentType implements Cloneable, Serializable { * Creates a new document type. * The document type id will be generated as a hash from the document type name. * - * @param name The name of the new document type + * @param name the name of the new document type * @param schema check for type ID collisions in this search definition */ - @SuppressWarnings("deprecation") public SDDocumentType(String name, Schema schema) { docType = new DocumentType(name); docType.contentStruct().setCompressionConfig(new CompressionConfig()); @@ -161,7 +168,7 @@ public class SDDocumentType implements Cloneable, Serializable { public SDDocumentType setStruct(DataType structType) { if (structType != null) { this.structType = structType; - inheritedTypes.clear(); + inheritedTypes.remove(VESPA_DOCUMENT.getDocumentName()); } else { if (docType.contentStruct() != null) { this.structType = docType.contentStruct(); @@ -200,7 +207,7 @@ public class SDDocumentType implements Cloneable, Serializable { if (schema.getDocument(getName()) == null) return; SDDocumentType doc = schema.getDocument(); throw new IllegalArgumentException("Failed creating document type '" + getName() + "', " + - "document type '" + doc.getName() + "' already uses ID '" + doc.getName() + "'"); + "document type '" + doc.getName() + "' already uses ID '" + doc.getName() + "'"); } public void setFieldId(SDField field, int id) { @@ -293,6 +300,8 @@ public class SDDocumentType implements Cloneable, Serializable { return fieldSet().iterator(); } + /** Returns the number of fields in this only, not including inherited fields */ + // TODO: Remove public int getFieldCount() { return docType.getFieldCount(); } diff --git a/config-model/src/main/javacc/SDParser.jj b/config-model/src/main/javacc/SDParser.jj index 07171dea803..d2894442ab9 100644 --- a/config-model/src/main/javacc/SDParser.jj +++ b/config-model/src/main/javacc/SDParser.jj @@ -840,14 +840,13 @@ void structOutside(Schema schema) : SDDocumentType structDefinition(Schema schema, SDDocumentType repo) : { String name; + String inherited = null; SDDocumentType struct; } { - <STRUCT> name = identifier() - { - struct = new SDDocumentType(name, schema); - } - lbrace() (structFieldDefinition(struct) (<NL>)*)* <RBRACE> + ( <STRUCT> name = identifier() (<NL>)* { struct = new SDDocumentType(name, schema); } + [ inheritsDocument(struct) (<NL>)* ] + lbrace() (structFieldDefinition(struct) (<NL>)*)* <RBRACE> ) { try { docMan.getDataType(name); diff --git a/config-model/src/test/java/com/yahoo/document/test/SDDocumentTypeTestCase.java b/config-model/src/test/java/com/yahoo/document/test/SDDocumentTypeTestCase.java index 4714f4396dd..f1bebdb0a29 100644 --- a/config-model/src/test/java/com/yahoo/document/test/SDDocumentTypeTestCase.java +++ b/config-model/src/test/java/com/yahoo/document/test/SDDocumentTypeTestCase.java @@ -5,12 +5,18 @@ import com.yahoo.document.DataType; import com.yahoo.document.DataTypeName; import com.yahoo.documentmodel.VespaDocumentType; import com.yahoo.searchdefinition.AbstractSchemaTestCase; +import com.yahoo.searchdefinition.SchemaBuilder; import com.yahoo.searchdefinition.document.SDDocumentType; import com.yahoo.searchdefinition.document.SDField; +import com.yahoo.searchdefinition.parser.ParseException; +import com.yahoo.searchdefinition.processing.ImportedFieldsResolver; +import com.yahoo.searchdefinition.processing.OnnxModelTypeResolver; +import com.yahoo.vespa.model.test.utils.DeployLoggerStub; import org.junit.Test; import java.util.Iterator; +import static com.yahoo.config.model.test.TestUtil.joinLines; import static org.junit.Assert.*; /** @@ -95,8 +101,43 @@ public class SDDocumentTypeTestCase extends AbstractSchemaTestCase { field = (SDField) fields.next(); assertEquals("childfield", field.getName()); + } - // TODO: Test uninheriting + @Test + public void testStructInheritance() throws ParseException { + String schemaLines = joinLines( + "schema test {" + + " document test {" + + " struct parent_struct {" + + " field parent_struct_field_1 type string {}" + + " }" + + " struct child_struct inherits parent_struct {" + + " field child_struct_field_1 type string {}" + + " }" + + " field child_array type array<child_struct> {" + + " indexing: summary\n" + + " struct-field child_struct_field_1 { indexing: attribute }" + + " struct-field parent_struct_field_1 { indexing: attribute }" + + " }" + + " }" + + "}"); + + SchemaBuilder builder = new SchemaBuilder(new DeployLoggerStub()); + builder.importString(schemaLines); + builder.build(true); + var application = builder.application(); + + SDDocumentType type = application.schemas().get("test").getDocument(); + + SDDocumentType parent_struct = type.getOwnedType("parent_struct"); + assertEquals(1, parent_struct.fieldSet().size()); + assertNotNull(parent_struct.getField("parent_struct_field_1")); + + SDDocumentType child_struct = type.getOwnedType("child_struct"); + assertTrue(child_struct.inheritedTypes().containsKey(parent_struct.getDocumentName())); + assertEquals(2, child_struct.fieldSet().size()); + assertNotNull(child_struct.getField("child_struct_field_1")); + assertNotNull(child_struct.getField("parent_struct_field_1")); } } diff --git a/config-model/src/test/java/com/yahoo/searchdefinition/derived/InheritanceTestCase.java b/config-model/src/test/java/com/yahoo/searchdefinition/derived/InheritanceTestCase.java index 97cfc48580d..79df1fc9501 100644 --- a/config-model/src/test/java/com/yahoo/searchdefinition/derived/InheritanceTestCase.java +++ b/config-model/src/test/java/com/yahoo/searchdefinition/derived/InheritanceTestCase.java @@ -50,7 +50,7 @@ public class InheritanceTestCase extends AbstractExportingTestCase { try { assertCorrectDeriving("inheritfromnull"); } catch (IllegalStateException e) { - assertEquals("Document type 'foo' not found.", e.getMessage()); + assertEquals("Document type 'foo' not found", e.getMessage()); } } |