aboutsummaryrefslogtreecommitdiffstats
path: root/config-model/src/main/java/com/yahoo/vespa/model/container/search/QueryProfiles.java
diff options
context:
space:
mode:
authorJon Bratseth <bratseth@yahoo-inc.com>2016-06-15 23:09:44 +0200
committerJon Bratseth <bratseth@yahoo-inc.com>2016-06-15 23:09:44 +0200
commit72231250ed81e10d66bfe70701e64fa5fe50f712 (patch)
tree2728bba1131a6f6e5bdf95afec7d7ff9358dac50 /config-model/src/main/java/com/yahoo/vespa/model/container/search/QueryProfiles.java
Publish
Diffstat (limited to 'config-model/src/main/java/com/yahoo/vespa/model/container/search/QueryProfiles.java')
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/container/search/QueryProfiles.java276
1 files changed, 276 insertions, 0 deletions
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/search/QueryProfiles.java b/config-model/src/main/java/com/yahoo/vespa/model/container/search/QueryProfiles.java
new file mode 100644
index 00000000000..cc57a58ed47
--- /dev/null
+++ b/config-model/src/main/java/com/yahoo/vespa/model/container/search/QueryProfiles.java
@@ -0,0 +1,276 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.vespa.model.container.search;
+
+import com.yahoo.search.query.profile.BackedOverridableQueryProfile;
+import com.yahoo.search.query.profile.QueryProfile;
+import com.yahoo.search.query.profile.QueryProfileRegistry;
+import com.yahoo.search.query.profile.SubstituteString;
+import com.yahoo.search.query.profile.types.FieldDescription;
+import com.yahoo.search.query.profile.types.QueryProfileType;
+import com.yahoo.search.query.profile.config.QueryProfilesConfig;
+
+import java.io.Serializable;
+import java.util.*;
+import java.util.Map.Entry;
+
+/**
+ * Owns the query profiles and query profile types to be handed to the qrs nodes.
+ * Owned by a container cluster
+ *
+ * @author bratseth
+ */
+public class QueryProfiles implements Serializable, QueryProfilesConfig.Producer {
+
+ private QueryProfileRegistry registry;
+
+ /**
+ * Creates a new set of query profiles for which the config can be returned at request
+ *
+ * @param registry the registry containing the query profiles and types of this.
+ * The given registry cannot be frozen on calling this.
+ */
+ public QueryProfiles(QueryProfileRegistry registry) {
+ this.registry = registry;
+ }
+
+ public QueryProfiles() {
+ this.registry = new QueryProfileRegistry();
+ }
+
+ public QueryProfileRegistry getRegistry() {
+ return registry;
+ }
+
+ @Override
+ public void getConfig(QueryProfilesConfig.Builder builder) {
+ for (QueryProfile profile : registry.allComponents()) {
+ builder.queryprofile(createConfig(profile));
+ }
+ for (QueryProfileType profileType : registry.getTypeRegistry().allComponents()) {
+ if ( ! profileType.isBuiltin())
+ builder.queryprofiletype(createConfig(profileType));
+ }
+ }
+
+ private QueryProfilesConfig.Queryprofile.Builder createConfig(QueryProfile profile) {
+ QueryProfilesConfig.Queryprofile.Builder qB = new QueryProfilesConfig.Queryprofile.Builder();
+ qB.id(profile.getId().stringValue());
+ if (profile.getType() != null)
+ qB.type(profile.getType().getId().stringValue());
+ for (QueryProfile inherited : profile.inherited())
+ qB.inherit(inherited.getId().stringValue());
+
+ if (profile.getVariants()!=null) {
+ for (String dimension : profile.getVariants().getDimensions())
+ qB.dimensions(dimension);
+ }
+ addFieldChildren(qB, profile, "");
+ addVariants(qB, profile);
+ return qB;
+ }
+
+ private void addFieldChildren(QueryProfilesConfig.Queryprofile.Builder qpB, QueryProfile profile, String namePrefix) {
+ List<Map.Entry<String,Object>> content=new ArrayList<>(profile.declaredContent().entrySet());
+ Collections.sort(content,new MapEntryKeyComparator());
+ if (profile.getValue()!=null) { // Add "prefix with dot removed"=value:
+ QueryProfilesConfig.Queryprofile.Property.Builder propB = new QueryProfilesConfig.Queryprofile.Property.Builder();
+ String fullName = namePrefix.substring(0, namePrefix.length() - 1);
+ Object value = profile.getValue();
+ if (value instanceof SubstituteString)
+ value=value.toString(); // Send only types understood by configBuilder downwards
+ propB.name(fullName);
+ if (value!=null) propB.value(value.toString());
+ qpB.property(propB);
+ }
+ for (Map.Entry<String,Object> field : content) {
+ addField(qpB, profile, field, namePrefix);
+ }
+ }
+
+ private void addVariantFieldChildren(QueryProfilesConfig.Queryprofile.Queryprofilevariant.Builder qpB,
+ QueryProfile profile, String namePrefix) {
+ List<Map.Entry<String,Object>> content=new ArrayList<>(profile.declaredContent().entrySet());
+ Collections.sort(content,new MapEntryKeyComparator());
+ if (profile.getValue()!=null) { // Add "prefix with dot removed"=value:
+ QueryProfilesConfig.Queryprofile.Queryprofilevariant.Property.Builder propB = new QueryProfilesConfig.Queryprofile.Queryprofilevariant.Property.Builder();
+ String fullName = namePrefix.substring(0, namePrefix.length() - 1);
+ Object value = profile.getValue();
+ if (value instanceof SubstituteString)
+ value=value.toString(); // Send only types understood by configBuilder downwards
+ propB.name(fullName);
+ if (value!=null) propB.value(value.toString());
+ qpB.property(propB);
+ }
+ for (Map.Entry<String,Object> field : content) {
+ addVariantField(qpB, field, namePrefix);
+ }
+ }
+
+ private void addField(QueryProfilesConfig.Queryprofile.Builder qpB,
+ QueryProfile profile, Entry<String, Object> field, String namePrefix) {
+ String fullName=namePrefix + field.getKey();
+ if (field.getValue() instanceof QueryProfile) {
+ QueryProfile subProfile=(QueryProfile)field.getValue();
+ if ( ! subProfile.isExplicit()) { // Implicitly defined profile - add content
+ addFieldChildren(qpB, subProfile,fullName + ".");
+ }
+ else { // Reference to an id'ed profile - output reference plus any local overrides
+ QueryProfilesConfig.Queryprofile.Reference.Builder refB = new QueryProfilesConfig.Queryprofile.Reference.Builder();
+ createReferenceFieldConfig(refB, profile, fullName, field.getKey(), ((BackedOverridableQueryProfile) subProfile).getBacking().getId().stringValue());
+ qpB.reference(refB);
+ addFieldChildren(qpB, subProfile,fullName + ".");
+ }
+ }
+ else { // a primitive
+ qpB.property(createPropertyFieldConfig(profile, fullName, field.getKey(), field.getValue()));
+ }
+ }
+
+ private void addVariantField(QueryProfilesConfig.Queryprofile.Queryprofilevariant.Builder qpB,
+ Entry<String, Object> field, String namePrefix) {
+ String fullName=namePrefix + field.getKey();
+ if (field.getValue() instanceof QueryProfile) {
+ QueryProfile subProfile=(QueryProfile)field.getValue();
+ if ( ! subProfile.isExplicit()) { // Implicitly defined profile - add content
+ addVariantFieldChildren(qpB, subProfile,fullName + ".");
+ }
+ else { // Reference to an id'ed profile - output reference plus any local overrides
+ QueryProfilesConfig.Queryprofile.Queryprofilevariant.Reference.Builder refB = new QueryProfilesConfig.Queryprofile.Queryprofilevariant.Reference.Builder();
+ createVariantReferenceFieldConfig(refB, fullName, ((BackedOverridableQueryProfile) subProfile).getBacking().getId().stringValue());
+ qpB.reference(refB);
+ addVariantFieldChildren(qpB, subProfile,fullName + ".");
+ }
+ }
+ else { // a primitive
+ qpB.property(createVariantPropertyFieldConfig(fullName, field.getValue()));
+ }
+ }
+
+ private void addVariants(QueryProfilesConfig.Queryprofile.Builder qB, QueryProfile profile) {
+ if (profile.getVariants()==null) return;
+ DeclaredQueryProfileVariants declaredVariants=new DeclaredQueryProfileVariants(profile);
+ for (DeclaredQueryProfileVariants.VariantQueryProfile variant : declaredVariants.getVariantQueryProfiles().values()) {
+ QueryProfilesConfig.Queryprofile.Queryprofilevariant.Builder varB = new QueryProfilesConfig.Queryprofile.Queryprofilevariant.Builder();
+ for (String dimensionValue : variant.getDimensionValues()) {
+ if (dimensionValue==null)
+ dimensionValue="*";
+ varB.fordimensionvalues(dimensionValue);
+ }
+ for (QueryProfile inherited : variant.inherited())
+ varB.inherit(inherited.getId().stringValue());
+
+ List<Map.Entry<String,Object>> content=new ArrayList<>(variant.getValues().entrySet());
+ Collections.sort(content,new MapEntryKeyComparator());
+ for (Map.Entry<String,Object> value : content) {
+ addVariantField(varB, value,"");
+ }
+ qB.queryprofilevariant(varB);
+ }
+ }
+
+ private void createReferenceFieldConfig(QueryProfilesConfig.Queryprofile.Reference.Builder refB, QueryProfile profile,
+ String fullName, String localName, String stringValue) {
+ refB.name(fullName);
+ if (stringValue!=null) refB.value(stringValue);
+ Boolean overridable=null;
+ if (profile!=null)
+ overridable=profile.isDeclaredOverridable(localName, null);
+ if (overridable!=null)
+ refB.overridable(""+overridable);
+ }
+
+ private void createVariantReferenceFieldConfig(QueryProfilesConfig.Queryprofile.Queryprofilevariant.Reference.Builder refB,
+ String fullName, String stringValue) {
+ refB.name(fullName);
+ if (stringValue!=null) refB.value(stringValue);
+ }
+
+ private QueryProfilesConfig.Queryprofile.Property.Builder createPropertyFieldConfig(
+ QueryProfile profile, String fullName, String localName, Object value) {
+ QueryProfilesConfig.Queryprofile.Property.Builder propB = new QueryProfilesConfig.Queryprofile.Property.Builder();
+ Boolean overridable=null;
+ if (value instanceof SubstituteString)
+ value=value.toString(); // Send only types understood by configBuilder downwards
+ propB.name(fullName);
+ if (value!=null) propB.value(value.toString());
+ if (profile!=null)
+ overridable=profile.isDeclaredOverridable(localName, null);
+ if (overridable!=null)
+ propB.overridable(""+overridable);
+ return propB;
+ }
+
+ private QueryProfilesConfig.Queryprofile.Queryprofilevariant.Property.Builder createVariantPropertyFieldConfig(
+ String fullName, Object value) {
+ QueryProfilesConfig.Queryprofile.Queryprofilevariant.Property.Builder propB = new QueryProfilesConfig.Queryprofile.Queryprofilevariant.Property.Builder();
+ if (value instanceof SubstituteString)
+ value=value.toString(); // Send only types understood by configBuilder downwards
+ propB.name(fullName);
+ if (value!=null) propB.value(value.toString());
+ return propB;
+ }
+
+ private QueryProfilesConfig.Queryprofiletype.Builder createConfig(QueryProfileType profileType) {
+ QueryProfilesConfig.Queryprofiletype.Builder qtB = new QueryProfilesConfig.Queryprofiletype.Builder();
+ qtB.id(profileType.getId().stringValue());
+ if (profileType.isDeclaredStrict())
+ qtB.strict(true);
+ if (profileType.getDeclaredMatchAsPath())
+ qtB.matchaspath(true);
+ for (QueryProfileType inherited : profileType.inherited())
+ qtB.inherit(inherited.getId().stringValue());
+ List<FieldDescription> fields=new ArrayList<>(profileType.declaredFields().values());
+ Collections.sort(fields);
+ for (FieldDescription field : fields)
+ qtB.field(createConfig(field));
+ return qtB;
+ }
+
+ private QueryProfilesConfig.Queryprofiletype.Field.Builder createConfig(FieldDescription field) {
+ QueryProfilesConfig.Queryprofiletype.Field.Builder fB = new QueryProfilesConfig.Queryprofiletype.Field.Builder();
+ fB.
+ name(field.getName()).
+ type(field.getType().stringValue());
+ if ( ! field.isOverridable())
+ fB.overridable(false);
+ if (field.isMandatory())
+ fB.mandatory(true);
+ String aliases=toSpaceSeparatedString(field.getAliases());
+ if (!aliases.isEmpty())
+ fB.alias(aliases);
+ return fB;
+ }
+
+ public String toSpaceSeparatedString(List<String> list) {
+ StringBuilder b=new StringBuilder();
+ for (Iterator<String> i=list.iterator(); i.hasNext(); ) {
+ b.append(i.next());
+ if (i.hasNext())
+ b.append(" ");
+ }
+ return b.toString();
+ }
+
+ private static class MapEntryKeyComparator implements Comparator<Map.Entry<String,Object>> {
+
+ public int compare(Map.Entry<String,Object> e1,Map.Entry<String,Object> e2) {
+ return e1.getKey().compareTo(e2.getKey());
+ }
+
+ public boolean equals(Object other) {
+ return other instanceof MapEntryKeyComparator;
+ }
+
+ }
+
+ /**
+ * The config produced by this
+ * @return query profiles config
+ */
+ public QueryProfilesConfig getConfig() {
+ QueryProfilesConfig.Builder qB = new QueryProfilesConfig.Builder();
+ getConfig(qB);
+ return new QueryProfilesConfig(qB);
+ }
+
+}