Compute lucene-style scores for our hits.
[beagle.git] / BeagleClient / Query.cs
blob5f5423f9f2fcad33909c0a2170925d84f68c2a4d
1 //
2 // Query.cs
3 //
4 // Copyright (C) 2004-2005 Novell, Inc.
5 //
7 //
8 // Permission is hereby granted, free of charge, to any person obtaining a
9 // copy of this software and associated documentation files (the "Software"),
10 // to deal in the Software without restriction, including without limitation
11 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 // and/or sell copies of the Software, and to permit persons to whom the
13 // Software is furnished to do so, subject to the following conditions:
15 // The above copyright notice and this permission notice shall be included in
16 // all copies or substantial portions of the Software.
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 // DEALINGS IN THE SOFTWARE.
28 using System;
29 using System.IO;
30 using System.Collections;
31 using System.Text;
32 using System.Xml.Serialization;
34 using Beagle.Util;
36 namespace Beagle {
38 public enum QueryDomain {
39 Local = 1,
40 System = 2,
41 Neighborhood = 4,
42 Global = 8
45 public class Query : RequestMessage {
47 // FIXME: This is a good default when on an airplane.
48 private Beagle.QueryDomain domainFlags = QueryDomain.Local | QueryDomain.System;
50 private ArrayList parts = new ArrayList ();
51 private ArrayList mimeTypes = new ArrayList ();
52 private ArrayList hitTypes = new ArrayList ();
53 private ArrayList searchSources = new ArrayList ();
55 private ArrayList exact_text = null;
56 private ArrayList stemmed_text = null;
58 private QueryPart_Or mime_type_part = null;
59 private QueryPart_Or hit_type_part = null;
61 // Events to make things nicer to clients
62 public delegate void HitsAdded (HitsAddedResponse response);
63 public event HitsAdded HitsAddedEvent;
65 public delegate void HitsSubtracted (HitsSubtractedResponse response);
66 public event HitsSubtracted HitsSubtractedEvent;
68 public delegate void Finished (FinishedResponse response);
69 public event Finished FinishedEvent;
71 public delegate void Cancelled (CancelledResponse response);
72 public event Cancelled CancelledEvent;
75 public Query () : base (true)
77 this.RegisterAsyncResponseHandler (typeof (HitsAddedResponse), OnHitsAdded);
78 this.RegisterAsyncResponseHandler (typeof (HitsSubtractedResponse), OnHitsSubtracted);
79 this.RegisterAsyncResponseHandler (typeof (FinishedResponse), OnFinished);
80 this.RegisterAsyncResponseHandler (typeof (CancelledResponse), OnCancelled);
81 this.RegisterAsyncResponseHandler (typeof (ErrorResponse), OnError);
82 this.RegisterAsyncResponseHandler (typeof (SearchTermResponse), OnSearchTerms);
85 public Query (string str) : this ()
87 AddText (str);
90 ///////////////////////////////////////////////////////////////
92 private void OnHitsAdded (ResponseMessage r)
94 HitsAddedResponse response = (HitsAddedResponse) r;
96 if (this.HitsAddedEvent != null)
97 this.HitsAddedEvent (response);
100 private void OnHitsSubtracted (ResponseMessage r)
102 HitsSubtractedResponse response = (HitsSubtractedResponse) r;
104 if (this.HitsSubtractedEvent != null)
105 this.HitsSubtractedEvent (response);
108 private void OnFinished (ResponseMessage r)
110 FinishedResponse response = (FinishedResponse) r;
112 if (this.FinishedEvent != null)
113 this.FinishedEvent (response);
116 private void OnCancelled (ResponseMessage r)
118 CancelledResponse response = (CancelledResponse) r;
120 if (this.CancelledEvent != null)
121 this.CancelledEvent (response);
124 private void OnError (ResponseMessage r)
126 ErrorResponse response = (ErrorResponse) r;
128 throw new ResponseMessageException (response);
131 private void OnSearchTerms (ResponseMessage r)
133 SearchTermResponse response = (SearchTermResponse) r;
134 ProcessSearchTermResponse (response);
137 ///////////////////////////////////////////////////////////////
139 // This is exposed for the benefit of QueryDriver.DoQueryLocal
140 public void ProcessSearchTermResponse (SearchTermResponse response)
142 exact_text = response.ExactText;
143 stemmed_text = response.StemmedText;
146 ///////////////////////////////////////////////////////////////
148 public void ClearParts ()
150 if (parts != null)
151 parts.Clear ();
154 public void AddPart (QueryPart part)
156 if (part != null)
157 parts.Add (part);
160 // This is a human-entered query string that will be parsed in
161 // the daemon.
162 public void AddText (string str)
164 QueryPart_Human part;
165 part = new QueryPart_Human ();
166 part.QueryString = str;
167 AddPart (part);
170 [XmlArrayItem (ElementName="Part", Type=typeof (QueryPart))]
171 [XmlArray (ElementName="Parts")]
172 public ArrayList Parts {
173 get { return parts; }
176 [XmlIgnore]
177 public ICollection Text {
178 get { return exact_text; }
181 [XmlIgnore]
182 public string QuotedText {
183 get {
184 StringBuilder builder = new StringBuilder ();
185 foreach (string text in Text) {
186 string text_cooked = text;
187 if (builder.Length > 0)
188 builder.Append (' ');
189 bool contains_space = (text.IndexOf (' ') != -1);
190 if (contains_space) {
191 text_cooked = text.Replace ("\"", "\\\"");
192 builder.Append ('"');
194 builder.Append (text_cooked);
195 if (contains_space)
196 builder.Append ('"');
198 return builder.ToString ();
202 [XmlIgnore]
203 public ICollection StemmedText {
204 get { return stemmed_text; }
207 ///////////////////////////////////////////////////////////////
209 // This API is DEPRECATED.
210 // The mime type is now stored in the beagle:MimeType property.
211 // To restrict on mime type, just do a normal property query.
213 public void AddMimeType (string str)
215 mimeTypes.Add (str);
217 if (mime_type_part == null) {
218 mime_type_part = new QueryPart_Or ();
219 AddPart (mime_type_part);
222 // Create a part for this mime type.
223 QueryPart_Property part;
224 part = new QueryPart_Property ();
225 part.Type = PropertyType.Keyword;
226 part.Key = "beagle:MimeType";
227 part.Value = str;
228 mime_type_part.Add (part);
231 public bool AllowsMimeType (string str)
233 if (mimeTypes.Count == 0)
234 return true;
235 foreach (string mt in mimeTypes)
236 if (str == mt)
237 return true;
238 return false;
241 [XmlArrayItem (ElementName="MimeType",
242 Type=typeof (string))]
243 [XmlArray (ElementName="MimeTypes")]
244 public ArrayList MimeTypes {
245 get { return mimeTypes; }
248 public bool HasMimeTypes {
249 get { return mimeTypes.Count > 0; }
252 ///////////////////////////////////////////////////////////////
254 // This API is DEPRECATED.
255 // The mime type is now stored in the beagle:Type property.
256 // To restrict on type, just do a normal property query.
258 public void AddHitType (string str)
260 hitTypes.Add (str);
262 if (hit_type_part == null) {
263 hit_type_part = new QueryPart_Or ();
264 AddPart (hit_type_part);
267 // Add a part for this hit type.
268 QueryPart_Property part;
269 part = new QueryPart_Property ();
270 part.Type = PropertyType.Keyword;
271 part.Key = "beagle:Type";
272 part.Value = str;
273 hit_type_part.Add (part);
276 public bool AllowsHitType (string str)
278 if (hitTypes.Count == 0)
279 return true;
280 foreach (string ht in hitTypes)
281 if (str == ht)
282 return true;
283 return false;
286 [XmlArrayItem (ElementName="HitType",
287 Type=typeof(string))]
288 [XmlArray (ElementName="HitTypes")]
289 public ArrayList HitTypes {
290 get { return hitTypes; }
293 [XmlIgnore]
294 public bool HasHitTypes {
295 get { return hitTypes.Count > 0; }
298 ///////////////////////////////////////////////////////////////
300 public void AddSource (string str)
302 searchSources.Add (str);
306 public bool AllowsSource (string str)
308 if (searchSources.Count == 0)
309 return true;
310 foreach (string ss in searchSources)
311 if (str.ToUpper () == ss.ToUpper ())
312 return true;
313 return false;
316 [XmlArrayItem (ElementName="Source",
317 Type=typeof (string))]
318 [XmlArray (ElementName="Sources")]
319 public ArrayList Sources {
320 get { return searchSources; }
323 [XmlIgnore]
324 public bool HasSources {
325 get { return searchSources.Count > 0; }
328 ///////////////////////////////////////////////////////////////
330 public void AddDomain (Beagle.QueryDomain d)
332 domainFlags |= d;
335 public void RemoveDomain (Beagle.QueryDomain d)
337 domainFlags &= ~d;
340 public bool AllowsDomain (Beagle.QueryDomain d)
342 return (domainFlags & d) != 0;
345 ///////////////////////////////////////////////////////////////
347 private int max_hits = 100;
348 public int MaxHits {
349 get { return max_hits; }
350 set { max_hits = value; }
353 ///////////////////////////////////////////////////////////////
355 [XmlIgnore]
356 public bool IsEmpty {
357 get { return parts.Count == 0
358 && mimeTypes.Count == 0
359 && searchSources.Count == 0; }