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

import com.yahoo.prelude.semantics.rule.Condition;

/**
 * A choice point in an rule evaluation. A choicepoint is open if there are other choices to make at the point,
 * closed if there are no further choices. In addition it contains enough information to enable
 * the rule evaluation to backtrack to this point
 *
 * @author bratseth
 */
public class Choicepoint {

    /** Whether there are (or may be) open choices to explore at this choicepoint yet */
    private boolean open=true;

    /** The number of tries made at this choice point */
    private int tries=0;

    /** The condition creating this choicepoint */
    private Condition condition;

    /** The state this choice point can be rolled back to */
    private State state;

    private RuleEvaluation owner;

    public Choicepoint(RuleEvaluation e, Condition condition) {
        this.owner=e;
        state=new State(this,e);
        this.condition=condition;
        if (e.getTraceLevel()>=5)
            e.trace(5,"Added choice point at " + e.currentItem() + " for '" + condition + "'");
    }

    /** Returns the condition which created this choice point */
    public Condition getCondition() { return condition; }

    /** Returns wether there are (or may be) open choices to explore at this choicepoint yet */
    public boolean isOpen() { return open; }

    /** Marks this choice point as closed (!open) - there are no further choices to explore */
    public void close() { this.open=false; }

    /** Returns the number open tries made at this point */
    public int tryCount() { return tries; }

    /** Registers that another try has been made */
    public void addTry() {
        tries++;
    }

    /**
     * Backtrack to the evaluation state at the point where this choicepoint were instantiated.
     */
    public void backtrack() {
        state.backtrack(owner);
        if (owner.getTraceLevel()>=5)
            owner.trace(5,"Backtracked to " + owner.currentItem() + " for '" + condition + "'");
    }

    /** Backtracks the position only, not matches */
    public void backtrackPosition() {
        state.backtrackPosition(owner);
    }

    /**
     * Updates the state of this choice point to the current state of its evaluation
     */
    public void updateState() {
        state.updateState(owner);
    }

    /** Returns the state of this choice point */
    public State getState() { return state; }

    /** The state of this choicepoint */
    public final static class State {

        private int position=0;

        private int referencedMatchCount=0;

        private int nonreferencedMatchCount=0;

        public State(Choicepoint choicepoint,RuleEvaluation evaluation) {
            updateState(evaluation);
        }

        public void updateState(RuleEvaluation evaluation) {
            position=evaluation.currentPosition();
            referencedMatchCount=evaluation.getReferencedMatchCount();
            nonreferencedMatchCount=evaluation.getNonreferencedMatchCount();
        }

        /** Backtrack to the evaluation state at the point where this choicepoint were instantiated */
        public void backtrack(RuleEvaluation e) {
            backtrackPosition(e);

            // Is this check masking errors?
            if (e.referencedMatches().size()>referencedMatchCount)
                e.referencedMatches().subList(referencedMatchCount,
                        e.referencedMatches().size())
                        .clear();
            // Is this check masking errors?
            if (e.nonreferencedMatches().size()>nonreferencedMatchCount)
                e.nonreferencedMatches().subList(nonreferencedMatchCount,
                        e.nonreferencedMatches().size())
                        .clear();
        }

        public void backtrackPosition(RuleEvaluation e) {
            e.setPosition(position);
        }

        public int getPosition() { return position; }

        public int getReferencedMatchCount() { return referencedMatchCount; }

        public int getNonreferencedMatchCount() { return nonreferencedMatchCount; }

    }

}