summaryrefslogtreecommitdiffstats
path: root/container-search/src/main/java/com/yahoo/search/query/profile/BackedOverridableQueryProfile.java
blob: 8f22c6902c36057821cc54996eeb7efa190aa49a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.search.query.profile;

import com.yahoo.processing.request.CompoundName;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * A wrapper of a query profile where overrides to the values in the referenced
 * profile can be set.
 * This is used to allow configured overrides (in a particular referencing profile) of a referenced query profile.
 * Properties which are defined as not overridable in the type (if any) of the referenced query profile
 * cannot be set.
 *
 * @author bratseth
 */
public class BackedOverridableQueryProfile extends OverridableQueryProfile implements Cloneable {

    /** The backing read only query profile, or null if this is not backed */
    private final QueryProfile backingProfile;

    /**
     * Creates an overridable profile from the given backing profile. The backing profile will never be
     * written to.
     *
     * @param backingProfile the backing profile, which is assumed read only, never null
     */
    public BackedOverridableQueryProfile(QueryProfile backingProfile) {
        super(backingProfile.getOwner());
        setType(backingProfile.getType());
        this.backingProfile = backingProfile;
    }

    @Override
    public String getSource() { return backingProfile.getSource(); }

    @Override
    public synchronized void freeze() {
        super.freeze();
        backingProfile.freeze();
    }

    @Override
    protected Object localLookup(String localName, DimensionBinding dimensionBinding) {
        Object valueInThis = super.localLookup(localName, dimensionBinding);
        if (valueInThis != null) return valueInThis;
        return backingProfile.localLookup(localName, dimensionBinding.createFor(backingProfile.getDimensions()));
    }

    protected Boolean isLocalInstanceOverridable(String localName) {
        Boolean valueInThis = super.isLocalInstanceOverridable(localName);
        if (valueInThis != null) return valueInThis;
        return backingProfile.isLocalInstanceOverridable(localName);
    }

    @Override
    protected QueryProfile createSubProfile(String name, DimensionBinding dimensionBinding) {
        Object backing = backingProfile.lookup(new CompoundName(name),
                                               true,
                                               dimensionBinding.createFor(backingProfile.getDimensions()));
        if (backing instanceof QueryProfile)
            return new BackedOverridableQueryProfile((QueryProfile)backing);
        else
            return new OverridableQueryProfile(getOwner()); // Nothing is set in this branch, so nothing to override, but need override checking
    }

    /** Returns a clone of this which can be independently overridden, but which refers to the same backing profile */
    @Override
    public BackedOverridableQueryProfile clone() {
        return (BackedOverridableQueryProfile)super.clone();
    }

    /** Returns the query profile backing this */
    public QueryProfile getBacking() { return backingProfile; }

    @Override
    public void addInherited(QueryProfile inherited) {
        backingProfile.addInherited(inherited);
    }

    void addInheritedHere(QueryProfile inherited) {
        super.addInherited(inherited);
    }

    @Override
    protected void visitVariants(boolean allowContent, QueryProfileVisitor visitor, DimensionBinding dimensionBinding) {
        super.visitVariants(allowContent, visitor, dimensionBinding);
        if (visitor.isDone()) return;
        backingProfile.visitVariants(allowContent, visitor, dimensionBinding.createFor(backingProfile.getDimensions()));
    }

    @Override
    protected void visitInherited(boolean allowContent, QueryProfileVisitor visitor, DimensionBinding dimensionBinding, QueryProfile owner) {
        super.visitInherited(allowContent, visitor, dimensionBinding, owner);
        if (visitor.isDone()) return;
        backingProfile.visitInherited(allowContent, visitor, dimensionBinding.createFor(backingProfile.getDimensions()), owner);
    }

    /** Returns a value from the content of this: The value in this, or the value from the backing if not set in this */
    protected Object getContent(String localKey) {
        Object value = super.getContent(localKey);
        if (value != null) return value;
        return backingProfile.getContent(localKey);
    }

    /**
     * Returns all the content from this:
     * All the values in this, and all values in the backing where an overriding value is not set in this
     */
    @Override
    protected Map<String, Object> getContent() {
        Map<String,Object> thisContent = super.getContent();
        Map<String,Object> backingContent = backingProfile.getContent();
        if (thisContent.isEmpty()) return backingContent; // Shortcut
        if (backingContent.isEmpty()) return thisContent; // Shortcut
        Map<String, Object> content = new HashMap<>(backingContent);
        content.putAll(thisContent);
        return content;
    }

    @Override
    public String toString() {
        return "overridable wrapper of " + backingProfile;
    }

    @Override
    public boolean isExplicit() {
        return backingProfile.isExplicit();
    }

    @Override
    public List<String> getDimensions() {
        List<String> dimensions = super.getDimensions();
        if (dimensions != null) return dimensions;
        return backingProfile.getDimensions();
    }

}