/********************************************************************** * * queryfilter.cpp -- base class for queryfilters * 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 "queryfilter.h" #include "fileutil.h" // translate will return true if successful bool queryfilterclass::translate (dbclass *db_ptr, int docnum, text_t &trans_OID) { infodbclass info; trans_OID.clear(); // get the info if (db_ptr == NULL) return false; if (!db_ptr->getinfo(docnum, info)) return false; // translate if (info["section"].empty()) return false; trans_OID = info["section"]; return true; } // whether document results are needed bool queryfilterclass::need_matching_docs (int filterResultOptions) { return ((filterResultOptions & FROID) || (filterResultOptions & FRranking) || (filterResultOptions & FRmetadata)); } // whether term information is needed bool queryfilterclass::need_term_info (int filterResultOptions) { return ((filterResultOptions & FRtermFreq) || (filterResultOptions & FRmatchTerms)); } ///////////////////////////////// // functions for queryfilterclass ///////////////////////////////// // get the query parameters void queryfilterclass::parse_query_params (const FilterRequest_t &request, vector &query_params, int &startresults, int &endresults, text_t &phrasematch, ostream &logout) { outconvertclass text_t2ascii; // set defaults for the return parameters query_params.erase(query_params.begin(), query_params.end()); startresults = filterOptions["StartResults"].defaultValue.getint(); endresults = filterOptions["EndResults"].defaultValue.getint(); phrasematch = filterOptions["PhraseMatch"].defaultValue; // set defaults for query parameters queryparamclass query; query.combinequery = "or"; // first one must be "or" query.collection = collection; query.index = filterOptions["Index"].defaultValue; query.subcollection = filterOptions["Subcollection"].defaultValue; query.language = filterOptions["Language"].defaultValue; query.querystring.clear(); query.search_type = (filterOptions["QueryType"].defaultValue == "ranked"); query.match_mode = (filterOptions["MatchMode"].defaultValue == "all"); query.casefolding = (filterOptions["Casefold"].defaultValue == "true"); query.stemming = (filterOptions["Stem"].defaultValue == "true"); query.accentfolding = (filterOptions["AccentFold"].defaultValue == "true"); query.maxdocs = filterOptions["Maxdocs"].defaultValue.getint(); query.level = filterOptions["Level"].defaultValue; query.filterstring = filterOptions["FilterString"].defaultValue; // Lucene specific query.sortfield = filterOptions["SortField"].defaultValue; // Lucene specific query.fuzziness = filterOptions["Fuzziness"].defaultValue; // Lucene specific query.maxnumeric = maxnumeric; 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 == "CombineQuery") { // add this query // "all", needed when combining queries where the document results are needed if (need_matching_docs (request.filterResultOptions)) query.maxdocs = -1; query_params.push_back (query); // start on next query query.clear(); query.combinequery = (*options_here).value; // set defaults for query parameters query.collection = collection; query.index = filterOptions["Index"].defaultValue; query.subcollection = filterOptions["Subcollection"].defaultValue; query.language = filterOptions["Language"].defaultValue; query.querystring.clear(); query.search_type = (filterOptions["QueryType"].defaultValue == "ranked"); query.match_mode = (filterOptions["MatchMode"].defaultValue == "all"); query.casefolding = (filterOptions["Casefold"].defaultValue == "true"); query.stemming = (filterOptions["Stem"].defaultValue == "true"); query.accentfolding = (filterOptions["AccentFold"].defaultValue == "true"); query.level = filterOptions["Level"].defaultValue; query.filterstring = filterOptions["FilterString"].defaultValue; // Lucene specific query.sortfield = filterOptions["SortField"].defaultValue; // Lucene specific query.fuzziness = filterOptions["Fuzziness"].defaultValue; // Lucene specific query.maxnumeric = maxnumeric; // "all", needed when combining queries where the document results are needed if (need_matching_docs (request.filterResultOptions)) query.maxdocs = -1; else query.maxdocs = filterOptions["Maxdocs"].defaultValue.getint(); } else 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 == "QueryType") { query.search_type = ((*options_here).value == "ranked"); } else if ((*options_here).name == "MatchMode") { query.match_mode = ((*options_here).value == "all"); if (query.match_mode == 1) query.maxdocs = -1; } else if ((*options_here).name == "Term") { query.querystring = (*options_here).value; } else if ((*options_here).name == "Casefold") { query.casefolding = ((*options_here).value == "true"); } else if ((*options_here).name == "Stem") { query.stemming = ((*options_here).value == "true"); } else if ((*options_here).name == "AccentFold") { query.accentfolding = ((*options_here).value == "true"); } else if ((*options_here).name == "Index"&& (*options_here).value !="") { query.index = (*options_here).value; } else if ((*options_here).name == "Subcollection") { query.subcollection = (*options_here).value; } else if ((*options_here).name == "Language") { query.language = (*options_here).value; } else if ((*options_here).name == "Maxdocs") { query.maxdocs = (*options_here).value.getint(); } else if ((*options_here).name == "PhraseMatch") { phrasematch = (*options_here).value; } else if ((*options_here).name == "Level") { query.level = (*options_here).value; } else if ((*options_here).name == "FilterString") { query.filterstring = (*options_here).value; } else if ((*options_here).name == "SortField") { query.sortfield = (*options_here).value; } else if ((*options_here).name == "Fuzziness") { query.fuzziness = (*options_here).value; } else { logout << text_t2ascii << "warning: unknown queryfilter option \"" << (*options_here).name << "\" ignored.\n\n"; } ++options_here; } // Store the start and end results in the query too, as lucene now needs to // pass them through to the Java query.startresults = startresults; query.endresults = endresults; // add the last query query_params.push_back (query); } queryfilterclass::queryfilterclass () { db_ptr = NULL; textsearchptr = NULL; maxnumeric = 4; FilterOption_t filtopt; filtopt.name = "CombineQuery"; filtopt.type = FilterOption_t::enumeratedt; filtopt.repeatable = FilterOption_t::onePerQuery; filtopt.defaultValue = "and"; filtopt.validValues.push_back("and"); filtopt.validValues.push_back("or"); filtopt.validValues.push_back("not"); filterOptions["CombineQuery"] = filtopt; // -- onePerQuery StartResults integer filtopt.clear(); 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("1000"); filterOptions["StartResults"] = filtopt; // -- onePerQuery EndResults integer filtopt.clear(); filtopt.name = "EndResults"; filtopt.type = FilterOption_t::integert; filtopt.repeatable = FilterOption_t::onePerQuery; filtopt.defaultValue = "10"; filtopt.validValues.push_back("-1"); filtopt.validValues.push_back("1000"); filterOptions["EndResults"] = filtopt; // -- onePerQuery QueryType enumerated (boolean, ranked) filtopt.clear(); filtopt.name = "QueryType"; filtopt.type = FilterOption_t::enumeratedt; filtopt.repeatable = FilterOption_t::onePerQuery; filtopt.defaultValue = "ranked"; filtopt.validValues.push_back("boolean"); filtopt.validValues.push_back("ranked"); filterOptions["QueryType"] = filtopt; // -- onePerQuery MatchMode enumerated (some, all) filtopt.clear(); filtopt.name = "MatchMode"; filtopt.type = FilterOption_t::enumeratedt; filtopt.repeatable = FilterOption_t::onePerQuery; filtopt.defaultValue = "some"; filtopt.validValues.push_back("some"); filtopt.validValues.push_back("all"); filterOptions["MatchMode"] = filtopt; // -- onePerTerm Term string ??? filtopt.clear(); filtopt.name = "Term"; filtopt.type = FilterOption_t::stringt; filtopt.repeatable = FilterOption_t::onePerTerm; filtopt.defaultValue = ""; filterOptions["Term"] = filtopt; // -- onePerTerm Casefold boolean filtopt.clear(); filtopt.name = "Casefold"; filtopt.type = FilterOption_t::booleant; filtopt.repeatable = FilterOption_t::onePerTerm; filtopt.defaultValue = "true"; filtopt.validValues.push_back("false"); filtopt.validValues.push_back("true"); filterOptions["Casefold"] = filtopt; // -- onePerTerm Stem boolean filtopt.clear(); filtopt.name = "Stem"; filtopt.type = FilterOption_t::booleant; filtopt.repeatable = FilterOption_t::onePerTerm; filtopt.defaultValue = "false"; filtopt.validValues.push_back("false"); filtopt.validValues.push_back("true"); filterOptions["Stem"] = filtopt; // -- onePerTerm AccentFold boolean filtopt.clear(); filtopt.name = "AccentFold"; filtopt.type = FilterOption_t::booleant; filtopt.repeatable = FilterOption_t::onePerTerm; filtopt.defaultValue = "false"; filtopt.validValues.push_back("false"); filtopt.validValues.push_back("true"); filterOptions["AccentFold"] = filtopt; // -- onePerTerm Index enumerated filtopt.clear(); filtopt.name = "Index"; filtopt.type = FilterOption_t::enumeratedt; filtopt.repeatable = FilterOption_t::onePerTerm; filtopt.defaultValue = ""; filterOptions["Index"] = filtopt; // -- onePerTerm Subcollection enumerated filtopt.clear(); filtopt.name = "Subcollection"; filtopt.type = FilterOption_t::enumeratedt; filtopt.repeatable = FilterOption_t::onePerTerm; filtopt.defaultValue = ""; filterOptions["Subcollection"] = filtopt; // -- onePerTerm Language enumerated filtopt.clear(); filtopt.name = "Language"; filtopt.type = FilterOption_t::enumeratedt; filtopt.repeatable = FilterOption_t::onePerTerm; filtopt.defaultValue = ""; filterOptions["Language"] = filtopt; // -- onePerQuery Maxdocs integer filtopt.clear(); filtopt.name = "Maxdocs"; filtopt.type = FilterOption_t::integert; filtopt.repeatable = FilterOption_t::onePerQuery; filtopt.defaultValue = "200"; filtopt.validValues.push_back("-1"); filtopt.validValues.push_back("1000"); filterOptions["Maxdocs"] = filtopt; // -- onePerQuery PhraseMatch enumerated filtopt.clear(); filtopt.name = "PhraseMatch"; filtopt.type = FilterOption_t::enumeratedt; filtopt.repeatable = FilterOption_t::onePerQuery; filtopt.defaultValue = "some_phrases"; filtopt.validValues.push_back ("all_phrases"); filtopt.validValues.push_back ("some_phrases"); filtopt.validValues.push_back ("all_docs"); filterOptions["PhraseMatch"] = filtopt; } queryfilterclass::~queryfilterclass () { // don't delete db_ptr or textsearchptr here, they'll be cleaned up by the source } void queryfilterclass::configure (const text_t &key, const text_tarray &cfgline) { filterclass::configure (key, cfgline); if (key == "indexmap") { indexmap.importmap (cfgline); // update the list of indexes in the filter information text_tarray options; indexmap.gettoarray (options); filterOptions["Index"].validValues = options; } else if (key == "defaultindex") { indexmap.from2to (cfgline[0], filterOptions["Index"].defaultValue); } else if (key == "subcollectionmap") { subcollectionmap.importmap (cfgline); // update the list of subcollections in the filter information text_tarray options; subcollectionmap.gettoarray (options); filterOptions["Subcollection"].validValues = options; } else if (key == "defaultsubcollection") { subcollectionmap.from2to (cfgline[0], filterOptions["Subcollection"].defaultValue); } else if (key == "languagemap") { languagemap.importmap (cfgline); // update the list of languages in the filter information text_tarray options; languagemap.gettoarray (options); filterOptions["Language"].validValues = options; } else if (key == "defaultlanguage") { languagemap.from2to (cfgline[0], filterOptions["Language"].defaultValue); } else if (key == "indexstem") { indexstem = cfgline[0]; } else if (key == "maxnumeric") { maxnumeric = cfgline[0].getint(); } } bool queryfilterclass::init (ostream &logout) { outconvertclass text_t2ascii; if (!filterclass::init(logout)) return false; if (filterOptions["Index"].defaultValue.empty()) { // use first index in map as default if no default is set explicitly text_tarray fromarray; indexmap.getfromarray(fromarray); if (fromarray.size()) { filterOptions["Index"].defaultValue = fromarray[0]; } } if (filterOptions["Subcollection"].defaultValue.empty()) { // use first subcollection in map as default if no default is set explicitly text_tarray fromarray; subcollectionmap.getfromarray(fromarray); if (fromarray.size()) { filterOptions["Subcollection"].defaultValue = fromarray[0]; } } if (filterOptions["Language"].defaultValue.empty()) { // use first language in map as default if no default is set explicitly text_tarray fromarray; languagemap.getfromarray(fromarray); if (fromarray.size()) { filterOptions["Language"].defaultValue = fromarray[0]; } } if (db_ptr == NULL) { // most likely a configuration problem logout << text_t2ascii << "configuration error: queryfilter contains a null dbclass\n\n"; return false; } // get the filename for the database and make sure it exists if (indexstem.empty()) { indexstem = collection; } db_filename = filename_cat(dbhome, "collect", collection, "index", "text", indexstem); db_filename += db_ptr->getfileextension(); if (!file_exists(db_filename)) { logout << text_t2ascii << "warning: database \"" << db_filename << "\" does not exist\n\n"; //return false; } return true; }