Move sort/filtering code out of reslist

This commit is contained in:
Jean-Francois Dockes
2010-12-18 15:45:12 +01:00
parent c6b771ca99
commit c79410da94
19 changed files with 339 additions and 145 deletions
+75 -3
View File
@@ -17,10 +17,10 @@ static char rcsid[] = "@(#$Id: docseq.cpp,v 1.11 2008-09-29 08:59:20 dockes Exp
* Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <math.h>
#include <time.h>
#include "docseq.h"
#include "filtseq.h"
#include "sortseq.h"
#include "debuglog.h"
int DocSequence::getSeqSlice(int offs, int cnt, vector<ResListEntry>& result)
{
@@ -35,3 +35,75 @@ int DocSequence::getSeqSlice(int offs, int cnt, vector<ResListEntry>& result)
return ret;
}
void DocSource::unwind()
{
RefCntr<DocSequence> base = m_seq;
while (!m_seq.isNull() && !(m_seq->getSourceSeq()).isNull()) {
base = m_seq->getSourceSeq();
}
m_seq = base;
}
bool DocSource::buildStack()
{
LOGDEB2(("DocSource::buildStack()\n"));
unwind();
if (m_seq.isNull())
return false;
// Filtering must be done before sorting, (which may
// truncates the original list)
if (m_seq->canFilter()) {
if (!m_seq->setFiltSpec(m_fspec)) {
LOGERR(("DocSource::buildStack: setfiltspec failed\n"));
}
} else {
if (m_fspec.isNotNull()) {
m_seq =
RefCntr<DocSequence>(new DocSeqFiltered(m_seq, m_fspec));
}
}
if (m_seq->canSort()) {
if (!m_seq->setSortSpec(m_sspec)) {
LOGERR(("DocSource::buildStack: setsortspec failed\n"));
}
} else {
if (m_sspec.isNotNull()) {
m_seq = RefCntr<DocSequence>(new DocSeqSorted(m_seq, m_sspec));
}
}
return true;
}
string DocSource::o_sort_trans;
string DocSource::o_filt_trans;
string DocSource::title()
{
string qual;
if (m_fspec.isNotNull() && !m_sspec.isNotNull())
qual = string(" (") + o_filt_trans + string(")");
else if (!m_fspec.isNotNull() && m_sspec.isNotNull())
qual = string(" (") + o_sort_trans + string(")");
else if (m_fspec.isNotNull() && m_sspec.isNotNull())
qual = string(" (") + o_sort_trans + string(",") + o_filt_trans + string(")");
return m_seq->title() + qual;
}
bool DocSource::setFiltSpec(const DocSeqFiltSpec &f)
{
LOGDEB2(("DocSource::setFiltSpec\n"));
m_fspec = f;
buildStack();
return true;
}
bool DocSource::setSortSpec(const DocSeqSortSpec &s)
{
LOGDEB2(("DocSource::setSortSpec\n"));
m_sspec = s;
buildStack();
return true;
}
+46 -10
View File
@@ -44,8 +44,8 @@ class DocSeqSortSpec {
crits.push_back(fld);
dirs.push_back(desc);
}
bool isNotNull() {return sortdepth > 0;}
bool isNotNull() const {return sortdepth > 0;}
void reset() {crits.clear(); dirs.clear();sortdepth = 0;}
int sortdepth; // We only re-sort the first sortdepth most relevant docs
std::vector<Field> crits;
std::vector<bool> dirs;
@@ -64,7 +64,7 @@ class DocSeqFiltSpec {
std::vector<Crit> crits;
std::vector<string> values;
void reset() {crits.clear(); values.clear();}
bool isNotNull() {return crits.size() != 0;}
bool isNotNull() const {return crits.size() != 0;}
};
/** Interface for a list of documents coming from some source.
@@ -94,7 +94,7 @@ class DocSequence {
virtual bool getDoc(int num, Rcl::Doc &doc, string *sh = 0) = 0;
/** Get next page of documents. This accumulates entries into the result
* list (doesn't reset it). */
* list parameter (doesn't reset it). */
virtual int getSeqSlice(int offs, int cnt, vector<ResListEntry>& result);
/** Get abstract for document. This is special because it may take time.
@@ -130,14 +130,15 @@ class DocSequence {
}
virtual list<string> expand(Rcl::Doc &) {return list<string>();}
/** Optional functionality. Yeah, not nice */
/** Optional functionality. */
virtual bool canFilter() {return false;}
virtual bool setFiltSpec(DocSeqFiltSpec &) {return false;}
virtual bool canSort() {return false;}
virtual bool setSortSpec(DocSeqSortSpec &) {return false;}
virtual bool setFiltSpec(const DocSeqFiltSpec &) {return false;}
virtual bool setSortSpec(const DocSeqSortSpec &) {return false;}
virtual RefCntr<DocSequence> getSourceSeq() {return RefCntr<DocSequence>();}
private:
string m_title;
string m_title;
};
/** A modifier has a child sequence which does the real work and does
@@ -145,8 +146,8 @@ class DocSequence {
*/
class DocSeqModifier : public DocSequence {
public:
DocSeqModifier(const string &t, RefCntr<DocSequence> iseq)
: DocSequence(t), m_seq(iseq)
DocSeqModifier(RefCntr<DocSequence> iseq)
: DocSequence(""), m_seq(iseq)
{}
virtual ~DocSeqModifier() {}
@@ -168,10 +169,45 @@ public:
{
m_seq->getUTerms(terms);
}
virtual string title() {return m_seq->title();}
virtual RefCntr<DocSequence> getSourceSeq() {return m_seq;}
protected:
RefCntr<DocSequence> m_seq;
};
// A DocSource can juggle docseqs of different kinds to implement
// sorting and filtering in ways depending on the base seqs capabilities
class DocSource : public DocSeqModifier {
public:
DocSource(RefCntr<DocSequence> iseq)
: DocSeqModifier(iseq)
{}
virtual bool canFilter() {return true;}
virtual bool canSort() {return true;}
virtual bool setFiltSpec(const DocSeqFiltSpec &);
virtual bool setSortSpec(const DocSeqSortSpec &);
virtual bool getDoc(int num, Rcl::Doc &doc, string *sh = 0)
{
return m_seq->getDoc(num, doc, sh);
}
virtual int getResCnt()
{
return m_seq->getResCnt();
}
static void set_translations(const string& sort, const string& filt)
{
o_sort_trans = sort;
o_filt_trans = filt;
}
virtual string title();
private:
bool buildStack();
void unwind();
DocSeqFiltSpec m_fspec;
DocSeqSortSpec m_sspec;
static string o_sort_trans;
static string o_filt_trans;
};
#endif /* _DOCSEQ_H_INCLUDED_ */
+22 -26
View File
@@ -28,7 +28,7 @@ static char rcsid[] = "@(#$Id: docseqdb.cpp,v 1.9 2008-11-13 10:57:46 dockes Exp
DocSequenceDb::DocSequenceDb(RefCntr<Rcl::Query> q, const string &t,
RefCntr<Rcl::SearchData> sdata)
: DocSequence(t), m_q(q), m_sdata(sdata), m_fsdata(sdata),
m_rescnt(-1), m_filt(false),
m_rescnt(-1),
m_queryBuildAbstract(true),
m_queryReplaceAbstract(false)
{
@@ -98,39 +98,31 @@ list<string> DocSequenceDb::expand(Rcl::Doc &doc)
return m_q->expand(doc);
}
bool DocSequenceDb::setFiltSpec(DocSeqFiltSpec &fs)
bool DocSequenceDb::setFiltSpec(const DocSeqFiltSpec &fs)
{
if (!fs.isNotNull()) {
m_fsdata = m_sdata;
m_filt = false;
return m_q->setQuery(m_sdata);
}
// We build a search spec by adding a filtering layer to the base one.
m_fsdata = RefCntr<Rcl::SearchData>(new Rcl::SearchData(Rcl::SCLT_AND));
Rcl::SearchDataClauseSub *cl =
new Rcl::SearchDataClauseSub(Rcl::SCLT_SUB, m_sdata);
m_fsdata->addClause(cl);
LOGDEB(("DocSequenceDb::setFiltSpec\n"));
if (fs.isNotNull()) {
// We build a search spec by adding a filtering layer to the base one.
m_fsdata = RefCntr<Rcl::SearchData>(new Rcl::SearchData(Rcl::SCLT_AND));
Rcl::SearchDataClauseSub *cl =
new Rcl::SearchDataClauseSub(Rcl::SCLT_SUB, m_sdata);
m_fsdata->addClause(cl);
for (unsigned int i = 0; i < fs.crits.size(); i++) {
switch (fs.crits[i]) {
case DocSeqFiltSpec::DSFS_MIMETYPE:
m_fsdata->addFiletype(fs.values[i]);
for (unsigned int i = 0; i < fs.crits.size(); i++) {
switch (fs.crits[i]) {
case DocSeqFiltSpec::DSFS_MIMETYPE:
m_fsdata->addFiletype(fs.values[i]);
}
}
} else {
m_fsdata = m_sdata;
}
m_filt = true;
return m_q->setQuery(m_fsdata);
}
// Need a way to access the translations for filtered ...
string DocSequenceDb::title()
{
LOGDEB(("DOcSequenceDb::title()\n"));
return m_filt ? DocSequence::title() + " (filtered)" : DocSequence::title();
}
bool DocSequenceDb::setSortSpec(DocSeqSortSpec &sortspec)
bool DocSequenceDb::setSortSpec(const DocSeqSortSpec &sortspec)
{
LOGDEB(("DocSequenceDb::setSortSpec\n"));
if (sortspec.isNotNull()) {
bool ascending = false;
for (unsigned int i = 0; i < sortspec.crits.size(); i++) {
@@ -149,3 +141,7 @@ bool DocSequenceDb::setSortSpec(DocSeqSortSpec &sortspec)
return m_q->setQuery(m_fsdata);
}
bool DocSequenceDb::setQuery()
{
return m_q->setQuery(m_fsdata);
}
+3 -4
View File
@@ -41,10 +41,10 @@ class DocSequenceDb : public DocSequence {
virtual string getDescription();
virtual list<string> expand(Rcl::Doc &doc);
virtual bool canFilter() {return true;}
virtual bool setFiltSpec(DocSeqFiltSpec &filtspec);
virtual bool setFiltSpec(const DocSeqFiltSpec &filtspec);
virtual bool canSort() {return true;}
virtual bool setSortSpec(DocSeqSortSpec &sortspec);
virtual string title();
virtual bool setSortSpec(const DocSeqSortSpec &sortspec);
virtual bool setQuery();
virtual void setAbstractParams(bool qba, bool qra)
{
m_queryBuildAbstract = qba;
@@ -56,7 +56,6 @@ class DocSequenceDb : public DocSequence {
RefCntr<Rcl::SearchData> m_sdata;
RefCntr<Rcl::SearchData> m_fsdata; // Filtered
int m_rescnt;
bool m_filt;
bool m_queryBuildAbstract;
bool m_queryReplaceAbstract;
};
+1 -8
View File
@@ -40,13 +40,6 @@ static bool filter(const DocSeqFiltSpec& fs, const Rcl::Doc *x)
return 0;
}
DocSeqFiltered::DocSeqFiltered(RefCntr<DocSequence> iseq,
DocSeqFiltSpec &filtspec,
const std::string &t)
: DocSeqModifier(t, iseq), m_spec(filtspec)
{
}
bool DocSeqFiltered::setFiltSpec(DocSeqFiltSpec &filtspec)
{
m_spec = filtspec;
@@ -59,7 +52,7 @@ bool DocSeqFiltered::getDoc(int idx, Rcl::Doc &doc, string *)
LOGDEB1(("DocSeqFiltered: fetching %d\n", idx));
if (idx >= (int)m_dbindices.size()) {
// Have to fetch xapian docs and filter until we get enough or
// Have to fetch docs and filter until we get enough or
// fail
m_dbindices.reserve(idx+1);
+4 -3
View File
@@ -30,9 +30,10 @@
* according to the given criteria.
*/
class DocSeqFiltered : public DocSeqModifier {
public:
DocSeqFiltered(RefCntr<DocSequence> iseq, DocSeqFiltSpec &filtspec,
const std::string &t);
public:
DocSeqFiltered(RefCntr<DocSequence> iseq, DocSeqFiltSpec &filtspec)
: DocSeqModifier(iseq), m_spec(filtspec)
{}
virtual ~DocSeqFiltered() {}
virtual bool canFilter() {return true;}
virtual bool setFiltSpec(DocSeqFiltSpec &filtspec);
-7
View File
@@ -68,13 +68,6 @@ public:
}
};
DocSeqSorted::DocSeqSorted(RefCntr<DocSequence> iseq, DocSeqSortSpec &sortspec,
const std::string &t)
: DocSeqModifier(t, iseq)
{
setSortSpec(sortspec);
}
bool DocSeqSorted::setSortSpec(DocSeqSortSpec &sortspec)
{
m_spec = sortspec;
+5 -2
View File
@@ -30,8 +30,11 @@
*/
class DocSeqSorted : public DocSeqModifier {
public:
DocSeqSorted(RefCntr<DocSequence> iseq, DocSeqSortSpec &sortspec,
const std::string &t);
DocSeqSorted(RefCntr<DocSequence> iseq, DocSeqSortSpec &sortspec)
: DocSeqModifier(iseq)
{
setSortSpec(sortspec);
}
virtual ~DocSeqSorted() {}
virtual bool canSort() {return true;}
virtual bool setSortSpec(DocSeqSortSpec &sortspec);