/********************************************************************** * * browsefilter.cpp -- * Copyright (C) 1999 The New Zealand Digital Library Project * * A component of the Greenstone digital library software * from the New Zealand Digital Library Project at the * University of Waikato, New Zealand. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * *********************************************************************/ #include "browsefilter.h" #include "fileutil.h" browsefilterclass::browsefilterclass () { db_ptr = NULL; // -- onePerQuery StartResults integer FilterOption_t filtopt; filtopt.name = "StartResults"; filtopt.type = FilterOption_t::integert; filtopt.repeatable = FilterOption_t::onePerQuery; filtopt.defaultValue = "1"; filtopt.validValues.push_back("1"); filtopt.validValues.push_back("10000"); filterOptions["StartResults"] = filtopt; // -- onePerQuery EndResults integer filtopt.clear(); filtopt.name = "EndResults"; filtopt.type = FilterOption_t::integert; filtopt.repeatable = FilterOption_t::onePerQuery; filtopt.defaultValue = "-1"; filtopt.validValues.push_back("-1"); filtopt.validValues.push_back("10000"); filterOptions["EndResults"] = filtopt; // -- onePerQuery ParentNode string ("" will return the browsing available) filtopt.clear(); filtopt.name = "ParentNode"; filtopt.type = FilterOption_t::stringt; filtopt.repeatable = FilterOption_t::onePerQuery; filtopt.defaultValue = g_EmptyText; filterOptions["ParentNode"] = filtopt; } browsefilterclass::~browsefilterclass () { } void browsefilterclass::configure (const text_t &key, const text_tarray &cfgline) { filterclass::configure (key, cfgline); if (key == "indexstem") { indexstem = cfgline[0]; } } bool browsefilterclass::init (ostream &logout) { outconvertclass text_t2ascii; if (!filterclass::init(logout)) return false; if (db_ptr == NULL) { // most likely a configuration problem logout << text_t2ascii << "configuration error: browsefilter contains a null dbclass\n\n"; return false; } if (indexstem.empty()) { indexstem = collection; } db_filename = resolve_db_filename(indexstem,db_ptr->getfileextension()); if (!file_exists(db_filename)) { logout << text_t2ascii << "warning: database \"" << db_filename << "\" does not exist\n\n"; // return false; } return true; } void browsefilterclass::filter (const FilterRequest_t &request, FilterResponse_t &response, comerror_t &err, ostream &logout) { int numDocs = 0; outconvertclass text_t2ascii; response.clear (); err = noError; if (db_ptr == NULL) { // most likely a configuration problem logout << text_t2ascii << "configuration error: browsefilter contains a null dbclass\n\n"; err = configurationError; return; } // open the database db_ptr->setlogout(&logout); if (!db_ptr->opendatabase (db_filename, DB_READER, 100, false)) { // most likely a system problem (we have already checked that the database exists) logout << text_t2ascii << "system problem: open on database \"" << db_filename << "\" failed\n\n"; err = systemProblem; return; } // get the browse parameters int startresults = filterOptions["StartResults"].defaultValue.getint(); int endresults = filterOptions["EndResults"].defaultValue.getint(); text_t parentnode = filterOptions["ParentNode"].defaultValue; OptionValue_tarray::const_iterator options_here = request.filterOptions.begin(); OptionValue_tarray::const_iterator options_end = request.filterOptions.end(); while (options_here != options_end) { if ((*options_here).name == "StartResults") startresults = (*options_here).value.getint(); else if ((*options_here).name == "EndResults") endresults = (*options_here).value.getint(); else if ((*options_here).name == "ParentNode") parentnode = (*options_here).value; else { logout << text_t2ascii << "warning: unknown browsefilter option \"" << (*options_here).name << "\" ignored.\n\n"; } ++options_here; } infodbclass info; // translate any ".fc", ".pr" etc. stuff in the parentnode parentnode = db_ptr->translate_OID (parentnode, info); // adjust topmost browsing node if (parentnode.empty()) parentnode = "browse"; // get the node if ((request.filterResultOptions & FROID) || (request.filterResultOptions & FRmetadata)) { if (!db_ptr->getinfo(parentnode, info)) { // didn't find the node logout << text_t2ascii << "warning: lookup for node \"" << parentnode << "\" failed for browsefilter.\n\n"; } else { // found the node // replace " with the parent node name and split the contains string // into the result set text_tarray resultset; text_t tmptext; text_t &contains = info["contains"]; text_t::iterator contains_here = contains.begin(); text_t::iterator contains_end = contains.end(); while (contains_here != contains_end) { if (*contains_here == '"') tmptext += parentnode; else if (*contains_here == ';') { if (!tmptext.empty()) resultset.push_back (tmptext); tmptext.clear(); } else tmptext.push_back(*contains_here); ++contains_here; } // insert the last result in the set if (!tmptext.empty()) resultset.push_back (tmptext); text_tarray offset_resultset; text_t &md_type = info["mdtype"]; if (!md_type.empty()) { text_t &md_offset = info["mdoffset"]; if (!md_offset.empty()) { text_t offsettext; text_t::iterator offset_here = md_offset.begin(); text_t::iterator offset_end = md_offset.end(); while (offset_here != offset_end) { if (*offset_here == ';') { if (offsettext.empty()) { offset_resultset.push_back ("0"); } else { offset_resultset.push_back (offsettext); } offsettext.clear(); } else { offsettext.push_back(*offset_here); } ++offset_here; } // insert the last result in the set if (offsettext.empty()) { offset_resultset.push_back ("0"); } else { offset_resultset.push_back (offsettext); } } else { // add 0 offset for each 'contains' entry text_tarray::iterator result_here = resultset.begin(); text_tarray::iterator result_end = resultset.end(); while (result_here != result_end) { offset_resultset.push_back("0"); ++result_here; } } // do an intersection with the input set if (!request.docSet.empty()) { text_tarray intersect_resultset; text_tarray intersect_offset_resultset; text_tarray::const_iterator resultset_here = resultset.begin(); text_tarray::const_iterator resultset_end = resultset.end(); text_tarray::const_iterator offset_resultset_here = offset_resultset.begin(); while (resultset_here != resultset_end) { if (in_set (request.docSet, *resultset_here)) { intersect_resultset.push_back (*resultset_here); intersect_offset_resultset.push_back (*offset_resultset_here); } ++resultset_here; ++offset_resultset_here; } resultset = intersect_resultset; offset_resultset = intersect_offset_resultset; } } else { // do an intersection with the input set if (!request.docSet.empty()) { intersect (resultset, request.docSet); } // add 0 offset for each 'contains' entry text_tarray::iterator result_here = resultset.begin(); text_tarray::iterator result_end = resultset.end(); while (result_here != result_end) { offset_resultset.push_back("0"); ++result_here; } } // create the response numDocs = resultset.size(); int resultnum = 1; ResultDocInfo_t resultdoc; text_tarray::iterator result_here = resultset.begin(); text_tarray::iterator result_end = resultset.end(); text_tarray::iterator offset_result_here = offset_resultset.begin(); while (result_here != result_end) { // if endresults is -1 get all results if ((endresults != -1) && (resultnum > endresults)) break; if (resultnum >= startresults) { resultdoc.OID = (*result_here); if (!md_type.empty()) { resultdoc.classifier_metadata_type = md_type; resultdoc.classifier_metadata_offset = offset_result_here->getint(); } response.docInfo.push_back(resultdoc); } ++resultnum; ++result_here; if (!md_type.empty()) ++offset_result_here; } } } db_ptr->closedatabase(); // Important that local library doesn't leave any files open response.numDocs = numDocs; response.isApprox = Exact; }