- 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 E9.cpp E9.h
Eval.cpp Eval.h Eval.cpp Eval.h
File.cpp File.h File.cpp File.h
Filter.cpp Filter.h
Hooks.cpp Hooks.h Hooks.cpp Hooks.h
ISO8601.cpp ISO8601.h ISO8601.cpp ISO8601.h
JSON.cpp JSON.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