Menu

[r3166]: / trunk / Src / UQuery.pas  Maximize  Restore  History

Download this file

324 lines (288 with data), 9.8 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
{
* This Source Code Form is subject to the terms of the Mozilla Public License,
* v. 2.0. If a copy of the MPL was not distributed with this file, You can
* obtain one at http://mozilla.org/MPL/2.0/
*
* Copyright (C) 2007-2013, Peter Johnson (www.delphidabbler.com).
*
* $Rev$
* $Date$
*
* Defines a singleton object that encapsulates a query on the code snippets
* database.
}
unit UQuery;
interface
uses
// Project
DB.UCategory, DB.USnippet, USearch;
type
{
IQuery:
Interface to object that encapsulates a query on the code snippets database.
It enables a search to be run against the database and provides access to
the selected snippets.
}
IQuery = interface(IInterface)
['{10998D72-CD5D-482B-9626-D771A50C53BA}']
function ApplySearch(Search: ISearch; const Refine: Boolean): Boolean;
{Runs query by applying a search to the whole database. If search succeeds
matching snippets and search are stored in query's Selection and Search
properties. If search fails Selection and Search are left unchanged.
@param Search [in] Search to apply.
@param Refine [in] Flag indicating whether any existing search should
be refined (True) or search should be of whole databas (False).
@return True if search succeeds and False if it fails.
}
procedure Reset;
{Resets query. Selection property is set to all snippets in database and
Search property is set to nul search.
}
/// <summary>Checks if there is an active search.</summary>
function IsSearchActive: Boolean;
function Refresh: Boolean;
{Re-applies the latest search if one exists.
@return True if search was re-applied, False if there was no search to
apply.
}
procedure Update;
{Updates query. Attempts to refresh query and, if that fails, resets it.
}
function GetLatestSearch: ISearch;
{Gets value of LatestSearch property.
@return Search object used to generate latest search.
}
function GetSelection: TSnippetList;
{Gets value of Selection property.
@return List of snippets matching current query.
}
procedure GetCatSelection(const Cat: TCategory;
const Snippets: TSnippetList);
{Provides list of snippets selected by last search that are in a specified
category.
@param Cat [in] Reference to required category.
@param Snippets [in] Object to receive snippet list. List is emptied
before snippets are copied in.
}
property LatestSearch: ISearch read GetLatestSearch;
{Reference to search object used to generate current query}
property Selection: TSnippetList read GetSelection;
{List of snippets that match current query. This records all snippets in
database if there is no search}
end;
function Query: IQuery;
{Returns singleton instance of object that encapsulates a query on the
snippets database.
@return Singleton object.
}
implementation
uses
// Delphi
SysUtils, Generics.Collections,
// Project
DB.UMain, UBaseObjects, USingleton;
type
{
TQuery:
Class that encapsulates a query on the code snippets database. It enables a
search to be run against the database and makes the found snippets
available. Must only be instantiated once as a singleton.
}
TQuery = class(TSingleton,
IQuery
)
strict private
var
fSelection: TSnippetList; // List of snippets selected by current query
fActiveSearches: TList<ISearch>; // List of currently active searches
class function GetInstance: IQuery; static;
{Gets singleton instance of class, creating it if necessary
@return Singleton instance.
}
function RunSearch(Search: ISearch): Boolean;
strict protected
procedure Initialize; override;
procedure Finalize; override;
public
class property Instance: IQuery read GetInstance;
{ IQuery methods }
function ApplySearch(Search: ISearch; const Refine: Boolean): Boolean;
{Runs query by applying a search to the whole database. If search succeeds
matching snippets and search are stored in query's Selection and Search
properties. If search fails Selection and Search are left unchanged.
@param Search [in] Search to apply.
@param Refine [in] Flag indicating whether any existing search should
be refined (True) or search should be of whole databas (False).
@return True if search succeeds and False if it fails.
}
/// <summary>Checks if there is an active search.</summary>
/// <remarks>A search is active if the latest search is not the null
/// search.</remarks>
function IsSearchActive: Boolean;
function Refresh: Boolean;
{Re-applies the latest search if one exists.
@return True if search was re-applied, False if there was no search to
apply.
}
procedure Reset;
{Resets query. Selection property is set to all snippets in database and
Search property is set to nul search.
}
procedure Update;
{Updates query. Attempts to refresh query and, if that fails, resets it.
}
function GetLatestSearch: ISearch;
{Gets reference to latest search object.
@return Required search object.
}
function GetSelection: TSnippetList;
{Gets reference to list of snippets selected by last search.
@return Reference to required list of snippets.
}
procedure GetCatSelection(const Cat: TCategory;
const SnipList: TSnippetList);
{Provides list of snippets selected by last search that are in a specified
category.
@param Cat [in] Reference to required category.
@param SnipList [in] Object to receive snippet list. List is emptied
before snippets are copied in.
}
end;
function Query: IQuery;
{Returns singleton instance of object that encapsulates a query on the
snippets database.
@return Singleton object.
}
begin
Result := TQuery.Instance;
end;
{ TQuery }
function TQuery.ApplySearch(Search: ISearch; const Refine: Boolean):
Boolean;
{Runs query by applying a search to the whole database. If search succeeds
matching snippets and search are stored in query's Selection and Search
properties. If search fails Selection and Search are left unchanged.
@param Search [in] Search to apply. Must not be nil or null search.
@param Refine [in] Flag indicating whether any existing search should be
refined (True) or search should be of whole databas (False).
@return True if search succeeds and False if it fails.
}
begin
Assert(Assigned(Search), ClassName + '.ApplySearch: Search is nil');
Assert(Assigned(Search.Filter),
ClassName + '.ApplySearch: Search.Filter is nil');
Assert(not Search.Filter.IsNull,
ClassName + '.ApplySearch: Search can''t be null');
if IsSearchActive and not Refine then
Reset;
Result := RunSearch(Search);
if not Result then
Exit;
// Search was successful
fActiveSearches.Add(Search);
end;
procedure TQuery.Finalize;
begin
fSelection.Free;
fActiveSearches.Free;
inherited;
end;
procedure TQuery.GetCatSelection(const Cat: TCategory;
const SnipList: TSnippetList);
{Provides list of snippets selected by last search that are in a specified
category.
@param Cat [in] Reference to required category.
@param SnipList [in] Object to receive snippet list. List is emptied before
snippets are copied in.
}
var
Idx: Integer; // Loops thru all snippets in selection
begin
SnipList.Clear;
for Idx := 0 to Pred(fSelection.Count) do
begin
if Cat.Snippets.Contains(fSelection[Idx]) then
SnipList.Add(fSelection[Idx]);
end;
end;
function TQuery.GetLatestSearch: ISearch;
{Gets reference to latest search object.
@return Required search object.
}
begin
if fActiveSearches.Count > 0 then
Result := fActiveSearches.Last
else
Result := TSearchFactory.CreateNullSearch;
end;
class function TQuery.GetInstance: IQuery;
{Gets singleton instance of class, creating it if necessary
@return Singleton instance.
}
begin
Result := TQuery.Create; // OK since multiple calls return same instance
end;
function TQuery.GetSelection: TSnippetList;
{Gets reference to list of snippets selected by last search.
@return Reference to required list of snippets.
}
begin
Result := fSelection;
end;
procedure TQuery.Initialize;
begin
inherited;
fSelection := TSnippetList.Create;
fActiveSearches := TList<ISearch>.Create;
Reset;
end;
function TQuery.IsSearchActive: Boolean;
begin
// Search is active if there is one or more in active search list
Result := fActiveSearches.Count > 0;
end;
function TQuery.Refresh: Boolean;
{Re-applies the latest search if one exists.
@return True if search was re-applied, False if there was no search to
apply.
}
var
Search: ISearch;
begin
if not IsSearchActive then
Exit(False);
fSelection.Assign(Database.Snippets);
for Search in fActiveSearches do
RunSearch(Search);
Result := True;
end;
procedure TQuery.Reset;
{Resets query. Selection property is set to all snippets in database and
Search property is set to nul search.
}
begin
fSelection.Assign(Database.Snippets);
fActiveSearches.Clear;
end;
function TQuery.RunSearch(Search: ISearch): Boolean;
var
FoundList: TSnippetList;
begin
FoundList := TSnippetList.Create;
try
Result := Search.Execute(fSelection, FoundList);
if not Result then
Exit;
fSelection.Assign(FoundList);
finally
FoundList.Free;
end;
end;
procedure TQuery.Update;
{Updates query. Attempts to refresh query and, if that fails, resets it.
}
begin
if not Refresh then
Reset;
end;
end.
Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.