summaryrefslogtreecommitdiffstats
path: root/config-model/src/main/java/com/yahoo/searchdefinition/document/Matching.java
blob: e2c036c24448a4d678b7bd229f40bd9f1061a1a2 (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
153
154
155
156
157
158
159
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.searchdefinition.document;

import java.io.Serializable;

/**
 * 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 Type defaultType = Type.TEXT;

    public enum Type {
        TEXT("text"),
        WORD("word"),
        EXACT("exact"),
        GRAM("gram");
        private String name;
        Type(String name) { this.name = name; }
        public String getName() { return name; }
    }

    /** Which match algorithm is used by this matching setup */
    public enum Algorithm {
        NORMAL("normal"),
        PREFIX("prefix"),
        SUBSTRING("substring"),
        SUFFIX("suffix");
        private String name;
        Algorithm(String name) { this.name = name; }
        public String getName() { return name; }
    }

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

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

    private boolean typeUserSet = false;

    private boolean algorithmUserSet = false;

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

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

    private String exactMatchTerminator=null;

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

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

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

    public void setType(Type type) {
        this.type = type;
        typeUserSet = true;
    }

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

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

    public Algorithm getAlgorithm() { return algorithm; }

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

    public boolean isAlgorithmUserSet() { return algorithmUserSet; }

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

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

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

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

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

    /**
     * Merge data from another matching object
     */
    public void merge(Matching m) {
        if (m.isAlgorithmUserSet()) {
            this.setAlgorithm(m.getAlgorithm());
        }
        if (m.isTypeUserSet()) {
            this.setType(m.getType());
            if (m.getType()==Type.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;
    }

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

    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)) return false;

        Matching other=(Matching)o;
        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!=other.gramSize) return false;
        return true;
    }

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

}