blob: 0ea977628c1f9372d298b4c1c5f3fe7d46d26515 [file] [log] [blame]
using Lucene.Net.Documents;
using System;
using System.Globalization;
namespace Lucene.Net.Codecs.SimpleText
{
/*
* 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 BytesRef = Util.BytesRef;
using Directory = Store.Directory;
using FieldInfo = Index.FieldInfo;
using FieldInfos = Index.FieldInfos;
using IIndexableField = Index.IIndexableField;
using IndexFileNames = Index.IndexFileNames;
using IndexOutput = Store.IndexOutput;
using IOContext = Store.IOContext;
using IOUtils = Util.IOUtils;
/// <summary>
/// Writes plain-text stored fields.
/// <para>
/// <b><font color="red">FOR RECREATIONAL USE ONLY</font></b>
/// </para>
/// @lucene.experimental
/// </summary>
public class SimpleTextStoredFieldsWriter : StoredFieldsWriter
{
private int _numDocsWritten;
private readonly Directory _directory;
private readonly string _segment;
private IndexOutput _output;
internal const string FIELDS_EXTENSION = "fld";
internal static readonly BytesRef TYPE_STRING = new BytesRef("string");
internal static readonly BytesRef TYPE_BINARY = new BytesRef("binary");
internal static readonly BytesRef TYPE_INT = new BytesRef("int");
internal static readonly BytesRef TYPE_LONG = new BytesRef("long");
internal static readonly BytesRef TYPE_FLOAT = new BytesRef("float");
internal static readonly BytesRef TYPE_DOUBLE = new BytesRef("double");
internal static readonly BytesRef END = new BytesRef("END");
internal static readonly BytesRef DOC = new BytesRef("doc ");
internal static readonly BytesRef NUM = new BytesRef(" numfields ");
internal static readonly BytesRef FIELD = new BytesRef(" field ");
internal static readonly BytesRef NAME = new BytesRef(" name ");
internal static readonly BytesRef TYPE = new BytesRef(" type ");
internal static readonly BytesRef VALUE = new BytesRef(" value ");
private readonly BytesRef _scratch = new BytesRef();
public SimpleTextStoredFieldsWriter(Directory directory, string segment, IOContext context)
{
_directory = directory;
_segment = segment;
var success = false;
try
{
_output = directory.CreateOutput(IndexFileNames.SegmentFileName(segment, "", FIELDS_EXTENSION), context);
success = true;
}
finally
{
if (!success)
{
Abort();
}
}
}
public override void StartDocument(int numStoredFields)
{
Write(DOC);
Write(Convert.ToString(_numDocsWritten, CultureInfo.InvariantCulture));
NewLine();
Write(NUM);
Write(Convert.ToString(numStoredFields, CultureInfo.InvariantCulture));
NewLine();
_numDocsWritten++;
}
public override void WriteField(FieldInfo info, IIndexableField field)
{
Write(FIELD);
Write(info.Number.ToString(CultureInfo.InvariantCulture));
NewLine();
Write(NAME);
Write(field.Name);
NewLine();
Write(TYPE);
// LUCENENET specific - To avoid boxing/unboxing, we don't
// call GetNumericValue(). Instead, we check the field.NumericType and then
// call the appropriate conversion method.
if (field.NumericType != NumericFieldType.NONE)
{
switch (field.NumericType)
{
case NumericFieldType.BYTE:
case NumericFieldType.INT16:
case NumericFieldType.INT32:
Write(TYPE_INT);
NewLine();
Write(VALUE);
Write(field.GetStringValue(CultureInfo.InvariantCulture));
NewLine();
break;
case NumericFieldType.INT64:
Write(TYPE_LONG);
NewLine();
Write(VALUE);
Write(field.GetStringValue(CultureInfo.InvariantCulture));
NewLine();
break;
case NumericFieldType.SINGLE:
Write(TYPE_FLOAT);
NewLine();
Write(VALUE);
// LUCENENET: Need to specify the "R" for round-trip: http://stackoverflow.com/a/611564
Write(field.GetStringValue("R", CultureInfo.InvariantCulture));
NewLine();
break;
case NumericFieldType.DOUBLE:
Write(TYPE_DOUBLE);
NewLine();
Write(VALUE);
// LUCENENET: Need to specify the "R" for round-trip: http://stackoverflow.com/a/611564
Write(field.GetStringValue("R", CultureInfo.InvariantCulture));
NewLine();
break;
default:
throw new ArgumentException("cannot store numeric type " + field.NumericType);
}
}
else
{
BytesRef bytes = field.GetBinaryValue();
if (bytes != null)
{
Write(TYPE_BINARY);
NewLine();
Write(VALUE);
Write(bytes);
NewLine();
}
else if (field.GetStringValue() == null)
{
throw new ArgumentException("field " + field.Name +
" is stored but does not have binaryValue, stringValue nor numericValue");
}
else
{
Write(TYPE_STRING);
NewLine();
Write(VALUE);
Write(field.GetStringValue());
NewLine();
}
}
}
public override void Abort()
{
try
{
Dispose();
}
finally
{
IOUtils.DeleteFilesIgnoringExceptions(_directory,
IndexFileNames.SegmentFileName(_segment, "", FIELDS_EXTENSION));
}
}
public override void Finish(FieldInfos fis, int numDocs)
{
if (_numDocsWritten != numDocs)
{
throw new Exception("mergeFields produced an invalid result: docCount is " + numDocs + " but only saw " +
_numDocsWritten + " file=" + _output +
"; now aborting this merge to prevent index corruption");
}
Write(END);
NewLine();
SimpleTextUtil.WriteChecksum(_output, _scratch);
}
protected override void Dispose(bool disposing)
{
if (!disposing) return;
try
{
IOUtils.Dispose(_output);
}
finally
{
_output = null;
}
}
private void Write(string s)
{
SimpleTextUtil.Write(_output, s, _scratch);
}
private void Write(BytesRef bytes)
{
SimpleTextUtil.Write(_output, bytes);
}
private void NewLine()
{
SimpleTextUtil.WriteNewline(_output);
}
}
}