/* | |
* 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. | |
*/ | |
using System; | |
using IndexReader = Lucene.Net.Index.IndexReader; | |
using Term = Lucene.Net.Index.Term; | |
namespace Lucene.Net.Search | |
{ | |
/// <summary> Subclass of FilteredTermEnum for enumerating all terms that match the | |
/// specified wildcard filter term. | |
/// <p> | |
/// Term enumerations are always ordered by Term.compareTo(). Each term in | |
/// the enumeration is greater than all that precede it. | |
/// | |
/// </summary> | |
/// <version> $Id: WildcardTermEnum.java 472959 2006-11-09 16:21:50Z yonik $ | |
/// </version> | |
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; | |
/// <summary> Creates a new <code>WildcardTermEnum</code>. Passing in a | |
/// {@link Lucene.Net.Index.Term Term} that does not contain a | |
/// <code>WILDCARD_CHAR</code> will cause an exception to be thrown. | |
/// <p> | |
/// After calling the constructor the enumeration is already pointing to the first | |
/// valid term if such a term exists. | |
/// </summary> | |
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 (field == 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; | |
} | |
/// <summary>***************************************** | |
/// String equality with support for wildcards | |
/// ****************************************** | |
/// </summary> | |
public const char WILDCARD_STRING = '*'; | |
public const char WILDCARD_CHAR = '?'; | |
/// <summary> Determines if a word matches a wildcard pattern. | |
/// <small>Work released by Granta Design Ltd after originally being done on | |
/// company time.</small> | |
/// </summary> | |
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 | |
{ | |
// to prevent "cat" matches "ca??" | |
if (wildchar == WILDCARD_CHAR) | |
{ | |
return false; | |
} | |
// 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; | |
} | |
} | |
} |