/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using Document = Lucene.Net.Documents.Document; using Fieldable = Lucene.Net.Documents.Fieldable; using Directory = Lucene.Net.Store.Directory; using IndexInput = Lucene.Net.Store.IndexInput; using IndexOutput = Lucene.Net.Store.IndexOutput; namespace Lucene.Net.Index { /// Access to the Fieldable Info file that describes document fields and whether or /// not they are indexed. Each segment has a separate Fieldable Info file. Objects /// of this class are thread-safe for multiple readers, but only one thread can /// be adding documents at a time, with no other reader or writer threads /// accessing this object. /// public sealed class FieldInfos { internal const byte IS_INDEXED = (byte) (0x1); internal const byte STORE_TERMVECTOR = (byte) (0x2); internal const byte STORE_POSITIONS_WITH_TERMVECTOR = (byte) (0x4); internal const byte STORE_OFFSET_WITH_TERMVECTOR = (byte) (0x8); internal const byte OMIT_NORMS = (byte) (0x10); private System.Collections.ArrayList byNumber = new System.Collections.ArrayList(); private System.Collections.Hashtable byName = new System.Collections.Hashtable(); public FieldInfos() { } /// Construct a FieldInfos object using the directory and the name of the file /// IndexInput /// /// The directory to open the IndexInput from /// /// The name of the file to open the IndexInput from in the Directory /// /// IOException public FieldInfos(Directory d, System.String name) { IndexInput input = d.OpenInput(name); try { Read(input); } finally { input.Close(); } } /// Adds field info for a Document. public void Add(Document doc) { System.Collections.IList fields = doc.GetFields(); System.Collections.IEnumerator fieldIterator = fields.GetEnumerator(); while (fieldIterator.MoveNext()) { Fieldable field = (Fieldable) fieldIterator.Current; Add(field.Name(), field.IsIndexed(), field.IsTermVectorStored(), field.IsStorePositionWithTermVector(), field.IsStoreOffsetWithTermVector(), field.GetOmitNorms()); } } /// Add fields that are indexed. Whether they have termvectors has to be specified. /// /// /// The names of the fields /// /// Whether the fields store term vectors or not /// /// treu if positions should be stored. /// /// true if offsets should be stored /// public void AddIndexed(System.Collections.ICollection names, bool storeTermVectors, bool storePositionWithTermVector, bool storeOffsetWithTermVector) { System.Collections.IEnumerator i = names.GetEnumerator(); while (i.MoveNext()) { System.Collections.DictionaryEntry t = (System.Collections.DictionaryEntry) i.Current; Add((System.String) t.Key, true, storeTermVectors, storePositionWithTermVector, storeOffsetWithTermVector); } } /// Assumes the fields are not storing term vectors. /// /// /// The names of the fields /// /// Whether the fields are indexed or not /// /// /// /// public void Add(System.Collections.ICollection names, bool isIndexed) { System.Collections.IEnumerator i = names.GetEnumerator(); while (i.MoveNext()) { System.Collections.DictionaryEntry t = (System.Collections.DictionaryEntry) i.Current; Add((System.String) t.Key, isIndexed); } } /// Calls 5 parameter add with false for all TermVector parameters. /// /// /// The name of the Fieldable /// /// true if the field is indexed /// /// /// public void Add(System.String name, bool isIndexed) { Add(name, isIndexed, false, false, false, false); } /// Calls 5 parameter add with false for term vector positions and offsets. /// /// /// The name of the field /// /// true if the field is indexed /// /// true if the term vector should be stored /// public void Add(System.String name, bool isIndexed, bool storeTermVector) { Add(name, isIndexed, storeTermVector, false, false, false); } /// If the field is not yet known, adds it. If it is known, checks to make /// sure that the isIndexed flag is the same as was given previously for this /// field. If not - marks it as being indexed. Same goes for the TermVector /// parameters. /// /// /// The name of the field /// /// true if the field is indexed /// /// true if the term vector should be stored /// /// true if the term vector with positions should be stored /// /// true if the term vector with offsets should be stored /// public void Add(System.String name, bool isIndexed, bool storeTermVector, bool storePositionWithTermVector, bool storeOffsetWithTermVector) { Add(name, isIndexed, storeTermVector, storePositionWithTermVector, storeOffsetWithTermVector, false); } /// If the field is not yet known, adds it. If it is known, checks to make /// sure that the isIndexed flag is the same as was given previously for this /// field. If not - marks it as being indexed. Same goes for the TermVector /// parameters. /// /// /// The name of the field /// /// true if the field is indexed /// /// true if the term vector should be stored /// /// true if the term vector with positions should be stored /// /// true if the term vector with offsets should be stored /// /// true if the norms for the indexed field should be omitted /// public void Add(System.String name, bool isIndexed, bool storeTermVector, bool storePositionWithTermVector, bool storeOffsetWithTermVector, bool omitNorms) { FieldInfo fi = FieldInfo(name); if (fi == null) { AddInternal(name, isIndexed, storeTermVector, storePositionWithTermVector, storeOffsetWithTermVector, omitNorms); } else { if (fi.isIndexed != isIndexed) { fi.isIndexed = true; // once indexed, always index } if (fi.storeTermVector != storeTermVector) { fi.storeTermVector = true; // once vector, always vector } if (fi.storePositionWithTermVector != storePositionWithTermVector) { fi.storePositionWithTermVector = true; // once vector, always vector } if (fi.storeOffsetWithTermVector != storeOffsetWithTermVector) { fi.storeOffsetWithTermVector = true; // once vector, always vector } if (fi.omitNorms != omitNorms) { fi.omitNorms = false; // once norms are stored, always store } } } private void AddInternal(System.String name, bool isIndexed, bool storeTermVector, bool storePositionWithTermVector, bool storeOffsetWithTermVector, bool omitNorms) { FieldInfo fi = new FieldInfo(name, isIndexed, byNumber.Count, storeTermVector, storePositionWithTermVector, storeOffsetWithTermVector, omitNorms); byNumber.Add(fi); byName[name] = fi; } public int FieldNumber(System.String fieldName) { try { FieldInfo fi = FieldInfo(fieldName); if (fi != null) return fi.number; } catch (System.IndexOutOfRangeException ioobe) { return - 1; } return - 1; } public FieldInfo FieldInfo(System.String fieldName) { return (FieldInfo) byName[fieldName]; } /// Return the fieldName identified by its number. /// /// /// fieldNumber /// /// the fieldName or an empty string when the field /// with the given number doesn't exist. /// public System.String FieldName(int fieldNumber) { FieldInfo fi = FieldInfo(fieldNumber); if (fi != null) return fi.name; return ""; } /// Return the fieldinfo object referenced by the fieldNumber. /// fieldNumber /// /// the FieldInfo object or null when the given fieldNumber /// doesn't exist. /// public FieldInfo FieldInfo(int fieldNumber) { if (fieldNumber > -1 && fieldNumber < byNumber.Count) return (FieldInfo) byNumber[fieldNumber]; return null; } public int Size() { return byNumber.Count; } public bool HasVectors() { bool hasVectors = false; for (int i = 0; i < Size(); i++) { if (FieldInfo(i).storeTermVector) { hasVectors = true; break; } } return hasVectors; } public void Write(Directory d, System.String name) { IndexOutput output = d.CreateOutput(name); try { Write(output); } finally { output.Close(); } } public void Write(IndexOutput output) { output.WriteVInt(Size()); for (int i = 0; i < Size(); i++) { FieldInfo fi = FieldInfo(i); byte bits = (byte) (0x0); if (fi.isIndexed) bits |= IS_INDEXED; if (fi.storeTermVector) bits |= STORE_TERMVECTOR; if (fi.storePositionWithTermVector) bits |= STORE_POSITIONS_WITH_TERMVECTOR; if (fi.storeOffsetWithTermVector) bits |= STORE_OFFSET_WITH_TERMVECTOR; if (fi.omitNorms) bits |= OMIT_NORMS; output.WriteString(fi.name); output.WriteByte(bits); } } private void Read(IndexInput input) { int size = input.ReadVInt(); //read in the size for (int i = 0; i < size; i++) { System.String name = String.Intern(input.ReadString()); byte bits = input.ReadByte(); bool isIndexed = (bits & IS_INDEXED) != 0; bool storeTermVector = (bits & STORE_TERMVECTOR) != 0; bool storePositionsWithTermVector = (bits & STORE_POSITIONS_WITH_TERMVECTOR) != 0; bool storeOffsetWithTermVector = (bits & STORE_OFFSET_WITH_TERMVECTOR) != 0; bool omitNorms = (bits & OMIT_NORMS) != 0; AddInternal(name, isIndexed, storeTermVector, storePositionsWithTermVector, storeOffsetWithTermVector, omitNorms); } } } }