blob: 314202ea96496bdf265abca3a5ab0f9af97506d3 [file] [log] [blame]
/*
* Copyright 2004 The Apache Software Foundation
*
* Licensed 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 Field = Lucene.Net.Documents.Field;
using Directory = Lucene.Net.Store.Directory;
using IndexInput = Lucene.Net.Store.IndexInput;
using IndexOutput = Lucene.Net.Store.IndexOutput;
namespace Lucene.Net.Index
{
/// <summary>Access to the Field Info file that describes document fields and whether or
/// not they are indexed. Each segment has a separate Field 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.
/// </summary>
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 /*internal*/ FieldInfos()
{
}
/// <summary> Construct a FieldInfos object using the directory and the name of the file
/// IndexInput
/// </summary>
/// <param name="d">The directory to open the IndexInput from
/// </param>
/// <param name="name">The name of the file to open the IndexInput from in the Directory
/// </param>
/// <throws> IOException </throws>
public /*internal*/ FieldInfos(Directory d, System.String name)
{
IndexInput input = d.OpenInput(name);
try
{
Read(input);
}
finally
{
input.Close();
}
}
/// <summary>Adds field info for a Document. </summary>
public void Add(Document doc)
{
foreach (Field field in doc.Fields())
{
Add(field.Name(), field.IsIndexed(), field.IsTermVectorStored(), field.IsStorePositionWithTermVector(), field.IsStoreOffsetWithTermVector(), field.GetOmitNorms());
}
}
/// <summary> Add fields that are indexed. Whether they have termvectors has to be specified.
///
/// </summary>
/// <param name="names">The names of the fields
/// </param>
/// <param name="storeTermVectors">Whether the fields store term vectors or not
/// </param>
/// <param name="storePositionWithTermVector">treu if positions should be stored.
/// </param>
/// <param name="storeOffsetWithTermVector">true if offsets should be stored
/// </param>
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);
}
}
/// <summary> Assumes the fields are not storing term vectors.
///
/// </summary>
/// <param name="names">The names of the fields
/// </param>
/// <param name="isIndexed">Whether the fields are indexed or not
///
/// </param>
/// <seealso cref="Add(String, boolean)">
/// </seealso>
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);
}
}
/// <summary> Calls 5 parameter add with false for all TermVector parameters.
///
/// </summary>
/// <param name="name">The name of the Field
/// </param>
/// <param name="isIndexed">true if the field is indexed
/// </param>
/// <seealso cref="Add(String, boolean, boolean, boolean, boolean)">
/// </seealso>
public void Add(System.String name, bool isIndexed)
{
Add(name, isIndexed, false, false, false, false);
}
/// <summary> Calls 5 parameter add with false for term vector positions and offsets.
///
/// </summary>
/// <param name="name">The name of the field
/// </param>
/// <param name="isIndexed"> true if the field is indexed
/// </param>
/// <param name="storeTermVector">true if the term vector should be stored
/// </param>
public void Add(System.String name, bool isIndexed, bool storeTermVector)
{
Add(name, isIndexed, storeTermVector, false, false, false);
}
/// <summary>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.
///
/// </summary>
/// <param name="name">The name of the field
/// </param>
/// <param name="isIndexed">true if the field is indexed
/// </param>
/// <param name="storeTermVector">true if the term vector should be stored
/// </param>
/// <param name="storePositionWithTermVector">true if the term vector with positions should be stored
/// </param>
/// <param name="storeOffsetWithTermVector">true if the term vector with offsets should be stored
/// </param>
public void Add(System.String name, bool isIndexed, bool storeTermVector, bool storePositionWithTermVector, bool storeOffsetWithTermVector)
{
Add(name, isIndexed, storeTermVector, storePositionWithTermVector, storeOffsetWithTermVector, false);
}
/// <summary>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.
///
/// </summary>
/// <param name="name">The name of the field
/// </param>
/// <param name="isIndexed">true if the field is indexed
/// </param>
/// <param name="storeTermVector">true if the term vector should be stored
/// </param>
/// <param name="storePositionWithTermVector">true if the term vector with positions should be stored
/// </param>
/// <param name="storeOffsetWithTermVector">true if the term vector with offsets should be stored
/// </param>
/// <param name="omitNorms">true if the norms for the indexed field should be omitted
/// </param>
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];
}
/// <summary> Return the fieldName identified by its number.
///
/// </summary>
/// <param name="fieldNumber">
/// </param>
/// <returns> the fieldName or an empty string when the field
/// with the given number doesn't exist.
/// </returns>
public System.String FieldName(int fieldNumber)
{
FieldInfo fi = FieldInfo(fieldNumber);
if (fi != null)
return fi.name;
return "";
/*
try
{
return FieldInfo(fieldNumber).name;
}
catch (System.NullReferenceException)
{
return "";
}
*/
}
/// <summary> Return the fieldinfo object referenced by the fieldNumber.</summary>
/// <param name="fieldNumber">
/// </param>
/// <returns> the FieldInfo object or null when the given fieldNumber
/// doesn't exist.
/// </returns>
public FieldInfo FieldInfo(int fieldNumber)
{
if (fieldNumber > -1 && fieldNumber < byNumber.Count)
return (FieldInfo) byNumber[fieldNumber];
return null;
/*
try
{
return (FieldInfo) byNumber[fieldNumber];
}
catch (System.ArgumentOutOfRangeException) // (System.IndexOutOfRangeException)
{
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);
}
}
}
}