- New Filter object to control filtering, instead of commands/Command.cpp.
This commit is contained in:
Paul Beckingham 2014-04-27 10:05:05 -07:00
parent 3e7052b500
commit fe2634b472
3 changed files with 305 additions and 0 deletions

View file

@ -20,6 +20,7 @@ set (task_SRCS A3.cpp A3.h
E9.cpp E9.h
Eval.cpp Eval.h
File.cpp File.h
Filter.cpp Filter.h
Hooks.cpp Hooks.h
ISO8601.cpp ISO8601.h
JSON.cpp JSON.h

254
src/Filter.cpp Normal file
View file

@ -0,0 +1,254 @@
////////////////////////////////////////////////////////////////////////////////
//
// Copyright 2006 - 2014, Paul Beckingham, Federico Hernandez.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
// http://www.opensource.org/licenses/mit-license.php
//
////////////////////////////////////////////////////////////////////////////////
#include <iostream> // TODO Remove
#include <cmake.h>
#include <Context.h>
#include <Eval.h>
#include <E9.h>
#include <Variant.h>
#include <Dates.h>
#include <Filter.h>
extern Context context;
////////////////////////////////////////////////////////////////////////////////
Filter::Filter ()
: _startCount (0)
, _endCount (0)
{
}
////////////////////////////////////////////////////////////////////////////////
Filter::~Filter ()
{
}
////////////////////////////////////////////////////////////////////////////////
// Take an input set of tasks and filter into a subset.
void Filter::subset (const std::vector <Task>& input, std::vector <Task>& output)
{
context.timer_filter.start ();
A3 filt = context.a3.extract_filter ();
filt.dump ("extract_filter");
if (context.config.getBoolean ("debug"))
{
Tree* t = context.a3t.tree ();
if (t)
context.debug (t->dump ());
}
std::string filterExpr = context.a3t.getFilterExpression ();
context.debug ("\033[1;37;42mFILTER\033[0m " + filterExpr);
if (filterExpr.length ())
{
E9 e (filt);
Eval eval;
eval.addSource (namedDates);
// TODO Need DOM source.
eval.compileExpression (filterExpr);
std::vector <Task>::const_iterator task;
for (task = input.begin (); task != input.end (); ++task)
{
bool oldFilter = e.evalFilter (*task);
if (oldFilter)
output.push_back (*task);
Variant var;
eval.evaluateCompiledExpression (var);
if (oldFilter != var.get_bool ())
std::cout << "# filter mismatch ID " << task->id << " UUID " << task->get ("uuid") << "\n";
}
}
else
output = input;
context.timer_filter.stop ();
}
////////////////////////////////////////////////////////////////////////////////
// Take the set of all tasks and filter into a subset.
void Filter::subset (std::vector <Task>& output)
{
context.timer_filter.start ();
A3 filt = context.a3.extract_filter ();
filt.dump ("extract_filter");
if (context.config.getBoolean ("debug"))
{
Tree* t = context.a3t.tree ();
if (t)
context.debug (t->dump ());
}
std::string filterExpr = context.a3t.getFilterExpression ();
context.debug ("\033[1;37;42mFILTER\033[0m " + filterExpr);
if (filterExpr.length ())
{
context.timer_filter.stop ();
const std::vector <Task>& pending = context.tdb2.pending.get_tasks ();
context.timer_filter.start ();
E9 e (filt);
Eval eval;
eval.addSource (namedDates);
// TODO Need DOM source.
eval.compileExpression (filterExpr);
output.clear ();
std::vector <Task>::const_iterator task;
for (task = pending.begin (); task != pending.end (); ++task)
{
bool oldFilter = e.evalFilter (*task);
if (oldFilter)
output.push_back (*task);
Variant var;
eval.evaluateCompiledExpression (var);
if (oldFilter != var.get_bool ())
std::cout << "# filter mismatch ID " << task->id << " UUID " << task->get ("uuid") << "\n";
}
if (! shortcut ())
{
context.timer_filter.stop ();
const std::vector <Task>& completed = context.tdb2.completed.get_tasks (); // TODO Optional
context.timer_filter.start ();
for (task = completed.begin (); task != completed.end (); ++task)
{
bool oldFilter = e.evalFilter (*task);
if (oldFilter)
output.push_back (*task);
Variant var;
eval.evaluateCompiledExpression (var);
if (oldFilter != var.get_bool ())
std::cout << "# filter mismatch ID " << task->id << " UUID " << task->get ("uuid") << "\n";
}
}
}
else
{
safety ();
context.timer_filter.stop ();
const std::vector <Task>& pending = context.tdb2.pending.get_tasks ();
const std::vector <Task>& completed = context.tdb2.completed.get_tasks ();
context.timer_filter.start ();
std::vector <Task>::const_iterator task;
for (task = pending.begin (); task != pending.end (); ++task)
output.push_back (*task);
for (task = completed.begin (); task != completed.end (); ++task)
output.push_back (*task);
}
context.timer_filter.stop ();
}
////////////////////////////////////////////////////////////////////////////////
// If the filter contains the restriction "status:pending", as the first filter
// term, then completed.data does not need to be loaded.
bool Filter::shortcut ()
{
/*
// Postfix: <status> <"pending"> <=>
// 0 1 2
if (filter.size () >= 3 &&
filter[0]._raw == "status" &&
filter[1]._raw.find ("pending") != std::string::npos &&
filter[2]._raw == "=")
{
context.debug ("Command::filter skipping completed.data (status:pending only)");
return true;
}
// Shortcut: If the filter contains no 'or' or 'xor' operators, IDs and no UUIDs.
int countId = 0;
int countUUID = 0;
int countOr = 0;
int countXor = 0;
std::vector <Arg>::const_iterator i;
for (i = filter.begin (); i != filter.end (); ++i)
{
if (i->_category == Arg::cat_op)
{
if (i->_raw == "or") ++countOr;
if (i->_raw == "xor") ++countXor;
}
else if (i->_category == Arg::cat_id) ++countId;
else if (i->_category == Arg::cat_uuid) ++countUUID;
}
if (countOr == 0 &&
countXor == 0 &&
countUUID == 0 &&
countId > 0)
{
context.debug ("Command::filter skipping completed.data (IDs, no OR, no XOR, no UUID)");
return true;
}
*/
return false;
}
////////////////////////////////////////////////////////////////////////////////
// Disaster avoidance mechanism.
void Filter::safety ()
{
/*
if (! _read_only)
{
A3 write_filter = context.a3.extract_filter ();
if (!write_filter.size ()) // Potential disaster.
{
// If user is willing to be asked, this can be avoided.
if (context.config.getBoolean ("confirmation") &&
confirm (STRING_TASK_SAFETY_VALVE))
return;
// No.
throw std::string (STRING_TASK_SAFETY_FAIL);
}
}
*/
}
////////////////////////////////////////////////////////////////////////////////

50
src/Filter.h Normal file
View file

@ -0,0 +1,50 @@
////////////////////////////////////////////////////////////////////////////////
//
// Copyright 2006 - 2014, Paul Beckingham, Federico Hernandez.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
// http://www.opensource.org/licenses/mit-license.php
//
////////////////////////////////////////////////////////////////////////////////
#ifndef INCLUDED_FILTER
#define INCLUDED_FILTER
#include <vector>
#include <Task.h>
class Filter
{
public:
Filter ();
~Filter ();
void subset (const std::vector <Task>&, std::vector <Task>&);
void subset (std::vector <Task>&);
bool shortcut ();
void safety ();
private:
int _startCount;
int _endCount;
};
#endif