diff options
Diffstat (limited to 'config-model/src/main')
6 files changed, 87 insertions, 49 deletions
diff --git a/config-model/src/main/java/com/yahoo/searchdefinition/Search.java b/config-model/src/main/java/com/yahoo/searchdefinition/Search.java index 7034a69bae4..415fcd1d34e 100644 --- a/config-model/src/main/java/com/yahoo/searchdefinition/Search.java +++ b/config-model/src/main/java/com/yahoo/searchdefinition/Search.java @@ -622,7 +622,7 @@ public class Search implements ImmutableSearch { @Override public String toString() { - return "search definition '" + getName() + "'"; + return "schema '" + getName() + "'"; } public boolean isAccessingDiskSummary(SummaryField field) { @@ -670,4 +670,9 @@ public class Search implements ImmutableSearch { return this; } + public void validate(DeployLogger logger) { + for (var summary : summaries.values()) + summary.validate(logger); + } + } diff --git a/config-model/src/main/java/com/yahoo/searchdefinition/SearchBuilder.java b/config-model/src/main/java/com/yahoo/searchdefinition/SearchBuilder.java index 78cc0d496b0..0f7ead43868 100644 --- a/config-model/src/main/java/com/yahoo/searchdefinition/SearchBuilder.java +++ b/config-model/src/main/java/com/yahoo/searchdefinition/SearchBuilder.java @@ -128,10 +128,10 @@ public class SearchBuilder { /** * Import search definition. * - * @param fileName The name of the file to import. - * @return The name of the imported object. - * @throws IOException Thrown if the file can not be read for some reason. - * @throws ParseException Thrown if the file does not contain a valid search definition. ``` + * @param fileName the name of the file to import + * @return the name of the imported object + * @throws IOException thrown if the file can not be read for some reason + * @throws ParseException thrown if the file does not contain a valid search definition */ public String importFile(String fileName) throws IOException, ParseException { File file = new File(fileName); @@ -146,10 +146,10 @@ public class SearchBuilder { * Reads and parses the search definition string provided by the given reader. Once all search definitions have been * imported, call {@link #build()}. * - * @param reader The reader whose content to import. - * @param searchDefDir The path to use when resolving file references. - * @return The name of the imported object. - * @throws ParseException Thrown if the file does not contain a valid search definition. + * @param reader the reader whose content to import + * @param searchDefDir the path to use when resolving file references + * @return the name of the imported object + * @throws ParseException thrown if the file does not contain a valid search definition */ public String importReader(NamedReader reader, String searchDefDir) throws IOException, ParseException { return importString(IOUtils.readAll(reader), searchDefDir); @@ -222,6 +222,9 @@ public class SearchBuilder { public void build(boolean validate) { if (isBuilt) throw new IllegalStateException("Model already built"); + if (validate) + searchList.forEach(search -> search.validate(deployLogger)); + List<Search> built = new ArrayList<>(); List<SDDocumentType> sdocs = new ArrayList<>(); sdocs.add(SDDocumentType.VESPA_DOCUMENT); @@ -230,6 +233,7 @@ public class SearchBuilder { sdocs.add(search.getDocument()); } } + var orderer = new SDDocumentTypeOrderer(sdocs, deployLogger); orderer.process(); for (SDDocumentType sdoc : orderer.getOrdered()) { @@ -255,7 +259,8 @@ public class SearchBuilder { builder.addToModel(searchList); if ( validate && ! builder.valid() ) - throw new IllegalArgumentException("Impossible to build a correct model."); + throw new IllegalArgumentException("Impossible to build a correct model"); + searchList = built; isBuilt = true; } @@ -332,6 +337,14 @@ public class SearchBuilder { return builder; } + public static SearchBuilder createFromStrings(DeployLogger logger, String ... schemas) throws ParseException { + SearchBuilder builder = new SearchBuilder(logger); + for (var schema : schemas) + builder.importString(schema); + builder.build(true); + return builder; + } + /** * Convenience factory method to import and build a {@link Search} object from a file. Only for testing. * 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 007a29c95b7..5d50abec8bb 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 @@ -38,9 +38,9 @@ import java.util.Set; public class SDDocumentType implements Cloneable, Serializable { public static final SDDocumentType VESPA_DOCUMENT; - private Map<DataTypeName, SDDocumentType> inheritedTypes = new HashMap<>(); - private Map<NewDocumentType.Name, SDDocumentType> ownedTypes = new HashMap<>(); - private AnnotationTypeRegistry annotationTypes = new AnnotationTypeRegistry(); + private final Map<DataTypeName, SDDocumentType> inheritedTypes = new HashMap<>(); + private final Map<NewDocumentType.Name, SDDocumentType> ownedTypes = new HashMap<>(); + private final AnnotationTypeRegistry annotationTypes = new AnnotationTypeRegistry(); private DocumentType docType; private DataType structType; // The field sets here are set from the processing step in SD, to ensure that the full Search and this SDDocumentType is built first. @@ -181,16 +181,16 @@ public class SDDocumentType implements Cloneable, Serializable { public DocumentType getDocumentType() { return docType; } public void inherit(DataTypeName name) { - if ( ! inheritedTypes.containsKey(name)) { - inheritedTypes.put(name, new TemporarySDDocumentType(name)); - } + inherit(new TemporarySDDocumentType(name)); } public void inherit(SDDocumentType type) { - if (type != null) { - if (!inheritedTypes.containsKey(type.getDocumentName()) || (inheritedTypes.get(type.getDocumentName()) instanceof TemporarySDDocumentType)) { - inheritedTypes.put(type.getDocumentName(), type); - } + if (type == null) return; + if (type.getName().equals(this.getName())) + throw new IllegalArgumentException("Document type '" + getName() + "' cannot inherit itself"); + if ( ! inheritedTypes.containsKey(type.getDocumentName()) || + (inheritedTypes.get(type.getDocumentName()) instanceof TemporarySDDocumentType)) { + inheritedTypes.put(type.getDocumentName(), type); } } @@ -208,10 +208,7 @@ public class SDDocumentType implements Cloneable, Serializable { field.setId(id, docType); } - /** Override getField, as it may need to ask inherited types that isn't registered in document type. - * @param name Name of field to get. - * @return The field found. - */ + /** Override getField, as it may need to ask inherited types that isn't registered in document type. */ public Field getField(String name) { if (name.contains(".")) { String superFieldName = name.substring(0,name.indexOf(".")); @@ -222,7 +219,7 @@ public class SDDocumentType implements Cloneable, Serializable { SDField superField = (SDField)f; return superField.getStructField(subFieldName); } else { - throw new IllegalArgumentException("Field "+f.getName()+" is not SDField"); + throw new IllegalArgumentException("Field " + f.getName() + " is not an SDField"); } } } @@ -246,18 +243,15 @@ public class SDDocumentType implements Cloneable, Serializable { docType.addField(field); } - /** - * This is SD parse-time inheritance check. - * - * @param field The field being verified. - */ + /** Parse-time inheritance check. */ private void verifyInheritance(Field field) { for (SDDocumentType parent : inheritedTypes.values()) { for (Field pField : parent.fieldSet()) { if (pField.getName().equals(field.getName())) { if (!pField.getDataType().equals(field.getDataType())) { - throw new IllegalArgumentException("For search '"+getName()+"', field '"+field.getName()+"': " + - "datatype can't be different from that of same field in supertype '"+parent.getName()+"'."); + throw new IllegalArgumentException("For search '" + getName() + "', field '" + field.getName() + + "': Datatype can not be different from that of same field " + + "in the supertype '" + parent.getName() + "'"); } } } @@ -304,6 +298,7 @@ public class SDDocumentType implements Cloneable, Serializable { return docType.getFieldCount(); } + @Override public String toString() { return "SD document type '" + docType.getName() + "'"; } @@ -342,4 +337,5 @@ public class SDDocumentType implements Cloneable, Serializable { public void setTemporaryImportedFields(TemporaryImportedFields temporaryImportedFields) { this.temporaryImportedFields = temporaryImportedFields; } + } diff --git a/config-model/src/main/java/com/yahoo/searchdefinition/processing/ImplicitSummaries.java b/config-model/src/main/java/com/yahoo/searchdefinition/processing/ImplicitSummaries.java index e05ca24cc77..edf9f744150 100644 --- a/config-model/src/main/java/com/yahoo/searchdefinition/processing/ImplicitSummaries.java +++ b/config-model/src/main/java/com/yahoo/searchdefinition/processing/ImplicitSummaries.java @@ -31,7 +31,7 @@ public class ImplicitSummaries extends Processor { public void process(boolean validate, boolean documentsOnly) { DocumentSummary defaultSummary = search.getSummary("default"); if (defaultSummary == null) { - defaultSummary = new DocumentSummary("default"); + defaultSummary = new DocumentSummary("default", search); defaultSummary.setFromDisk(true); search.addSummary(defaultSummary); } @@ -116,7 +116,7 @@ public class ImplicitSummaries extends Processor { private DocumentSummary getOrCreateAttributePrefetchSummary(Search search) { DocumentSummary summary = search.getSummary("attributeprefetch"); if (summary == null) { - summary = new DocumentSummary("attributeprefetch"); + summary = new DocumentSummary("attributeprefetch", search); search.addSummary(summary); } return summary; @@ -209,10 +209,10 @@ public class ImplicitSummaries extends Processor { } } - private void addToDestination(String destinationName, SummaryField summaryField,Search search) { + private void addToDestination(String destinationName, SummaryField summaryField, Search search) { DocumentSummary destination = search.getSummary(destinationName); if (destination == null) { - destination = new DocumentSummary(destinationName); + destination = new DocumentSummary(destinationName, search); search.addSummary(destination); destination.add(summaryField); } diff --git a/config-model/src/main/java/com/yahoo/vespa/documentmodel/DocumentSummary.java b/config-model/src/main/java/com/yahoo/vespa/documentmodel/DocumentSummary.java index f648e18dfda..23c1a48b6fe 100644 --- a/config-model/src/main/java/com/yahoo/vespa/documentmodel/DocumentSummary.java +++ b/config-model/src/main/java/com/yahoo/vespa/documentmodel/DocumentSummary.java @@ -1,10 +1,14 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.documentmodel; +import com.yahoo.config.application.api.DeployLogger; +import com.yahoo.searchdefinition.Search; + import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; +import java.util.logging.Level; /** * A document summary definition - a list of summary fields. @@ -15,15 +19,14 @@ public class DocumentSummary extends FieldView { private boolean fromDisk = false; private boolean omitSummaryFeatures = false; - private DocumentSummary inherited; + private String inherited; - /** - * Creates a DocumentSummary with the given name. - * - * @param name The name to use for this summary. - */ - public DocumentSummary(String name) { + private final Search owner; + + /** Creates a DocumentSummary with the given name. */ + public DocumentSummary(String name, Search owner) { super(name); + this.owner = owner; } public void setFromDisk(boolean fromDisk) { this.fromDisk = fromDisk; } @@ -44,7 +47,7 @@ public class DocumentSummary extends FieldView { * in different classes have the same summary transform, because this is * what is supported by the backend currently. * - * @param summaryField The summaryfield to add + * @param summaryField the summaryfield to add */ public void add(SummaryField summaryField) { summaryField.addDestination(getName()); @@ -97,18 +100,39 @@ public class DocumentSummary extends FieldView { } /** Sets the parent of this. Both summaries must be present in the same search definition */ - public void setInherited(DocumentSummary inherited) { + public void setInherited(String inherited) { this.inherited = inherited; } /** Returns the parent of this, or null if none is inherited */ public DocumentSummary getInherited() { + return owner.getSummary(inherited); + } + + /** Returns the name of the summary this was declared to inherit, or null if not sett to inherit anything */ + public String getInheritedName() { return inherited; } + @Override public String toString() { - return "document summary '" + getName() + "'" + - (inherited == null ? "" : " inheriting from '" + inherited.getName() + "'"); + return "document summary '" + getName() + "'"; + } + + public void validate(DeployLogger logger) { + if (inherited != null) { + if ( ! owner.getSummaries().containsKey(inherited)) { + logger.log(Level.WARNING, + this + " inherits " + inherited + " but this" + " is not present in " + owner); + logger.logApplicationPackage(Level.WARNING, + this + " inherits " + inherited + " but this" + " is not present in " + owner); + // TODO: When safe, replace the above by + // throw new IllegalArgumentException(this + " inherits " + inherited + " but this" + + // " is not present in " + owner); + // ... and update SummaryTestCase.testValidationOfInheritedSummary + } + } + } } diff --git a/config-model/src/main/javacc/SDParser.jj b/config-model/src/main/javacc/SDParser.jj index 11ebd7c8b3e..19bea494347 100644 --- a/config-model/src/main/javacc/SDParser.jj +++ b/config-model/src/main/javacc/SDParser.jj @@ -1776,7 +1776,7 @@ Object documentSummary(Search search) : } { ( <DOCUMENTSUMMARY> - name = identifierWithDash() { search.addSummary(summary = new DocumentSummary(name)); } + name = identifierWithDash() { search.addSummary(summary = new DocumentSummary(name, search)); } [inheritsDocumentSummary(summary, search)] lbrace() ( @@ -1803,7 +1803,7 @@ void inheritsDocumentSummary(DocumentSummary documentSummary, Search search) : { <INHERITS> name = identifierWithDash() { - documentSummary.setInherited(search.getSummaries().get(name)); + documentSummary.setInherited(name); } } |