Lucene.Net  3.0.3
Lucene.Net is a port of the Lucene search engine library, written in C# and targeted at .NET runtime users.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Properties Pages
WildcardTermEnum.cs
Go to the documentation of this file.
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 using System;
19 
20 using IndexReader = Lucene.Net.Index.IndexReader;
21 using Term = Lucene.Net.Index.Term;
22 
23 namespace Lucene.Net.Search
24 {
25 
26  /// <summary> Subclass of FilteredTermEnum for enumerating all terms that match the
27  /// specified wildcard filter term.
28  /// <p/>
29  /// Term enumerations are always ordered by Term.compareTo(). Each term in
30  /// the enumeration is greater than all that precede it.
31  /// </summary>
33  {
34  internal Term searchTerm;
35  internal System.String field;
36  internal System.String text;
37  internal System.String pre;
38  internal int preLen;
39  internal bool endEnum = false;
40 
41  /// <summary> Creates a new <c>WildcardTermEnum</c>.
42  /// <p/>
43  /// After calling the constructor the enumeration is already pointing to the first
44  /// valid term if such a term exists.
45  /// </summary>
46  public WildcardTermEnum(IndexReader reader, Term term):base()
47  {
48  searchTerm = term;
49  field = searchTerm.Field;
50  System.String searchTermText = searchTerm.Text;
51 
52  int sidx = searchTermText.IndexOf((System.Char) WILDCARD_STRING);
53  int cidx = searchTermText.IndexOf((System.Char) WILDCARD_CHAR);
54  int idx = sidx;
55  if (idx == - 1)
56  {
57  idx = cidx;
58  }
59  else if (cidx >= 0)
60  {
61  idx = System.Math.Min(idx, cidx);
62  }
63  pre = idx != - 1?searchTerm.Text.Substring(0, (idx) - (0)):"";
64 
65  preLen = pre.Length;
66  text = searchTermText.Substring(preLen);
67  SetEnum(reader.Terms(new Term(searchTerm.Field, pre)));
68  }
69 
70  /*protected internal*/ protected internal override bool TermCompare(Term term)
71  {
72  if ((System.Object) field == (System.Object) term.Field)
73  {
74  System.String searchText = term.Text;
75  if (searchText.StartsWith(pre))
76  {
77  return WildcardEquals(text, 0, searchText, preLen);
78  }
79  }
80  endEnum = true;
81  return false;
82  }
83 
84  public override float Difference()
85  {
86  return 1.0f;
87  }
88 
89  public override bool EndEnum()
90  {
91  return endEnum;
92  }
93 
94  /// <summary>*****************************************
95  /// String equality with support for wildcards
96  /// ******************************************
97  /// </summary>
98 
99  public const char WILDCARD_STRING = '*';
100  public const char WILDCARD_CHAR = '?';
101 
102  /// <summary> Determines if a word matches a wildcard pattern.
103  /// <small>Work released by Granta Design Ltd after originally being done on
104  /// company time.</small>
105  /// </summary>
106  public static bool WildcardEquals(System.String pattern, int patternIdx, System.String string_Renamed, int stringIdx)
107  {
108  int p = patternIdx;
109 
110  for (int s = stringIdx; ; ++p, ++s)
111  {
112  // End of string yet?
113  bool sEnd = (s >= string_Renamed.Length);
114  // End of pattern yet?
115  bool pEnd = (p >= pattern.Length);
116 
117  // If we're looking at the end of the string...
118  if (sEnd)
119  {
120  // Assume the only thing left on the pattern is/are wildcards
121  bool justWildcardsLeft = true;
122 
123  // Current wildcard position
124  int wildcardSearchPos = p;
125  // While we haven't found the end of the pattern,
126  // and haven't encountered any non-wildcard characters
127  while (wildcardSearchPos < pattern.Length && justWildcardsLeft)
128  {
129  // Check the character at the current position
130  char wildchar = pattern[wildcardSearchPos];
131 
132  // If it's not a wildcard character, then there is more
133  // pattern information after this/these wildcards.
134  if (wildchar != WILDCARD_CHAR && wildchar != WILDCARD_STRING)
135  {
136  justWildcardsLeft = false;
137  }
138  else
139  {
140  // to prevent "cat" matches "ca??"
141  if (wildchar == WILDCARD_CHAR)
142  {
143  return false;
144  }
145 
146  // Look at the next character
147  wildcardSearchPos++;
148  }
149  }
150 
151  // This was a prefix wildcard search, and we've matched, so
152  // return true.
153  if (justWildcardsLeft)
154  {
155  return true;
156  }
157  }
158 
159  // If we've gone past the end of the string, or the pattern,
160  // return false.
161  if (sEnd || pEnd)
162  {
163  break;
164  }
165 
166  // Match a single character, so continue.
167  if (pattern[p] == WILDCARD_CHAR)
168  {
169  continue;
170  }
171 
172  //
173  if (pattern[p] == WILDCARD_STRING)
174  {
175  // Look at the character beyond the '*' characters.
176  while (p < pattern.Length && pattern[p] == WILDCARD_STRING)
177  ++p;
178  // Examine the string, starting at the last character.
179  for (int i = string_Renamed.Length; i >= s; --i)
180  {
181  if (WildcardEquals(pattern, p, string_Renamed, i))
182  {
183  return true;
184  }
185  }
186  break;
187  }
188  if (pattern[p] != string_Renamed[s])
189  {
190  break;
191  }
192  }
193  return false;
194  }
195  }
196 }