/* * Copyright 2004 The Apache Software Foundation * * Licensed 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 System; using IndexReader = Lucene.Net.Index.IndexReader; using Term = Lucene.Net.Index.Term; namespace Lucene.Net.Search { /// Subclass of FilteredTermEnum for enumerating all terms that match the /// specified wildcard filter term. ///

/// Term enumerations are always ordered by Term.compareTo(). Each term in /// the enumeration is greater than all that precede it. /// ///

/// $Id: WildcardTermEnum.cs,v 1.3 2005/10/06 19:29:57 dsd Exp $ /// public class WildcardTermEnum : FilteredTermEnum { internal Term searchTerm; internal System.String field = ""; internal System.String text = ""; internal System.String pre = ""; internal int preLen = 0; internal bool endEnum = false; /// Creates a new WildcardTermEnum. Passing in a /// {@link Lucene.Net.Index.Term Term} that does not contain a /// WILDCARD_CHAR will cause an exception to be thrown. ///

/// After calling the constructor the enumeration is already pointing to the first /// valid term if such a term exists. ///

public WildcardTermEnum(IndexReader reader, Term term):base() { searchTerm = term; field = searchTerm.Field(); text = searchTerm.Text(); int sidx = text.IndexOf((System.Char) WILDCARD_STRING); int cidx = text.IndexOf((System.Char) WILDCARD_CHAR); int idx = sidx; if (idx == - 1) { idx = cidx; } else if (cidx >= 0) { idx = System.Math.Min(idx, cidx); } pre = searchTerm.Text().Substring(0, (idx) - (0)); preLen = pre.Length; text = text.Substring(preLen); SetEnum(reader.Terms(new Term(searchTerm.Field(), pre))); } protected internal override bool TermCompare(Term term) { if ((System.Object) field == (System.Object) term.Field()) { System.String searchText = term.Text(); if (searchText.StartsWith(pre)) { return WildcardEquals(text, 0, searchText, preLen); } } endEnum = true; return false; } public override float Difference() { return 1.0f; } public override bool EndEnum() { return endEnum; } /// ***************************************** /// String equality with support for wildcards /// ****************************************** /// public const char WILDCARD_STRING = '*'; public const char WILDCARD_CHAR = '?'; /// Determines if a word matches a wildcard pattern. /// Work released by Granta Design Ltd after originally being done on /// company time. /// public static bool WildcardEquals(System.String pattern, int patternIdx, System.String string_Renamed, int stringIdx) { int p = patternIdx; for (int s = stringIdx; ; ++p, ++s) { // End of string yet? bool sEnd = (s >= string_Renamed.Length); // End of pattern yet? bool pEnd = (p >= pattern.Length); // If we're looking at the end of the string... if (sEnd) { // Assume the only thing left on the pattern is/are wildcards bool justWildcardsLeft = true; // Current wildcard position int wildcardSearchPos = p; // While we haven't found the end of the pattern, // and haven't encountered any non-wildcard characters while (wildcardSearchPos < pattern.Length && justWildcardsLeft) { // Check the character at the current position char wildchar = pattern[wildcardSearchPos]; // If it's not a wildcard character, then there is more // pattern information after this/these wildcards. if (wildchar != WILDCARD_CHAR && wildchar != WILDCARD_STRING) { justWildcardsLeft = false; } else { // Look at the next character wildcardSearchPos++; } } // This was a prefix wildcard search, and we've matched, so // return true. if (justWildcardsLeft) { return true; } } // If we've gone past the end of the string, or the pattern, // return false. if (sEnd || pEnd) { break; } // Match a single character, so continue. if (pattern[p] == WILDCARD_CHAR) { continue; } // if (pattern[p] == WILDCARD_STRING) { // Look at the character beyond the '*'. ++p; // Examine the string, starting at the last character. for (int i = string_Renamed.Length; i >= s; --i) { if (WildcardEquals(pattern, p, string_Renamed, i)) { return true; } } break; } if (pattern[p] != string_Renamed[s]) { break; } } return false; } public override void Close() { base.Close(); searchTerm = null; field = null; text = null; } } }