FieldCacheImpl.cs
上传用户:zhangkuixh
上传日期:2013-09-30
资源大小:5473k
文件大小:15k
源码类别:

搜索引擎

开发平台:

C#

  1. /*
  2.  * Copyright 2004 The Apache Software Foundation
  3.  * 
  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
  7.  * 
  8.  * http://www.apache.org/licenses/LICENSE-2.0
  9.  * 
  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.
  15.  */
  16. using System;
  17. using IndexReader = Lucene.Net.Index.IndexReader;
  18. using Term = Lucene.Net.Index.Term;
  19. using TermDocs = Lucene.Net.Index.TermDocs;
  20. using TermEnum = Lucene.Net.Index.TermEnum;
  21. using StringIndex = Lucene.Net.Search.StringIndex;
  22. namespace Lucene.Net.Search
  23. {
  24. /// <summary> Expert: The default cache implementation, storing all values in memory.
  25. /// A WeakHashMap is used for storage.
  26. /// 
  27. /// <p>Created: May 19, 2004 4:40:36 PM
  28. /// 
  29. /// </summary>
  30. /// <author>   Tim Jones (Nacimiento Software)
  31. /// </author>
  32. /// <since>   lucene 1.4
  33. /// </since>
  34. /// <version>  $Id: FieldCacheImpl.java 331964 2005-11-09 06:44:10Z otis $
  35. /// </version>
  36. class FieldCacheImpl : FieldCache
  37. {
  38. public class AnonymousClassIntParser : IntParser
  39. {
  40. public virtual int ParseInt(System.String value_Renamed)
  41. {
  42. return System.Int32.Parse(value_Renamed);
  43. }
  44. }
  45. public class AnonymousClassFloatParser : FloatParser
  46. {
  47. public virtual float ParseFloat(System.String value_Renamed)
  48. {
  49. return System.Single.Parse(value_Renamed);
  50. }
  51. }
  52. /// <summary>Expert: Every key in the internal cache is of this type. </summary>
  53. internal class Entry
  54. {
  55. internal System.String field; // which Field
  56. internal int type; // which SortField type
  57. internal System.Object custom; // which custom comparator
  58. /// <summary>Creates one of these objects. </summary>
  59. internal Entry(System.String field, int type)
  60. {
  61. this.field = String.Intern(field);
  62. this.type = type;
  63. this.custom = null;
  64. }
  65. /// <summary>Creates one of these objects for a custom comparator. </summary>
  66. internal Entry(System.String field, System.Object custom)
  67. {
  68. this.field = String.Intern(field);
  69. this.type = SortField.CUSTOM;
  70. this.custom = custom;
  71. }
  72. /// <summary>Two of these are equal iff they reference the same field and type. </summary>
  73. public  override bool Equals(System.Object o)
  74. {
  75. if (o is Entry)
  76. {
  77. Entry other = (Entry) o;
  78. if (other.field == field && other.type == type)
  79. {
  80. if (other.custom == null)
  81. {
  82. if (custom == null)
  83. return true;
  84. }
  85. else if (other.custom.Equals(custom))
  86. {
  87. return true;
  88. }
  89. }
  90. }
  91. return false;
  92. }
  93. /// <summary>Composes a hashcode based on the field and type. </summary>
  94. public override int GetHashCode()
  95. {
  96. return field.GetHashCode() ^ type ^ (custom == null?0:custom.GetHashCode());
  97. }
  98. }
  99. private static readonly IntParser INT_PARSER;
  100. private static readonly FloatParser FLOAT_PARSER;
  101. /// <summary>The internal cache. Maps Entry to array of interpreted term values. *</summary>
  102. internal System.Collections.IDictionary cache = new System.Collections.Hashtable();
  103. /// <summary>See if an object is in the cache. </summary>
  104. internal virtual System.Object Lookup(IndexReader reader, System.String field, int type)
  105. {
  106. Entry entry = new Entry(field, type);
  107. lock (this)
  108. {
  109. System.Collections.Hashtable readerCache = (System.Collections.Hashtable) cache[reader];
  110. if (readerCache == null)
  111. return null;
  112. return readerCache[entry];
  113. }
  114. }
  115. /// <summary>See if a custom object is in the cache. </summary>
  116. internal virtual System.Object Lookup(IndexReader reader, System.String field, System.Object comparer)
  117. {
  118. Entry entry = new Entry(field, comparer);
  119. lock (this)
  120. {
  121. System.Collections.Hashtable readerCache = (System.Collections.Hashtable) cache[reader];
  122. if (readerCache == null)
  123. return null;
  124. return readerCache[entry];
  125. }
  126. }
  127. /// <summary>Put an object into the cache. </summary>
  128. internal virtual System.Object Store(IndexReader reader, System.String field, int type, System.Object value_Renamed)
  129. {
  130. Entry entry = new Entry(field, type);
  131. lock (this)
  132. {
  133. System.Collections.Hashtable readerCache = (System.Collections.Hashtable) cache[reader];
  134. if (readerCache == null)
  135. {
  136. readerCache = new System.Collections.Hashtable();
  137. cache[reader] = readerCache;
  138. }
  139. System.Object tempObject;
  140. tempObject = readerCache[entry];
  141. readerCache[entry] = value_Renamed;
  142. return tempObject;
  143. }
  144. }
  145. /// <summary>Put a custom object into the cache. </summary>
  146. internal virtual System.Object Store(IndexReader reader, System.String field, System.Object comparer, System.Object value_Renamed)
  147. {
  148. Entry entry = new Entry(field, comparer);
  149. lock (this)
  150. {
  151. System.Collections.Hashtable readerCache = (System.Collections.Hashtable) cache[reader];
  152. if (readerCache == null)
  153. {
  154. readerCache = new System.Collections.Hashtable();
  155. cache[reader] = readerCache;
  156. }
  157. System.Object tempObject;
  158. tempObject = readerCache[entry];
  159. readerCache[entry] = value_Renamed;
  160. return tempObject;
  161. }
  162. }
  163. // inherit javadocs
  164. public virtual int[] GetInts(IndexReader reader, System.String field)
  165. {
  166. return GetInts(reader, field, INT_PARSER);
  167. }
  168. // inherit javadocs
  169. public virtual int[] GetInts(IndexReader reader, System.String field, IntParser parser)
  170. {
  171. field = String.Intern(field);
  172. System.Object ret = Lookup(reader, field, parser);
  173. if (ret == null)
  174. {
  175. int[] retArray = new int[reader.MaxDoc()];
  176. if (retArray.Length > 0)
  177. {
  178. TermDocs termDocs = reader.TermDocs();
  179. TermEnum termEnum = reader.Terms(new Term(field, ""));
  180. try
  181. {
  182. if (termEnum.Term() == null)
  183. {
  184. throw new System.SystemException("no terms in field " + field);
  185. }
  186. do 
  187. {
  188. Term term = termEnum.Term();
  189. if (term.Field() != field)
  190. break;
  191. int termval = parser.ParseInt(term.Text());
  192. termDocs.Seek(termEnum);
  193. while (termDocs.Next())
  194. {
  195. retArray[termDocs.Doc()] = termval;
  196. }
  197. }
  198. while (termEnum.Next());
  199. }
  200. finally
  201. {
  202. termDocs.Close();
  203. termEnum.Close();
  204. }
  205. }
  206. Store(reader, field, parser, retArray);
  207. return retArray;
  208. }
  209. return (int[]) ret;
  210. }
  211. // inherit javadocs
  212. public virtual float[] GetFloats(IndexReader reader, System.String field)
  213. {
  214. return GetFloats(reader, field, FLOAT_PARSER);
  215. }
  216. // inherit javadocs
  217. public virtual float[] GetFloats(IndexReader reader, System.String field, FloatParser parser)
  218. {
  219. field = String.Intern(field);
  220. System.Object ret = Lookup(reader, field, parser);
  221. if (ret == null)
  222. {
  223. float[] retArray = new float[reader.MaxDoc()];
  224. if (retArray.Length > 0)
  225. {
  226. TermDocs termDocs = reader.TermDocs();
  227. TermEnum termEnum = reader.Terms(new Term(field, ""));
  228. try
  229. {
  230. if (termEnum.Term() == null)
  231. {
  232. throw new System.SystemException("no terms in field " + field);
  233. }
  234. do 
  235. {
  236. Term term = termEnum.Term();
  237. if (term.Field() != field)
  238. break;
  239. float termval = parser.ParseFloat(term.Text());
  240. termDocs.Seek(termEnum);
  241. while (termDocs.Next())
  242. {
  243. retArray[termDocs.Doc()] = termval;
  244. }
  245. }
  246. while (termEnum.Next());
  247. }
  248. finally
  249. {
  250. termDocs.Close();
  251. termEnum.Close();
  252. }
  253. }
  254. Store(reader, field, parser, retArray);
  255. return retArray;
  256. }
  257. return (float[]) ret;
  258. }
  259. // inherit javadocs
  260. public virtual System.String[] GetStrings(IndexReader reader, System.String field)
  261. {
  262. field = String.Intern(field);
  263. System.Object ret = Lookup(reader, field, SortField.STRING);
  264. if (ret == null)
  265. {
  266. System.String[] retArray = new System.String[reader.MaxDoc()];
  267. if (retArray.Length > 0)
  268. {
  269. TermDocs termDocs = reader.TermDocs();
  270. TermEnum termEnum = reader.Terms(new Term(field, ""));
  271. try
  272. {
  273. if (termEnum.Term() == null)
  274. {
  275. throw new System.SystemException("no terms in field " + field);
  276. }
  277. do 
  278. {
  279. Term term = termEnum.Term();
  280. if (term.Field() != field)
  281. break;
  282. System.String termval = term.Text();
  283. termDocs.Seek(termEnum);
  284. while (termDocs.Next())
  285. {
  286. retArray[termDocs.Doc()] = termval;
  287. }
  288. }
  289. while (termEnum.Next());
  290. }
  291. finally
  292. {
  293. termDocs.Close();
  294. termEnum.Close();
  295. }
  296. }
  297. Store(reader, field, SortField.STRING, retArray);
  298. return retArray;
  299. }
  300. return (System.String[]) ret;
  301. }
  302. // inherit javadocs
  303. public virtual StringIndex GetStringIndex(IndexReader reader, System.String field)
  304. {
  305. field = String.Intern(field);
  306. System.Object ret = Lookup(reader, field, Lucene.Net.Search.FieldCache_Fields.STRING_INDEX);
  307. if (ret == null)
  308. {
  309. int[] retArray = new int[reader.MaxDoc()];
  310. System.String[] mterms = new System.String[reader.MaxDoc() + 1];
  311. if (retArray.Length > 0)
  312. {
  313. TermDocs termDocs = reader.TermDocs();
  314. TermEnum termEnum = reader.Terms(new Term(field, ""));
  315. int t = 0; // current term number
  316. // an entry for documents that have no terms in this field
  317. // should a document with no terms be at top or bottom?
  318. // this puts them at the top - if it is changed, FieldDocSortedHitQueue
  319. // needs to change as well.
  320. mterms[t++] = null;
  321. try
  322. {
  323. if (termEnum.Term() == null)
  324. {
  325. throw new System.SystemException("no terms in field " + field);
  326. }
  327. do 
  328. {
  329. Term term = termEnum.Term();
  330. if (term.Field() != field)
  331. break;
  332. // store term text
  333. // we expect that there is at most one term per document
  334. if (t >= mterms.Length)
  335. throw new System.SystemException("there are more terms than " + "documents in field "" + field + "", but it's impossible to sort on " + "tokenized fields");
  336. mterms[t] = term.Text();
  337. termDocs.Seek(termEnum);
  338. while (termDocs.Next())
  339. {
  340. retArray[termDocs.Doc()] = t;
  341. }
  342. t++;
  343. }
  344. while (termEnum.Next());
  345. }
  346. finally
  347. {
  348. termDocs.Close();
  349. termEnum.Close();
  350. }
  351. if (t == 0)
  352. {
  353. // if there are no terms, make the term array
  354. // have a single null entry
  355. mterms = new System.String[1];
  356. }
  357. else if (t < mterms.Length)
  358. {
  359. // if there are less terms than documents,
  360. // trim off the dead array space
  361. System.String[] terms = new System.String[t];
  362. Array.Copy(mterms, 0, terms, 0, t);
  363. mterms = terms;
  364. }
  365. }
  366. StringIndex value_Renamed = new StringIndex(retArray, mterms);
  367. Store(reader, field, Lucene.Net.Search.FieldCache_Fields.STRING_INDEX, value_Renamed);
  368. return value_Renamed;
  369. }
  370. return (StringIndex) ret;
  371. }
  372. /// <summary>The pattern used to detect integer values in a field </summary>
  373. /// <summary>removed for java 1.3 compatibility
  374. /// protected static final Pattern pIntegers = Pattern.compile ("[0-9\-]+");
  375. /// 
  376. /// </summary>
  377. /// <summary>The pattern used to detect float values in a field </summary>
  378. /// <summary> removed for java 1.3 compatibility
  379. /// protected static final Object pFloats = Pattern.compile ("[0-9+\-\.eEfFdD]+");
  380. /// </summary>
  381. // inherit javadocs
  382. public virtual System.Object GetAuto(IndexReader reader, System.String field)
  383. {
  384. field = String.Intern(field);
  385. System.Object ret = Lookup(reader, field, SortField.AUTO);
  386. if (ret == null)
  387. {
  388. TermEnum enumerator = reader.Terms(new Term(field, ""));
  389. try
  390. {
  391. Term term = enumerator.Term();
  392. if (term == null)
  393. {
  394. throw new System.SystemException("no terms in field " + field + " - cannot determine sort type");
  395. }
  396. if (term.Field() == field)
  397. {
  398. System.String termtext = term.Text().Trim();
  399. /**
  400. * Java 1.4 level code:
  401. if (pIntegers.matcher(termtext).matches())
  402. return IntegerSortedHitQueue.comparator (reader, enumerator, field);
  403. else if (pFloats.matcher(termtext).matches())
  404. return FloatSortedHitQueue.comparator (reader, enumerator, field);
  405. */
  406. // Java 1.3 level code:
  407. try
  408. {
  409. System.Int32.Parse(termtext);
  410. ret = GetInts(reader, field);
  411. }
  412. catch (System.FormatException nfe1)
  413. {
  414. try
  415. {
  416. System.Single.Parse(termtext);
  417. ret = GetFloats(reader, field);
  418. }
  419. catch (System.FormatException nfe2)
  420. {
  421. ret = GetStringIndex(reader, field);
  422. }
  423. }
  424. if (ret != null)
  425. {
  426. Store(reader, field, SortField.AUTO, ret);
  427. }
  428. }
  429. else
  430. {
  431. throw new System.SystemException("field "" + field + "" does not appear to be indexed");
  432. }
  433. }
  434. finally
  435. {
  436. enumerator.Close();
  437. }
  438. }
  439. return ret;
  440. }
  441. // inherit javadocs
  442. public virtual System.IComparable[] GetCustom(IndexReader reader, System.String field, SortComparator comparator)
  443. {
  444. field = String.Intern(field);
  445. System.Object ret = Lookup(reader, field, comparator);
  446. if (ret == null)
  447. {
  448. System.IComparable[] retArray = new System.IComparable[reader.MaxDoc()];
  449. if (retArray.Length > 0)
  450. {
  451. TermDocs termDocs = reader.TermDocs();
  452. TermEnum termEnum = reader.Terms(new Term(field, ""));
  453. try
  454. {
  455. if (termEnum.Term() == null)
  456. {
  457. throw new System.SystemException("no terms in field " + field);
  458. }
  459. do 
  460. {
  461. Term term = termEnum.Term();
  462. if (term.Field() != field)
  463. break;
  464. System.IComparable termval = comparator.GetComparable(term.Text());
  465. termDocs.Seek(termEnum);
  466. while (termDocs.Next())
  467. {
  468. retArray[termDocs.Doc()] = termval;
  469. }
  470. }
  471. while (termEnum.Next());
  472. }
  473. finally
  474. {
  475. termDocs.Close();
  476. termEnum.Close();
  477. }
  478. }
  479. Store(reader, field, comparator, retArray);
  480. return retArray;
  481. }
  482. return (System.IComparable[]) ret;
  483. }
  484. static FieldCacheImpl()
  485. {
  486. INT_PARSER = new AnonymousClassIntParser();
  487. FLOAT_PARSER = new AnonymousClassFloatParser();
  488. }
  489. }
  490. }