1/*------------------------------------------------------------------------------
2* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team
3*
4* Distributable under the terms of either the Apache License (Version 2.0) or
5* the GNU Lesser General Public License, as specified in the COPYING file.
6------------------------------------------------------------------------------*/
7#ifndef _lucene_search_FieldSortedHitQueue_
8#define _lucene_search_FieldSortedHitQueue_
9
10#if defined(_LUCENE_PRAGMA_ONCE)
11# pragma once
12#endif
13
14#include "FieldCache.h"
15#include "Sort.h"
16#include "FieldDocSortedHitQueue.h"
17#include "SearchHeader.h"
18#include "FieldCacheImpl.h"
19#include "CLucene/util/PriorityQueue.h"
20
21CL_NS_DEF(search)
22
23
24/**
25 * Expert: A hit queue for sorting by hits by terms in more than one field.
26 * Uses <code>FieldCache.DEFAULT</code> for maintaining internal term lookup tables.
27 *
28 * @see Searchable#search(Query,Filter,int32_t,Sort)
29 * @see FieldCache
30 */
31class FieldSortedHitQueue: public CL_NS(util)::PriorityQueue<FieldDoc*,
32 CL_NS(util)::Deletor::Object<FieldDoc> > {
33
34 ///the type that is stored in the field cache. can't use a typedef because
35 ///the decorated name would become too long
36 class hitqueueCacheReaderType: public CL_NS(util)::CLHashMap<FieldCacheImpl::FileEntry*,
37 ScoreDocComparator*,
38 FieldCacheImpl::FileEntry::Compare,
39 FieldCacheImpl::FileEntry::Equals,
40 CL_NS(util)::Deletor::Object<FieldCacheImpl::FileEntry>,
41 CL_NS(util)::Deletor::Object<ScoreDocComparator> >{
42
43 public:
44 hitqueueCacheReaderType(bool deleteValue){
45 setDeleteKey(true);
46 setDeleteValue(deleteValue);
47 }
48 ~hitqueueCacheReaderType(){
49 clear();
50 }
51
52 };
53
54public: //todo: remove this and below after close callback is implemented
55 //note: typename gets too long if using cacheReaderType as a typename
56 typedef CL_NS(util)::CLHashMap<CL_NS(index)::IndexReader*,
57 hitqueueCacheReaderType*,
58 CL_NS(util)::Compare::Void<CL_NS(index)::IndexReader>,
59 CL_NS(util)::Equals::Void<CL_NS(index)::IndexReader>,
60 CL_NS(util)::Deletor::Object<CL_NS(index)::IndexReader>,
61 CL_NS(util)::Deletor::Object<hitqueueCacheReaderType> > hitqueueCacheType;
62
63 /** Internal cache of comparators. Similar to FieldCache, only
64 * caches comparators instead of term values.
65 */
66 static hitqueueCacheType Comparators;
67private:
68
69 /** Returns a comparator if it is in the cache.*/
70 static ScoreDocComparator* lookup (CL_NS(index)::IndexReader* reader, const TCHAR* field, int32_t type, SortComparatorSource* factory);
71
72 /** Stores a comparator into the cache.
73 returns the valid ScoreDocComparator.
74 */
75 static void store (CL_NS(index)::IndexReader* reader, const TCHAR* field, int32_t type, SortComparatorSource* factory, ScoreDocComparator* value);
76
77
78 //todo: Locale locale, not implemented yet
79 static ScoreDocComparator* getCachedComparator (CL_NS(index)::IndexReader* reader,
80 const TCHAR* fieldname, int32_t type, SortComparatorSource* factory);
81
82
83 /**
84 * Returns a comparator for sorting hits according to a field containing integers.
85 * @param reader Index to use.
86 * @param fieldname Field containg integer values.
87 * @return Comparator for sorting hits.
88 * @throws IOException If an error occurs reading the index.
89 */
90 static ScoreDocComparator* comparatorInt (CL_NS(index)::IndexReader* reader, const TCHAR* fieldname);
91
92 /**
93 * Returns a comparator for sorting hits according to a field containing floats.
94 * @param reader Index to use.
95 * @param fieldname Field containg float values.
96 * @return Comparator for sorting hits.
97 * @throws IOException If an error occurs reading the index.
98 */
99 static ScoreDocComparator* comparatorFloat (CL_NS(index)::IndexReader* reader, const TCHAR* fieldname);
100
101 /**
102 * Returns a comparator for sorting hits according to a field containing strings.
103 * @param reader Index to use.
104 * @param fieldname Field containg string values.
105 * @return Comparator for sorting hits.
106 * @throws IOException If an error occurs reading the index.
107 */
108 static ScoreDocComparator* comparatorString (CL_NS(index)::IndexReader* reader, const TCHAR* fieldname);
109
110
111 //todo:
112 /**
113 * Returns a comparator for sorting hits according to a field containing strings.
114 * @param reader Index to use.
115 * @param fieldname Field containg string values.
116 * @return Comparator for sorting hits.
117 * @throws IOException If an error occurs reading the index.
118
119 static ScoreDocComparator* comparatorStringLocale (IndexReader* reader, TCHAR* fieldname, Locale locale){
120 Collator collator = Collator.getInstance (locale);
121 TCHAR* field = fieldname.intern();
122 TCHAR** index = FieldCache.DEFAULT.getStrings (reader, field);
123 return _CLNEW ScoreDocComparator() {
124
125 public int32_t compare (ScoreDoc i, ScoreDoc j) {
126 return collator.compare (index[i.doc], index[j.doc]);
127 }
128
129 public Comparable sortValue (ScoreDoc i) {
130 return index[i.doc];
131 }
132
133 public int32_t sortType() {
134 return SortField.STRING;
135 }
136 };
137 }*/
138
139 /**
140 * Returns a comparator for sorting hits according to values in the given field.
141 * The terms in the field are looked at to determine whether they contain integers,
142 * floats or strings. Once the type is determined, one of the other static methods
143 * in this class is called to get the comparator.
144 * @param reader Index to use.
145 * @param fieldname Field containg values.
146 * @return Comparator for sorting hits.
147 * @throws IOException If an error occurs reading the index.
148 */
149 static ScoreDocComparator* comparatorAuto (CL_NS(index)::IndexReader* reader, const TCHAR* fieldname);
150
151
152protected:
153 /** Stores a comparator corresponding to each field being sorted by */
154 ScoreDocComparator** comparators;
155 int32_t comparatorsLen;
156
157 /** Stores the sort criteria being used. */
158 SortField** fields;
159 int32_t fieldsLen;
160
161 /** Stores the maximum score value encountered, for normalizing.
162 * we only care about scores greater than 1.0 - if all the scores
163 * are less than 1.0, we don't have to normalize. */
164 qreal maxscore;
165
166 /**
167 * Returns whether <code>a</code> is less relevant than <code>b</code>.
168 * @param a ScoreDoc
169 * @param b ScoreDoc
170 * @return <code>true</code> if document <code>a</code> should be sorted after document <code>b</code>.
171 */
172 bool lessThan (FieldDoc* docA, FieldDoc* docB);
173public:
174
175 /**
176 * Creates a hit queue sorted by the given list of fields.
177 * @param reader Index to use.
178 * @param fields Field names, in priority order (highest priority first). Cannot be <code>null</code> or empty.
179 * @param size The number of hits to retain. Must be greater than zero.
180 * @throws IOException
181 */
182 FieldSortedHitQueue (CL_NS(index)::IndexReader* reader, SortField** fields, int32_t size);
183
184 ~FieldSortedHitQueue();
185
186 /**
187 * Callback for when IndexReader closes. This causes
188 * any Comparators to be removed for the specified reader.
189 */
190 static void closeCallback(CL_NS(index)::IndexReader* reader, void* param);
191
192 /**
193 * Given a FieldDoc object, stores the values used
194 * to sort the given document. These values are not the raw
195 * values out of the index, but the internal representation
196 * of them. This is so the given search hit can be collated
197 * by a MultiSearcher with other search hits.
198 * @param doc The FieldDoc to store sort values into.
199 * @return The same FieldDoc passed in.
200 * @see Searchable#search(Query,Filter,int32_t,Sort)
201 */
202 FieldDoc* fillFields (FieldDoc* doc) const;
203
204 void setFields (SortField** fields){
205 this->fields = fields;
206 }
207
208 /** Returns the SortFields being used by this hit queue. */
209 SortField** getFields() {
210 return fields;
211 }
212};
213
214
215CL_NS_END
216#endif
217