diff options
author | Arne H Juul <arnej@yahooinc.com> | 2022-02-23 16:34:00 +0000 |
---|---|---|
committer | Arne H Juul <arnej@yahooinc.com> | 2022-02-24 07:45:39 +0000 |
commit | 5a9f23a256b8bc14df4992af97e99375c30c2117 (patch) | |
tree | e43e82eb5abb60cc2a789b2817b59323a81ddf52 /config-model/src/main | |
parent | b43b67d7730aa467e233c1071d8fb82ac0fd6068 (diff) |
flesh out some classes
* allow multiple "match" blocks
* wrap indexing op in a more useful manner
Diffstat (limited to 'config-model/src/main')
13 files changed, 539 insertions, 114 deletions
diff --git a/config-model/src/main/java/com/yahoo/searchdefinition/parser/ParsedDocument.java b/config-model/src/main/java/com/yahoo/searchdefinition/parser/ParsedDocument.java index 3de1959a977..0b11b3a63ee 100644 --- a/config-model/src/main/java/com/yahoo/searchdefinition/parser/ParsedDocument.java +++ b/config-model/src/main/java/com/yahoo/searchdefinition/parser/ParsedDocument.java @@ -1,8 +1,13 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.searchdefinition.parser; +import com.google.common.collect.ImmutableList; import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.Optional; /** * This class holds the extracted information after parsing a @@ -13,21 +18,38 @@ import java.util.List; public class ParsedDocument { private final String name; private final List<String> inherited = new ArrayList<>(); + private final Map<String, ParsedField> docFields = new HashMap<>(); + private final Map<String, ParsedStruct> docStructs = new HashMap<>(); + private final Map<String, ParsedAnnotation> docAnnotations = new HashMap<>(); - public ParsedDocument(String name) { + public ParsedDocument(String name) { this.name = name; } String name() { return name; } + List<String> getInherited() { return ImmutableList.copyOf(inherited); } + List<ParsedAnnotation> getAnnotations() { return ImmutableList.copyOf(docAnnotations.values()); } + List<ParsedField> getFields() { return ImmutableList.copyOf(docFields.values()); } + List<ParsedStruct> getStructs() { return ImmutableList.copyOf(docStructs.values()); } + void inherit(String other) { inherited.add(other); } - void addField(ParsedField field) {} - void addStruct(ParsedStruct type) {} - void addAnnotation(ParsedAnnotation type) {} + void addField(ParsedField field) { + String fieldName = field.name(); + if (docFields.containsKey(fieldName)) { + throw new IllegalArgumentException("document-summary "+this.name+" already has field "+fieldName); + } + docFields.put(fieldName, field); + } - /* - private final List<ParsedField> fields = new ArrayList<>(); - List<ParsedField> getFields() { return fields; } - */ + void addStruct(ParsedStruct struct) { + String sName = struct.name(); + if (docStructs.containsKey(sName)) { + throw new IllegalArgumentException("document "+this.name+" already has struct "+sName); + } + docStructs.put(sName, struct); + } + + void addAnnotation(ParsedAnnotation type) {} } diff --git a/config-model/src/main/java/com/yahoo/searchdefinition/parser/ParsedDocumentSummary.java b/config-model/src/main/java/com/yahoo/searchdefinition/parser/ParsedDocumentSummary.java index bc0408a5881..7b54cef51fb 100644 --- a/config-model/src/main/java/com/yahoo/searchdefinition/parser/ParsedDocumentSummary.java +++ b/config-model/src/main/java/com/yahoo/searchdefinition/parser/ParsedDocumentSummary.java @@ -1,8 +1,13 @@ package com.yahoo.searchdefinition.parser; +import com.google.common.collect.ImmutableList; import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.Optional; /** * This class holds the extracted information after parsing a @@ -12,15 +17,42 @@ import java.util.List; **/ class ParsedDocumentSummary { - public final String name; - final List<ParsedSummaryField> fields = new ArrayList<>(); + private final String name; + private boolean omitSummaryFeatures; + private boolean fromDisk; + private final List<String> inherited = new ArrayList<>(); + private final Map<String, ParsedSummaryField> fields = new HashMap<>(); ParsedDocumentSummary(String name) { this.name = name; } - void addField(ParsedSummaryField field) { fields.add(field); } - void setFromDisk(boolean value) {} - void setOmitSummaryFeatures(boolean value) {} - void inherit(String other) {} + String name() { return this.name; } + boolean getOmitSummaryFeatures() { return omitSummaryFeatures; } + boolean getFromDisk() { return fromDisk; } + List<ParsedSummaryField> getSummaryFields() { return ImmutableList.copyOf(fields.values()); } + List<String> getInherited() { return ImmutableList.copyOf(inherited); } + + void addField(ParsedSummaryField field) { + String fieldName = field.name(); + if (fields.containsKey(fieldName)) { + throw new IllegalArgumentException("document-summary "+this.name+" already has field "+fieldName); + } + fields.put(fieldName, field); + } + + void setFromDisk(boolean value) { + this.fromDisk = value; + } + + void setOmitSummaryFeatures(boolean value) { + this.omitSummaryFeatures = value; + } + + void inherit(String other) { + if (! inherited.isEmpty()) { + throw new IllegalArgumentException("double inherit: document-summary "+this.name); + } + inherited.add(other); + } } diff --git a/config-model/src/main/java/com/yahoo/searchdefinition/parser/ParsedField.java b/config-model/src/main/java/com/yahoo/searchdefinition/parser/ParsedField.java index 39b699afcd1..a2a8e895cfd 100644 --- a/config-model/src/main/java/com/yahoo/searchdefinition/parser/ParsedField.java +++ b/config-model/src/main/java/com/yahoo/searchdefinition/parser/ParsedField.java @@ -3,6 +3,14 @@ package com.yahoo.searchdefinition.parser; import com.yahoo.searchdefinition.document.Stemming; +import com.google.common.collect.ImmutableList; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + /** * This class holds the extracted information after parsing a "field" * block, using simple data structures as far as possible. Do not put @@ -13,6 +21,26 @@ class ParsedField { private final String name; private ParsedType type; + private boolean hasBolding = false; + private boolean isFilter = false; + private int overrideId = 0; + private boolean isLiteral = false; + private boolean isNormal = false; + private Integer weight; + private String normalizing; + private final ParsedMatchSettings matchInfo = new ParsedMatchSettings(); + private Optional<Stemming> stemming = Optional.empty(); + private Optional<ParsedIndexingOp> indexingOp = Optional.empty(); + private Optional<ParsedSorting> sortSettings = Optional.empty(); + + private final Map<String, ParsedAttribute> attributes = new HashMap<>(); + private final Map<String, ParsedIndex> fieldIndexes = new HashMap<>(); + private final Map<String, String> aliases = new HashMap<>(); + private final Map<String, String> rankTypes = new HashMap<>(); + private final Map<String, ParsedField> structFields = new HashMap<>(); + private final Map<String, ParsedSummaryField> summaryFields = new HashMap<>(); + private final List<DictionaryOption> dictionaryOptions = new ArrayList<>(); + private final List<String> queryCommands = new ArrayList<>(); ParsedField(String name, ParsedType type) { this.name = name; @@ -21,25 +49,87 @@ class ParsedField { String name() { return this.name; } ParsedType getType() { return this.type; } + boolean getBolding() { return this.hasBolding; } + boolean getFilter() { return this.isFilter; } + boolean hasIdOverride() { return overrideId != 0; } + int idOverride() { return overrideId; } + List<DictionaryOption> getDictionaryOptions() { return ImmutableList.copyOf(dictionaryOptions); } + List<ParsedIndex> getIndexes() { return ImmutableList.copyOf(fieldIndexes.values()); } + List<String> getAliases() { return ImmutableList.copyOf(aliases.keySet()); } + String lookupAliasedFrom(String alias) { return aliases.get(alias); } + ParsedMatchSettings matchSettings() { return this.matchInfo; } + + void addAlias(String from, String to) { + if (aliases.containsKey(to)) { + throw new IllegalArgumentException("field "+this.name+" already has alias "+to); + } + aliases.put(to, from); + } + + void addIndex(ParsedIndex index) { + String idxName = index.name(); + if (fieldIndexes.containsKey(idxName)) { + throw new IllegalArgumentException("field "+this.name+" already has index "+idxName); + } + fieldIndexes.put(idxName, index); + } + + void addRankType(String index, String rankType) { + rankTypes.put(index, rankType); + } + + void dictionary(DictionaryOption option) { + dictionaryOptions.add(option); + } + + void setBolding(boolean value) { this.hasBolding = value; } + void setFilter(boolean value) { this.isFilter = value; } + void setId(int id) { this.overrideId = id; } + void setLiteral(boolean value) { this.isLiteral = value; } + void setNormal(boolean value) { this.isNormal = value; } + void setNormalizing(String value) { this.normalizing = value; } + void setStemming(Stemming stemming) { this.stemming = Optional.of(stemming); } + void setWeight(int weight) { this.weight = weight; } - void addAlias(String from, String to) {} - void addIndex(ParsedIndex index) {} - void addRankType(String index, String rankType) {} - void dictionary(DictionaryOption option) {} - void setBolding(boolean value) {} - void setFilter(boolean value) {} - void setId(int id) {} - void setIndexingRewrite(boolean value) {} - void setLiteral(boolean value) {} - void setNormal(boolean value) {} - void setNormalizing(String value) {} - void setSorting(ParsedSorting sorting) {} - void setStemming(Stemming stemming) {} - void setWeight(int weight) {} - void addAttribute(ParsedAttribute attr) {} - void addIndexingOperation(Object indx) {} - void addMatchSettings(ParsedMatchSettings settings) {} - void addQueryCommand(String queryCommand) {} - void addStructField(ParsedField structField) {} - void addSummaryField(ParsedSummaryField summaryField) {} + void addAttribute(ParsedAttribute attribute) { + String attrName = attribute.name(); + if (attributes.containsKey(attrName)) { + throw new IllegalArgumentException("field "+this.name+" already has attribute "+attrName); + } + attributes.put(attrName, attribute); + } + + void setIndexingOperation(ParsedIndexingOp idxOp) { + if (indexingOp.isPresent()) { + throw new IllegalArgumentException("field "+this.name+" already has indexing"); + } + indexingOp = Optional.of(idxOp); + } + + void setSorting(ParsedSorting sorting) { + if (sortSettings.isPresent()) { + throw new IllegalArgumentException("field "+this.name+" already has sorting"); + } + this.sortSettings = Optional.of(sorting); + } + + void addQueryCommand(String command) { + queryCommands.add(command); + } + + void addStructField(ParsedField structField) { + String fieldName = structField.name(); + if (structFields.containsKey(fieldName)) { + throw new IllegalArgumentException("field "+this.name+" already has struct-field "+fieldName); + } + structFields.put(fieldName, structField); + } + + void addSummaryField(ParsedSummaryField summaryField) { + String fieldName = summaryField.name(); + if (summaryFields.containsKey(fieldName)) { + throw new IllegalArgumentException("field "+this.name+" already has summary field "+fieldName); + } + summaryFields.put(fieldName, summaryField); + } } diff --git a/config-model/src/main/java/com/yahoo/searchdefinition/parser/ParsedFieldSet.java b/config-model/src/main/java/com/yahoo/searchdefinition/parser/ParsedFieldSet.java index ca2734db5e8..0720955b1dd 100644 --- a/config-model/src/main/java/com/yahoo/searchdefinition/parser/ParsedFieldSet.java +++ b/config-model/src/main/java/com/yahoo/searchdefinition/parser/ParsedFieldSet.java @@ -1,7 +1,12 @@ package com.yahoo.searchdefinition.parser; +import com.google.common.collect.ImmutableList; import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.Optional; /** * This class holds the extracted information after parsing a "fieldset" @@ -11,14 +16,18 @@ import java.util.List; **/ class ParsedFieldSet { - public final String name; - final List<String> fields = new ArrayList<>(); + private final String name; + private final List<String> fields = new ArrayList<>(); + private final List<String> queryCommands = new ArrayList<>(); + private final ParsedMatchSettings matchInfo = new ParsedMatchSettings(); ParsedFieldSet(String name) { this.name = name; } + String name() { return this.name; } + ParsedMatchSettings matchSettings() { return this.matchInfo; } + void addField(String field) { fields.add(field); } - void addQueryCommand(String queryCommand) {} - void addMatchSettings(ParsedMatchSettings matchInfo) {} + void addQueryCommand(String command) { queryCommands.add(command); } } diff --git a/config-model/src/main/java/com/yahoo/searchdefinition/parser/ParsedIndex.java b/config-model/src/main/java/com/yahoo/searchdefinition/parser/ParsedIndex.java index d017718e467..a23d8bce63a 100644 --- a/config-model/src/main/java/com/yahoo/searchdefinition/parser/ParsedIndex.java +++ b/config-model/src/main/java/com/yahoo/searchdefinition/parser/ParsedIndex.java @@ -2,6 +2,14 @@ package com.yahoo.searchdefinition.parser; import com.yahoo.searchdefinition.document.HnswIndexParams; +import com.yahoo.searchdefinition.document.Stemming; + +import com.google.common.collect.ImmutableList; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; /** * This class holds the extracted information after parsing an "index" @@ -12,18 +20,66 @@ import com.yahoo.searchdefinition.document.HnswIndexParams; class ParsedIndex { private final String name; - + private boolean enableBm25 = false; + private boolean isPrefix = false; + private HnswIndexParams hnswParams; + private final List<String> aliases = new ArrayList<>(); + private Optional<Stemming> stemming = Optional.empty(); + private Integer arity; + private Long lowerBound; + private Long upperBound; + private Double densePLT; + ParsedIndex(String name) { this.name = name; } - void addAlias(String alias) {} - void setArity(int arity) {} - void setDensePostingListThreshold(double threshold) {} - void setEnableBm25(boolean value) {} - void setHnswIndexParams(HnswIndexParams params) {} - void setLowerBound(long bound) {} - void setPrefix(boolean value) {} - void setStemming(String stemming) {} - void setUpperBound(long bound) {} + String name() { return this.name; } + boolean getEnableBm25() { return this.enableBm25; } + boolean getPrefix() { return this.isPrefix; } + HnswIndexParams getHnswIndexParams() { return this.hnswParams; } + List<String> getAliases() { return ImmutableList.copyOf(aliases); } + boolean hasStemming() { return stemming.isPresent(); } + Stemming getStemming() { return stemming.get(); } + Integer getArity() { return this.arity; } + Long getLowerBound() { return this.lowerBound; } + Long getUpperBound() { return this.upperBound; } + Double getDensePostingListThreshold() { return this.densePLT; } + + + void addAlias(String alias) { + aliases.add(alias); + } + + void setArity(int arity) { + this.arity = arity; + } + + void setDensePostingListThreshold(double threshold) { + this.densePLT = threshold; + } + + void setEnableBm25(boolean value) { + this.enableBm25 = value; + } + + void setHnswIndexParams(HnswIndexParams params) { + this.hnswParams = params; + } + + void setLowerBound(long value) { + this.lowerBound = value; + } + + void setPrefix(boolean value) { + this.isPrefix = value; + } + + void setStemming(Stemming stemming) { + this.stemming = Optional.of(stemming); + } + + void setUpperBound(long value) { + this.upperBound = value; + } } diff --git a/config-model/src/main/java/com/yahoo/searchdefinition/parser/ParsedIndexingOp.java b/config-model/src/main/java/com/yahoo/searchdefinition/parser/ParsedIndexingOp.java new file mode 100644 index 00000000000..4178de904de --- /dev/null +++ b/config-model/src/main/java/com/yahoo/searchdefinition/parser/ParsedIndexingOp.java @@ -0,0 +1,37 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.searchdefinition.parser; + +import com.yahoo.vespa.indexinglanguage.ExpressionSearcher; +import com.yahoo.vespa.indexinglanguage.expressions.AttributeExpression; +import com.yahoo.vespa.indexinglanguage.expressions.Expression; +import com.yahoo.vespa.indexinglanguage.expressions.IndexExpression; +import com.yahoo.vespa.indexinglanguage.expressions.LowerCaseExpression; +import com.yahoo.vespa.indexinglanguage.expressions.ScriptExpression; +import com.yahoo.vespa.indexinglanguage.expressions.SummaryExpression; + +/** + * This class wraps an indexing script expression, with some helper + * methods for extracting information from it + * @author arnej27959 + **/ +class ParsedIndexingOp { + + private final ScriptExpression script; + + ParsedIndexingOp(ScriptExpression script) { + this.script = script; + } + + ScriptExpression script() { return this.script; } + + public boolean doesAttributing() { return containsExpression(AttributeExpression.class); } + public boolean doesIndexing() { return containsExpression(IndexExpression.class); } + public boolean doesLowerCasing() { return containsExpression(LowerCaseExpression.class); } + public boolean doesSummarying() { return containsExpression(SummaryExpression.class); } + + private <T extends Expression> boolean containsExpression(Class<T> searchFor) { + var searcher = new ExpressionSearcher<>(searchFor); + var expr = searcher.searchIn(script); + return (expr != null); + } +} diff --git a/config-model/src/main/java/com/yahoo/searchdefinition/parser/ParsedMatchSettings.java b/config-model/src/main/java/com/yahoo/searchdefinition/parser/ParsedMatchSettings.java index acc76853453..f497aed59ae 100644 --- a/config-model/src/main/java/com/yahoo/searchdefinition/parser/ParsedMatchSettings.java +++ b/config-model/src/main/java/com/yahoo/searchdefinition/parser/ParsedMatchSettings.java @@ -1,5 +1,7 @@ package com.yahoo.searchdefinition.parser; +import java.util.Optional; + /** * This class holds the extracted information after parsing a "match" * block, using simple data structures as far as possible. Do not put @@ -8,10 +10,25 @@ package com.yahoo.searchdefinition.parser; **/ public class ParsedMatchSettings { - void setType(MatchType type) {} - void setCase(MatchCase type) {} - void setAlgorithm(MatchAlgorithm type) {} - void setExactTerminator(String terminator) {} - void setGramSize(int size) {} - void setMaxLength(int size) {} + private Optional<MatchType> matchType = Optional.empty(); + private Optional<MatchCase> matchCase = Optional.empty(); + private Optional<MatchAlgorithm> matchAlgorithm = Optional.empty(); + private Optional<String> exactTerminator = Optional.empty(); + private Optional<Integer> gramSize = Optional.empty(); + private Optional<Integer> maxLength = Optional.empty(); + + Optional<MatchType> getMatchType() { return this.matchType; } + Optional<MatchCase> getMatchCase() { return this.matchCase; } + Optional<MatchAlgorithm> getMatchAlgorithm() { return this.matchAlgorithm; } + Optional<String> getExactTerminator() { return this.exactTerminator; } + Optional<Integer> getGramSize() { return this.gramSize; } + Optional<Integer> getMaxLength() { return this.maxLength; } + + // TODO - consider allowing each set only once: + void setType(MatchType value) { this.matchType = Optional.of(value); } + void setCase(MatchCase value) { this.matchCase = Optional.of(value); } + void setAlgorithm(MatchAlgorithm value) { this.matchAlgorithm = Optional.of(value); } + void setExactTerminator(String value) { this.exactTerminator = Optional.of(value); } + void setGramSize(int value) { this.gramSize = Optional.of(value); } + void setMaxLength(int value) { this.maxLength = Optional.of(value); } } diff --git a/config-model/src/main/java/com/yahoo/searchdefinition/parser/ParsedRankFunction.java b/config-model/src/main/java/com/yahoo/searchdefinition/parser/ParsedRankFunction.java index 9f843ca15a7..fd84681364b 100644 --- a/config-model/src/main/java/com/yahoo/searchdefinition/parser/ParsedRankFunction.java +++ b/config-model/src/main/java/com/yahoo/searchdefinition/parser/ParsedRankFunction.java @@ -1,6 +1,10 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.searchdefinition.parser; +import com.google.common.collect.ImmutableList; +import java.util.ArrayList; +import java.util.List; + /** * This class holds the extracted information after parsing a * "function" block in a rank-profile, using simple data structures as @@ -10,12 +14,31 @@ package com.yahoo.searchdefinition.parser; class ParsedRankFunction { private final String name; + private boolean inline; + private String expression; + private final List<String> parameters = new ArrayList<>(); ParsedRankFunction(String name) { this.name = name; } - void addParameter(String param) {} - void setInline(boolean inline) {} - void setExpression(String expr) {} + String name() { return this.name; } + boolean getInline() { return this.inline; } + String getExpression() { return this.expression; } + List<String> getParameters() { return ImmutableList.copyOf(parameters); } + + void addParameter(String param) { + if (parameters.contains(param)) { + throw new IllegalArgumentException("function "+this.name+" cannot have parameter "+param+" twice"); + } + parameters.add(param); + } + + void setInline(boolean value) { + this.inline = value; + } + + void setExpression(String value) { + this.expression = value; + } } diff --git a/config-model/src/main/java/com/yahoo/searchdefinition/parser/ParsedRankProfile.java b/config-model/src/main/java/com/yahoo/searchdefinition/parser/ParsedRankProfile.java index 16b7b507121..810965aedd8 100644 --- a/config-model/src/main/java/com/yahoo/searchdefinition/parser/ParsedRankProfile.java +++ b/config-model/src/main/java/com/yahoo/searchdefinition/parser/ParsedRankProfile.java @@ -7,6 +7,14 @@ import com.yahoo.searchlib.rankingexpression.FeatureList; import com.yahoo.searchlib.rankingexpression.evaluation.TensorValue; import com.yahoo.searchlib.rankingexpression.evaluation.Value; +import com.google.common.collect.ImmutableList; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + /** * This class holds the extracted information after parsing a * rank-profile block in a schema (.sd) file, using simple data diff --git a/config-model/src/main/java/com/yahoo/searchdefinition/parser/ParsedSchema.java b/config-model/src/main/java/com/yahoo/searchdefinition/parser/ParsedSchema.java index 1bfbb2a045c..463e7afd010 100644 --- a/config-model/src/main/java/com/yahoo/searchdefinition/parser/ParsedSchema.java +++ b/config-model/src/main/java/com/yahoo/searchdefinition/parser/ParsedSchema.java @@ -1,12 +1,17 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.searchdefinition.parser; + import com.yahoo.searchdefinition.OnnxModel; import com.yahoo.searchdefinition.RankingConstant; import com.yahoo.searchdefinition.document.Stemming; +import com.google.common.collect.ImmutableList; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.Optional; /** * This class holds the extracted information after parsing @@ -15,33 +20,143 @@ import java.util.List; * @author arnej27959 **/ public class ParsedSchema { + + public static class ImportedField { + public final String asFieldName; + public final String refFieldName; + public final String foreignFieldName; + public ImportedField(String asField, String refField, String foreignField) { + this.asFieldName = asField; + this.refFieldName = refField; + this.foreignFieldName = foreignField; + } + } + private final String name; + private boolean rawAsBase64 = false; // TODO Vespa 8 flip default + private Optional<ParsedDocument> myDocument = Optional.empty(); + private Optional<Stemming> defaultStemming = Optional.empty(); + private final List<ImportedField> importedFields = new ArrayList<>(); + private final List<OnnxModel> onnxModels = new ArrayList<>(); + private final List<RankingConstant> rankingConstants = new ArrayList<>(); private final List<String> inherited = new ArrayList<>(); + private final Map<String, ParsedAnnotation> extraAnnotations = new HashMap<>(); + private final Map<String, ParsedDocumentSummary> docSums = new HashMap<>(); + private final Map<String, ParsedField> extraFields = new HashMap<>(); + private final Map<String, ParsedFieldSet> fieldSets = new HashMap<>(); + private final Map<String, ParsedIndex> extraIndexes = new HashMap<>(); + private final Map<String, ParsedRankProfile> rankProfiles = new HashMap<>(); + private final Map<String, ParsedStruct> extraStructs = new HashMap<>(); public ParsedSchema(String name) { this.name = name; } String name() { return name; } + boolean getRawAsBase64() { return rawAsBase64; } + boolean hasDocument() { return myDocument.isPresent(); } + ParsedDocument getDocument() { return myDocument.get(); } + boolean hasStemming() { return defaultStemming.isPresent(); } + Stemming getStemming() { return defaultStemming.get(); } + List<ImportedField> getImportedFields() { return ImmutableList.copyOf(importedFields); } + List<OnnxModel> getOnnxModels() { return ImmutableList.copyOf(onnxModels); } + List<ParsedAnnotation> getAnnotations() { return ImmutableList.copyOf(extraAnnotations.values()); } + List<ParsedDocumentSummary> getDocumentSummaries() { return ImmutableList.copyOf(docSums.values()); } + List<ParsedField> getFields() { return ImmutableList.copyOf(extraFields.values()); } + List<ParsedFieldSet> getFieldSets() { return ImmutableList.copyOf(fieldSets.values()); } + List<ParsedIndex> getIndexes() { return ImmutableList.copyOf(extraIndexes.values()); } + List<ParsedRankProfile> getRankProfiles() { return ImmutableList.copyOf(rankProfiles.values()); } + List<ParsedStruct> getStructs() { return ImmutableList.copyOf(extraStructs.values()); } + List<RankingConstant> getRankingConstants() { return ImmutableList.copyOf(rankingConstants); } + List<String> getInherited() { return ImmutableList.copyOf(inherited); } + + void addAnnotation(ParsedAnnotation annotation) { + String annName = annotation.name(); + if (extraAnnotations.containsKey(annName)) { + throw new IllegalArgumentException("schema "+this.name+" already has annotation "+annName); + } + extraAnnotations.put(annName, annotation); + } + + void addDocument(ParsedDocument document) { + if (myDocument.isPresent()) { + throw new IllegalArgumentException("schema "+this.name+" already has "+myDocument.get().name() + + "cannot add document "+document.name()); + } + myDocument = Optional.of(document); + } + + void addDocumentSummary(ParsedDocumentSummary docsum) { + String dsName = docsum.name(); + if (docSums.containsKey(dsName)) { + throw new IllegalArgumentException("schema "+this.name+" already has document-summary "+dsName); + } + docSums.put(dsName, docsum); + } + + void addField(ParsedField field) { + String fieldName = field.name(); + if (extraFields.containsKey(fieldName)) { + throw new IllegalArgumentException("schema "+this.name+" already has field "+fieldName); + } + extraFields.put(fieldName, field); + } + + void addFieldSet(ParsedFieldSet fieldSet) { + String fsName = fieldSet.name(); + if (fieldSets.containsKey(fsName)) { + throw new IllegalArgumentException("schema "+this.name+" already has fieldset "+fsName); + } + fieldSets.put(fsName, fieldSet); + } + + void addImportedField(String asFieldName, String refFieldName, String foregnFieldName) { + importedFields.add(new ImportedField(asFieldName, refFieldName, foregnFieldName)); + } + + void addIndex(ParsedIndex index) { + String idxName = index.name(); + if (extraIndexes.containsKey(idxName)) { + throw new IllegalArgumentException("schema "+this.name+" already has index "+idxName); + } + extraIndexes.put(idxName, index); + } + + void addOnnxModel(OnnxModel model) { + onnxModels.add(model); + } + + void addRankProfile(ParsedRankProfile profile) { + String rpName = profile.name(); + if (rankProfiles.containsKey(rpName)) { + throw new IllegalArgumentException("schema "+this.name+" already has rank-profile "+rpName); + } + rankProfiles.put(rpName, profile); + } + + void addRankingConstant(RankingConstant constant) { + rankingConstants.add(constant); + } + + void addStruct(ParsedStruct struct) { + String sName = struct.name(); + if (extraStructs.containsKey(sName)) { + throw new IllegalArgumentException("schema "+this.name+" already has struct "+sName); + } + extraStructs.put(sName, struct); + } + + void enableRawAsBase64(boolean value) { + this.rawAsBase64 = value; + } - void addAnnotation(ParsedAnnotation annotation) {} - void addDocument(ParsedDocument document) {} - void addDocumentSummary(ParsedDocumentSummary docsum) {} - void addField(ParsedField field) {} - void addFieldSet(ParsedFieldSet fieldSet) {} - void addImportedField(String asFieldName, String refFieldName, String foregnFieldName) {} - void addIndex(ParsedIndex index) {} - void addOnnxModel(OnnxModel model) {} - void addRankProfile(ParsedRankProfile profile) {} - void addRankingConstant(RankingConstant constant) {} - void addStruct(ParsedStruct struct) {} - void enableRawAsBase64(boolean value) {} void inherit(String other) { inherited.add(other); } - void setStemming(Stemming value) {} - /* - private final List<ParsedField> fields = new ArrayList<>(); - List<ParsedField> getFields() { return fields; } - */ + void setStemming(Stemming value) { + if (defaultStemming.isPresent() && (defaultStemming.get() != value)) { + throw new IllegalArgumentException("schema " + this.name + " already has stemming " + + defaultStemming.get() + "cannot also set " + value); + } + defaultStemming = Optional.of(value); + } } - diff --git a/config-model/src/main/java/com/yahoo/searchdefinition/parser/ParsedStruct.java b/config-model/src/main/java/com/yahoo/searchdefinition/parser/ParsedStruct.java index b081e0505ee..239bc74d4d0 100644 --- a/config-model/src/main/java/com/yahoo/searchdefinition/parser/ParsedStruct.java +++ b/config-model/src/main/java/com/yahoo/searchdefinition/parser/ParsedStruct.java @@ -1,8 +1,11 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.searchdefinition.parser; +import com.google.common.collect.ImmutableList; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; /** * This class holds the extracted information after parsing a "struct" @@ -13,16 +16,24 @@ import java.util.List; public class ParsedStruct { private final String name; private final List<String> inherited = new ArrayList<>(); - private final List<ParsedField> fields = new ArrayList<>(); + private final Map<String, ParsedField> fields = new HashMap<>(); - public ParsedStruct(String name) { + public ParsedStruct(String name) { this.name = name; } - /* TODO make immutable */ - List<ParsedField> getFields() { return fields; } + String name() { return this.name; } + List<ParsedField> getFields() { return ImmutableList.copyOf(fields.values()); } + List<String> getInherited() { return ImmutableList.copyOf(inherited); } + + void addField(ParsedField field) { + String fieldName = field.name(); + if (fields.containsKey(fieldName)) { + throw new IllegalArgumentException("struct "+this.name+" already has field "+fieldName); + } + fields.put(fieldName, field); + } void inherit(String other) { inherited.add(other); } - void addField(ParsedField field) { fields.add(field); } } diff --git a/config-model/src/main/java/com/yahoo/searchdefinition/parser/ParsedSummaryField.java b/config-model/src/main/java/com/yahoo/searchdefinition/parser/ParsedSummaryField.java index d18a4906b86..bc95efae44f 100644 --- a/config-model/src/main/java/com/yahoo/searchdefinition/parser/ParsedSummaryField.java +++ b/config-model/src/main/java/com/yahoo/searchdefinition/parser/ParsedSummaryField.java @@ -1,8 +1,13 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.searchdefinition.parser; +import com.google.common.collect.ImmutableList; import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.Optional; /** * This class holds the extracted information after parsing a summary @@ -13,27 +18,33 @@ import java.util.List; **/ class ParsedSummaryField { - public final String name; - public final Object type; + private final String name; + private final ParsedType type; + private boolean isDyn = false; + private boolean isMEO = false; + private boolean isFull = false; + private boolean isBold = false; + private final List<String> sources = new ArrayList<>(); + private final List<String> destinations = new ArrayList<>(); ParsedSummaryField(String name) { this.name = name; this.type = null; } - ParsedSummaryField(String name, Object type) { + + ParsedSummaryField(String name, ParsedType type) { this.name = name; this.type = type; } - String getName() { return name; } - Object getType() { return type; } - - boolean isDyn = false; - boolean isMEO = false; - boolean isFull = false; - boolean isBold = false; - final List<String> sources = new ArrayList<>(); - final List<String> destinations = new ArrayList<>(); + String name() { return name; } + ParsedType type() { return type; } + List<String> getDestinations() { return ImmutableList.copyOf(destinations); } + List<String> getSources() { return ImmutableList.copyOf(sources); } + boolean getBolded() { return isBold; } + boolean getDynamic() { return isDyn; } + boolean getFull() { return isFull; } + boolean getMatchedElementsOnly() { return isMEO; } void addDestination(String dst) { destinations.add(dst); } void addSource(String src) { sources.add(src); } diff --git a/config-model/src/main/javacc/IntermediateParser.jj b/config-model/src/main/javacc/IntermediateParser.jj index 1c245fe910c..5f5cb22a6e0 100644 --- a/config-model/src/main/javacc/IntermediateParser.jj +++ b/config-model/src/main/javacc/IntermediateParser.jj @@ -33,6 +33,7 @@ import com.yahoo.searchdefinition.RankingConstant; import com.yahoo.searchdefinition.Schema; import com.yahoo.searchdefinition.document.HnswIndexParams; import com.yahoo.searchdefinition.document.Stemming; +import com.yahoo.searchdefinition.document.SDField; import com.yahoo.searchdefinition.fieldoperation.IndexingOperation; import com.yahoo.searchlib.rankingexpression.FeatureList; import com.yahoo.searchlib.rankingexpression.evaluation.TensorValue; @@ -652,10 +653,8 @@ void fieldSet(ParsedSchema schema) : (( ( <FIELDS><COLON> name = identifier() { fieldSet.addField(name); } ( <COMMA> name = identifier() { fieldSet.addField(name); } )* ) - | - ( <QUERYCOMMAND> <COLON> (queryCommand = identifierWithDash() | queryCommand = quotedString())) { fieldSet.addQueryCommand(queryCommand); } - | - ( matchInfo = matchSettings() ) { fieldSet.addMatchSettings(matchInfo); } + | ( <QUERYCOMMAND> <COLON> (queryCommand = identifierWithDash() | queryCommand = quotedString())) { fieldSet.addQueryCommand(queryCommand); } + | matchSettings(fieldSet.matchSettings()) ) (<NL>)* )+ <RBRACE> { @@ -854,7 +853,7 @@ void structFieldDefinition(ParsedStruct struct) : } field = new ParsedField(name, type); } - lbrace() (id(field) (<NL>)*)? (match(field) (<NL>)*)* <RBRACE> { + lbrace() (id(field) (<NL>)*)? (matchSettings(field.matchSettings()) (<NL>)*)* <RBRACE> { struct.addField(field); } } @@ -900,7 +899,7 @@ void fieldBody(ParsedField field) : { } indexInsideField(field) | indexing(field) | indexingRewrite(field) | - match(field) | + matchSettings(field.matchSettings()) | normalizing(field) | queryCommand(field) | rank(field) | @@ -923,7 +922,7 @@ void structFieldBody(ParsedField field) : { } ( summaryInField(field) | indexing(field) | attribute(field) | - match(field) | + matchSettings(field.matchSettings()) | queryCommand(field) | structField(field) | summaryTo(field) ) @@ -946,7 +945,14 @@ void indexing(ParsedField field) : { } */ void indexingOperation(ParsedField field, boolean multiLine) : { } { - { field.addIndexingOperation(newIndexingOperation(multiLine)); } + { + IndexingOperation oldOp = newIndexingOperation(multiLine); + // TODO conversion via SDField is very ugly + SDField tmpField = new SDField("temp", com.yahoo.document.DataType.STRING); + oldOp.apply(tmpField); + ParsedIndexingOp newOp = new ParsedIndexingOp(tmpField.getIndexingScript()); + field.setIndexingOperation(newOp); + } } /** @@ -1446,22 +1452,10 @@ void alias(ParsedField field) : } } -void match(ParsedField field) : -{ - ParsedMatchSettings matchInfo; -} -{ - matchInfo = matchSettings() { field.addMatchSettings(matchInfo); } -} - -ParsedMatchSettings matchSettings() : -{ - ParsedMatchSettings matchInfo = new ParsedMatchSettings(); -} +void matchSettings(ParsedMatchSettings matchInfo) : { } { <MATCH> ( (<COLON> matchType(matchInfo)) | (lbrace() (matchItem(matchInfo) (<NL>)*)* <RBRACE>) ) - { return matchInfo; } } void matchType(ParsedMatchSettings matchInfo) : { } @@ -1683,7 +1677,7 @@ void indexBody(ParsedIndex index) : { ( <PREFIX> { index.setPrefix(true); } | <ALIAS> <COLON> str = identifierWithDash() { index.addAlias(str); } - | <STEMMING> <COLON> str = identifierWithDash() { index.setStemming(str); } + | <STEMMING> <COLON> str = identifierWithDash() { index.setStemming(Stemming.get(str)); } | <ARITY> <COLON> arity = integer() { index.setArity(arity); } | <LOWERBOUND> <COLON> num = consumeLong() { index.setLowerBound(num); } | <UPPERBOUND> <COLON> num = consumeLong() { index.setUpperBound(num); } |