| 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) |
| { |
| Codec.codecFactory = codecFactory ?? throw new ArgumentNullException(nameof(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; |
| } |
| } |
| } |