// ----------------------------------------------------------------------- // // // 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. // // // ----------------------------------------------------------------------- namespace Lucene.Net.Analysis { using System; using System.IO; using System.Reflection; using Lucene.Net.Support; using Lucene.Net.Support.Threading; /// /// TODO: update /// public abstract class Analyzer : IDisposable { private ThreadLocal threadLocalTokenStream; private bool disposed = false; /// /// Initializes a new instance of the class. /// protected Analyzer() { if (this.AssertSealed() == false) throw new TypeLoadException( "{0} can not be used. It must be sealed or at least seal" + " the TokenStream and ResuableTokenStream methods" .Inject(this.GetType().Name)); } /// /// Gets the offset gap. /// /// An instance of . public virtual int OffsetGap { get { return 0; } } /// /// Gets or sets the previous token stream or token stream storage object. /// /// /// /// This can be used to store the previous token stream directly or it can /// use a custom storage mechanism like . /// /// /// The property name deviates from the Java version because the name is misleading. /// /// /// The previous token stream. Returns null if the value has not been set. /// /// Thrown when is already disposed. /// protected object PreviousTokenStreamOrStorage { get { if (this.disposed) throw new ObjectDisposedException(this.GetType().FullName); if (!this.threadLocalTokenStream.IsValueCreated) return null; return this.threadLocalTokenStream.Value; } set { if (this.disposed) throw new ObjectDisposedException(this.GetType().FullName); this.threadLocalTokenStream.Value = value; } } /// /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// public void Dispose() { this.Dispose(true); GC.SuppressFinalize(this); } /// /// Gets the position increment gap. /// /// Name of the field. /// An instance of . public virtual int GetPositionIncrementGap(string fieldName) { return 0; } /// /// Creates a using the specified . /// /// /// /// Subclasses that implement this method should always be able to handle null /// values for the field name for backwards compatibility. /// /// /// Name of the field. /// The reader. /// /// An instance of . /// public abstract TokenStream TokenStream(string fieldName, StreamReader reader); /// /// Finds or creates a that is permits the /// to be re-used on the same thread. /// /// /// /// Any Class that manages the current and does not need to use more /// than one at the same time should use this method for /// better performance. /// /// /// Name of the field. /// The reader. /// /// An instance of . /// public virtual TokenStream ReusableTokenStream(string fieldName, StreamReader reader) { return this.TokenStream(fieldName, reader); } /// /// Releases unmanaged and - optionally - managed resources /// /// true to release both managed and unmanaged resources; false to release only unmanaged resources. protected virtual void Dispose(bool disposing) { if (disposing) { this.disposed = true; this.threadLocalTokenStream.Dispose(); this.threadLocalTokenStream = null; } } // AssertSealed was ported from java-lucene-core, but I'm not convinced // this is best way to handle this kind of design decision in .NET. // It might be better to create an analysis tool or put these kind of // assertions inside the testing framework. // TODO: remove AssertSealed() / assertSealed. private bool AssertSealed() { Type type = this.GetType(); if (type.IsSealed || type.IsAbstract) return true; BindingFlags flags = BindingFlags.Public | BindingFlags.Instance; MethodInfo tokenStreamMethod = type.GetMethod("TokenStream", flags); MethodInfo reuseableTokenStreamMethod = type.GetMethod("ReusableTokenStreamMethod", flags); if (tokenStreamMethod != null && !tokenStreamMethod.IsFinal) return false; return reuseableTokenStreamMethod == null || reuseableTokenStreamMethod.IsFinal; } } }