aboutsummaryrefslogtreecommitdiffstats
path: root/document/src/main/java/com/yahoo/document/select/DocumentSelector.java
blob: 686a0cb8e4a56d6e09bd3c81a6fcc2e3f13705c2 (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
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.document.select;

import com.yahoo.document.DocumentOperation;
import com.yahoo.document.select.parser.ParseException;
import com.yahoo.document.select.parser.SelectInput;
import com.yahoo.document.select.parser.SelectParser;
import com.yahoo.document.select.parser.TokenMgrException;
import com.yahoo.document.select.rule.ExpressionNode;

/**
 * A document selector is a filter which accepts or rejects documents
 * based on their type and content. A document selector has a textual
 * representation which is called the
 * <a href="https://docs.vespa.ai/en/reference/document-select-language.html">document selection language</a>.
 *
 * Document selectors are multithread safe.
 *
 * @author bratseth
 */
public class DocumentSelector {

    private final ExpressionNode expression;

    /**
     * Creates a document selector from a Document Selection Language string
     *
     * @param selector the string to parse as a selector
     * @throws ParseException Thrown if the string could not be parsed
     */
    public DocumentSelector(String selector) throws ParseException {
        SelectInput input = new SelectInput(selector);
        try {
            SelectParser parser = new SelectParser(input);
            expression = parser.expression();
        } catch (TokenMgrException e) {
            ParseException t = new ParseException("Tokenization error parsing document selector '" + selector + "'");
            throw (ParseException)t.initCause(e);
        } catch (RuntimeException | ParseException e) {
            ParseException t = new ParseException("Exception parsing document selector '" + selector + "'");
            throw (ParseException)t.initCause(e instanceof ParseException ?
                                              new ParseException(input.formatException(e.getMessage())) : e);
        }
    }

    /**
     * Returns true if the document referenced by this document operation is accepted by this selector
     *
     * @param op a document operation
     * @return true if the document is accepted
     * @throws RuntimeException if the evaluation enters an illegal state
     */
    public Result accepts(DocumentOperation op) {
        return accepts(new Context(op));
    }

    /**
     * Returns true if the document referenced by this context is accepted by this selector
     *
     * @param context the context to match in
     * @return true if the document is accepted
     * @throws RuntimeException if the evaluation enters an illegal state
     */
    public Result accepts(Context context) {
        return Result.toResult(expression.evaluate(context));
    }

    /**
     * Returns the list of different variables resulting in a true state for this expression
     *
     * @param op the document to evaluate
     * @return true if the document is accepted
     * @throws RuntimeException if the evaluation enters an illegal state
     */
    public ResultList getMatchingResultList(DocumentOperation op) {
        return getMatchingResultList(new Context(op));
    }

    /**
     * Returns the list of different variables resulting in a true state for this expression
     *
     * @param context the context to match in
     * @return true if the document is accepted
     * @throws RuntimeException if the evaluation enters an illegal state
     */
    private ResultList getMatchingResultList(Context context) {
        return ResultList.toResultList(expression.evaluate(context));
    }

    /** Returns this selector as a Document Selection Language string */
    @Override
    public String toString() {
        return expression.toString();
    }

    /** Visits the expression tree */
    public void visit(Visitor visitor) {
        expression.accept(visitor);
    }

}