~slub.team/goobi-indexserver/3.x

« back to all changes in this revision

Viewing changes to lucene/src/java/org/apache/lucene/search/WildcardTermEnum.java

  • Committer: Sebastian Meyer
  • Date: 2012-08-03 09:12:40 UTC
  • Revision ID: sebastian.meyer@slub-dresden.de-20120803091240-x6861b0vabq1xror
Remove Lucene and Solr source code and add patches instead
Fix Bug #985487: Auto-suggestion for the search interface

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
package org.apache.lucene.search;
2
 
 
3
 
/**
4
 
 * Licensed to the Apache Software Foundation (ASF) under one or more
5
 
 * contributor license agreements.  See the NOTICE file distributed with
6
 
 * this work for additional information regarding copyright ownership.
7
 
 * The ASF licenses this file to You under the Apache License, Version 2.0
8
 
 * (the "License"); you may not use this file except in compliance with
9
 
 * the License.  You may obtain a copy of the License at
10
 
 *
11
 
 *     http://www.apache.org/licenses/LICENSE-2.0
12
 
 *
13
 
 * Unless required by applicable law or agreed to in writing, software
14
 
 * distributed under the License is distributed on an "AS IS" BASIS,
15
 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
 
 * See the License for the specific language governing permissions and
17
 
 * limitations under the License.
18
 
 */
19
 
 
20
 
import java.io.IOException;
21
 
 
22
 
import org.apache.lucene.index.IndexReader;
23
 
import org.apache.lucene.index.Term;
24
 
 
25
 
/**
26
 
 * Subclass of FilteredTermEnum for enumerating all terms that match the
27
 
 * specified wildcard filter term.
28
 
 * <p>
29
 
 * Term enumerations are always ordered by Term.compareTo().  Each term in
30
 
 * the enumeration is greater than all that precede it.
31
 
 */
32
 
public class WildcardTermEnum extends FilteredTermEnum {
33
 
  final Term searchTerm;
34
 
  final String field;
35
 
  final String text;
36
 
  final String pre;
37
 
  final int preLen;
38
 
  boolean endEnum = false;
39
 
 
40
 
  /**
41
 
   * Creates a new <code>WildcardTermEnum</code>.
42
 
   * <p>
43
 
   * After calling the constructor the enumeration is already pointing to the first 
44
 
   * valid term if such a term exists.
45
 
   */
46
 
  public WildcardTermEnum(IndexReader reader, Term term) throws IOException {
47
 
    super();
48
 
    searchTerm = term;
49
 
    field = searchTerm.field();
50
 
    final String searchTermText = searchTerm.text();
51
 
 
52
 
    final int sidx = searchTermText.indexOf(WILDCARD_STRING);
53
 
    final int cidx = searchTermText.indexOf(WILDCARD_CHAR);
54
 
    int idx = sidx;
55
 
    if (idx == -1) {
56
 
      idx = cidx;
57
 
    }
58
 
    else if (cidx >= 0) {
59
 
      idx = Math.min(idx, cidx);
60
 
    }
61
 
    pre = idx != -1?searchTerm.text().substring(0,idx): "";
62
 
 
63
 
    preLen = pre.length();
64
 
    text = searchTermText.substring(preLen);
65
 
    setEnum(reader.terms(new Term(searchTerm.field(), pre)));
66
 
  }
67
 
 
68
 
  @Override
69
 
  protected final boolean termCompare(Term term) {
70
 
    if (field == term.field()) {
71
 
      String searchText = term.text();
72
 
      if (searchText.startsWith(pre)) {
73
 
        return wildcardEquals(text, 0, searchText, preLen);
74
 
      }
75
 
    }
76
 
    endEnum = true;
77
 
    return false;
78
 
  }
79
 
 
80
 
  @Override
81
 
  public float difference() {
82
 
    return 1.0f;
83
 
  }
84
 
 
85
 
  @Override
86
 
  public final boolean endEnum() {
87
 
    return endEnum;
88
 
  }
89
 
 
90
 
  /********************************************
91
 
   * String equality with support for wildcards
92
 
   ********************************************/
93
 
 
94
 
  public static final char WILDCARD_STRING = '*';
95
 
  public static final char WILDCARD_CHAR = '?';
96
 
 
97
 
  /**
98
 
   * Determines if a word matches a wildcard pattern.
99
 
   * <small>Work released by Granta Design Ltd after originally being done on
100
 
   * company time.</small>
101
 
   */
102
 
  public static final boolean wildcardEquals(String pattern, int patternIdx,
103
 
    String string, int stringIdx)
104
 
  {
105
 
    int p = patternIdx;
106
 
    
107
 
    for (int s = stringIdx; ; ++p, ++s)
108
 
      {
109
 
        // End of string yet?
110
 
        boolean sEnd = (s >= string.length());
111
 
        // End of pattern yet?
112
 
        boolean pEnd = (p >= pattern.length());
113
 
 
114
 
        // If we're looking at the end of the string...
115
 
        if (sEnd)
116
 
        {
117
 
          // Assume the only thing left on the pattern is/are wildcards
118
 
          boolean justWildcardsLeft = true;
119
 
 
120
 
          // Current wildcard position
121
 
          int wildcardSearchPos = p;
122
 
          // While we haven't found the end of the pattern,
123
 
          // and haven't encountered any non-wildcard characters
124
 
          while (wildcardSearchPos < pattern.length() && justWildcardsLeft)
125
 
          {
126
 
            // Check the character at the current position
127
 
            char wildchar = pattern.charAt(wildcardSearchPos);
128
 
            
129
 
            // If it's not a wildcard character, then there is more
130
 
            // pattern information after this/these wildcards.
131
 
            if (wildchar != WILDCARD_CHAR && wildchar != WILDCARD_STRING)
132
 
            {
133
 
              justWildcardsLeft = false;
134
 
            }
135
 
            else
136
 
            {
137
 
              // to prevent "cat" matches "ca??"
138
 
              if (wildchar == WILDCARD_CHAR) {
139
 
                return false;
140
 
              }
141
 
              
142
 
              // Look at the next character
143
 
              wildcardSearchPos++;
144
 
            }
145
 
          }
146
 
 
147
 
          // This was a prefix wildcard search, and we've matched, so
148
 
          // return true.
149
 
          if (justWildcardsLeft)
150
 
          {
151
 
            return true;
152
 
          }
153
 
        }
154
 
 
155
 
        // If we've gone past the end of the string, or the pattern,
156
 
        // return false.
157
 
        if (sEnd || pEnd)
158
 
        {
159
 
          break;
160
 
        }
161
 
 
162
 
        // Match a single character, so continue.
163
 
        if (pattern.charAt(p) == WILDCARD_CHAR)
164
 
        {
165
 
          continue;
166
 
        }
167
 
 
168
 
        //
169
 
        if (pattern.charAt(p) == WILDCARD_STRING)
170
 
        {
171
 
          // Look at the character beyond the '*' characters.
172
 
          while (p < pattern.length() && pattern.charAt(p) == WILDCARD_STRING)
173
 
            ++p;
174
 
          // Examine the string, starting at the last character.
175
 
          for (int i = string.length(); i >= s; --i)
176
 
          {
177
 
            if (wildcardEquals(pattern, p, string, i))
178
 
            {
179
 
              return true;
180
 
            }
181
 
          }
182
 
          break;
183
 
        }
184
 
        if (pattern.charAt(p) != string.charAt(s))
185
 
        {
186
 
          break;
187
 
        }
188
 
      }
189
 
      return false;
190
 
  }
191
 
}