2006-02-27 Gabor Kelemen <kelemeng@gnome.hu>
[beagle.git] / bludgeon / QueryFu.cs
blob93de45054c5db6c535fcd78a0f88fed2cf1b388f
2 using System;
3 using System.Collections;
4 using System.Threading;
6 using Beagle.Util;
7 using Beagle;
9 namespace Bludgeon {
11 public class QueryFu {
13 static public Query NewTokenQuery (string token)
15 Query query;
16 query = new Query ();
18 QueryPart_Text part;
19 part = new QueryPart_Text ();
20 part.Text = token;
21 query.AddPart (part);
23 return query;
26 static public Query NewTokenQuery (int id)
28 return NewTokenQuery (Token.IdToString (id));
31 static Random random = new Random ();
33 static public Query NewRandomQuery (int length,
34 bool allow_inexpensive)
36 return NewRandomQuery (length, allow_inexpensive, false);
39 static private Query NewRandomQuery (int length,
40 bool allow_inexpensive,
41 bool inside_an_or)
43 Query query;
44 query = new Query ();
46 // One in four queries will contain some OR terms.
47 if (! inside_an_or && random.Next (4) == 0) {
48 int N = random.Next (3) + 1;
49 for (int i = 0; i < N; ++i) {
50 QueryPart_Or part;
51 part = new QueryPart_Or ();
53 int sub_length;
54 sub_length = random.Next (length) + 1;
55 if (sub_length < 2)
56 sub_length = 2;
58 // We generate a new query at random, and stuff its QueryParts
59 // into our Or QueryPart.
60 Query or_query;
61 or_query = NewRandomQuery (sub_length, allow_inexpensive, true);
62 foreach (QueryPart sub_part in or_query.Parts)
63 part.Add (sub_part);
65 query.AddPart (part);
69 if (allow_inexpensive && ! inside_an_or) {
70 int mime_type;
71 mime_type = random.Next (3);
72 if (mime_type == 0)
73 query.AddMimeType ("inode/directory");
74 else if (mime_type == 1)
75 query.AddMimeType ("text/plain");
78 // Every query must contain at least
79 // one required part.
80 bool contains_required;
81 contains_required = false;
83 for (int i = 0; i < length; ++i) {
84 QueryPart_Text part;
85 part = new QueryPart_Text ();
86 part.Text = Token.GetRandom ();
88 // Prohibited parts are not allowed inside an or
89 if (contains_required && ! inside_an_or) {
90 if (random.Next (2) == 0)
91 part.Logic = QueryPartLogic.Prohibited;
92 } else {
93 // This part will be required.
94 contains_required = true;
97 if (random.Next (2) == 0)
98 part.SearchTextProperties = false;
99 else if (allow_inexpensive && random.Next (2) == 0)
100 part.SearchFullText = false;
102 query.AddPart (part);
105 if (allow_inexpensive && random.Next (3) == 0) {
106 DateTime a, b;
107 FileSystemObject.PickTimestampRange (out a, out b);
109 QueryPart_DateRange part;
110 part = new QueryPart_DateRange ();
111 part.StartDate = a;
112 part.EndDate = b;
113 query.AddPart (part);
116 return query;
119 static public Query NewRandomQuery ()
121 return NewRandomQuery (2 + random.Next (4), true);
124 /////////////////////////////////////////////////////////////
126 static public string QueryPartToString (QueryPart abstract_part)
128 string msg;
129 msg = "????";
131 if (abstract_part is QueryPart_Text) {
132 QueryPart_Text part;
133 part = (QueryPart_Text) abstract_part;
135 msg = part.Text;
136 if (! (part.SearchFullText && part.SearchTextProperties)) {
137 if (part.SearchFullText)
138 msg += " IN FULLTEXT";
139 else if (part.SearchTextProperties)
140 msg += " IN TEXT PROPERTIES";
141 } else
142 msg += " IN ANY TEXT";
144 } else if (abstract_part is QueryPart_Property) {
145 QueryPart_Property part;
146 part = (QueryPart_Property) abstract_part;
147 msg = String.Format ("PROPERTY {0} = {1}", part.Key, part.Value);
148 } else if (abstract_part is QueryPart_DateRange) {
149 QueryPart_DateRange part;
150 part = (QueryPart_DateRange) abstract_part;
151 msg = String.Format ("DATE RANGE {0} to {1}", part.StartDate, part.EndDate);
154 if (abstract_part.Logic == QueryPartLogic.Prohibited)
155 msg = "NOT " + msg;
158 return msg;
161 static public void SpewQuery (Query query)
163 int i = 0;
165 foreach (QueryPart abstract_part in query.Parts) {
167 ++i;
169 if (abstract_part is QueryPart_Or) {
170 QueryPart_Or part = abstract_part as QueryPart_Or;
171 int j = 0;
172 Log.Spew ("{0}: OR", i);
173 foreach (QueryPart sub_part in part.SubParts) {
174 ++j;
175 Log.Spew (" {0}.{1}: {2}", i, j, QueryPartToString (sub_part));
178 } else {
179 Log.Spew ("{0}: {1}", i, QueryPartToString (abstract_part));
184 /////////////////////////////////////////////////////////////
186 private class QueryClosure {
188 public Hashtable Hits;
189 private Query query;
191 public QueryClosure (Query query)
193 this.Hits = UriFu.NewHashtable ();
194 this.query = query;
197 public void OnHitsAdded (HitsAddedResponse response)
199 foreach (Hit hit in response.Hits)
200 Hits [hit.Uri] = hit;
203 public void OnFinished (FinishedResponse response)
205 query.Close ();
210 static public Hashtable GetHits (Query q)
212 QueryClosure qc;
213 qc = new QueryClosure (q);
214 q.HitsAddedEvent += qc.OnHitsAdded;
215 q.FinishedEvent += qc.OnFinished;
217 q.SendAsyncBlocking ();
219 return qc.Hits;
222 static public ICollection GetUris (Query q)
224 return GetHits (q).Keys;