2 * Copyright 2004 The Apache Software Foundation
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 using IndexReader
= Lucene
.Net
.Index
.IndexReader
;
19 using Term
= Lucene
.Net
.Index
.Term
;
20 using TermDocs
= Lucene
.Net
.Index
.TermDocs
;
21 using TermEnum
= Lucene
.Net
.Index
.TermEnum
;
22 using StringIndex
= Lucene
.Net
.Search
.StringIndex
;
24 namespace Lucene
.Net
.Search
27 /// <summary> Expert: The default cache implementation, storing all values in memory.
28 /// A WeakHashMap is used for storage.
30 /// <p>Created: May 19, 2004 4:40:36 PM
33 /// <author> Tim Jones (Nacimiento Software)
35 /// <since> lucene 1.4
37 /// <version> $Id: FieldCacheImpl.cs,v 1.3 2006/10/02 17:09:02 joeshaw Exp $
39 class FieldCacheImpl
: FieldCache
41 public class AnonymousClassIntParser
: IntParser
43 public virtual int ParseInt(System
.String value_Renamed
)
45 return System
.Int32
.Parse(value_Renamed
);
48 public class AnonymousClassFloatParser
: FloatParser
50 public virtual float ParseFloat(System
.String value_Renamed
)
52 return System
.Single
.Parse(value_Renamed
);
56 /// <summary>Expert: Every key in the internal cache is of this type. </summary>
59 internal System
.String field
; // which Field
60 internal int type
; // which SortField type
61 internal System
.Object custom
; // which custom comparator
63 /// <summary>Creates one of these objects. </summary>
64 internal Entry(System
.String field
, int type
)
66 this.field
= String
.Intern(field
);
71 /// <summary>Creates one of these objects for a custom comparator. </summary>
72 internal Entry(System
.String field
, System
.Object custom
)
74 this.field
= String
.Intern(field
);
75 this.type
= SortField
.CUSTOM
;
79 /// <summary>Two of these are equal iff they reference the same field and type. </summary>
80 public override bool Equals(System
.Object o
)
84 Entry other
= (Entry
) o
;
85 if (other
.field
== field
&& other
.type
== type
)
87 if (other
.custom
== null)
92 else if (other
.custom
.Equals(custom
))
101 /// <summary>Composes a hashcode based on the field and type. </summary>
102 public override int GetHashCode()
104 return field
.GetHashCode() ^ type ^
(custom
== null?0:custom
.GetHashCode());
108 private static readonly IntParser INT_PARSER
;
110 private static readonly FloatParser FLOAT_PARSER
;
112 /// <summary>The internal cache. Maps Entry to array of interpreted term values. *</summary>
113 internal System
.Collections
.IDictionary cache
= new System
.Collections
.Hashtable();
115 /// <summary>See if an object is in the cache. </summary>
116 internal virtual System
.Object
Lookup(IndexReader reader
, System
.String field
, int type
)
118 Entry entry
= new Entry(field
, type
);
121 System
.Collections
.Hashtable readerCache
= (System
.Collections
.Hashtable
) cache
[reader
];
122 if (readerCache
== null)
124 return readerCache
[entry
];
128 /// <summary>See if a custom object is in the cache. </summary>
129 internal virtual System
.Object
Lookup(IndexReader reader
, System
.String field
, System
.Object comparer
)
131 Entry entry
= new Entry(field
, comparer
);
134 System
.Collections
.Hashtable readerCache
= (System
.Collections
.Hashtable
) cache
[reader
];
135 if (readerCache
== null)
137 return readerCache
[entry
];
141 /// <summary>Put an object into the cache. </summary>
142 internal virtual System
.Object
Store(IndexReader reader
, System
.String field
, int type
, System
.Object value_Renamed
)
144 Entry entry
= new Entry(field
, type
);
147 System
.Collections
.Hashtable readerCache
= (System
.Collections
.Hashtable
) cache
[reader
];
148 if (readerCache
== null)
150 readerCache
= new System
.Collections
.Hashtable();
151 cache
[reader
] = readerCache
;
153 System
.Object tempObject
;
154 tempObject
= readerCache
[entry
];
155 readerCache
[entry
] = value_Renamed
;
160 /// <summary>Put a custom object into the cache. </summary>
161 internal virtual System
.Object
Store(IndexReader reader
, System
.String field
, System
.Object comparer
, System
.Object value_Renamed
)
163 Entry entry
= new Entry(field
, comparer
);
166 System
.Collections
.Hashtable readerCache
= (System
.Collections
.Hashtable
) cache
[reader
];
167 if (readerCache
== null)
169 readerCache
= new System
.Collections
.Hashtable();
170 cache
[reader
] = readerCache
;
172 System
.Object tempObject
;
173 tempObject
= readerCache
[entry
];
174 readerCache
[entry
] = value_Renamed
;
180 public virtual int[] GetInts(IndexReader reader
, System
.String field
)
182 return GetInts(reader
, field
, INT_PARSER
);
186 public virtual int[] GetInts(IndexReader reader
, System
.String field
, IntParser parser
)
188 field
= String
.Intern(field
);
189 System
.Object ret
= Lookup(reader
, field
, parser
);
192 int[] retArray
= new int[reader
.MaxDoc()];
193 if (retArray
.Length
> 0)
195 TermDocs termDocs
= reader
.TermDocs();
196 TermEnum termEnum
= reader
.Terms(new Term(field
, ""));
199 if (termEnum
.Term() == null)
201 throw new System
.SystemException("no terms in field " + field
);
205 Term term
= termEnum
.Term();
206 if (term
.Field() != field
)
208 int termval
= parser
.ParseInt(term
.Text());
209 termDocs
.Seek(termEnum
);
210 while (termDocs
.Next())
212 retArray
[termDocs
.Doc()] = termval
;
215 while (termEnum
.Next());
223 Store(reader
, field
, parser
, retArray
);
230 public virtual float[] GetFloats(IndexReader reader
, System
.String field
)
232 return GetFloats(reader
, field
, FLOAT_PARSER
);
236 public virtual float[] GetFloats(IndexReader reader
, System
.String field
, FloatParser parser
)
238 field
= String
.Intern(field
);
239 System
.Object ret
= Lookup(reader
, field
, parser
);
242 float[] retArray
= new float[reader
.MaxDoc()];
243 if (retArray
.Length
> 0)
245 TermDocs termDocs
= reader
.TermDocs();
246 TermEnum termEnum
= reader
.Terms(new Term(field
, ""));
249 if (termEnum
.Term() == null)
251 throw new System
.SystemException("no terms in field " + field
);
255 Term term
= termEnum
.Term();
256 if (term
.Field() != field
)
261 termval
= SupportClass
.Single
.Parse(term
.Text());
267 termDocs
.Seek(termEnum
);
268 while (termDocs
.Next())
270 retArray
[termDocs
.Doc()] = termval
;
273 while (termEnum
.Next());
281 Store(reader
, field
, parser
, retArray
);
284 return (float[]) ret
;
288 public virtual System
.String
[] GetStrings(IndexReader reader
, System
.String field
)
290 field
= String
.Intern(field
);
291 System
.Object ret
= Lookup(reader
, field
, SortField
.STRING
);
294 System
.String
[] retArray
= new System
.String
[reader
.MaxDoc()];
295 if (retArray
.Length
> 0)
297 TermDocs termDocs
= reader
.TermDocs();
298 TermEnum termEnum
= reader
.Terms(new Term(field
, ""));
301 if (termEnum
.Term() == null)
303 throw new System
.SystemException("no terms in field " + field
);
307 Term term
= termEnum
.Term();
308 if (term
.Field() != field
)
310 System
.String termval
= term
.Text();
311 termDocs
.Seek(termEnum
);
312 while (termDocs
.Next())
314 retArray
[termDocs
.Doc()] = termval
;
317 while (termEnum
.Next());
325 Store(reader
, field
, SortField
.STRING
, retArray
);
328 return (System
.String
[]) ret
;
332 public virtual StringIndex
GetStringIndex(IndexReader reader
, System
.String field
)
334 field
= String
.Intern(field
);
335 System
.Object ret
= Lookup(reader
, field
, Lucene
.Net
.Search
.FieldCache_Fields
.STRING_INDEX
);
338 int[] retArray
= new int[reader
.MaxDoc()];
339 System
.String
[] mterms
= new System
.String
[reader
.MaxDoc() + 1];
340 if (retArray
.Length
> 0)
342 TermDocs termDocs
= reader
.TermDocs();
343 TermEnum termEnum
= reader
.Terms(new Term(field
, ""));
344 int t
= 0; // current term number
346 // an entry for documents that have no terms in this field
347 // should a document with no terms be at top or bottom?
348 // this puts them at the top - if it is changed, FieldDocSortedHitQueue
349 // needs to change as well.
354 if (termEnum
.Term() == null)
356 throw new System
.SystemException("no terms in field " + field
);
360 Term term
= termEnum
.Term();
361 if (term
.Field() != field
)
365 // we expect that there is at most one term per document
366 if (t
>= mterms
.Length
)
367 throw new System
.SystemException("there are more terms than " + "documents in field \"" + field
+ "\", but it's impossible to sort on " + "tokenized fields");
368 mterms
[t
] = term
.Text();
370 termDocs
.Seek(termEnum
);
371 while (termDocs
.Next())
373 retArray
[termDocs
.Doc()] = t
;
378 while (termEnum
.Next());
388 // if there are no terms, make the term array
389 // have a single null entry
390 mterms
= new System
.String
[1];
392 else if (t
< mterms
.Length
)
394 // if there are less terms than documents,
395 // trim off the dead array space
396 System
.String
[] terms
= new System
.String
[t
];
397 Array
.Copy(mterms
, 0, terms
, 0, t
);
401 StringIndex value_Renamed
= new StringIndex(retArray
, mterms
);
402 Store(reader
, field
, Lucene
.Net
.Search
.FieldCache_Fields
.STRING_INDEX
, value_Renamed
);
403 return value_Renamed
;
405 return (StringIndex
) ret
;
408 /// <summary>The pattern used to detect integer values in a field </summary>
409 /// <summary>removed for java 1.3 compatibility
410 /// protected static final Pattern pIntegers = Pattern.compile ("[0-9\\-]+");
414 /// <summary>The pattern used to detect float values in a field </summary>
415 /// <summary> removed for java 1.3 compatibility
416 /// protected static final Object pFloats = Pattern.compile ("[0-9+\\-\\.eEfFdD]+");
420 public virtual System
.Object
GetAuto(IndexReader reader
, System
.String field
)
422 field
= String
.Intern(field
);
423 System
.Object ret
= Lookup(reader
, field
, SortField
.AUTO
);
426 TermEnum enumerator
= reader
.Terms(new Term(field
, ""));
429 Term term
= enumerator
.Term();
432 throw new System
.SystemException("no terms in field " + field
+ " - cannot determine sort type");
434 if (term
.Field() == field
)
436 System
.String termtext
= term
.Text().Trim();
439 * Java 1.4 level code:
441 if (pIntegers.matcher(termtext).matches())
442 return IntegerSortedHitQueue.comparator (reader, enumerator, field);
444 else if (pFloats.matcher(termtext).matches())
445 return FloatSortedHitQueue.comparator (reader, enumerator, field);
448 // Java 1.3 level code:
451 System
.Int32
.Parse(termtext
);
452 ret
= GetInts(reader
, field
);
454 catch (System
.FormatException nfe1
)
458 System
.Single
.Parse(termtext
);
459 ret
= GetFloats(reader
, field
);
461 catch (System
.FormatException nfe2
)
463 ret
= GetStringIndex(reader
, field
);
468 Store(reader
, field
, SortField
.AUTO
, ret
);
473 throw new System
.SystemException("field \"" + field
+ "\" does not appear to be indexed");
485 public virtual System
.IComparable
[] GetCustom(IndexReader reader
, System
.String field
, SortComparator comparator
)
487 field
= String
.Intern(field
);
488 System
.Object ret
= Lookup(reader
, field
, comparator
);
491 System
.IComparable
[] retArray
= new System
.IComparable
[reader
.MaxDoc()];
492 if (retArray
.Length
> 0)
494 TermDocs termDocs
= reader
.TermDocs();
495 TermEnum termEnum
= reader
.Terms(new Term(field
, ""));
498 if (termEnum
.Term() == null)
500 throw new System
.SystemException("no terms in field " + field
);
504 Term term
= termEnum
.Term();
505 if (term
.Field() != field
)
507 System
.IComparable termval
= comparator
.GetComparable(term
.Text());
508 termDocs
.Seek(termEnum
);
509 while (termDocs
.Next())
511 retArray
[termDocs
.Doc()] = termval
;
514 while (termEnum
.Next());
522 Store(reader
, field
, comparator
, retArray
);
525 return (System
.IComparable
[]) ret
;
527 static FieldCacheImpl()
529 INT_PARSER
= new AnonymousClassIntParser();
530 FLOAT_PARSER
= new AnonymousClassFloatParser();