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

« back to all changes in this revision

Viewing changes to lucene/src/java/org/apache/lucene/index/FieldInfos.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.index;
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 org.apache.lucene.document.Document;
21
 
import org.apache.lucene.document.Fieldable;
22
 
import org.apache.lucene.index.FieldInfo.IndexOptions;
23
 
import org.apache.lucene.store.Directory;
24
 
import org.apache.lucene.store.IndexInput;
25
 
import org.apache.lucene.store.IndexOutput;
26
 
import org.apache.lucene.util.StringHelper;
27
 
 
28
 
import java.io.IOException;
29
 
import java.util.*;
30
 
 
31
 
/** Access to the Fieldable Info file that describes document fields and whether or
32
 
 *  not they are indexed. Each segment has a separate Fieldable Info file. Objects
33
 
 *  of this class are thread-safe for multiple readers, but only one thread can
34
 
 *  be adding documents at a time, with no other reader or writer threads
35
 
 *  accessing this object.
36
 
 */
37
 
final class FieldInfos {
38
 
 
39
 
  // Used internally (ie not written to *.fnm files) for pre-2.9 files
40
 
  public static final int FORMAT_PRE = -1;
41
 
 
42
 
  // First used in 2.9; prior to 2.9 there was no format header
43
 
  public static final int FORMAT_START = -2;
44
 
 
45
 
  // First used in 3.4: omit only positional information
46
 
  public static final int FORMAT_OMIT_POSITIONS = -3;
47
 
 
48
 
  // whenever you add a new format, make it 1 smaller (negative version logic)!
49
 
  static final int CURRENT_FORMAT = FORMAT_OMIT_POSITIONS;
50
 
  
51
 
  static final byte IS_INDEXED = 0x1;
52
 
  static final byte STORE_TERMVECTOR = 0x2;
53
 
  static final byte STORE_POSITIONS_WITH_TERMVECTOR = 0x4;
54
 
  static final byte STORE_OFFSET_WITH_TERMVECTOR = 0x8;
55
 
  static final byte OMIT_NORMS = 0x10;
56
 
  static final byte STORE_PAYLOADS = 0x20;
57
 
  static final byte OMIT_TERM_FREQ_AND_POSITIONS = 0x40;
58
 
  static final byte OMIT_POSITIONS = -128;
59
 
 
60
 
  private final ArrayList<FieldInfo> byNumber = new ArrayList<FieldInfo>();
61
 
  private final HashMap<String,FieldInfo> byName = new HashMap<String,FieldInfo>();
62
 
  private int format;
63
 
 
64
 
  FieldInfos() { }
65
 
 
66
 
  /**
67
 
   * Construct a FieldInfos object using the directory and the name of the file
68
 
   * IndexInput
69
 
   * @param d The directory to open the IndexInput from
70
 
   * @param name The name of the file to open the IndexInput from in the Directory
71
 
   * @throws IOException
72
 
   */
73
 
  FieldInfos(Directory d, String name) throws IOException {
74
 
    IndexInput input = d.openInput(name);
75
 
    try {
76
 
      try {
77
 
        read(input, name);
78
 
      } catch (IOException ioe) {
79
 
        if (format == FORMAT_PRE) {
80
 
          // LUCENE-1623: FORMAT_PRE (before there was a
81
 
          // format) may be 2.3.2 (pre-utf8) or 2.4.x (utf8)
82
 
          // encoding; retry with input set to pre-utf8
83
 
          input.seek(0);
84
 
          input.setModifiedUTF8StringsMode();
85
 
          byNumber.clear();
86
 
          byName.clear();
87
 
          try {
88
 
            read(input, name);
89
 
          } catch (Throwable t) {
90
 
            // Ignore any new exception & throw original IOE
91
 
            throw ioe;
92
 
          }
93
 
        } else {
94
 
          // The IOException cannot be caused by
95
 
          // LUCENE-1623, so re-throw it
96
 
          throw ioe;
97
 
        }
98
 
      }
99
 
    } finally {
100
 
      input.close();
101
 
    }
102
 
  }
103
 
 
104
 
  /**
105
 
   * Returns a deep clone of this FieldInfos instance.
106
 
   */
107
 
  @Override
108
 
  synchronized public Object clone() {
109
 
    FieldInfos fis = new FieldInfos();
110
 
    final int numField = byNumber.size();
111
 
    for(int i=0;i<numField;i++) {
112
 
      FieldInfo fi = (FieldInfo) ( byNumber.get(i)).clone();
113
 
      fis.byNumber.add(fi);
114
 
      fis.byName.put(fi.name, fi);
115
 
    }
116
 
    return fis;
117
 
  }
118
 
 
119
 
  /** Adds field info for a Document. */
120
 
  synchronized public void add(Document doc) {
121
 
    List<Fieldable> fields = doc.getFields();
122
 
    for (Fieldable field : fields) {
123
 
      add(field.name(), field.isIndexed(), field.isTermVectorStored(), field.isStorePositionWithTermVector(),
124
 
              field.isStoreOffsetWithTermVector(), field.getOmitNorms(), false, field.getIndexOptions());
125
 
    }
126
 
  }
127
 
 
128
 
  /** Returns true if any fields do not omitTermFreqAndPositions */
129
 
  boolean hasProx() {
130
 
    final int numFields = byNumber.size();
131
 
    for(int i=0;i<numFields;i++) {
132
 
      final FieldInfo fi = fieldInfo(i);
133
 
      if (fi.isIndexed && fi.indexOptions == IndexOptions.DOCS_AND_FREQS_AND_POSITIONS) {
134
 
        return true;
135
 
      }
136
 
    }
137
 
    return false;
138
 
  }
139
 
  
140
 
  /**
141
 
   * Add fields that are indexed. Whether they have termvectors has to be specified.
142
 
   * 
143
 
   * @param names The names of the fields
144
 
   * @param storeTermVectors Whether the fields store term vectors or not
145
 
   * @param storePositionWithTermVector true if positions should be stored.
146
 
   * @param storeOffsetWithTermVector true if offsets should be stored
147
 
   */
148
 
  synchronized public void addIndexed(Collection<String> names, boolean storeTermVectors, boolean storePositionWithTermVector, 
149
 
                         boolean storeOffsetWithTermVector) {
150
 
    for (String name : names) {
151
 
      add(name, true, storeTermVectors, storePositionWithTermVector, storeOffsetWithTermVector);
152
 
    }
153
 
  }
154
 
 
155
 
  /**
156
 
   * Assumes the fields are not storing term vectors.
157
 
   * 
158
 
   * @param names The names of the fields
159
 
   * @param isIndexed Whether the fields are indexed or not
160
 
   * 
161
 
   * @see #add(String, boolean)
162
 
   */
163
 
  synchronized public void add(Collection<String> names, boolean isIndexed) {
164
 
    for (String name : names) {
165
 
      add(name, isIndexed);
166
 
    }
167
 
  }
168
 
 
169
 
  /**
170
 
   * Calls 5 parameter add with false for all TermVector parameters.
171
 
   * 
172
 
   * @param name The name of the Fieldable
173
 
   * @param isIndexed true if the field is indexed
174
 
   * @see #add(String, boolean, boolean, boolean, boolean)
175
 
   */
176
 
  synchronized public void add(String name, boolean isIndexed) {
177
 
    add(name, isIndexed, false, false, false, false);
178
 
  }
179
 
 
180
 
  /**
181
 
   * Calls 5 parameter add with false for term vector positions and offsets.
182
 
   * 
183
 
   * @param name The name of the field
184
 
   * @param isIndexed  true if the field is indexed
185
 
   * @param storeTermVector true if the term vector should be stored
186
 
   */
187
 
  synchronized public void add(String name, boolean isIndexed, boolean storeTermVector){
188
 
    add(name, isIndexed, storeTermVector, false, false, false);
189
 
  }
190
 
  
191
 
  /** If the field is not yet known, adds it. If it is known, checks to make
192
 
   *  sure that the isIndexed flag is the same as was given previously for this
193
 
   *  field. If not - marks it as being indexed.  Same goes for the TermVector
194
 
   * parameters.
195
 
   * 
196
 
   * @param name The name of the field
197
 
   * @param isIndexed true if the field is indexed
198
 
   * @param storeTermVector true if the term vector should be stored
199
 
   * @param storePositionWithTermVector true if the term vector with positions should be stored
200
 
   * @param storeOffsetWithTermVector true if the term vector with offsets should be stored
201
 
   */
202
 
  synchronized public void add(String name, boolean isIndexed, boolean storeTermVector,
203
 
                  boolean storePositionWithTermVector, boolean storeOffsetWithTermVector) {
204
 
 
205
 
    add(name, isIndexed, storeTermVector, storePositionWithTermVector, storeOffsetWithTermVector, false);
206
 
  }
207
 
 
208
 
    /** If the field is not yet known, adds it. If it is known, checks to make
209
 
   *  sure that the isIndexed flag is the same as was given previously for this
210
 
   *  field. If not - marks it as being indexed.  Same goes for the TermVector
211
 
   * parameters.
212
 
   *
213
 
   * @param name The name of the field
214
 
   * @param isIndexed true if the field is indexed
215
 
   * @param storeTermVector true if the term vector should be stored
216
 
   * @param storePositionWithTermVector true if the term vector with positions should be stored
217
 
   * @param storeOffsetWithTermVector true if the term vector with offsets should be stored
218
 
   * @param omitNorms true if the norms for the indexed field should be omitted
219
 
   */
220
 
  synchronized public void add(String name, boolean isIndexed, boolean storeTermVector,
221
 
                  boolean storePositionWithTermVector, boolean storeOffsetWithTermVector, boolean omitNorms) {
222
 
    add(name, isIndexed, storeTermVector, storePositionWithTermVector,
223
 
        storeOffsetWithTermVector, omitNorms, false, IndexOptions.DOCS_AND_FREQS_AND_POSITIONS);
224
 
  }
225
 
  
226
 
  /** If the field is not yet known, adds it. If it is known, checks to make
227
 
   *  sure that the isIndexed flag is the same as was given previously for this
228
 
   *  field. If not - marks it as being indexed.  Same goes for the TermVector
229
 
   * parameters.
230
 
   *
231
 
   * @param name The name of the field
232
 
   * @param isIndexed true if the field is indexed
233
 
   * @param storeTermVector true if the term vector should be stored
234
 
   * @param storePositionWithTermVector true if the term vector with positions should be stored
235
 
   * @param storeOffsetWithTermVector true if the term vector with offsets should be stored
236
 
   * @param omitNorms true if the norms for the indexed field should be omitted
237
 
   * @param storePayloads true if payloads should be stored for this field
238
 
   * @param indexOptions if term freqs should be omitted for this field
239
 
   */
240
 
  synchronized public FieldInfo add(String name, boolean isIndexed, boolean storeTermVector,
241
 
                       boolean storePositionWithTermVector, boolean storeOffsetWithTermVector,
242
 
                       boolean omitNorms, boolean storePayloads, IndexOptions indexOptions) {
243
 
    FieldInfo fi = fieldInfo(name);
244
 
    if (fi == null) {
245
 
      return addInternal(name, isIndexed, storeTermVector, storePositionWithTermVector, storeOffsetWithTermVector, omitNorms, storePayloads, indexOptions);
246
 
    } else {
247
 
      fi.update(isIndexed, storeTermVector, storePositionWithTermVector, storeOffsetWithTermVector, omitNorms, storePayloads, indexOptions);
248
 
    }
249
 
    assert fi.indexOptions == IndexOptions.DOCS_AND_FREQS_AND_POSITIONS || !fi.storePayloads;
250
 
    return fi;
251
 
  }
252
 
 
253
 
  synchronized public FieldInfo add(FieldInfo fi) {
254
 
    return add(fi.name, fi.isIndexed, fi.storeTermVector,
255
 
               fi.storePositionWithTermVector, fi.storeOffsetWithTermVector,
256
 
               fi.omitNorms, fi.storePayloads,
257
 
               fi.indexOptions);
258
 
  }
259
 
 
260
 
  private FieldInfo addInternal(String name, boolean isIndexed,
261
 
                                boolean storeTermVector, boolean storePositionWithTermVector, 
262
 
                                boolean storeOffsetWithTermVector, boolean omitNorms, boolean storePayloads, IndexOptions indexOptions) {
263
 
    name = StringHelper.intern(name);
264
 
    FieldInfo fi = new FieldInfo(name, isIndexed, byNumber.size(), storeTermVector, storePositionWithTermVector,
265
 
                                 storeOffsetWithTermVector, omitNorms, storePayloads, indexOptions);
266
 
    byNumber.add(fi);
267
 
    byName.put(name, fi);
268
 
    return fi;
269
 
  }
270
 
 
271
 
  public int fieldNumber(String fieldName) {
272
 
    FieldInfo fi = fieldInfo(fieldName);
273
 
    return (fi != null) ? fi.number : -1;
274
 
  }
275
 
 
276
 
  public FieldInfo fieldInfo(String fieldName) {
277
 
    return  byName.get(fieldName);
278
 
  }
279
 
 
280
 
  /**
281
 
   * Return the fieldName identified by its number.
282
 
   * 
283
 
   * @param fieldNumber
284
 
   * @return the fieldName or an empty string when the field
285
 
   * with the given number doesn't exist.
286
 
   */  
287
 
  public String fieldName(int fieldNumber) {
288
 
        FieldInfo fi = fieldInfo(fieldNumber);
289
 
        return (fi != null) ? fi.name : "";
290
 
  }
291
 
 
292
 
  /**
293
 
   * Return the fieldinfo object referenced by the fieldNumber.
294
 
   * @param fieldNumber
295
 
   * @return the FieldInfo object or null when the given fieldNumber
296
 
   * doesn't exist.
297
 
   */  
298
 
  public FieldInfo fieldInfo(int fieldNumber) {
299
 
        return (fieldNumber >= 0) ? byNumber.get(fieldNumber) : null;
300
 
  }
301
 
 
302
 
  public int size() {
303
 
    return byNumber.size();
304
 
  }
305
 
 
306
 
  public boolean hasVectors() {
307
 
    boolean hasVectors = false;
308
 
    for (int i = 0; i < size(); i++) {
309
 
      if (fieldInfo(i).storeTermVector) {
310
 
        hasVectors = true;
311
 
        break;
312
 
      }
313
 
    }
314
 
    return hasVectors;
315
 
  }
316
 
 
317
 
  public void write(Directory d, String name) throws IOException {
318
 
    IndexOutput output = d.createOutput(name);
319
 
    try {
320
 
      write(output);
321
 
    } finally {
322
 
      output.close();
323
 
    }
324
 
  }
325
 
 
326
 
  public void write(IndexOutput output) throws IOException {
327
 
    output.writeVInt(CURRENT_FORMAT);
328
 
    output.writeVInt(size());
329
 
    for (int i = 0; i < size(); i++) {
330
 
      FieldInfo fi = fieldInfo(i);
331
 
      assert fi.indexOptions == IndexOptions.DOCS_AND_FREQS_AND_POSITIONS || !fi.storePayloads;
332
 
      byte bits = 0x0;
333
 
      if (fi.isIndexed) bits |= IS_INDEXED;
334
 
      if (fi.storeTermVector) bits |= STORE_TERMVECTOR;
335
 
      if (fi.storePositionWithTermVector) bits |= STORE_POSITIONS_WITH_TERMVECTOR;
336
 
      if (fi.storeOffsetWithTermVector) bits |= STORE_OFFSET_WITH_TERMVECTOR;
337
 
      if (fi.omitNorms) bits |= OMIT_NORMS;
338
 
      if (fi.storePayloads) bits |= STORE_PAYLOADS;
339
 
      if (fi.indexOptions == IndexOptions.DOCS_ONLY)
340
 
        bits |= OMIT_TERM_FREQ_AND_POSITIONS;
341
 
      else if (fi.indexOptions == IndexOptions.DOCS_AND_FREQS)
342
 
        bits |= OMIT_POSITIONS;
343
 
      
344
 
      output.writeString(fi.name);
345
 
      output.writeByte(bits);
346
 
    }
347
 
  }
348
 
 
349
 
  private void read(IndexInput input, String fileName) throws IOException {
350
 
    int firstInt = input.readVInt();
351
 
 
352
 
    if (firstInt < 0) {
353
 
      // This is a real format
354
 
      format = firstInt;
355
 
    } else {
356
 
      format = FORMAT_PRE;
357
 
    }
358
 
 
359
 
    if (format != FORMAT_PRE && format != FORMAT_START && format != FORMAT_OMIT_POSITIONS) {
360
 
      throw new CorruptIndexException("unrecognized format " + format + " in file \"" + fileName + "\"");
361
 
    }
362
 
 
363
 
    int size;
364
 
    if (format == FORMAT_PRE) {
365
 
      size = firstInt;
366
 
    } else {
367
 
      size = input.readVInt(); //read in the size
368
 
    }
369
 
 
370
 
    for (int i = 0; i < size; i++) {
371
 
      String name = StringHelper.intern(input.readString());
372
 
      byte bits = input.readByte();
373
 
      boolean isIndexed = (bits & IS_INDEXED) != 0;
374
 
      boolean storeTermVector = (bits & STORE_TERMVECTOR) != 0;
375
 
      boolean storePositionsWithTermVector = (bits & STORE_POSITIONS_WITH_TERMVECTOR) != 0;
376
 
      boolean storeOffsetWithTermVector = (bits & STORE_OFFSET_WITH_TERMVECTOR) != 0;
377
 
      boolean omitNorms = (bits & OMIT_NORMS) != 0;
378
 
      boolean storePayloads = (bits & STORE_PAYLOADS) != 0;
379
 
      final IndexOptions indexOptions;
380
 
      if ((bits & OMIT_TERM_FREQ_AND_POSITIONS) != 0) {
381
 
        indexOptions = IndexOptions.DOCS_ONLY;
382
 
      } else if ((bits & OMIT_POSITIONS) != 0) {
383
 
        if (format <= FORMAT_OMIT_POSITIONS) {
384
 
          indexOptions = IndexOptions.DOCS_AND_FREQS;
385
 
        } else {
386
 
          throw new CorruptIndexException("Corrupt fieldinfos, OMIT_POSITIONS set but format=" + format + " (resource: " + input + ")");
387
 
        }
388
 
      } else {
389
 
        indexOptions = IndexOptions.DOCS_AND_FREQS_AND_POSITIONS;
390
 
      }
391
 
      
392
 
      // LUCENE-3027: past indices were able to write
393
 
      // storePayloads=true when omitTFAP is also true,
394
 
      // which is invalid.  We correct that, here:
395
 
      if (indexOptions != IndexOptions.DOCS_AND_FREQS_AND_POSITIONS) {
396
 
        storePayloads = false;
397
 
      }
398
 
 
399
 
      addInternal(name, isIndexed, storeTermVector, storePositionsWithTermVector, storeOffsetWithTermVector, omitNorms, storePayloads, indexOptions);
400
 
    }
401
 
 
402
 
    if (input.getFilePointer() != input.length()) {
403
 
      throw new CorruptIndexException("did not read all bytes from file \"" + fileName + "\": read " + input.getFilePointer() + " vs size " + input.length() + " (resource: " + input + ")");
404
 
    }    
405
 
  }
406
 
 
407
 
}