aboutsummaryrefslogtreecommitdiffstats
path: root/config-model/src/main/java/com/yahoo/schema/document/Matching.java
blob: 9d68553fa804f9dbcdb1162fd7b99ce7aae1519e (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
141
142
143
144
145
146
147
148
149
150
151
152
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.schema.document;

import com.yahoo.schema.processing.NGramMatch;

import java.io.Serializable;
import java.util.OptionalInt;

/**
 * Defines how a field should be matched.
 * Matching objects can be compared based on their content, but they are <i>not</i> immutable.
 *
 * @author bratseth
 */
public class Matching implements Cloneable, Serializable {

    public static final MatchType defaultType = MatchType.TEXT;

    private MatchType type = MatchType.TEXT;
    private Case casing = Case.UNCASED;

    /** The basic match algorithm */
    private MatchAlgorithm algorithm = MatchAlgorithm.NORMAL;

    private boolean typeUserSet = false;

    private boolean algorithmUserSet = false;

    /** The gram size is the n in n-gram, or empty if not set. Should only be set with gram matching. */
    private OptionalInt gramSize = OptionalInt.empty();

    /** Maximum number of characters to consider when searching in this field. Used for limiting resources, especially in streaming search. */
    private Integer maxLength;
    /** Maximum number of occurrences for each term */
    private Integer maxTermOccurrences;

    private String exactMatchTerminator = null;

    /** Creates a matching of type "text" */
    public Matching() {}

    public Matching(MatchType type) {
        this.type = type;
    }

    public MatchType getType() { return type; }
    public Case getCase() { return casing; }

    public Matching setType(MatchType type) {
        this.type = type;
        typeUserSet = true;
        return this;
    }

    public Matching setCase(Case casing) {
        this.casing = casing;
        return this;
    }

    public Integer maxLength() { return maxLength; }
    public Matching maxLength(int maxLength) { this.maxLength = maxLength; return this; }
    public Integer maxTermOccurrences() { return maxTermOccurrences; }
    public Matching maxTermOccurrences(int maxTermOccurrences) { this.maxTermOccurrences = maxTermOccurrences; return this; }
    public boolean isTypeUserSet() { return typeUserSet; }

    public MatchAlgorithm getAlgorithm() { return algorithm; }

    public void setAlgorithm(MatchAlgorithm algorithm) {
        this.algorithm = algorithm;
        algorithmUserSet = true;
    }

    public boolean isAlgorithmUserSet() { return algorithmUserSet; }

    public boolean isPrefix() { return algorithm == MatchAlgorithm.PREFIX; }

    public boolean isSubstring() { return algorithm == MatchAlgorithm.SUBSTRING; }

    public boolean isSuffix() { return algorithm == MatchAlgorithm.SUFFIX; }

    /** Returns the gram size, or empty if not set. Should only be set with gram matching. */
    public OptionalInt getGramSize() { return gramSize; }

    public void setGramSize(int gramSize) { this.gramSize = OptionalInt.of(gramSize); }

    /**
     * Merge data from another matching object
     */
    public void merge(Matching m) {
        if (m == null) return;
        if (m.isAlgorithmUserSet()) {
            this.setAlgorithm(m.getAlgorithm());
        }
        if (m.isTypeUserSet()) {
            this.setType(m.getType());
            if (m.getType() == MatchType.GRAM)
              gramSize = m.gramSize;
        }
        if (m.getExactMatchTerminator() != null) {
            this.setExactMatchTerminator(m.getExactMatchTerminator());
        }
    }

    /**
     * If exact matching is used, this returns the terminator string
     * which terminates an exact matched sequence in queries. If exact
     * matching is not used, or no terminator is set, this is null
     */
    public String getExactMatchTerminator() { return exactMatchTerminator; }

    /**
     * Sets the terminator string which terminates an exact matched
     * sequence in queries (used if type is EXACT).
     */
    public void setExactMatchTerminator(String exactMatchTerminator) {
        this.exactMatchTerminator = exactMatchTerminator;
    }

    @Override
    public String toString() {
        return type + " matching [" + (type == MatchType.GRAM ? "gram size " + gramSize.orElse(NGramMatch.DEFAULT_GRAM_SIZE) : "supports " + algorithm) +
               "], [exact-terminator " + exactMatchTerminator + "]";
    }

    @Override
    public Matching clone() {
        try {
            return (Matching)super.clone();
        }
        catch (CloneNotSupportedException e) {
            throw new RuntimeException("Programming error");
        }
    }

    @Override
    public boolean equals(Object o) {
        if (! (o instanceof Matching other)) return false;

        if ( ! other.type.equals(this.type)) return false;
        if ( ! other.algorithm.equals(this.algorithm)) return false;
        if ( this.exactMatchTerminator == null && other.exactMatchTerminator != null) return false;
        if ( this.exactMatchTerminator != null && ( ! this.exactMatchTerminator.equals(other.exactMatchTerminator)) )
            return false;
        if ( ! gramSize.equals(other.gramSize)) return false;
        return true;
    }

    @Override public int hashCode() {
        return java.util.Objects.hash(type, algorithm, exactMatchTerminator, gramSize);
    }

}