aboutsummaryrefslogtreecommitdiffstats
path: root/container-search/src/main/java/com/yahoo/prelude/query/Highlight.java
blob: d0f75191dd7a4b6be3187224fb9329bb2eb93648 (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
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.prelude.query;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import static com.yahoo.language.LinguisticsCase.toLowerCase;

/**
 * Class encapsulating information on extra highlight-terms for a query
 *
 * @author Mathias Lidal
 */
public class Highlight implements Cloneable {

    /** The name of the property map which contains extra highlight terms */
    public static final String HIGHLIGHTTERMS = "highlightterms";

    private Map<String, AndItem> highlightItems = new LinkedHashMap<>();

    private Map<String, List<String>> highlightTerms = new LinkedHashMap<>();

    public Highlight() {}

    private void addHighlightItem(String key, Item value) {
        AndItem item = highlightItems.get(key);
        if (item == null) {
            item = new AndItem();
            highlightItems.put(key, item);
        }
        item.addItem(value);
    }

    /**
     * Add custom highlight term
     *
     * @param field the field name
     * @param item the term to be highlighted
     */
    public void addHighlightTerm(String field, String item) {
        addHighlightItem(field, new WordItem(toLowerCase(item), field, true));
    }

    /**
     * Add custom highlight phrase
     *
     * @param field the field name
     * @param phrase the list of terms to be highlighted as a phrase
     */
    public void addHighlightPhrase(String field, List<String> phrase) {
        PhraseItem pi = new PhraseItem();
        pi.setIndexName(field);
        for (String s : phrase)
            pi.addItem(new WordItem(toLowerCase(s), field, true));
        addHighlightItem(field, pi);
    }

    /** Returns the modifiable map of highlight items (never null) */
    public Map<String, AndItem> getHighlightItems() {
        return highlightItems;
    }

    @Override
    public Highlight clone() {
        try {
            Highlight clone = (Highlight) super.clone();

            clone.highlightItems = new LinkedHashMap<>();
            for (Map.Entry<String,AndItem> entry: highlightItems.entrySet()) {
                clone.highlightItems.put(entry.getKey(),(AndItem)entry.getValue().clone());
            }

            clone.highlightTerms = new LinkedHashMap<>();
            for (Map.Entry<String, List<String>> entry : highlightTerms.entrySet())
                clone.highlightTerms.put(entry.getKey(), new ArrayList<>(entry.getValue()));

            return clone;

        } catch (CloneNotSupportedException e) {
            throw new RuntimeException(e);
        }
    }

    public Map<String, List<String>> getHighlightTerms() { return highlightTerms; }

    /** Prepares this for binary serialization. For internal use - see {@link com.yahoo.search.Query#prepare} */
    public void prepare() {
        this.highlightTerms.clear();

        for (String index : getHighlightItems().keySet()) {
            AndItem root = getHighlightItems().get(index);
            List<WordItem> words = new ArrayList<>();
            List<CompositeItem> phrases = new ArrayList<>();
            for (Iterator<Item> i = root.getItemIterator(); i.hasNext(); ) {
                Item item = i.next();
                if (item instanceof WordItem) {
                    words.add((WordItem)item);
                } else if (item instanceof CompositeItem) {
                    phrases.add((CompositeItem)item);
                }
            }

            List<String> terms = new ArrayList<>();
            terms.add(String.valueOf(words.size() + phrases.size()));
            for (WordItem item : words) {
                terms.add(item.getWord());
            }

            for (CompositeItem item : phrases) {
                terms.add("\"");
                terms.add(String.valueOf(item.getItemCount()));
                for (Iterator<Item> i = item.getItemIterator(); i.hasNext(); ) {
                    terms.add(((IndexedItem)i.next()).getIndexedString());
                }
                terms.add("\"");
            }

            if (terms.size() > 1)
                this.highlightTerms.put(index, terms);
        }
    }

}