blob: b489c8c8791bbd99300d90d9aee9f7e3de71abae [file] [log] [blame]
using Lucene.Net.Util;
using System;
using System.Collections.Generic;
namespace Lucene.Net.Codecs
{
/*
* 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.
*/
/// <summary>
/// Encodes/decodes an inverted index segment.
/// <para/>
/// Note, when extending this class, the name (<see cref="Name"/>) is
/// written into the index. In order for the segment to be read, the
/// name must resolve to your implementation via <see cref="ForName(string)"/>.
/// This method uses <see cref="ICodecFactory.GetCodec(string)"/> to resolve codec names.
/// <para/>
/// To implement your own codec:
/// <list type="number">
/// <item><description>Subclass this class.</description></item>
/// <item><description>Subclass <see cref="DefaultCodecFactory"/>, override the <see cref="DefaultCodecFactory.Initialize()"/> method,
/// and add the line <c>base.ScanForCodecs(typeof(YourCodec).Assembly)</c>.
/// If you have any codec classes in your assembly
/// that are not meant for reading, you can add the <see cref="ExcludeCodecFromScanAttribute"/>
/// to them so they are ignored by the scan.</description></item>
/// <item><description>set the new <see cref="ICodecFactory"/> by calling <see cref="SetCodecFactory"/> at application startup.</description></item>
/// </list>
/// If your codec has dependencies, you may also override <see cref="DefaultCodecFactory.GetCodec(Type)"/> to inject
/// them via pure DI or a DI container. See <a href="http://blog.ploeh.dk/2014/05/19/di-friendly-framework/">DI-Friendly Framework</a>
/// to understand the approach used.
/// <para/>
/// <b>Codec Names</b>
/// <para/>
/// Unlike the Java version, codec names are by default convention-based on the class name.
/// If you name your custom codec class "MyCustomCodec", the codec name will the same name
/// without the "Codec" suffix: "MyCustom".
/// <para/>
/// You can override this default behavior by using the <see cref="CodecNameAttribute"/> to
/// name the codec differently than this convention. Codec names must be all ASCII alphanumeric,
/// and less than 128 characters in length.
/// </summary>
/// <seealso cref="DefaultCodecFactory"/>
/// <seealso cref="ICodecFactory"/>
/// <seealso cref="CodecNameAttribute"/>
// LUCENENET specific - refactored this class so it depends on ICodecFactory rather than
// the Java-centric NamedSPILoader
public abstract class Codec //: NamedSPILoader.INamedSPI
{
private static ICodecFactory codecFactory = new DefaultCodecFactory();
private readonly string name;
/// <summary>
/// Sets the <see cref="ICodecFactory"/> instance used to instantiate
/// <see cref="Codec"/> subclasses.
/// </summary>
/// <param name="codecFactory">The new <see cref="ICodecFactory"/>.</param>
/// <exception cref="ArgumentNullException">The <paramref name="codecFactory"/> parameter is <c>null</c>.</exception>
public static void SetCodecFactory(ICodecFactory codecFactory)
{
if (codecFactory == null)
throw new ArgumentNullException("codecFactory");
Codec.codecFactory = codecFactory;
}
/// <summary>
/// Gets the associated codec factory.
/// </summary>
/// <returns>The codec factory.</returns>
public static ICodecFactory GetCodecFactory()
{
return codecFactory;
}
/// <summary>
/// Creates a new codec.
/// <para/>
/// The <see cref="Codec.Name"/> will be written into the index segment: in order for
/// the segment to be read this class should be registered by subclassing <see cref="DefaultCodecFactory"/> and
/// calling <see cref="DefaultCodecFactory.ScanForCodecs(System.Reflection.Assembly)"/> in the class constructor.
/// The new <see cref="ICodecFactory"/> can be registered by calling <see cref="SetCodecFactory"/> at application startup.</summary>
protected Codec()
{
name = NamedServiceFactory<Codec>.GetServiceName(this.GetType());
}
/// <summary>
/// Returns this codec's name. </summary>
public string Name => name;
/// <summary>
/// Encodes/decodes postings. </summary>
public abstract PostingsFormat PostingsFormat { get; }
/// <summary>
/// Encodes/decodes docvalues. </summary>
public abstract DocValuesFormat DocValuesFormat { get; }
/// <summary>
/// Encodes/decodes stored fields. </summary>
public abstract StoredFieldsFormat StoredFieldsFormat { get; }
/// <summary>
/// Encodes/decodes term vectors. </summary>
public abstract TermVectorsFormat TermVectorsFormat { get; }
/// <summary>
/// Encodes/decodes field infos file. </summary>
public abstract FieldInfosFormat FieldInfosFormat { get; }
/// <summary>
/// Encodes/decodes segment info file. </summary>
public abstract SegmentInfoFormat SegmentInfoFormat { get; }
/// <summary>
/// Encodes/decodes document normalization values. </summary>
public abstract NormsFormat NormsFormat { get; }
/// <summary>
/// Encodes/decodes live docs. </summary>
public abstract LiveDocsFormat LiveDocsFormat { get; }
/// <summary>
/// Looks up a codec by name. </summary>
public static Codec ForName(string name)
{
return codecFactory.GetCodec(name);
}
/// <summary>
/// Returns a list of all available codec names. </summary>
public static ICollection<string> AvailableCodecs
{
get
{
if (codecFactory is IServiceListable)
{
return ((IServiceListable)codecFactory).AvailableServices;
}
else
{
throw new NotSupportedException("The current CodecFactory class does not implement IServiceListable.");
}
}
}
// LUCENENET specific: Removed the ReloadCodecs() method because
// this goes against the grain of standard DI practices.
private static Codec defaultCodec;
/// <summary>
/// Expert: returns the default codec used for newly created
/// <seealso cref="Index.IndexWriterConfig"/>s.
/// </summary>
// TODO: should we use this, or maybe a system property is better?
public static Codec Default
{
get
{
// Lazy load the default codec if not already supplied
if (defaultCodec == null)
{
defaultCodec = Codec.ForName("Lucene46");
}
return defaultCodec;
}
set => defaultCodec = value;
}
/// <summary>
/// Returns the codec's name. Subclasses can override to provide
/// more detail (such as parameters).
/// </summary>
public override string ToString()
{
return name;
}
}
}