/* * 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.Collections.Generic; 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 : System.ICloneable { 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); internal const byte STORE_PAYLOADS = (byte)(0x20); internal const byte OMIT_TF = (byte)(0x40); private List byNumber = new List(); private Dictionary byName = new Dictionary(); 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, string name) { IndexInput input = d.OpenInput(name); try { Read(input); } finally { input.Close(); } } /// Returns a deep clone of this FieldInfos instance. public object Clone() { lock (this) { FieldInfos fis = new FieldInfos(); int numField = byNumber.Count; for (int i = 0; i < numField; i++) { FieldInfo fi = (FieldInfo)(byNumber[i].Clone()); fis.byNumber.Add(fi); fis.byName[fi.name] = fi; } return fis; } } /// Adds field info for a Document. public void Add(Document doc) { lock (this) { 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()); } } } /// /// Returns true if any fields *do not* omit tf. /// /// internal bool HasProx() { int numFields = byNumber.Count; for (int i = 0; i < numFields; i++) if (!FieldInfo(i).omitTf) return true; return false; } /// 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) { lock (this) { System.Collections.IEnumerator i = names.GetEnumerator(); while (i.MoveNext()) { System.Collections.DictionaryEntry t = (System.Collections.DictionaryEntry)i.Current; Add((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(ICollection names, bool isIndexed) { lock (this) { IEnumerator i = names.GetEnumerator(); while (i.MoveNext()) { Add(i.Current, 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(string name, bool isIndexed) { lock (this) { 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(string name, bool isIndexed, bool storeTermVector) { lock (this) { 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(string name, bool isIndexed, bool storeTermVector, bool storePositionWithTermVector, bool storeOffsetWithTermVector) { lock (this) { 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(string name, bool isIndexed, bool storeTermVector, bool storePositionWithTermVector, bool storeOffsetWithTermVector, bool omitNorms) { lock (this) { Add(name, isIndexed, storeTermVector, storePositionWithTermVector, storeOffsetWithTermVector, omitNorms, 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 /// /// true if the norms for the indexed field should be omitted /// /// true if payloads should be stored for this field /// public FieldInfo Add(string name, bool isIndexed, bool storeTermVector, bool storePositionWithTermVector, bool storeOffsetWithTermVector, bool omitNorms, bool storePayloads, bool omitTf) { lock (this) { FieldInfo fi = FieldInfo(name); if (fi == null) { return AddInternal(name, isIndexed, storeTermVector, storePositionWithTermVector, storeOffsetWithTermVector, omitNorms, storePayloads, omitTf); } else { fi.update(isIndexed, storeTermVector, storePositionWithTermVector, storeOffsetWithTermVector, omitNorms, storePayloads, omitTf); } return fi; } } public FieldInfo Add(FieldInfo fieldInfo) { lock (this) { FieldInfo fi = FieldInfo(fieldInfo.name); if (fi == null) { return AddInternal(fieldInfo.name, fieldInfo.isIndexed, fieldInfo.storeTermVector, fieldInfo.storePositionWithTermVector, fieldInfo.storeOffsetWithTermVector, fieldInfo.omitNorms, fieldInfo.storePayloads, fieldInfo.omitTf); } else { fi.update(fieldInfo); } return fi; } } private FieldInfo AddInternal(string name, bool isIndexed, bool storeTermVector, bool storePositionWithTermVector, bool storeOffsetWithTermVector, bool omitNorms, bool storePayloads, bool omitTf) { FieldInfo fi = new FieldInfo(name, isIndexed, byNumber.Count, storeTermVector, storePositionWithTermVector, storeOffsetWithTermVector, omitNorms, storePayloads, omitTf); byNumber.Add(fi); byName[name] = fi; return fi; } public int FieldNumber(string fieldName) { FieldInfo fi = FieldInfo(fieldName); return (fi != null) ? fi.number : -1; } public FieldInfo FieldInfo(string fieldName) { return byName.ContainsKey(fieldName) ? byName[fieldName] : null; } /// 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 string FieldName(int fieldNumber) { FieldInfo fi = FieldInfo(fieldNumber); return (fi != null) ? fi.name : ""; } /// Return the fieldinfo object referenced by the fieldNumber. /// /// /// the FieldInfo object or null when the given fieldNumber /// doesn't exist. /// public FieldInfo FieldInfo(int fieldNumber) { return (fieldNumber >= 0) ? byNumber[fieldNumber] : 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, 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; if (fi.storePayloads) bits |= STORE_PAYLOADS; if (fi.omitTf) bits |= OMIT_TF; 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++) { 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; bool storePayloads = (bits & STORE_PAYLOADS) != 0; bool omitTf = (bits & OMIT_TF) != 0; AddInternal(name, isIndexed, storeTermVector, storePositionsWithTermVector, storeOffsetWithTermVector, omitNorms, storePayloads, omitTf); } } } }