com.yahoo.vespa.model.container.search.DeclaredQueryProfileVariants Maven / Gradle / Ivy
// Copyright Vespa.ai. 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.OverridableQueryProfile;
import com.yahoo.search.query.profile.QueryProfile;
import com.yahoo.search.query.profile.QueryProfileVariants;
import java.util.*;
/**
* Represents a set of query profile variants (more or less) as they were declared -
* a helper to produce config, which is also using the "declared" representation
*
* @author bratseth
*/
public class DeclaredQueryProfileVariants {
private final Map variantQueryProfiles = new LinkedHashMap<>();
public DeclaredQueryProfileVariants(QueryProfile profile) {
// Recreates the declared view (settings per set of dimensions)
// from the runtime view (dimension-value pairs per variable)
// yes, this is a little backwards, but the complexity of two representations
// is contained right here...
// TODO: This has become unnecessary as the variants now retains the original structure
for (Map.Entry fieldValueEntry : profile.getVariants().getFieldValues().entrySet()) {
for (QueryProfileVariants.FieldValue fieldValue : fieldValueEntry.getValue().asList()) {
addVariant(fieldValueEntry.getKey(),
fieldValue.getValue(),
profile.getVariants().getVariant(fieldValue.getDimensionValues(), false).isOverridable(fieldValueEntry.getKey()),
fieldValue.getDimensionValues().getValues());
}
}
for (QueryProfileVariants.FieldValue fieldValue : profile.getVariants().getInherited().asList()) {
for (QueryProfile inherited : (List)fieldValue.getValue())
addVariantInherited(inherited,fieldValue.getDimensionValues().getValues());
}
dereferenceCompoundedVariants(profile, "");
}
private void addVariant(String name, Object value, Boolean overridable, String[] dimensionValues) {
String dimensionString = toCanonicalString(dimensionValues);
VariantQueryProfile variant = variantQueryProfiles.get(dimensionString);
if (variant == null) {
variant = new VariantQueryProfile(dimensionValues);
variantQueryProfiles.put(dimensionString, variant);
}
variant.getValues().put(name, value);
if (overridable != null)
variant.getOverriable().put(name, overridable);
}
private void addVariantInherited(QueryProfile inherited,String[] dimensionValues) {
String dimensionString = toCanonicalString(dimensionValues);
VariantQueryProfile variant = variantQueryProfiles.get(dimensionString);
if (variant == null) {
variant = new VariantQueryProfile(dimensionValues);
variantQueryProfiles.put(dimensionString, variant);
}
variant.inherit(inherited);
}
private void dereferenceCompoundedVariants(QueryProfile profile,String prefix) {
// A variant of a.b is represented as the value a pointing to an anonymous profile a
// having the variants
for (Map.Entry entry : profile.declaredContent().entrySet()) {
if ( ! (entry.getValue() instanceof QueryProfile)) continue;
QueryProfile subProfile = (QueryProfile)entry.getValue();
// Export if defined implicitly in this, or if this contains overrides
if (!subProfile.isExplicit() || subProfile instanceof OverridableQueryProfile) {
String entryPrefix = prefix + entry.getKey() + ".";
dereferenceCompoundedVariants(subProfile.getVariants(), entryPrefix);
dereferenceCompoundedVariants(subProfile, entryPrefix);
}
}
if (profile.getVariants() == null) return;
// We need to do the same dereferencing to overridables pointed to by variants of this
for (Map.Entry fieldValueEntry : profile.getVariants().getFieldValues().entrySet()) {
for (QueryProfileVariants.FieldValue fieldValue : fieldValueEntry.getValue().asList()) {
if ( ! (fieldValue.getValue() instanceof QueryProfile)) continue;
QueryProfile subProfile = (QueryProfile)fieldValue.getValue();
// Export if defined implicitly in this, or if this contains overrides
if (!subProfile.isExplicit() || subProfile instanceof OverridableQueryProfile) {
String entryPrefix = prefix + fieldValueEntry.getKey() + ".";
dereferenceCompoundedVariants(subProfile.getVariants(), entryPrefix);
dereferenceCompoundedVariants(subProfile, entryPrefix);
}
}
}
}
private void dereferenceCompoundedVariants(QueryProfileVariants profileVariants, String prefix) {
if (profileVariants == null) return;
for (Map.Entry fieldVariant : profileVariants.getFieldValues().entrySet()) {
for (QueryProfileVariants.FieldValue variantValue : fieldVariant.getValue().asList()) {
addVariant(prefix + fieldVariant.getKey(), variantValue.getValue(), null, variantValue.getDimensionValues().getValues());
}
}
}
public String toCanonicalString(String[] dimensionValues) {
StringBuilder b = new StringBuilder();
for (String dimensionValue : dimensionValues) {
if (dimensionValue != null)
b.append(dimensionValue);
else
b.append("*");
b.append(",");
}
b.deleteCharAt(b.length() - 1); // Remove last,
return b.toString();
}
public Map getVariantQueryProfiles() { return variantQueryProfiles; }
public static class VariantQueryProfile {
private final Map values = new LinkedHashMap<>();
private final Map overridable = new HashMap<>();
private final List inherited = new ArrayList<>();
private final String[] dimensionValues;
public VariantQueryProfile(String[] dimensionValues) {
this.dimensionValues = dimensionValues;
}
public String[] getDimensionValues() { return dimensionValues; }
public void inherit(QueryProfile inheritedProfile) {
inherited.add(inheritedProfile);
}
public List inherited() { return inherited; }
public Map getValues() { return values; }
public Map getOverriable() { return overridable; }
}
}