xact metadata searches get passed up to the entry
That is, if a metadata tag cannot be found in a transaction, look in the parent entry to see if it was set there. Transactions "inherit" notational details from their entries.
This commit is contained in:
parent
67d63366cb
commit
ee5e0600aa
5 changed files with 108 additions and 42 deletions
92
src/item.cc
92
src/item.cc
|
|
@ -37,19 +37,62 @@ bool item_t::use_effective_date = false;
|
||||||
|
|
||||||
bool item_t::has_tag(const string& tag) const
|
bool item_t::has_tag(const string& tag) const
|
||||||
{
|
{
|
||||||
if (! metadata)
|
DEBUG("item.meta", "Checking if item has tag: " << tag);
|
||||||
|
if (! metadata) {
|
||||||
|
DEBUG("item.meta", "Item has no metadata at all");
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
string_map::const_iterator i = metadata->find(tag);
|
string_map::const_iterator i = metadata->find(tag);
|
||||||
|
if (SHOW_DEBUG("item.meta")) {
|
||||||
|
if (i == metadata->end())
|
||||||
|
DEBUG("item.meta", "Item does not have this tag");
|
||||||
|
else
|
||||||
|
DEBUG("item.meta", "Item has the tag!");
|
||||||
|
}
|
||||||
return i != metadata->end();
|
return i != metadata->end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool item_t::has_tag(const mask_t& tag_mask,
|
||||||
|
const optional<mask_t>& value_mask) const
|
||||||
|
{
|
||||||
|
if (metadata) {
|
||||||
|
foreach (const string_map::value_type& data, *metadata) {
|
||||||
|
if (tag_mask.match(data.first)) {
|
||||||
|
if (! value_mask)
|
||||||
|
return true;
|
||||||
|
else if (data.second)
|
||||||
|
return value_mask->match(*data.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
optional<string> item_t::get_tag(const string& tag) const
|
optional<string> item_t::get_tag(const string& tag) const
|
||||||
{
|
{
|
||||||
|
DEBUG("item.meta", "Getting item tag: " << tag);
|
||||||
if (metadata) {
|
if (metadata) {
|
||||||
|
DEBUG("item.meta", "Item has metadata");
|
||||||
string_map::const_iterator i = metadata->find(tag);
|
string_map::const_iterator i = metadata->find(tag);
|
||||||
if (i != metadata->end())
|
if (i != metadata->end()) {
|
||||||
|
DEBUG("item.meta", "Found the item!");
|
||||||
return (*i).second;
|
return (*i).second;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
return none;
|
||||||
|
}
|
||||||
|
|
||||||
|
optional<string> item_t::get_tag(const mask_t& tag_mask,
|
||||||
|
const optional<mask_t>& value_mask) const
|
||||||
|
{
|
||||||
|
if (metadata) {
|
||||||
|
foreach (const string_map::value_type& data, *metadata) {
|
||||||
|
if (tag_mask.match(data.first) &&
|
||||||
|
(! value_mask ||
|
||||||
|
(data.second && value_mask->match(*data.second))))
|
||||||
|
return data.second;
|
||||||
|
}
|
||||||
|
}
|
||||||
return none;
|
return none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -146,48 +189,15 @@ namespace {
|
||||||
|
|
||||||
value_t has_tag(call_scope_t& args) {
|
value_t has_tag(call_scope_t& args) {
|
||||||
item_t& item(find_scope<item_t>(args));
|
item_t& item(find_scope<item_t>(args));
|
||||||
if (! item.metadata)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
IF_DEBUG("item.meta") {
|
|
||||||
foreach (const item_t::string_map::value_type& data, *item.metadata) {
|
|
||||||
*_log_stream << " Tag: " << data.first << "\n";
|
|
||||||
*_log_stream << "Value: ";
|
|
||||||
if (data.second)
|
|
||||||
*_log_stream << *data.second << "\n";
|
|
||||||
else
|
|
||||||
*_log_stream << "<none>\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
value_t& arg(args[0]);
|
|
||||||
|
|
||||||
if (arg.is_string()) {
|
|
||||||
if (args.size() == 1) {
|
if (args.size() == 1) {
|
||||||
|
if (args[0].is_string())
|
||||||
return item.has_tag(args[0].as_string());
|
return item.has_tag(args[0].as_string());
|
||||||
}
|
else if (args[0].is_mask())
|
||||||
else if (optional<string> tag = item.get_tag(args[0].as_string())) {
|
return item.has_tag(args[0].as_mask());
|
||||||
if (args[1].is_string()) {
|
} else {
|
||||||
return args[1].as_string() == *tag;
|
return item.has_tag(args[0].to_mask(),
|
||||||
}
|
args[1].to_mask());
|
||||||
else if (args[1].is_mask()) {
|
|
||||||
return args[1].as_mask().match(*tag);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (arg.is_mask()) {
|
|
||||||
foreach (const item_t::string_map::value_type& data, *item.metadata) {
|
|
||||||
if (arg.as_mask().match(data.first)) {
|
|
||||||
if (args.size() == 1)
|
|
||||||
return true;
|
|
||||||
else if (data.second) {
|
|
||||||
if (args[1].is_string())
|
|
||||||
return args[1].as_string() == *data.second;
|
|
||||||
else if (args[1].is_mask())
|
|
||||||
return args[1].as_mask().match(*data.second);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -120,9 +120,16 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool has_tag(const string& tag) const;
|
virtual bool has_tag(const string& tag) const;
|
||||||
|
virtual bool has_tag(const mask_t& tag_mask,
|
||||||
|
const optional<mask_t>& value_mask = none) const;
|
||||||
|
|
||||||
virtual optional<string> get_tag(const string& tag) const;
|
virtual optional<string> get_tag(const string& tag) const;
|
||||||
|
virtual optional<string> get_tag(const mask_t& tag_mask,
|
||||||
|
const optional<mask_t>& value_mask = none) const;
|
||||||
|
|
||||||
virtual void set_tag(const string& tag,
|
virtual void set_tag(const string& tag,
|
||||||
const optional<string>& value = none);
|
const optional<string>& value = none);
|
||||||
|
|
||||||
virtual void parse_tags(const char * p, int current_year = -1);
|
virtual void parse_tags(const char * p, int current_year = -1);
|
||||||
virtual void append_note(const char * p, int current_year = -1);
|
virtual void append_note(const char * p, int current_year = -1);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -943,6 +943,9 @@ void value_t::in_place_cast(type_t cast_type)
|
||||||
case AMOUNT:
|
case AMOUNT:
|
||||||
set_amount(amount_t(as_string()));
|
set_amount(amount_t(as_string()));
|
||||||
return;
|
return;
|
||||||
|
case MASK:
|
||||||
|
set_mask(as_string());
|
||||||
|
return;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
38
src/xact.cc
38
src/xact.cc
|
|
@ -36,6 +36,44 @@
|
||||||
|
|
||||||
namespace ledger {
|
namespace ledger {
|
||||||
|
|
||||||
|
bool xact_t::has_tag(const string& tag) const
|
||||||
|
{
|
||||||
|
if (item_t::has_tag(tag))
|
||||||
|
return true;
|
||||||
|
if (entry)
|
||||||
|
return entry->has_tag(tag);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool xact_t::has_tag(const mask_t& tag_mask,
|
||||||
|
const optional<mask_t>& value_mask) const
|
||||||
|
{
|
||||||
|
if (item_t::has_tag(tag_mask, value_mask))
|
||||||
|
return true;
|
||||||
|
if (entry)
|
||||||
|
return entry->has_tag(tag_mask, value_mask);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
optional<string> xact_t::get_tag(const string& tag) const
|
||||||
|
{
|
||||||
|
if (optional<string> value = item_t::get_tag(tag))
|
||||||
|
return value;
|
||||||
|
if (entry)
|
||||||
|
return entry->get_tag(tag);
|
||||||
|
return none;
|
||||||
|
}
|
||||||
|
|
||||||
|
optional<string> xact_t::get_tag(const mask_t& tag_mask,
|
||||||
|
const optional<mask_t>& value_mask) const
|
||||||
|
{
|
||||||
|
if (optional<string> value = item_t::get_tag(tag_mask, value_mask))
|
||||||
|
return value;
|
||||||
|
if (entry)
|
||||||
|
return entry->get_tag(tag_mask, value_mask);
|
||||||
|
return none;
|
||||||
|
}
|
||||||
|
|
||||||
date_t xact_t::date() const
|
date_t xact_t::date() const
|
||||||
{
|
{
|
||||||
if (item_t::use_effective_date) {
|
if (item_t::use_effective_date) {
|
||||||
|
|
|
||||||
|
|
@ -107,6 +107,14 @@ public:
|
||||||
TRACE_DTOR(xact_t);
|
TRACE_DTOR(xact_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual bool has_tag(const string& tag) const;
|
||||||
|
virtual bool has_tag(const mask_t& tag_mask,
|
||||||
|
const optional<mask_t>& value_mask = none) const;
|
||||||
|
|
||||||
|
virtual optional<string> get_tag(const string& tag) const;
|
||||||
|
virtual optional<string> get_tag(const mask_t& tag_mask,
|
||||||
|
const optional<mask_t>& value_mask = none) const;
|
||||||
|
|
||||||
virtual date_t date() const;
|
virtual date_t date() const;
|
||||||
virtual optional<date_t> effective_date() const;
|
virtual optional<date_t> effective_date() const;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue