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:
John Wiegley 2009-02-14 05:37:53 -04:00
parent 67d63366cb
commit ee5e0600aa
5 changed files with 108 additions and 42 deletions

View file

@ -37,18 +37,61 @@ bool item_t::use_effective_date = false;
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;
}
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();
}
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
{
DEBUG("item.meta", "Getting item tag: " << tag);
if (metadata) {
DEBUG("item.meta", "Item has metadata");
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 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;
}
@ -146,48 +189,15 @@ namespace {
value_t has_tag(call_scope_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());
}
else if (optional<string> tag = item.get_tag(args[0].as_string())) {
if (args[1].is_string()) {
return args[1].as_string() == *tag;
}
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);
}
}
}
else if (args[0].is_mask())
return item.has_tag(args[0].as_mask());
} else {
return item.has_tag(args[0].to_mask(),
args[1].to_mask());
}
return false;
}

View file

@ -120,9 +120,16 @@ public:
}
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 void set_tag(const string& tag,
const optional<string>& value = none);
virtual void parse_tags(const char * p, int current_year = -1);
virtual void append_note(const char * p, int current_year = -1);

View file

@ -943,6 +943,9 @@ void value_t::in_place_cast(type_t cast_type)
case AMOUNT:
set_amount(amount_t(as_string()));
return;
case MASK:
set_mask(as_string());
return;
default:
break;
}

View file

@ -36,6 +36,44 @@
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
{
if (item_t::use_effective_date) {

View file

@ -107,6 +107,14 @@ public:
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 optional<date_t> effective_date() const;