source: gsdl/trunk/src/colservr/collectset.cpp@ 15002

Last change on this file since 15002 was 15002, checked in by davidb, 16 years ago

Collections can now be put in to "groups" i.e. can be located inside another collection, which is marked as "collectgroup" true. The top-level collection appears on the home page, and when clicked upon display a new "home page" with only the collections appearing within its folder displayed. To implement this, the main change is in collectset.cpp, which now runs "add_all_collection_groups" after it has added all the top-level collections. comtypes.h has been updated to include the new field, "isCollectGroup". Finally, pageaction.cpp has been updated so these changes are reflected in the home page generated.

  • Property svn:keywords set to Author Date Id Revision
File size: 13.2 KB
Line 
1/**********************************************************************
2 *
3 * collectset.cpp --
4 * Copyright (C) 1999 The New Zealand Digital Library Project
5 *
6 * A component of the Greenstone digital library software
7 * from the New Zealand Digital Library Project at the
8 * University of Waikato, New Zealand.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 *
24 *********************************************************************/
25
26
27#include "collectserver.h"
28#include "filter.h"
29#include "browsefilter.h"
30#include "queryfilter.h"
31#include "infodbclass.h"
32#include "mgqueryfilter.h"
33#include "mgppqueryfilter.h"
34#include "mggdbmsource.h"
35#include "lucenequeryfilter.h"
36#include "lucenegdbmsource.h"
37
38#include "fileutil.h"
39#include <assert.h>
40
41#include "colservrconfig.h"
42#include "recptconfig.h"
43#include "fileutil.h"
44#include "collectset.h"
45
46collectset::collectset (text_t &gsdlhome) {
47
48 text_tarray collections;
49 text_t collectdir;
50
51 // get gsdlhome (if we fail the error will be picked up later -- in
52 // cgiwrapper)
53
54 if (site_cfg_read (gsdlhome, httpdomain, httpprefix)) {
55 if (!gsdlhome.empty() && directory_exists(gsdlhome)) {
56 collectdir = filename_cat (gsdlhome, "collect");
57 if (read_dir (collectdir, collections)) {
58
59 text_tarray::const_iterator thiscol = collections.begin();
60 text_tarray::const_iterator endcol = collections.end();
61
62 while (thiscol != endcol) {
63 // ignore the modelcol
64 if (*thiscol == "modelcol") {
65 ++thiscol;
66 continue;
67 }
68
69 this->add_collection (*thiscol, gsdlhome);
70
71 ++thiscol;
72 }
73
74 this->add_all_collection_groups(gsdlhome);
75 }
76 }
77 }
78}
79
80collectset::~collectset () {
81 collectservermapclass::iterator here = cservers.begin();
82 collectservermapclass::iterator end = cservers.end();
83
84 while (here != end) {
85 if ((*here).second.c != NULL) {
86 delete (*here).second.c;
87 }
88 ++here;
89 }
90 cservers.clear();
91}
92
93bool collectset::init (ostream &logout) {
94 collectservermapclass::iterator here = cservers.begin();
95 collectservermapclass::iterator end = cservers.end();
96
97 while (here != end) {
98 assert ((*here).second.c != NULL);
99 if ((*here).second.c != NULL) {
100 const colservrconf &configinfo = (*here).second.c->get_configinfo ();
101
102 // configure this collection server
103
104 // note that we read build.cfg before collect.cfg so that the indexmaps
105 // are available to decode defaultindex, defaultsubcollection, and
106 // defaultlanguage
107
108 bool failed_build_cfg = false;
109 if (!build_cfg_read (*((*here).second.c), configinfo.gsdlhome,
110 configinfo.collection)) {
111 failed_build_cfg = true;
112
113 outconvertclass text_t2ascii;
114 logout << text_t2ascii
115 << "Warning: couldn't read build.cfg file for collection \"" //****
116 << configinfo.collection << "\", gsdlhome=\""
117 << configinfo.gsdlhome << "\"\n";
118 }
119
120 bool failed_collect_cfg = false;
121 if (!collect_cfg_read (*((*here).second.c), configinfo.gsdlhome,
122 configinfo.collection)) {
123 failed_collect_cfg = true;
124 outconvertclass text_t2ascii;
125 logout << text_t2ascii
126 << "Warning: couldn't read collect.cfg file for collection \""
127 << configinfo.collection << "\", gsdlhome=\""
128 << configinfo.gsdlhome << "\"\n";
129 }
130
131
132 bool is_colgroup = (*here).second.c->is_collection_group();
133
134 if (failed_collect_cfg) {
135 ++here;
136 continue;
137 }
138
139 if (failed_build_cfg && (!is_colgroup)) {
140 ++here;
141 continue;
142 }
143 // let a failed build.cfg through if its 'collect.cfg' marks it as 'collectgroup true'
144
145 if (!(*here).second.c->init (logout)) return false;
146
147 (*here).second.c->configure("httpdomain",httpdomain);
148 (*here).second.c->configure("httpprefix",httpprefix);
149 }
150 ++here;
151 }
152
153 return true;
154}
155
156collectservermapclass collectset::servers()
157{ return cservers;
158}
159
160
161void collectset::add_all_collections(const text_t &gsdlhome) {
162
163 text_tarray collections;
164 text_t collectdir = filename_cat(gsdlhome, "collect");
165 if (read_dir(collectdir, collections)) {
166
167 text_tarray::const_iterator thiscol = collections.begin();
168 text_tarray::const_iterator endcol = collections.end();
169
170 while (thiscol != endcol) {
171
172 // ignore the modelcol
173 if (*thiscol == "modelcol") {
174 ++thiscol;
175 continue;
176 }
177
178 // create collection server and add to null protocol
179 this->add_collection (*thiscol, gsdlhome);
180
181 ++thiscol;
182 }
183
184 this->add_all_collection_groups(gsdlhome);
185 }
186}
187
188// add_collection sets up the collectionserver and calls
189// add_collectserver
190void collectset::add_collection (const text_t &collection,
191 const text_t &gsdlhome) {
192
193 this->remove_collection(collection);
194
195 // read config file to see if built with mg, mgpp, or lucene
196 // -- we can rely on the collection (and therefore the build.cfg)
197 // being here since this is the null protocol - a nicer way to
198 // do this would be preferable though - Stefan.
199 text_t buildtype = "mg"; // mg is default
200
201 text_tarray cfgline;
202 text_t key;
203 text_t build_cfg = filename_cat(gsdlhome, "collect", collection, "index", "build.cfg");
204 char *build_cfgc = build_cfg.getcstr();
205 ifstream confin(build_cfgc);
206
207 if (confin) {
208 while (read_cfg_line(confin, cfgline) >= 0) {
209 if (cfgline.size() == 2) {
210 key = cfgline[0];
211 cfgline.erase(cfgline.begin());
212 if (key == "buildtype") {
213 buildtype = cfgline[0];
214 break;
215 }
216 }
217 }
218 confin.close();
219 }
220 delete []build_cfgc;
221
222 collectserver *cserver = new collectserver();
223 gdbmclass *gdbmhandler = new gdbmclass();
224
225 // add a null filter
226 filterclass *filter = new filterclass ();
227 cserver->add_filter (filter);
228
229 // add a browse filter
230 browsefilterclass *browsefilter = new browsefilterclass();
231 browsefilter->set_gdbmptr (gdbmhandler);
232
233 cserver->add_filter (browsefilter);
234
235 if (buildtype == "mg") {
236 mgsearch = new mgsearchclass();
237
238 // add a query filter
239 mgqueryfilterclass *queryfilter = new mgqueryfilterclass();
240 queryfilter->set_gdbmptr (gdbmhandler);
241 queryfilter->set_textsearchptr (mgsearch);
242 cserver->add_filter (queryfilter);
243
244 // add a mg and gdbm source
245 mggdbmsourceclass *mggdbmsource = new mggdbmsourceclass ();
246 mggdbmsource->set_gdbmptr (gdbmhandler);
247 mggdbmsource->set_textsearchptr (mgsearch);
248 cserver->add_source (mggdbmsource);
249 }
250 else if (buildtype == "mgpp") {
251 mgppsearch = new mgppsearchclass();
252
253 // add a query filter
254 mgppqueryfilterclass *queryfilter = new mgppqueryfilterclass();
255 queryfilter->set_gdbmptr (gdbmhandler);
256 queryfilter->set_textsearchptr (mgppsearch);
257 cserver->add_filter (queryfilter);
258
259 // add a mg and gdbm source
260 mggdbmsourceclass *mggdbmsource = new mggdbmsourceclass ();
261 mggdbmsource->set_gdbmptr (gdbmhandler);
262 mggdbmsource->set_textsearchptr (mgppsearch);
263 cserver->add_source (mggdbmsource);
264 }
265 else if (buildtype == "lucene") {
266 lucenesearch = new lucenesearchclass();
267 lucenesearch->set_gsdlhome(gsdlhome);
268
269 // add a query filter
270 lucenequeryfilterclass *queryfilter = new lucenequeryfilterclass();
271 queryfilter->set_gdbmptr (gdbmhandler);
272 queryfilter->set_textsearchptr (lucenesearch);
273 cserver->add_filter (queryfilter);
274
275 // add a lucene and gdbm source
276 lucenegdbmsourceclass *lucenegdbmsource = new lucenegdbmsourceclass ();
277 lucenegdbmsource->set_gdbmptr (gdbmhandler);
278 lucenegdbmsource->set_textsearchptr (lucenesearch);
279 cserver->add_source (lucenegdbmsource);
280 }
281
282 // inform collection server and everything it contains about its
283 // collection name
284 cserver->configure ("collection", collection);
285 cserver->configure ("gsdlhome", gsdlhome);
286
287 cservers.addcollectserver (cserver);
288}
289
290void collectset::remove_all_collections () {
291
292 // first unload any cached mg databases
293 if (mgsearch != NULL) {
294 mgsearch->unload_database();
295 }
296
297 // now delete the collection server objects
298 collectservermapclass::iterator here = cservers.begin();
299 collectservermapclass::iterator end = cservers.end();
300
301 while (here != end) {
302 if ((*here).second.c != NULL) {
303 delete (*here).second.c;
304 }
305 ++here;
306 }
307 cservers.clear();
308}
309
310void collectset::add_collection_group(const text_t& collection,
311 const text_t& gsdlhome)
312{
313 text_tarray group;
314 text_t collect_group_dir = filename_cat (gsdlhome, "collect", collection);
315
316 // need to read collect.cfg for 'collectgroup' as class hasn't been initialised through 'init' yet
317 text_t is_collect_group;
318 text_tarray cfgline;
319 text_t key;
320 text_t build_cfg = filename_cat(gsdlhome, "collect", collection, "etc", "collect.cfg");
321 char *collect_cfgc = build_cfg.getcstr();
322 ifstream confin(collect_cfgc);
323
324 if (confin) {
325 while (read_cfg_line(confin, cfgline) >= 0) {
326 if (cfgline.size() == 2) {
327 key = cfgline[0];
328 cfgline.erase(cfgline.begin());
329 if (key == "collectgroup") {
330 is_collect_group = cfgline[0];
331 break;
332 }
333 }
334 }
335 confin.close();
336 }
337 delete []collect_cfgc;
338
339 if (is_collect_group == "true") {
340
341 if (read_dir (collect_group_dir, group)) {
342
343 text_tarray::const_iterator thiscol = group.begin();
344 text_tarray::const_iterator endcol = group.end();
345
346 while (thiscol != endcol) {
347 // ignore the modelcol
348 if (*thiscol == "etc") {
349 ++thiscol;
350 continue;
351 }
352
353 this->add_collection (collection + "/" + *thiscol, gsdlhome);
354
355 ++thiscol;
356 }
357 }
358 }
359}
360
361void collectset::add_all_collection_groups (const text_t& gsdlhome)
362
363{
364 collectservermapclass::iterator here = cservers.begin();
365 collectservermapclass::iterator end = cservers.end();
366
367 while (here != end) {
368 text_t collection = (*here).second.c->get_collection_name();
369 this->add_collection_group(collection,gsdlhome);
370
371 ++here;
372 }
373}
374
375
376// remove_collection deletes the collection server of collection.
377// This only needs to be called if a collectionserver is to be
378// removed while the library is running. The destructor function
379// cleans up all collectservers when the program exits.
380void collectset::remove_collection (const text_t &collection) {
381
382 // do nothing if no collection server exists for this collection
383 if (cservers.getcollectserver(collection) == NULL) return;
384
385 // first unload any cached mg databases - we may need to do something
386 // similar to this for mgpp and lucene too
387 if (mgsearch != NULL) {
388 mgsearch->unload_database();
389 }
390
391 // now delete the collection server object
392 collectservermapclass::iterator here = cservers.begin();
393 collectservermapclass::iterator end = cservers.end();
394
395 while (here != end) {
396 if ((*here).second.c != NULL && (*here).first == collection) {
397 delete (*here).second.c;
398 cservers.erase (here);
399 return;
400 }
401 ++here;
402 }
403}
404
405
406// remove_collection deletes the collection server of collection.
407// This only needs to be called if a collectionserver is to be
408// removed while the library is running. The destructor function
409// cleans up all collectservers when the program exits.
410void collectset::remove_collection (const text_t &collection, ostream &logout) {
411
412 remove_collection(collection);
413
414 outconvertclass text_t2ascii;
415 logout << text_t2ascii << "nullproto::remove_collection: failed to remove collectserver for "
416 << collection << "\n";
417}
418
419void collectset::configure(const text_t &key, const text_tarray &cfgline)
420{
421 if (key == "collection" || key == "collectdir") return;
422
423 collectservermapclass::iterator here = cservers.begin();
424 collectservermapclass::iterator end = cservers.end();
425
426 while (here != end) {
427 assert ((*here).second.c != NULL);
428 if ((*here).second.c != NULL) {
429 if (key == "collectinfo") {
430 if ((*here).first == cfgline[0]) {
431 (*here).second.c->configure ("gsdlhome", cfgline[1]);
432 (*here).second.c->configure ("gdbmhome", cfgline[2]);
433 }
434 } else {
435 (*here).second.c->configure (key, cfgline);
436 }
437 }
438
439 ++here;
440 }
441}
442
443void collectset::getCollectionList (text_tarray &collist)
444{
445 collist.erase(collist.begin(),collist.end());
446
447 collectservermapclass::iterator here = cservers.begin();
448 collectservermapclass::iterator end = cservers.end();
449 while (here != end) {
450 assert ((*here).second.c != NULL);
451 if ((*here).second.c != NULL) {
452 collist.push_back ((*here).second.c->get_collection_name());
453 }
454 ++here;
455 }
456}
457
458void collectset::setReceptionistServers(receptionist &recpt, text_t &gsdlhome)
459{
460 collectservermapclass::iterator here = cservers.begin();
461 collectservermapclass::iterator end = cservers.end();
462 while (here != end) {
463 assert ((*here).second.c != NULL);
464
465 text_tarray colinfo;
466 colinfo.push_back((*here).second.c->get_collection_name());
467 colinfo.push_back(gsdlhome);
468 colinfo.push_back(gsdlhome);
469 recpt.configure("collectinfo", colinfo);
470
471 ++here;
472 }
473}
Note: See TracBrowser for help on using the repository browser.