DOM: Refactored the contextual ::get

This commit is contained in:
Paul Beckingham
2015-09-07 16:12:54 -04:00
parent 91c05ea157
commit 2854304e60

View File

@@ -192,10 +192,11 @@ bool DOM::get (const std::string& name, Variant& value)
// annotations.<N>.entry // annotations.<N>.entry
// annotations.<N>.description // annotations.<N>.description
// //
// This code emphasizes speed, hence 'id' being evaluated first. // This code emphasizes speed, hence 'id' and 'urgecny' being evaluated first
// as special cases.
bool DOM::get (const std::string& name, const Task& task, Variant& value) bool DOM::get (const std::string& name, const Task& task, Variant& value)
{ {
// <attr> // Quickly deal with the most common cases.
if (task.size () && name == "id") if (task.size () && name == "id")
{ {
value = Variant (static_cast<int> (task.id)); value = Variant (static_cast<int> (task.id));
@@ -211,93 +212,57 @@ bool DOM::get (const std::string& name, const Task& task, Variant& value)
// split name on '.' // split name on '.'
std::vector <std::string> elements; std::vector <std::string> elements;
split (elements, name, '.'); split (elements, name, '.');
auto size = elements.size ();
if (size == 1)
{
std::string canonical;
if (task.size () && context.cli2.canonicalize (canonical, "attribute", name))
{
Column* column = context.columns[canonical];
if (column)
{
if (column->is_uda () && ! task.has (canonical))
{
value = Variant ("");
return true;
}
if (column->type () == "date")
{
auto numeric = task.get_date (canonical);
if (numeric == 0)
value = Variant ("");
else
value = Variant (numeric, Variant::type_date);
}
else if (column->type () == "duration" || canonical == "recur")
value = Variant ((time_t) ISO8601p (task.get (canonical)), Variant::type_duration);
else if (column->type () == "numeric")
value = Variant (task.get_float (canonical));
else // string
value = Variant (task.get (canonical));
return true;
}
}
}
else if (size > 1)
{
Task ref;
Task ref (task);
Nibbler n (elements[0]); Nibbler n (elements[0]);
n.save (); n.save ();
int id; int id;
std::string uuid; std::string uuid;
bool proceed = false;
// If elements[0] is a UUID, load that task (if necessary), and clobber ref.
if (n.getPartialUUID (uuid) && n.depleted ()) if (n.getPartialUUID (uuid) && n.depleted ())
{ {
if (uuid == task.get ("uuid")) if (uuid != ref.get ("uuid"))
ref = task;
else
context.tdb2.get (uuid, ref); context.tdb2.get (uuid, ref);
proceed = true; // Eat elements[0]/UUID.
elements.erase (elements.begin ());
} }
else else
{ {
// If elements[0] is a ID, load that task (if necessary), and clobber ref.
if (n.getInt (id) && n.depleted ()) if (n.getInt (id) && n.depleted ())
{ {
if (id == task.id) if (id != ref.id)
ref = task;
else
context.tdb2.get (id, ref); context.tdb2.get (id, ref);
proceed = true; // Eat elements[0]/ID.
elements.erase (elements.begin ());
} }
} }
if (proceed) auto size = elements.size ();
std::string canonical;
if (context.cli2.canonicalize (canonical, "attribute", elements[0]))
{ {
if (elements[1] == "id") // Now that 'ref' is the contextual task, and any ID/UUID is chopped off the
// elements vector, DOM resolution is now simple.
if (ref.size () && size == 1 && canonical == "id")
{ {
value = Variant (static_cast<int> (ref.id)); value = Variant (static_cast<int> (ref.id));
return true; return true;
} }
else if (elements[1] == "urgency")
if (ref.size () && size == 1 && canonical == "urgency")
{ {
value = Variant (ref.urgency_c ()); value = Variant (ref.urgency_c ());
return true; return true;
} }
std::string canonical;
if (context.cli2.canonicalize (canonical, "attribute", elements[1]))
{
if (size == 2)
{
Column* column = context.columns[canonical]; Column* column = context.columns[canonical];
if (column)
if (ref.size () && size == 1 && column)
{ {
if (column->is_uda () && ! ref.has (canonical)) if (column->is_uda () && ! ref.has (canonical))
{ {
@@ -313,10 +278,9 @@ bool DOM::get (const std::string& name, const Task& task, Variant& value)
else else
value = Variant (numeric, Variant::type_date); value = Variant (numeric, Variant::type_date);
} }
else if (column->type () == "duration") else if (column->type () == "duration" || canonical == "recur")
{ {
auto period = ref.get (canonical); auto period = ref.get (canonical);
context.debug ("ref.get(" + canonical + ") --> " + period);
ISO8601p iso; ISO8601p iso;
std::string::size_type cursor = 0; std::string::size_type cursor = 0;
@@ -324,8 +288,6 @@ bool DOM::get (const std::string& name, const Task& task, Variant& value)
value = Variant ((time_t) iso._value, Variant::type_duration); value = Variant ((time_t) iso._value, Variant::type_duration);
else else
value = Variant ((time_t) ISO8601p (ref.get (canonical)), Variant::type_duration); value = Variant ((time_t) ISO8601p (ref.get (canonical)), Variant::type_duration);
context.debug ("value --> " + (std::string) value);
} }
else if (column->type () == "numeric") else if (column->type () == "numeric")
value = Variant (ref.get_float (canonical)); value = Variant (ref.get_float (canonical));
@@ -334,49 +296,34 @@ bool DOM::get (const std::string& name, const Task& task, Variant& value)
return true; return true;
} }
}
else if (size == 3) if (ref.size () && size == 2 && canonical == "tags")
{ {
// tags.<tag> value = Variant (ref.hasTag (elements[1]) ? elements[1] : "");
if (canonical == "tags")
{
value = Variant (ref.hasTag (elements[2]) ? elements[2] : "");
return true; return true;
} }
Column* column = context.columns[canonical]; if (ref.size () && size == 2 && column && column->type () == "date")
if (column && column->type () == "date")
{ {
// <date>.year
// <date>.month
// <date>.day
// <date>.week
// <date>.weekday
// <date>.julian
// <date>.hour
// <date>.minute
// <date>.second
Date date (ref.get_date (canonical)); Date date (ref.get_date (canonical));
if (elements[2] == "year") { value = Variant (static_cast<int> (date.year ())); return true; } if (elements[1] == "year") { value = Variant (static_cast<int> (date.year ())); return true; }
else if (elements[2] == "month") { value = Variant (static_cast<int> (date.month ())); return true; } else if (elements[1] == "month") { value = Variant (static_cast<int> (date.month ())); return true; }
else if (elements[2] == "day") { value = Variant (static_cast<int> (date.day ())); return true; } else if (elements[1] == "day") { value = Variant (static_cast<int> (date.day ())); return true; }
else if (elements[2] == "week") { value = Variant (static_cast<int> (date.week ())); return true; } else if (elements[1] == "week") { value = Variant (static_cast<int> (date.week ())); return true; }
else if (elements[2] == "weekday") { value = Variant (static_cast<int> (date.dayOfWeek ())); return true; } else if (elements[1] == "weekday") { value = Variant (static_cast<int> (date.dayOfWeek ())); return true; }
else if (elements[2] == "julian") { value = Variant (static_cast<int> (date.dayOfYear ())); return true; } else if (elements[1] == "julian") { value = Variant (static_cast<int> (date.dayOfYear ())); return true; }
else if (elements[2] == "hour") { value = Variant (static_cast<int> (date.hour ())); return true; } else if (elements[1] == "hour") { value = Variant (static_cast<int> (date.hour ())); return true; }
else if (elements[2] == "minute") { value = Variant (static_cast<int> (date.minute ())); return true; } else if (elements[1] == "minute") { value = Variant (static_cast<int> (date.minute ())); return true; }
else if (elements[2] == "second") { value = Variant (static_cast<int> (date.second ())); return true; } else if (elements[1] == "second") { value = Variant (static_cast<int> (date.second ())); return true; }
} }
} }
}
else if (elements[1] == "annotations") if (ref.size () && size == 3 && elements[0] == "annotations")
{
if (size == 4)
{ {
std::map <std::string, std::string> annos; std::map <std::string, std::string> annos;
ref.getAnnotations (annos); ref.getAnnotations (annos);
int a = strtol (elements[2].c_str (), NULL, 10); int a = strtol (elements[1].c_str (), NULL, 10);
int count = 0; int count = 0;
// Count off the 'a'th annotation. // Count off the 'a'th annotation.
@@ -384,14 +331,14 @@ bool DOM::get (const std::string& name, const Task& task, Variant& value)
{ {
if (++count == a) if (++count == a)
{ {
if (elements[3] == "entry") if (elements[2] == "entry")
{ {
// annotation_1234567890 // annotation_1234567890
// 0 ^11 // 0 ^11
value = Variant ((time_t) strtol (i.first.substr (11).c_str (), NULL, 10), Variant::type_date); value = Variant ((time_t) strtol (i.first.substr (11).c_str (), NULL, 10), Variant::type_date);
return true; return true;
} }
else if (elements[3] == "description") else if (elements[2] == "description")
{ {
value = Variant (i.second); value = Variant (i.second);
return true; return true;
@@ -399,12 +346,13 @@ bool DOM::get (const std::string& name, const Task& task, Variant& value)
} }
} }
} }
else if (size == 5)
if (ref.size () && size == 4 && elements[0] == "annotations" && elements[2] == "entry")
{ {
std::map <std::string, std::string> annos; std::map <std::string, std::string> annos;
ref.getAnnotations (annos); ref.getAnnotations (annos);
int a = strtol (elements[2].c_str (), NULL, 10); int a = strtol (elements[1].c_str (), NULL, 10);
int count = 0; int count = 0;
// Count off the 'a'th annotation. // Count off the 'a'th annotation.
@@ -422,18 +370,15 @@ bool DOM::get (const std::string& name, const Task& task, Variant& value)
// <annotations>.<N>.entry.minute // <annotations>.<N>.entry.minute
// <annotations>.<N>.entry.second // <annotations>.<N>.entry.second
Date date (i.first.substr (11)); Date date (i.first.substr (11));
if (elements[4] == "year") { value = Variant (static_cast<int> (date.year ())); return true; } if (elements[3] == "year") { value = Variant (static_cast<int> (date.year ())); return true; }
else if (elements[4] == "month") { value = Variant (static_cast<int> (date.month ())); return true; } else if (elements[3] == "month") { value = Variant (static_cast<int> (date.month ())); return true; }
else if (elements[4] == "day") { value = Variant (static_cast<int> (date.day ())); return true; } else if (elements[3] == "day") { value = Variant (static_cast<int> (date.day ())); return true; }
else if (elements[4] == "week") { value = Variant (static_cast<int> (date.week ())); return true; } else if (elements[3] == "week") { value = Variant (static_cast<int> (date.week ())); return true; }
else if (elements[4] == "weekday") { value = Variant (static_cast<int> (date.dayOfWeek ())); return true; } else if (elements[3] == "weekday") { value = Variant (static_cast<int> (date.dayOfWeek ())); return true; }
else if (elements[4] == "julian") { value = Variant (static_cast<int> (date.dayOfYear ())); return true; } else if (elements[3] == "julian") { value = Variant (static_cast<int> (date.dayOfYear ())); return true; }
else if (elements[4] == "hour") { value = Variant (static_cast<int> (date.hour ())); return true; } else if (elements[3] == "hour") { value = Variant (static_cast<int> (date.hour ())); return true; }
else if (elements[4] == "minute") { value = Variant (static_cast<int> (date.minute ())); return true; } else if (elements[3] == "minute") { value = Variant (static_cast<int> (date.minute ())); return true; }
else if (elements[4] == "second") { value = Variant (static_cast<int> (date.second ())); return true; } else if (elements[3] == "second") { value = Variant (static_cast<int> (date.second ())); return true; }
}
}
}
} }
} }
} }