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

« back to all changes in this revision

Viewing changes to lucene/src/java/org/apache/lucene/analysis/CharTokenizer.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.analysis;
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
 
import java.io.Reader;
22
 
 
23
 
import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;
24
 
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
25
 
import org.apache.lucene.util.AttributeSource;
26
 
import org.apache.lucene.util.CharacterUtils;
27
 
import org.apache.lucene.util.Version;
28
 
import org.apache.lucene.util.VirtualMethod;
29
 
import org.apache.lucene.util.CharacterUtils.CharacterBuffer;
30
 
 
31
 
/**
32
 
 * An abstract base class for simple, character-oriented tokenizers. 
33
 
 * <p>
34
 
 * <a name="version">You must specify the required {@link Version} compatibility
35
 
 * when creating {@link CharTokenizer}:
36
 
 * <ul>
37
 
 * <li>As of 3.1, {@link CharTokenizer} uses an int based API to normalize and
38
 
 * detect token codepoints. See {@link #isTokenChar(int)} and
39
 
 * {@link #normalize(int)} for details.</li>
40
 
 * </ul>
41
 
 * <p>
42
 
 * A new {@link CharTokenizer} API has been introduced with Lucene 3.1. This API
43
 
 * moved from UTF-16 code units to UTF-32 codepoints to eventually add support
44
 
 * for <a href=
45
 
 * "http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Character.html#supplementary"
46
 
 * >supplementary characters</a>. The old <i>char</i> based API has been
47
 
 * deprecated and should be replaced with the <i>int</i> based methods
48
 
 * {@link #isTokenChar(int)} and {@link #normalize(int)}.
49
 
 * </p>
50
 
 * <p>
51
 
 * As of Lucene 3.1 each {@link CharTokenizer} - constructor expects a
52
 
 * {@link Version} argument. Based on the given {@link Version} either the new
53
 
 * API or a backwards compatibility layer is used at runtime. For
54
 
 * {@link Version} < 3.1 the backwards compatibility layer ensures correct
55
 
 * behavior even for indexes build with previous versions of Lucene. If a
56
 
 * {@link Version} >= 3.1 is used {@link CharTokenizer} requires the new API to
57
 
 * be implemented by the instantiated class. Yet, the old <i>char</i> based API
58
 
 * is not required anymore even if backwards compatibility must be preserved.
59
 
 * {@link CharTokenizer} subclasses implementing the new API are fully backwards
60
 
 * compatible if instantiated with {@link Version} < 3.1.
61
 
 * </p>
62
 
 * <p>
63
 
 * <strong>Note:</strong> If you use a subclass of {@link CharTokenizer} with {@link Version} >=
64
 
 * 3.1 on an index build with a version < 3.1, created tokens might not be
65
 
 * compatible with the terms in your index.
66
 
 * </p>
67
 
 **/
68
 
public abstract class CharTokenizer extends Tokenizer {
69
 
  
70
 
  /**
71
 
   * Creates a new {@link CharTokenizer} instance
72
 
   * 
73
 
   * @param matchVersion
74
 
   *          Lucene version to match See {@link <a href="#version">above</a>}
75
 
   * @param input
76
 
   *          the input to split up into tokens
77
 
   */
78
 
  public CharTokenizer(Version matchVersion, Reader input) {
79
 
    super(input);
80
 
    charUtils = CharacterUtils.getInstance(matchVersion);
81
 
    useOldAPI = useOldAPI(matchVersion);
82
 
 
83
 
  }
84
 
  
85
 
  /**
86
 
   * Creates a new {@link CharTokenizer} instance
87
 
   * 
88
 
   * @param matchVersion
89
 
   *          Lucene version to match See {@link <a href="#version">above</a>}
90
 
   * @param source
91
 
   *          the attribute source to use for this {@link Tokenizer}
92
 
   * @param input
93
 
   *          the input to split up into tokens
94
 
   */
95
 
  public CharTokenizer(Version matchVersion, AttributeSource source,
96
 
      Reader input) {
97
 
    super(source, input);
98
 
    charUtils = CharacterUtils.getInstance(matchVersion);
99
 
    useOldAPI = useOldAPI(matchVersion);
100
 
  }
101
 
  
102
 
  /**
103
 
   * Creates a new {@link CharTokenizer} instance
104
 
   * 
105
 
   * @param matchVersion
106
 
   *          Lucene version to match See {@link <a href="#version">above</a>}
107
 
   * @param factory
108
 
   *          the attribute factory to use for this {@link Tokenizer}
109
 
   * @param input
110
 
   *          the input to split up into tokens
111
 
   */
112
 
  public CharTokenizer(Version matchVersion, AttributeFactory factory,
113
 
      Reader input) {
114
 
    super(factory, input);
115
 
    charUtils = CharacterUtils.getInstance(matchVersion);
116
 
    useOldAPI = useOldAPI(matchVersion);
117
 
  }
118
 
  
119
 
  /**
120
 
   * Creates a new {@link CharTokenizer} instance
121
 
   * @param input the input to split up into tokens
122
 
   * @deprecated use {@link #CharTokenizer(Version, Reader)} instead. This will be
123
 
   *             removed in Lucene 4.0.
124
 
   */
125
 
  @Deprecated
126
 
  public CharTokenizer(Reader input) {
127
 
    this(Version.LUCENE_30, input);
128
 
  }
129
 
 
130
 
  /**
131
 
   * Creates a new {@link CharTokenizer} instance
132
 
   * @param input the input to split up into tokens
133
 
   * @param source the attribute source to use for this {@link Tokenizer}
134
 
   * @deprecated use {@link #CharTokenizer(Version, AttributeSource, Reader)} instead. This will be
135
 
   *             removed in Lucene 4.0.
136
 
   */
137
 
  @Deprecated
138
 
  public CharTokenizer(AttributeSource source, Reader input) {
139
 
    this(Version.LUCENE_30, source, input);
140
 
  }
141
 
 
142
 
  /**
143
 
   * Creates a new {@link CharTokenizer} instance
144
 
   * @param input the input to split up into tokens
145
 
   * @param factory the attribute factory to use for this {@link Tokenizer}
146
 
   * @deprecated use {@link #CharTokenizer(Version, AttributeSource.AttributeFactory, Reader)} instead. This will be
147
 
   *             removed in Lucene 4.0.
148
 
   */
149
 
  @Deprecated
150
 
  public CharTokenizer(AttributeFactory factory, Reader input) {
151
 
    this(Version.LUCENE_30, factory, input);
152
 
  }
153
 
  
154
 
  private int offset = 0, bufferIndex = 0, dataLen = 0, finalOffset = 0;
155
 
  private static final int MAX_WORD_LEN = 255;
156
 
  private static final int IO_BUFFER_SIZE = 4096;
157
 
  
158
 
  private final CharTermAttribute termAtt = addAttribute(CharTermAttribute.class);;
159
 
  private final OffsetAttribute offsetAtt = addAttribute(OffsetAttribute.class);
160
 
  
161
 
  private final CharacterUtils charUtils;
162
 
  private final CharacterBuffer ioBuffer = CharacterUtils.newCharacterBuffer(IO_BUFFER_SIZE);
163
 
  
164
 
  /**
165
 
   * @deprecated this will be removed in lucene 4.0
166
 
   */
167
 
  @Deprecated
168
 
  private final boolean useOldAPI;
169
 
  
170
 
  /**
171
 
   * @deprecated this will be removed in lucene 4.0
172
 
   */
173
 
  @Deprecated
174
 
  private static final VirtualMethod<CharTokenizer> isTokenCharMethod =
175
 
    new VirtualMethod<CharTokenizer>(CharTokenizer.class, "isTokenChar", char.class);
176
 
  
177
 
  /**
178
 
   * @deprecated this will be removed in lucene 4.0
179
 
   */
180
 
  @Deprecated
181
 
  private static final VirtualMethod<CharTokenizer> normalizeMethod =
182
 
    new VirtualMethod<CharTokenizer>(CharTokenizer.class, "normalize", char.class);
183
 
 
184
 
  /**
185
 
   * Returns true iff a UTF-16 code unit should be included in a token. This
186
 
   * tokenizer generates as tokens adjacent sequences of characters which
187
 
   * satisfy this predicate. Characters for which this is <code>false</code> are
188
 
   * used to define token boundaries and are not included in tokens.
189
 
   * <p>
190
 
   * Note: This method cannot handle <a href=
191
 
   * "http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Character.html#supplementary"
192
 
   * >supplementary characters</a>. To support all Unicode characters, including
193
 
   * supplementary characters, use the {@link #isTokenChar(int)} method.
194
 
   * </p>
195
 
   * 
196
 
   * @deprecated use {@link #isTokenChar(int)} instead. This method will be
197
 
   *             removed in Lucene 4.0.
198
 
   */
199
 
  @Deprecated  
200
 
  protected boolean isTokenChar(char c) {
201
 
    return isTokenChar((int)c); 
202
 
  }
203
 
 
204
 
  /**
205
 
   * Called on each token UTF-16 code unit to normalize it before it is added to the
206
 
   * token. The default implementation does nothing. Subclasses may use this to,
207
 
   * e.g., lowercase tokens.
208
 
   * <p>
209
 
   * Note: This method cannot handle <a href=
210
 
   * "http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Character.html#supplementary"
211
 
   * >supplementary characters</a>. To support all Unicode characters, including
212
 
   * supplementary characters, use the {@link #normalize(int)} method.
213
 
   * </p>
214
 
   * 
215
 
   * @deprecated use {@link #normalize(int)} instead. This method will be
216
 
   *             removed in Lucene 4.0.
217
 
   */
218
 
  @Deprecated 
219
 
  protected char normalize(char c) {
220
 
    return (char) normalize((int) c);
221
 
  }
222
 
 
223
 
  /**
224
 
   * Returns true iff a codepoint should be included in a token. This tokenizer
225
 
   * generates as tokens adjacent sequences of codepoints which satisfy this
226
 
   * predicate. Codepoints for which this is false are used to define token
227
 
   * boundaries and are not included in tokens.
228
 
   * <p>
229
 
   * As of Lucene 3.1 the char based API ({@link #isTokenChar(char)} and
230
 
   * {@link #normalize(char)}) has been depreciated in favor of a Unicode 4.0
231
 
   * compatible int based API to support codepoints instead of UTF-16 code
232
 
   * units. Subclasses of {@link CharTokenizer} must not override the char based
233
 
   * methods if a {@link Version} >= 3.1 is passed to the constructor.
234
 
   * <p>
235
 
   * <p>
236
 
   * NOTE: This method will be marked <i>abstract</i> in Lucene 4.0.
237
 
   * </p>
238
 
   */
239
 
  protected boolean isTokenChar(int c) {
240
 
    throw new UnsupportedOperationException("since LUCENE_31 subclasses of CharTokenizer must implement isTokenChar(int)");
241
 
  }
242
 
 
243
 
  /**
244
 
   * Called on each token character to normalize it before it is added to the
245
 
   * token. The default implementation does nothing. Subclasses may use this to,
246
 
   * e.g., lowercase tokens.
247
 
   * <p>
248
 
   * As of Lucene 3.1 the char based API ({@link #isTokenChar(char)} and
249
 
   * {@link #normalize(char)}) has been depreciated in favor of a Unicode 4.0
250
 
   * compatible int based API to support codepoints instead of UTF-16 code
251
 
   * units. Subclasses of {@link CharTokenizer} must not override the char based
252
 
   * methods if a {@link Version} >= 3.1 is passed to the constructor.
253
 
   * <p>
254
 
   * <p>
255
 
   * NOTE: This method will be marked <i>abstract</i> in Lucene 4.0.
256
 
   * </p>
257
 
   */
258
 
  protected int normalize(int c) {
259
 
    return c;
260
 
  }
261
 
 
262
 
  @Override
263
 
  public final boolean incrementToken() throws IOException {
264
 
    clearAttributes();
265
 
    if(useOldAPI) // TODO remove this in LUCENE 4.0
266
 
      return incrementTokenOld();
267
 
    int length = 0;
268
 
    int start = -1; // this variable is always initialized
269
 
    char[] buffer = termAtt.buffer();
270
 
    while (true) {
271
 
      if (bufferIndex >= dataLen) {
272
 
        offset += dataLen;
273
 
        if(!charUtils.fill(ioBuffer, input)) { // read supplementary char aware with CharacterUtils
274
 
          dataLen = 0; // so next offset += dataLen won't decrement offset
275
 
          if (length > 0) {
276
 
            break;
277
 
          } else {
278
 
            finalOffset = correctOffset(offset);
279
 
            return false;
280
 
          }
281
 
        }
282
 
        dataLen = ioBuffer.getLength();
283
 
        bufferIndex = 0;
284
 
      }
285
 
      // use CharacterUtils here to support < 3.1 UTF-16 code unit behavior if the char based methods are gone
286
 
      final int c = charUtils.codePointAt(ioBuffer.getBuffer(), bufferIndex);
287
 
      bufferIndex += Character.charCount(c);
288
 
 
289
 
      if (isTokenChar(c)) {               // if it's a token char
290
 
        if (length == 0) {                // start of token
291
 
          assert start == -1;
292
 
          start = offset + bufferIndex - 1;
293
 
        } else if (length >= buffer.length-1) { // check if a supplementary could run out of bounds
294
 
          buffer = termAtt.resizeBuffer(2+length); // make sure a supplementary fits in the buffer
295
 
        }
296
 
        length += Character.toChars(normalize(c), buffer, length); // buffer it, normalized
297
 
        if (length >= MAX_WORD_LEN) // buffer overflow! make sure to check for >= surrogate pair could break == test
298
 
          break;
299
 
      } else if (length > 0)             // at non-Letter w/ chars
300
 
        break;                           // return 'em
301
 
    }
302
 
 
303
 
    termAtt.setLength(length);
304
 
    assert start != -1;
305
 
    offsetAtt.setOffset(correctOffset(start), finalOffset = correctOffset(start+length));
306
 
    return true;
307
 
    
308
 
  }
309
 
  
310
 
  /**
311
 
   * The <= 3.0 version of incrementToken. This is a backwards compat implementation used
312
 
   * if a version <= 3.0 is provided to the ctor. 
313
 
   * @deprecated remove in 4.0
314
 
   */
315
 
  @Deprecated
316
 
  private boolean incrementTokenOld() throws IOException {
317
 
    int length = 0;
318
 
    int start = -1; // this variable is always initialized
319
 
    char[] buffer = termAtt.buffer();
320
 
    final char[] oldIoBuffer = ioBuffer.getBuffer();
321
 
    while (true) {
322
 
 
323
 
      if (bufferIndex >= dataLen) {
324
 
        offset += dataLen;
325
 
        dataLen = input.read(oldIoBuffer);
326
 
        if (dataLen == -1) {
327
 
          dataLen = 0;                            // so next offset += dataLen won't decrement offset
328
 
          if (length > 0) {
329
 
            break;
330
 
          } else {
331
 
            finalOffset = correctOffset(offset);
332
 
            return false;
333
 
          }
334
 
        }
335
 
        bufferIndex = 0;
336
 
      }
337
 
 
338
 
      final char c = oldIoBuffer[bufferIndex++];
339
 
 
340
 
      if (isTokenChar(c)) {               // if it's a token char
341
 
 
342
 
        if (length == 0) {                // start of token
343
 
          assert start == -1;
344
 
          start = offset + bufferIndex - 1;
345
 
        } else if (length == buffer.length) {
346
 
          buffer = termAtt.resizeBuffer(1+length);
347
 
        }
348
 
 
349
 
        buffer[length++] = normalize(c); // buffer it, normalized
350
 
 
351
 
        if (length == MAX_WORD_LEN)      // buffer overflow!
352
 
          break;
353
 
 
354
 
      } else if (length > 0)             // at non-Letter w/ chars
355
 
        break;                           // return 'em
356
 
    }
357
 
 
358
 
    termAtt.setLength(length);
359
 
    assert start != -1;
360
 
    offsetAtt.setOffset(correctOffset(start), correctOffset(start+length));
361
 
    return true;
362
 
  }  
363
 
  
364
 
  
365
 
  
366
 
  @Override
367
 
  public final void end() {
368
 
    // set final offset
369
 
    offsetAtt.setOffset(finalOffset, finalOffset);
370
 
  }
371
 
 
372
 
  @Override
373
 
  public void reset(Reader input) throws IOException {
374
 
    super.reset(input);
375
 
    bufferIndex = 0;
376
 
    offset = 0;
377
 
    dataLen = 0;
378
 
    finalOffset = 0;
379
 
    ioBuffer.reset(); // make sure to reset the IO buffer!!
380
 
  }
381
 
 
382
 
  /**
383
 
   * @deprecated this will be removed in lucene 4.0
384
 
   */
385
 
  @Deprecated
386
 
  private boolean useOldAPI(Version matchVersion) {
387
 
    final Class<? extends CharTokenizer> clazz = this.getClass();
388
 
    if (matchVersion.onOrAfter(Version.LUCENE_31)
389
 
        && (isTokenCharMethod.isOverriddenAsOf(clazz) || normalizeMethod
390
 
            .isOverriddenAsOf(clazz))) throw new IllegalArgumentException(
391
 
        "For matchVersion >= LUCENE_31, CharTokenizer subclasses must not override isTokenChar(char) or normalize(char).");
392
 
    return !matchVersion.onOrAfter(Version.LUCENE_31);
393
 
  } 
394
 
}
 
 
b'\\ No newline at end of file'