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
FieldDocSortedHitQueue.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 using Lucene.Net.Util;
20 
21 namespace Lucene.Net.Search
22 {
23 
24  /// <summary> Expert: Collects sorted results from Searchable's and collates them.
25  /// The elements put into this queue must be of type FieldDoc.
26  ///
27  /// <p/>Created: Feb 11, 2004 2:04:21 PM
28  ///
29  /// </summary>
30  /// <since> lucene 1.4
31  /// </since>
33  {
34  internal volatile SortField[] fields = null;
35 
36  // used in the case where the fields are sorted by locale
37  // based strings
38  internal volatile System.Globalization.CompareInfo[] collators;
39 
40 
41  /// <summary> Creates a hit queue sorted by the given list of fields.</summary>
42  /// <param name="size">The number of hits to retain. Must be greater than zero.</param>
43  internal FieldDocSortedHitQueue(int size)
44  {
45  Initialize(size);
46  }
47 
48 
49  /// <summary> Allows redefinition of sort fields if they are <c>null</c>.
50  /// This is to handle the case using ParallelMultiSearcher where the
51  /// original list contains AUTO and we don't know the actual sort
52  /// type until the values come back. The fields can only be set once.
53  /// This method is thread safe.
54  /// </summary>
55  /// <param name="fields"></param>
56  internal virtual void SetFields(SortField[] fields)
57  {
58  lock (this)
59  {
60  this.fields = fields;
61  this.collators = HasCollators(fields);
62  }
63  }
64 
65  /// <summary>Returns the fields being used to sort. </summary>
66  internal virtual SortField[] GetFields()
67  {
68  return fields;
69  }
70 
71 
72  /// <summary>Returns an array of collators, possibly <c>null</c>. The collators
73  /// correspond to any SortFields which were given a specific locale.
74  /// </summary>
75  /// <param name="fields">Array of sort fields.</param>
76  /// <returns> Array, possibly <c>null</c>.</returns>
77  private System.Globalization.CompareInfo[] HasCollators(SortField[] fields)
78  {
79  if (fields == null)
80  return null;
81  System.Globalization.CompareInfo[] ret = new System.Globalization.CompareInfo[fields.Length];
82  for (int i = 0; i < fields.Length; ++i)
83  {
84  System.Globalization.CultureInfo locale = fields[i].Locale;
85  if (locale != null)
86  ret[i] = locale.CompareInfo;
87  }
88  return ret;
89  }
90 
91 
92  /// <summary> Returns whether <c>a</c> is less relevant than <c>b</c>.</summary>
93  /// <param name="docA">ScoreDoc</param>
94  /// <param name="docB">ScoreDoc</param>
95  /// <returns><c>true</c> if document <c>a</c> should be sorted after document <c>b</c>.</returns>
96  public override bool LessThan(FieldDoc docA, FieldDoc docB)
97  {
98  int n = fields.Length;
99  int c = 0;
100  for (int i = 0; i < n && c == 0; ++i)
101  {
102  int type = fields[i].Type;
103  if(type == SortField.STRING)
104  {
105  string s1 = (string) docA.fields[i];
106  string s2 = (string) docB.fields[i];
107  // null values need to be sorted first, because of how FieldCache.getStringIndex()
108  // works - in that routine, any documents without a value in the given field are
109  // put first. If both are null, the next SortField is used
110  if (s1 == null)
111  {
112  c = (s2 == null) ? 0 : -1;
113  }
114  else if (s2 == null)
115  {
116  c = 1;
117  }
118  else if (fields[i].Locale == null)
119  {
120  c = s1.CompareTo(s2);
121  }
122  else
123  {
124  c = collators[i].Compare(s1, s2);
125  }
126  }
127  else
128  {
129  c = docA.fields[i].CompareTo(docB.fields[i]);
130  if (type == SortField.SCORE)
131  {
132  c = -c;
133  }
134  }
135  if (fields[i].Reverse)
136  {
137  c = - c;
138  }
139  }
140 
141  // avoid random sort order that could lead to duplicates (bug #31241):
142  if (c == 0)
143  return docA.Doc > docB.Doc;
144 
145  return c > 0;
146  }
147  }
148 }