| using Lucene.Net.Index; |
| using Lucene.Net.Support; |
| using Lucene.Net.Util; |
| using System; |
| using System.Collections.Generic; |
| using System.IO; |
| |
| 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 terms, postings, and proximity data. |
| /// <para/> |
| /// Note, when extending this class, the name (<see cref="Name"/>) may |
| /// written into the index in certain configurations. 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="IPostingsFormatFactory.GetPostingsFormat(string)"/> to resolve format names. |
| /// <para/> |
| /// If you implement your own format: |
| /// <list type="number"> |
| /// <item><description>Subclass this class.</description></item> |
| /// <item><description>Subclass <see cref="DefaultPostingsFormatFactory"/>, override <see cref="DefaultPostingsFormatFactory.Initialize()"/>, |
| /// and add the line <c>base.ScanForPostingsFormats(typeof(YourPostingsFormat).Assembly)</c>. |
| /// If you have any format classes in your assembly |
| /// that are not meant for reading, you can add the <see cref="ExcludePostingsFormatFromScanAttribute"/> |
| /// to them so they are ignored by the scan.</description></item> |
| /// <item><description>Set the new <see cref="IPostingsFormatFactory"/> by calling <see cref="SetPostingsFormatFactory(IPostingsFormatFactory)"/> |
| /// at application startup.</description></item> |
| /// </list> |
| /// If your format has dependencies, you may also override <see cref="DefaultPostingsFormatFactory.GetPostingsFormat(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>PostingsFormat Names</b> |
| /// <para/> |
| /// Unlike the Java version, format names are by default convention-based on the class name. |
| /// If you name your custom format class "MyCustomPostingsFormat", the codec name will the same name |
| /// without the "PostingsFormat" suffix: "MyCustom". |
| /// <para/> |
| /// You can override this default behavior by using the <see cref="PostingsFormatNameAttribute"/> to |
| /// name the format differently than this convention. Format names must be all ASCII alphanumeric, |
| /// and less than 128 characters in length. |
| /// <para/> |
| /// @lucene.experimental |
| /// </summary> |
| /// <seealso cref="DefaultPostingsFormatFactory"/> |
| /// <seealso cref="IPostingsFormatFactory"/> |
| /// <seealso cref="PostingsFormatNameAttribute"/> |
| // LUCENENET specific - refactored this class so it depends on IPostingsFormatFactory rather than |
| // the Java-centric NamedSPILoader |
| public abstract class PostingsFormat //: NamedSPILoader.INamedSPI |
| { |
| private static IPostingsFormatFactory postingsFormatFactory = new DefaultPostingsFormatFactory(); |
| |
| /// <summary> |
| /// Zero-length <see cref="PostingsFormat"/> array. </summary> |
| public static readonly PostingsFormat[] EMPTY = Arrays.Empty<PostingsFormat>(); |
| |
| /// <summary> |
| /// Unique name that's used to retrieve this format when |
| /// reading the index. |
| /// </summary> |
| private readonly string name; |
| |
| /// <summary> |
| /// Sets the <see cref="IPostingsFormatFactory"/> instance used to instantiate |
| /// <see cref="PostingsFormat"/> subclasses. |
| /// </summary> |
| /// <param name="postingsFormatFactory">The new <see cref="IPostingsFormatFactory"/>.</param> |
| /// <exception cref="ArgumentNullException">The <paramref name="postingsFormatFactory"/> parameter is <c>null</c>.</exception> |
| public static void SetPostingsFormatFactory(IPostingsFormatFactory postingsFormatFactory) |
| { |
| if (postingsFormatFactory == null) |
| throw new ArgumentNullException("postingsFormatFactory"); |
| PostingsFormat.postingsFormatFactory = postingsFormatFactory; |
| } |
| |
| /// <summary> |
| /// Gets the associated <see cref="PostingsFormat"/> factory. |
| /// </summary> |
| /// <returns>The <see cref="PostingsFormat"/> factory.</returns> |
| public static IPostingsFormatFactory GetPostingsFormatFactory() |
| { |
| return postingsFormatFactory; |
| } |
| |
| /// <summary> |
| /// Creates a new postings format. |
| /// <para/> |
| /// The provided name will be written into the index segment in some configurations |
| /// (such as when using <see cref="PerField.PerFieldPostingsFormat"/>): in such configurations, |
| /// for the segment to be read this class should be registered by subclassing <see cref="DefaultPostingsFormatFactory"/> and |
| /// calling <see cref="DefaultPostingsFormatFactory.ScanForPostingsFormats(System.Reflection.Assembly)"/> in the class constructor. |
| /// The new <see cref="IPostingsFormatFactory"/> can be registered by calling <see cref="SetPostingsFormatFactory(IPostingsFormatFactory)"/> at application startup.</summary> |
| protected PostingsFormat() |
| { |
| this.name = NamedServiceFactory<PostingsFormat>.GetServiceName(this.GetType()); |
| } |
| |
| /// <summary> |
| /// Returns this posting format's name. </summary> |
| public string Name => name; |
| |
| /// <summary> |
| /// Writes a new segment. </summary> |
| public abstract FieldsConsumer FieldsConsumer(SegmentWriteState state); |
| |
| /// <summary> |
| /// Reads a segment. NOTE: by the time this call |
| /// returns, it must hold open any files it will need to |
| /// use; else, those files may be deleted. |
| /// Additionally, required files may be deleted during the execution of |
| /// this call before there is a chance to open them. Under these |
| /// circumstances an <see cref="IOException"/> should be thrown by the implementation. |
| /// <see cref="IOException"/>s are expected and will automatically cause a retry of the |
| /// segment opening logic with the newly revised segments. |
| /// </summary> |
| public abstract FieldsProducer FieldsProducer(SegmentReadState state); |
| |
| public override string ToString() |
| { |
| return "PostingsFormat(name=" + name + ")"; |
| } |
| |
| /// <summary> |
| /// Looks up a format by name. </summary> |
| public static PostingsFormat ForName(string name) |
| { |
| return postingsFormatFactory.GetPostingsFormat(name); |
| } |
| |
| /// <summary> |
| /// Returns a list of all available format names. </summary> |
| public static ICollection<string> AvailablePostingsFormats |
| { |
| get |
| { |
| if (postingsFormatFactory is IServiceListable) |
| { |
| return ((IServiceListable)postingsFormatFactory).AvailableServices; |
| } |
| else |
| { |
| throw new NotSupportedException("The current PostingsFormat factory class does not implement IServiceListable."); |
| } |
| } |
| } |
| |
| // LUCENENET specific: Removed the ReloadPostingsFormats() method because |
| // this goes against the grain of standard DI practices. |
| } |
| } |