Consolidated solution for RDB merge ('apply'). Potentially one bug fixed (tag mapping)

This commit is contained in:
Matthias Koefferlein 2024-08-17 22:03:00 +02:00
parent 2eef9c38d6
commit 0f833da652
3 changed files with 196 additions and 161 deletions

View File

@ -278,7 +278,7 @@ template <> RDB_PUBLIC bool Value<db::DText>::is_shape () const
} }
bool ValueBase::compare (const ValueBase *a, const ValueBase *b) bool ValueBase::compare (const ValueBase *a, const ValueBase *b)
{ {
// compare is the intrinsic compare of equal type and type index for different types. // compare is the intrinsic compare of equal type and type index for different types.
if (a->type_index () == b->type_index ()) { if (a->type_index () == b->type_index ()) {
@ -416,7 +416,7 @@ ValueBase::create_from_shape (const db::Shape &shape, const db::CplxTrans &trans
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
// ValueWrapper implementation // ValueWrapper implementation
std::string std::string
ValueWrapper::to_string () const ValueWrapper::to_string () const
{ {
std::string r; std::string r;
@ -437,14 +437,14 @@ ValueWrapper::to_string () const
return r; return r;
} }
void void
ValueWrapper::from_string (const std::string &s) ValueWrapper::from_string (const std::string &s)
{ {
tl::Extractor ex (s.c_str ()); tl::Extractor ex (s.c_str ());
from_string (ex); from_string (ex);
} }
void void
ValueWrapper::from_string (tl::Extractor &ex) ValueWrapper::from_string (tl::Extractor &ex)
{ {
id_type tag_id = 0; id_type tag_id = 0;
@ -453,7 +453,7 @@ ValueWrapper::from_string (tl::Extractor &ex)
bool user_tag = ex.test ("#"); bool user_tag = ex.test ("#");
std::string tn; std::string tn;
ex.read_word_or_quoted (tn); ex.read_word_or_quoted (tn);
tag_id = rdb::Tags::id_for_name (tn, user_tag); tag_id = rdb::Tags::id_for_name (tn, user_tag);
@ -482,11 +482,11 @@ Values::compare (const Values &other, const std::set<id_type> &common_tags) cons
Values::const_iterator a = begin (), b = other.begin (); Values::const_iterator a = begin (), b = other.begin ();
while (a != end () && b != other.end ()) { while (a != end () && b != other.end ()) {
id_type t12 = 0; id_type t1 = 0;
while (a != end () && a->tag_id () != 0) { while (a != end () && a->tag_id () != 0) {
auto j = common_tags.find (a->tag_id ()); auto j = common_tags.find (a->tag_id ());
if (j != common_tags.end ()) { if (j != common_tags.end ()) {
t12 = a->tag_id (); t1 = a->tag_id ();
break; break;
} }
++a; ++a;
@ -506,8 +506,8 @@ Values::compare (const Values &other, const std::set<id_type> &common_tags) cons
return b != other.end (); return b != other.end ();
} }
if (t12 != t2) { if (t1 != t2) {
return t12 < t2; return t1 < t2;
} }
if (a->get () && b->get ()) { if (a->get () && b->get ()) {
@ -528,7 +528,7 @@ Values::compare (const Values &other, const std::set<id_type> &common_tags) cons
return b != other.end (); return b != other.end ();
} }
std::string std::string
Values::to_string () const Values::to_string () const
{ {
std::string r; std::string r;
@ -547,7 +547,7 @@ Values::to_string () const
return r; return r;
} }
void void
Values::from_string (const std::string &s) Values::from_string (const std::string &s)
{ {
tl::Extractor ex (s.c_str ()); tl::Extractor ex (s.c_str ());
@ -567,7 +567,7 @@ Values::from_string (const std::string &s)
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
// Cell implementation // Cell implementation
void void
Cells::import_cell (const Cell &c) Cells::import_cell (const Cell &c)
{ {
Cell *cell; Cell *cell;
@ -582,7 +582,7 @@ Cells::import_cell (const Cell &c)
cell->references ().insert (*r); cell->references ().insert (*r);
} }
} }
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
// Cell implementation // Cell implementation
@ -615,7 +615,7 @@ Cell::~Cell ()
// .. nothing yet .. // .. nothing yet ..
} }
std::pair<bool, db::DCplxTrans> std::pair<bool, db::DCplxTrans>
Cell::path_to (id_type parent_cell_id, const Database *db) const Cell::path_to (id_type parent_cell_id, const Database *db) const
{ {
if (parent_cell_id == id ()) { if (parent_cell_id == id ()) {
@ -626,7 +626,7 @@ Cell::path_to (id_type parent_cell_id, const Database *db) const
} }
} }
std::pair<bool, db::DCplxTrans> std::pair<bool, db::DCplxTrans>
Cell::path_to (id_type parent_cell_id, const Database *db, std::set <id_type> &visited, const db::DCplxTrans &trans) const Cell::path_to (id_type parent_cell_id, const Database *db, std::set <id_type> &visited, const db::DCplxTrans &trans) const
{ {
for (reference_iterator r = references ().begin (); r != references ().end (); ++r) { for (reference_iterator r = references ().begin (); r != references ().end (); ++r) {
@ -654,15 +654,15 @@ Cell::path_to (id_type parent_cell_id, const Database *db, std::set <id_type> &v
return std::pair<bool, db::DCplxTrans> (false, db::DCplxTrans ()); return std::pair<bool, db::DCplxTrans> (false, db::DCplxTrans ());
} }
void void
Cell::import_references (const References &references) Cell::import_references (const References &references)
{ {
for (References::const_iterator r = references.begin (); r != references.end (); ++r) { for (References::const_iterator r = references.begin (); r != references.end (); ++r) {
m_references.insert (*r); m_references.insert (*r);
} }
} }
std::string std::string
Cell::qname () const Cell::qname () const
{ {
if (m_variant.empty ()) { if (m_variant.empty ()) {
@ -687,7 +687,7 @@ References::References (Cell *cell)
// .. nothing yet .. // .. nothing yet ..
} }
void void
References::set_database (Database *database) References::set_database (Database *database)
{ {
mp_database = database; mp_database = database;
@ -705,20 +705,20 @@ Reference::Reference (References *references)
// .. nothing yet .. // .. nothing yet ..
} }
void void
Reference::set_trans_str (const std::string &s) Reference::set_trans_str (const std::string &s)
{ {
tl::Extractor ex (s.c_str ()); tl::Extractor ex (s.c_str ());
ex.read (m_trans); ex.read (m_trans);
} }
std::string std::string
Reference::trans_str () const Reference::trans_str () const
{ {
return m_trans.to_string (); return m_trans.to_string ();
} }
void void
Reference::set_parent_cell_qname (const std::string &qname) Reference::set_parent_cell_qname (const std::string &qname)
{ {
tl_assert (mp_database != 0); tl_assert (mp_database != 0);
@ -729,7 +729,7 @@ Reference::set_parent_cell_qname (const std::string &qname)
m_parent_cell_id = cell->id (); m_parent_cell_id = cell->id ();
} }
std::string std::string
Reference::parent_cell_qname () const Reference::parent_cell_qname () const
{ {
tl_assert (mp_database != 0); tl_assert (mp_database != 0);
@ -787,7 +787,7 @@ Category::sub_categories ()
return *mp_sub_categories; return *mp_sub_categories;
} }
std::string std::string
Category::path () const Category::path () const
{ {
std::vector <std::string> path_elements; std::vector <std::string> path_elements;
@ -810,7 +810,7 @@ Category::path () const
return r; return r;
} }
void void
Category::import_sub_categories (Categories *categories) Category::import_sub_categories (Categories *categories)
{ {
if (mp_sub_categories) { if (mp_sub_categories) {
@ -826,7 +826,7 @@ Category::import_sub_categories (Categories *categories)
} }
} }
void void
Category::set_database (Database *database) Category::set_database (Database *database)
{ {
mp_database = database; mp_database = database;
@ -838,14 +838,14 @@ Category::set_database (Database *database)
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
// Categories implementation // Categories implementation
void void
Categories::clear () Categories::clear ()
{ {
m_categories.clear (); m_categories.clear ();
m_categories_by_name.clear (); m_categories_by_name.clear ();
} }
void void
Categories::add_category (Category *cat) Categories::add_category (Category *cat)
{ {
cat->set_database (mp_database.get ()); cat->set_database (mp_database.get ());
@ -853,7 +853,7 @@ Categories::add_category (Category *cat)
m_categories_by_name.insert (std::make_pair (cat->name (), cat)); m_categories_by_name.insert (std::make_pair (cat->name (), cat));
} }
void void
Categories::set_database (Database *database) Categories::set_database (Database *database)
{ {
mp_database = database; mp_database = database;
@ -863,7 +863,7 @@ Categories::set_database (Database *database)
} }
Category * Category *
Categories::category_by_name (const char *path) Categories::category_by_name (const char *path)
{ {
std::string component; std::string component;
tl::Extractor ex (path); tl::Extractor ex (path);
@ -881,7 +881,7 @@ Categories::category_by_name (const char *path)
return 0; return 0;
} }
void void
Categories::import_category (Category *category) Categories::import_category (Category *category)
{ {
Category *cat; Category *cat;
@ -945,13 +945,31 @@ Tags::Tags ()
// .. nothing yet .. // .. nothing yet ..
} }
void void
Tags::clear () Tags::clear ()
{ {
m_tags_per_id.clear (); m_tags_per_id.clear ();
m_tags.clear (); m_tags.clear ();
} }
void
Tags::remove_tag (id_type id)
{
auto j = m_tags_per_id.find (id);
if (j != m_tags_per_id.end ()) {
m_tags.erase (m_tags.begin () + j->second);
for (auto i = m_tags_per_id.begin (); i != m_tags_per_id.end (); ++i) {
if (i->second > j->second) {
i->second -= 1;
}
}
m_tags_per_id.erase (id);
}
}
const Tag & const Tag &
Tags::tag (const std::string &name, bool user_tag) const Tags::tag (const std::string &name, bool user_tag) const
{ {
@ -995,7 +1013,7 @@ Tags::import_tag (const Tag &t)
tt.set_description (t.description ()); tt.set_description (t.description ());
} }
bool bool
Tags::has_tag (const std::string &name, bool user_tag) const Tags::has_tag (const std::string &name, bool user_tag) const
{ {
return m_tags_per_id.find (id_for_name (name, user_tag)) != m_tags_per_id.end (); return m_tags_per_id.find (id_for_name (name, user_tag)) != m_tags_per_id.end ();
@ -1043,31 +1061,31 @@ Item &Item::operator= (const Item &d)
return *this; return *this;
} }
void void
Item::add_tag (id_type tag_id) Item::add_tag (id_type tag_id)
{ {
m_tag_ids.insert (tag_id); m_tag_ids.insert (tag_id);
} }
void void
Item::remove_tag (id_type tag_id) Item::remove_tag (id_type tag_id)
{ {
m_tag_ids.erase (tag_id); m_tag_ids.erase (tag_id);
} }
void void
Item::remove_tags () Item::remove_tags ()
{ {
m_tag_ids.clear (); m_tag_ids.clear ();
} }
bool bool
Item::has_tag (id_type tag_id) const Item::has_tag (id_type tag_id) const
{ {
return m_tag_ids.find (tag_id) != m_tag_ids.end (); return m_tag_ids.find (tag_id) != m_tag_ids.end ();
} }
std::string std::string
Item::cell_qname () const Item::cell_qname () const
{ {
tl_assert (mp_database != 0); tl_assert (mp_database != 0);
@ -1076,7 +1094,7 @@ Item::cell_qname () const
return cell->qname (); return cell->qname ();
} }
void void
Item::set_cell_qname (const std::string &qname) Item::set_cell_qname (const std::string &qname)
{ {
tl_assert (mp_database != 0); tl_assert (mp_database != 0);
@ -1096,7 +1114,7 @@ Item::category_name () const
return category->path (); return category->path ();
} }
void void
Item::set_category_name (const std::string &path) Item::set_category_name (const std::string &path)
{ {
tl_assert (mp_database != 0); tl_assert (mp_database != 0);
@ -1107,7 +1125,7 @@ Item::set_category_name (const std::string &path)
m_category_id = category->id (); m_category_id = category->id ();
} }
std::string std::string
Item::tag_str () const Item::tag_str () const
{ {
tl_assert (mp_database != 0); tl_assert (mp_database != 0);
@ -1135,7 +1153,7 @@ Item::tag_str () const
return r; return r;
} }
void void
Item::set_tag_str (const std::string &tags) Item::set_tag_str (const std::string &tags)
{ {
tl_assert (mp_database != 0); tl_assert (mp_database != 0);
@ -1153,7 +1171,7 @@ Item::set_tag_str (const std::string &tags)
} }
#if defined(HAVE_QT) #if defined(HAVE_QT)
void void
Item::set_image (const QImage &image) Item::set_image (const QImage &image)
{ {
if (image.isNull ()) { if (image.isNull ()) {
@ -1341,7 +1359,7 @@ Database::import_tags (const Tags &tags)
} }
} }
void void
Database::import_categories (Categories *categories) Database::import_categories (Categories *categories)
{ {
set_modified (); set_modified ();
@ -1352,7 +1370,7 @@ Database::import_categories (Categories *categories)
mp_categories->set_database (this); mp_categories->set_database (this);
} }
void void
Database::import_cells (const Cells &cells) Database::import_cells (const Cells &cells)
{ {
set_modified (); set_modified ();
@ -1399,13 +1417,13 @@ Database::create_category (Categories *container, const std::string &name)
} }
Category * Category *
Database::category_by_name_non_const (const std::string &name) Database::category_by_name_non_const (const std::string &name)
{ {
return mp_categories->category_by_name (name.c_str ()); return mp_categories->category_by_name (name.c_str ());
} }
Category * Category *
Database::category_by_id_non_const (id_type id) Database::category_by_id_non_const (id_type id)
{ {
std::map <id_type, Category *>::const_iterator c = m_categories_by_id.find (id); std::map <id_type, Category *>::const_iterator c = m_categories_by_id.find (id);
if (c != m_categories_by_id.end ()) { if (c != m_categories_by_id.end ()) {
@ -1460,7 +1478,7 @@ Database::create_cell (const std::string &name, const std::string &variant, cons
} else { } else {
new_cell = new Cell (++m_next_id, name, std::string (), layout_name); new_cell = new Cell (++m_next_id, name, std::string (), layout_name);
} }
m_cells.add_cell (new_cell); m_cells.add_cell (new_cell);
@ -1468,7 +1486,7 @@ Database::create_cell (const std::string &name, const std::string &variant, cons
m_cells_by_qname.insert (std::make_pair (new_cell->qname (), new_cell)); m_cells_by_qname.insert (std::make_pair (new_cell->qname (), new_cell));
} else { } else {
new_cell = new Cell (++m_next_id, name, variant, layout_name); new_cell = new Cell (++m_next_id, name, variant, layout_name);
m_cells.add_cell (new_cell); m_cells.add_cell (new_cell);
m_cells_by_id.insert (std::make_pair (new_cell->id (), new_cell)); m_cells_by_id.insert (std::make_pair (new_cell->id (), new_cell));
@ -1496,7 +1514,7 @@ Database::create_cell (const std::string &name, const std::string &variant, cons
} }
other_cell->set_variant (tl::to_string (variant_index + 1)); other_cell->set_variant (tl::to_string (variant_index + 1));
m_cells_by_qname.insert (std::make_pair (other_cell->qname (), other_cell)); m_cells_by_qname.insert (std::make_pair (other_cell->qname (), other_cell));
} }
@ -1542,21 +1560,21 @@ Database::cell_by_id_non_const (id_type id)
} }
} }
void void
Database::set_tag_description (id_type tag_id, const std::string &description) Database::set_tag_description (id_type tag_id, const std::string &description)
{ {
set_modified (); set_modified ();
tags_non_const ().tag (tag_id).set_description (description); tags_non_const ().tag (tag_id).set_description (description);
} }
void void
Database::add_item_tag (const Item *item, id_type tag) Database::add_item_tag (const Item *item, id_type tag)
{ {
set_modified (); set_modified ();
const_cast <Item *> (item)->add_tag (tag); const_cast <Item *> (item)->add_tag (tag);
} }
void void
Database::remove_item_tag (const Item *item, id_type tag) Database::remove_item_tag (const Item *item, id_type tag)
{ {
set_modified (); set_modified ();
@ -1571,7 +1589,7 @@ Database::set_item_comment (const Item *item, const std::string &comment)
} }
#if defined(HAVE_QT) #if defined(HAVE_QT)
void void
Database::set_item_image (const Item *item, const QImage &image) Database::set_item_image (const Item *item, const QImage &image)
{ {
set_modified (); set_modified ();
@ -1586,14 +1604,14 @@ Database::set_item_image_str (const Item *item, const std::string &image_str)
const_cast <Item *> (item)->set_image_str (image_str); const_cast <Item *> (item)->set_image_str (image_str);
} }
void void
Database::set_item_multiplicity (const Item *item, size_t n) Database::set_item_multiplicity (const Item *item, size_t n)
{ {
set_modified (); set_modified ();
const_cast <Item *> (item)->set_multiplicity (n); const_cast <Item *> (item)->set_multiplicity (n);
} }
void void
Database::set_item_visited (const Item *item_c, bool visited) Database::set_item_visited (const Item *item_c, bool visited)
{ {
if (visited != item_c->visited ()) { if (visited != item_c->visited ()) {
@ -1654,7 +1672,7 @@ Database::create_item (id_type cell_id, id_type category_id)
static std::list<ItemRef> empty_list; static std::list<ItemRef> empty_list;
std::pair<Database::const_item_ref_iterator, Database::const_item_ref_iterator> std::pair<Database::const_item_ref_iterator, Database::const_item_ref_iterator>
Database::items_by_cell_and_category (id_type cell_id, id_type category_id) const Database::items_by_cell_and_category (id_type cell_id, id_type category_id) const
{ {
std::map <std::pair <id_type, id_type>, std::list<ItemRef> >::const_iterator i = m_items_by_cell_and_category_id.find (std::make_pair (cell_id, category_id)); std::map <std::pair <id_type, id_type>, std::list<ItemRef> >::const_iterator i = m_items_by_cell_and_category_id.find (std::make_pair (cell_id, category_id));
@ -1731,7 +1749,7 @@ Database::num_items (id_type cell_id, id_type category_id) const
} }
} }
size_t size_t
Database::num_items_visited (id_type cell_id, id_type category_id) const Database::num_items_visited (id_type cell_id, id_type category_id) const
{ {
std::map <std::pair <id_type, id_type>, size_t>::const_iterator n = m_num_items_visited_by_cell_and_category.find (std::make_pair (cell_id, category_id)); std::map <std::pair <id_type, id_type>, size_t>::const_iterator n = m_num_items_visited_by_cell_and_category.find (std::make_pair (cell_id, category_id));
@ -1915,8 +1933,6 @@ Database::apply (const rdb::Database &other)
{ {
std::map<id_type, id_type> cell2cell; std::map<id_type, id_type> cell2cell;
std::map<id_type, id_type> cat2cat; std::map<id_type, id_type> cat2cat;
std::map<id_type, id_type> tag2tag;
std::map<id_type, id_type> rev_tag2tag;
for (auto c = other.cells ().begin (); c != other.cells ().end (); ++c) { for (auto c = other.cells ().begin (); c != other.cells ().end (); ++c) {
// TODO: do we have a consistent scheme of naming variants? What requirements // TODO: do we have a consistent scheme of naming variants? What requirements

View File

@ -68,10 +68,10 @@ class Items;
/** /**
* @brief A report item's category * @brief A report item's category
* *
* An item is member of exactly one category. This can be a check for example. * An item is member of exactly one category. This can be a check for example.
* A category is described by a name and a description string. An Id is provided * A category is described by a name and a description string. An Id is provided
* to reference this category from actual report items. * to reference this category from actual report items.
* Categories can be organized hierarchically for which a category collection * Categories can be organized hierarchically for which a category collection
* is provided and member of the individual category. * is provided and member of the individual category.
* *
* A category can only be created by the database object, since the * A category can only be created by the database object, since the
@ -112,7 +112,7 @@ public:
* *
* This method must not be used for items in the database to keep the database consistent. * This method must not be used for items in the database to keep the database consistent.
*/ */
void set_id (id_type id) void set_id (id_type id)
{ {
m_id = id; m_id = id;
} }
@ -130,7 +130,7 @@ public:
* *
* This method must not be used for items in the database to keep the database consistent. * This method must not be used for items in the database to keep the database consistent.
*/ */
void set_name (const std::string &d) void set_name (const std::string &d)
{ {
m_name = d; m_name = d;
} }
@ -155,7 +155,7 @@ public:
/** /**
* @brief The description string (setter) * @brief The description string (setter)
*/ */
void set_description (const std::string &d) void set_description (const std::string &d)
{ {
m_description = d; m_description = d;
} }
@ -181,7 +181,7 @@ public:
/** /**
* @brief The parent (owner) of this category (getter) * @brief The parent (owner) of this category (getter)
*/ */
Category *parent () Category *parent ()
{ {
return mp_parent; return mp_parent;
} }
@ -192,7 +192,7 @@ public:
* This method is provided for persistency application only. It should not be used otherwise. * This method is provided for persistency application only. It should not be used otherwise.
* The Category object will take over ownership over the sub categories. * The Category object will take over ownership over the sub categories.
*/ */
void import_sub_categories (Categories *categories); void import_sub_categories (Categories *categories);
/** /**
* @brief Report the number of items * @brief Report the number of items
@ -242,7 +242,7 @@ private:
* @brief Default constructor * @brief Default constructor
* *
* Creates a category object with empty name and description. * Creates a category object with empty name and description.
* This constructor is private to allow only the database to produce a * This constructor is private to allow only the database to produce a
* category object. * category object.
*/ */
Category (const std::string &name); Category (const std::string &name);
@ -262,9 +262,9 @@ private:
{ {
m_num_items_visited += d; m_num_items_visited += d;
} }
/** /**
* @brief Add an offset to the number of items * @brief Add an offset to the number of items
*/ */
void add_to_num_items (int d) void add_to_num_items (int d)
{ {
@ -279,7 +279,7 @@ private:
m_num_items = 0; m_num_items = 0;
m_num_items_visited = 0; m_num_items_visited = 0;
} }
/** /**
* @brief Set the database reference * @brief Set the database reference
*/ */
@ -293,10 +293,10 @@ private:
/** /**
* @brief The collection of categories * @brief The collection of categories
* *
* A generic collection of categories used for the root node and * A generic collection of categories used for the root node and
* sub-category nodes. * sub-category nodes.
*/ */
class RDB_PUBLIC Categories class RDB_PUBLIC Categories
{ {
public: public:
typedef tl::shared_collection<Category>::const_iterator const_iterator; typedef tl::shared_collection<Category>::const_iterator const_iterator;
@ -327,39 +327,39 @@ public:
/** /**
* @brief Iterate the categories inside this collection (begin iterator) * @brief Iterate the categories inside this collection (begin iterator)
*/ */
const_iterator begin () const const_iterator begin () const
{ {
return m_categories.begin (); return m_categories.begin ();
} }
/** /**
* @brief Iterate the categories inside this collection (end iterator) * @brief Iterate the categories inside this collection (end iterator)
*/ */
const_iterator end () const const_iterator end () const
{ {
return m_categories.end (); return m_categories.end ();
} }
/** /**
* @brief Iterate the categories inside this collection (begin iterator) * @brief Iterate the categories inside this collection (begin iterator)
*/ */
iterator begin () iterator begin ()
{ {
return m_categories.begin (); return m_categories.begin ();
} }
/** /**
* @brief Iterate the categories inside this collection (end iterator) * @brief Iterate the categories inside this collection (end iterator)
*/ */
iterator end () iterator end ()
{ {
return m_categories.end (); return m_categories.end ();
} }
/** /**
* @brief Find a category by name * @brief Find a category by name
* *
* The name is actually a path expression which specifies the category starting from the given * The name is actually a path expression which specifies the category starting from the given
* node with a '.' separated path notation. I.e. 'a.b' is the sub-category 'b' of category 'a'. * node with a '.' separated path notation. I.e. 'a.b' is the sub-category 'b' of category 'a'.
* If no such category can be found, 0 is returned. * If no such category can be found, 0 is returned.
*/ */
@ -371,7 +371,7 @@ public:
/** /**
* @brief Find a category by name (non-const version) * @brief Find a category by name (non-const version)
* *
* The name is actually a path expression which specifies the category starting from the given * The name is actually a path expression which specifies the category starting from the given
* node with a '.' separated path notation. I.e. 'a.b' is the sub-category 'b' of category 'a'. * node with a '.' separated path notation. I.e. 'a.b' is the sub-category 'b' of category 'a'.
* If no such category can be found, 0 is returned. * If no such category can be found, 0 is returned.
*/ */
@ -388,7 +388,7 @@ public:
* This method is provided for persistency application only. It should not be used otherwise. * This method is provided for persistency application only. It should not be used otherwise.
* This will take over ownership over the category. * This will take over ownership over the category.
*/ */
void import_category (Category *category); void import_category (Category *category);
/** /**
* @brief Gets the database reference * @brief Gets the database reference
@ -403,7 +403,7 @@ public:
friend class Category; friend class Category;
tl::shared_collection<Category> m_categories; tl::shared_collection<Category> m_categories;
std::map <std::string, Category *> m_categories_by_name; std::map <std::string, Category *> m_categories_by_name;
tl::weak_ptr<Database> mp_database; tl::weak_ptr<Database> mp_database;
Categories () Categories ()
@ -422,7 +422,7 @@ public:
* A value has a value (as the name says) and an optional tag id. Tag id's identify * A value has a value (as the name says) and an optional tag id. Tag id's identify
* the value and make the value a named one. * the value and make the value a named one.
*/ */
class RDB_PUBLIC ValueBase class RDB_PUBLIC ValueBase
{ {
public: public:
ValueBase () ValueBase ()
@ -496,14 +496,14 @@ public:
return m_value; return m_value;
} }
C &value () C &value ()
{ {
return m_value; return m_value;
} }
int type_index () const int type_index () const
{ {
return type_index_of<C> (); return type_index_of<C> ();
} }
bool compare (const ValueBase *other) const; bool compare (const ValueBase *other) const;
@ -535,7 +535,7 @@ RDB_PUBLIC_TEMPLATE ValueBase *make_value (const T &value)
/** /**
* @brief A class encapsulating ValueBase pointer * @brief A class encapsulating ValueBase pointer
*/ */
class RDB_PUBLIC ValueWrapper class RDB_PUBLIC ValueWrapper
{ {
public: public:
/** /**
@ -592,7 +592,7 @@ public:
/** /**
* @brief Get the pointer * @brief Get the pointer
*/ */
ValueBase *get () ValueBase *get ()
{ {
return mp_ptr; return mp_ptr;
} }
@ -627,7 +627,7 @@ public:
} }
/** /**
* @brief Convert the values collection to a string * @brief Convert the values collection to a string
*/ */
std::string to_string () const; std::string to_string () const;
@ -672,19 +672,16 @@ public:
} }
/** /**
* @brief Assignment * @brief Assignment
*/ */
Values &operator= (const Values &d); Values &operator= (const Values &d);
/** /**
* @brief Compare two value sets (less operator) * @brief Compare two value sets (less operator)
* *
* This compare function will use the tag mapping provided by tag map ("this" tag id to "other" tag id). * This compare function will use the tags provide in "common_tags". Tags outside this set are ignored.
* Values with tags not listed in the tag map will not be compared.
* Untagged values (tag_id 0) will be compared always. * Untagged values (tag_id 0) will be compared always.
* *
* "rev_tag_map" needs to be the reverse of "tag_map".
*
* The order of the values matters. * The order of the values matters.
*/ */
bool compare (const Values &other, const std::set<id_type> &common_tags) const; bool compare (const Values &other, const std::set<id_type> &common_tags) const;
@ -708,7 +705,7 @@ public:
/** /**
* @brief The non-const iterator (begin) * @brief The non-const iterator (begin)
*/ */
iterator begin () iterator begin ()
{ {
return m_values.begin (); return m_values.begin ();
} }
@ -758,7 +755,7 @@ public:
} }
/** /**
* @brief Convert the values collection to a string * @brief Convert the values collection to a string
*/ */
std::string to_string () const; std::string to_string () const;
@ -774,8 +771,8 @@ private:
/** /**
* @brief A report item * @brief A report item
* *
* A report item is one information item in the report. * A report item is one information item in the report.
* The value of a report item is manyfold. Values can be keyed, * The value of a report item is manyfold. Values can be keyed,
* i.e. multiple values can be present with different keys. * i.e. multiple values can be present with different keys.
* Each value can be of different types where the type is specified by a type Id. * Each value can be of different types where the type is specified by a type Id.
*/ */
@ -789,12 +786,12 @@ public:
Item (Items *items); Item (Items *items);
/** /**
* @brief Copy constructor * @brief Copy constructor
*/ */
Item (const Item &d); Item (const Item &d);
/** /**
* @brief Assignment * @brief Assignment
*/ */
Item &operator= (const Item &d); Item &operator= (const Item &d);
@ -816,7 +813,7 @@ public:
* *
* This method must not be used for items in the database to keep the database consistent. * This method must not be used for items in the database to keep the database consistent.
*/ */
void set_cell_id (id_type id) void set_cell_id (id_type id)
{ {
m_cell_id = id; m_cell_id = id;
} }
@ -846,7 +843,7 @@ public:
* *
* This method must not be used for items in the database to keep the database consistent. * This method must not be used for items in the database to keep the database consistent.
*/ */
void set_category_id (id_type id) void set_category_id (id_type id)
{ {
m_category_id = id; m_category_id = id;
} }
@ -1073,9 +1070,9 @@ private:
}; };
/** /**
* @brief An item reference * @brief An item reference
* *
* This is basically a wrapper for a pointer that correctly * This is basically a wrapper for a pointer that correctly
* maps const * and non-const * values through the operator-> * maps const * and non-const * values through the operator->
* overloads. * overloads.
*/ */
@ -1141,7 +1138,7 @@ public:
/** /**
* @brief Construct an item list with a database reference * @brief Construct an item list with a database reference
*/ */
Items (Database *database) Items (Database *database)
: mp_database (database) : mp_database (database)
{ {
// .. nothing yet .. // .. nothing yet ..
@ -1150,33 +1147,33 @@ public:
/** /**
* @brief Iterate the items inside this collection (begin iterator) * @brief Iterate the items inside this collection (begin iterator)
*/ */
const_iterator begin () const const_iterator begin () const
{ {
return m_items.begin (); return m_items.begin ();
} }
/** /**
* @brief Iterate the items inside this collection (end iterator) * @brief Iterate the items inside this collection (end iterator)
*/ */
const_iterator end () const const_iterator end () const
{ {
return m_items.end (); return m_items.end ();
} }
/** /**
* @brief Iterate the items inside this collection (non-const begin iterator) * @brief Iterate the items inside this collection (non-const begin iterator)
*/ */
iterator begin () iterator begin ()
{ {
return m_items.begin (); return m_items.begin ();
} }
/** /**
* @brief Iterate the items inside this collection (non-const end iterator) * @brief Iterate the items inside this collection (non-const end iterator)
*/ */
iterator end () iterator end ()
{ {
return m_items.end (); return m_items.end ();
} }
/** /**
@ -1195,7 +1192,7 @@ public:
* *
* This method is provided for persistency application only. It should not be used otherwise. * This method is provided for persistency application only. It should not be used otherwise.
*/ */
Item &back () Item &back ()
{ {
return m_items.back (); return m_items.back ();
} }
@ -1203,7 +1200,7 @@ public:
/** /**
* @brief Get the database reference * @brief Get the database reference
*/ */
Database *database () Database *database ()
{ {
return mp_database; return mp_database;
} }
@ -1350,7 +1347,7 @@ private:
}; };
/** /**
* @brief A collection of references * @brief A collection of references
*/ */
class RDB_PUBLIC References class RDB_PUBLIC References
{ {
@ -1393,7 +1390,7 @@ public:
/** /**
* @brief Begin iterator (non-const) * @brief Begin iterator (non-const)
*/ */
iterator begin () iterator begin ()
{ {
return m_references.begin (); return m_references.begin ();
} }
@ -1401,7 +1398,7 @@ public:
/** /**
* @brief End iterator (non-const) * @brief End iterator (non-const)
*/ */
iterator end () iterator end ()
{ {
return m_references.end (); return m_references.end ();
} }
@ -1417,7 +1414,7 @@ public:
/** /**
* @brief Get the database reference * @brief Get the database reference
*/ */
Database *database () Database *database ()
{ {
return mp_database; return mp_database;
} }
@ -1500,7 +1497,7 @@ public:
* *
* This method must not be used for items in the database to keep the database consistent. * This method must not be used for items in the database to keep the database consistent.
*/ */
void set_id (id_type id) void set_id (id_type id)
{ {
m_id = id; m_id = id;
} }
@ -1518,7 +1515,7 @@ public:
* *
* This method must not be used for items in the database to keep the database consistent. * This method must not be used for items in the database to keep the database consistent.
*/ */
void set_name (const std::string &d) void set_name (const std::string &d)
{ {
m_name = d; m_name = d;
} }
@ -1536,7 +1533,7 @@ public:
* *
* This method must not be used for items in the database to keep the database consistent. * This method must not be used for items in the database to keep the database consistent.
*/ */
void set_variant (const std::string &v) void set_variant (const std::string &v)
{ {
m_variant = v; m_variant = v;
} }
@ -1591,7 +1588,7 @@ public:
/** /**
* @brief The reference collection (non-const) * @brief The reference collection (non-const)
*/ */
References &references () References &references ()
{ {
return m_references; return m_references;
} }
@ -1604,10 +1601,10 @@ public:
void import_references (const References &references); void import_references (const References &references);
/** /**
* @brief Get one example transformation leading from this cell to a given parent cell * @brief Get one example transformation leading from this cell to a given parent cell
* *
* This method will try to determine one path from the given cell to the given parent * This method will try to determine one path from the given cell to the given parent
* cell and return the accumulated transformation for this path. * cell and return the accumulated transformation for this path.
* If no path is found, the first parameter of the returned pair is false, otherwise it's * If no path is found, the first parameter of the returned pair is false, otherwise it's
* true. * true.
*/ */
@ -1616,7 +1613,7 @@ public:
/** /**
* @brief Get the database reference * @brief Get the database reference
*/ */
Database *database () Database *database ()
{ {
return mp_database; return mp_database;
} }
@ -1654,7 +1651,7 @@ private:
} }
/** /**
* @brief Add an offset to the number of items * @brief Add an offset to the number of items
*/ */
void add_to_num_items (int d) void add_to_num_items (int d)
{ {
@ -1669,7 +1666,7 @@ private:
m_num_items = 0; m_num_items = 0;
m_num_items_visited = 0; m_num_items_visited = 0;
} }
/** /**
* @brief Set the database reference * @brief Set the database reference
*/ */
@ -1683,7 +1680,7 @@ private:
}; };
/** /**
* @brief A collection of cells * @brief A collection of cells
*/ */
class RDB_PUBLIC Cells class RDB_PUBLIC Cells
{ {
@ -1743,7 +1740,7 @@ public:
/** /**
* @brief Begin iterator (non-const) * @brief Begin iterator (non-const)
*/ */
iterator begin () iterator begin ()
{ {
return m_cells.begin (); return m_cells.begin ();
} }
@ -1751,7 +1748,7 @@ public:
/** /**
* @brief End iterator (non-const) * @brief End iterator (non-const)
*/ */
iterator end () iterator end ()
{ {
return m_cells.end (); return m_cells.end ();
} }
@ -1784,7 +1781,7 @@ public:
/** /**
* @brief Get the database reference (non-const) * @brief Get the database reference (non-const)
*/ */
Database *database () Database *database ()
{ {
return mp_database.get (); return mp_database.get ();
} }
@ -1848,9 +1845,9 @@ public:
/** /**
* @brief Gets a flag indicating whether the tag is a user tag or a system tag * @brief Gets a flag indicating whether the tag is a user tag or a system tag
* *
* If this flag is false, the tag is a system tag used for tagging "waived" and * If this flag is false, the tag is a system tag used for tagging "waived" and
* similar conditions. Otherwise it is a user tag which can be used freely to * similar conditions. Otherwise it is a user tag which can be used freely to
* tag arbitrary conditions. * tag arbitrary conditions.
*/ */
bool is_user_tag () const bool is_user_tag () const
@ -1863,7 +1860,7 @@ public:
* *
* See \is_user_tag for details. * See \is_user_tag for details.
*/ */
void set_user_tag (bool user) void set_user_tag (bool user)
{ {
m_is_user_tag = user; m_is_user_tag = user;
} }
@ -1881,7 +1878,7 @@ public:
* *
* This method must not be used for items in the database to keep the database consistent. * This method must not be used for items in the database to keep the database consistent.
*/ */
void set_id (id_type id) void set_id (id_type id)
{ {
m_id = id; m_id = id;
} }
@ -1900,7 +1897,7 @@ public:
* The name of the tag must not be changed when the tag is already part of a Tags collection. * The name of the tag must not be changed when the tag is already part of a Tags collection.
* Otherwise, the tag collection becomes inconsistent. * Otherwise, the tag collection becomes inconsistent.
*/ */
void set_name (const std::string &name) void set_name (const std::string &name)
{ {
m_name = name; m_name = name;
} }
@ -1921,7 +1918,7 @@ public:
typedef tag_list_type::const_iterator const_iterator; typedef tag_list_type::const_iterator const_iterator;
/** /**
* @brief Default constructor for the tags list * @brief Default constructor for the tags list
* *
* This method is provided for persistency application only. It should not be used otherwise. * This method is provided for persistency application only. It should not be used otherwise.
*/ */
@ -1972,16 +1969,27 @@ public:
* @brief Import a tag * @brief Import a tag
* *
* This method is provided for persistency application only. It should not be used otherwise. * This method is provided for persistency application only. It should not be used otherwise.
* This will assign a new id to the tag and replace any tag with that * This will assign a new id to the tag and replace any tag with that
* name. * name.
*/ */
void import_tag (const Tag &tag); void import_tag (const Tag &tag);
/** /**
* @brief Clear the collection of tags * @brief Clear the collection of tags
*
* NOTE: this will not remove the tags from items or values, so the use cases for this method
* are limited.
*/ */
void clear (); void clear ();
/**
* @brief Removes the tag with the given ID
*
* NOTE: this will not remove the tags from items or values, so the use cases for this method
* are limited.
*/
void remove_tag (id_type id);
/** /**
* @brief Gets the name and user flag for a tag ID * @brief Gets the name and user flag for a tag ID
* *
@ -2013,7 +2021,7 @@ private:
/** /**
* @brief The database object * @brief The database object
*/ */
class RDB_PUBLIC Database class RDB_PUBLIC Database
: public gsi::ObjectBase, : public gsi::ObjectBase,
public tl::Object public tl::Object
{ {
@ -2123,7 +2131,7 @@ public:
} }
/** /**
* @brief Set the top cell name * @brief Set the top cell name
*/ */
void set_top_cell_name (const std::string &topcell) void set_top_cell_name (const std::string &topcell)
{ {
@ -2179,17 +2187,17 @@ public:
void import_categories (Categories *categories); void import_categories (Categories *categories);
/** /**
* @brief Create a category and register it * @brief Create a category and register it
*/ */
Category *create_category (const std::string &name); Category *create_category (const std::string &name);
/** /**
* @brief Create a category as a subcategory and register it * @brief Create a category as a subcategory and register it
*/ */
Category *create_category (Category *parent, const std::string &name); Category *create_category (Category *parent, const std::string &name);
/** /**
* @brief Create a category as a subcategory in the container and register it * @brief Create a category as a subcategory in the container and register it
* *
* Hint: this method does not set the parent properly and must not be used * Hint: this method does not set the parent properly and must not be used
* under normal circumstances. It is provided as a internal method and * under normal circumstances. It is provided as a internal method and
@ -2268,7 +2276,7 @@ public:
* @brief Create a cell variant and register it * @brief Create a cell variant and register it
* *
* A cell with name name/variant combination must not exist already. * A cell with name name/variant combination must not exist already.
* If the variant string is empty, this method behaves the same as the * If the variant string is empty, this method behaves the same as the
* method without variant. * method without variant.
* *
* "layout_name" is the name of the cell in the layout. If empty, the layout * "layout_name" is the name of the cell in the layout. If empty, the layout
@ -2417,7 +2425,7 @@ public:
/** /**
* @brief Get an iterator pair that delivers the const items (ItemRef) for a given cell * @brief Get an iterator pair that delivers the const items (ItemRef) for a given cell
*/ */
std::pair<const_item_ref_iterator, const_item_ref_iterator> items_by_cell (id_type cell_id) const; std::pair<const_item_ref_iterator, const_item_ref_iterator> items_by_cell (id_type cell_id) const;
/** /**
* @brief Get an iterator pair that delivers the non-const items (ItemRef) for a given cell * @brief Get an iterator pair that delivers the non-const items (ItemRef) for a given cell
@ -2427,7 +2435,7 @@ public:
/** /**
* @brief Get an iterator that delivers the const items (ItemRef) for a given category * @brief Get an iterator that delivers the const items (ItemRef) for a given category
*/ */
std::pair<const_item_ref_iterator, const_item_ref_iterator> items_by_category (id_type category_id) const; std::pair<const_item_ref_iterator, const_item_ref_iterator> items_by_category (id_type category_id) const;
/** /**
* @brief Get an iterator that delivers the non-const items (ItemRef) for a given category * @brief Get an iterator that delivers the non-const items (ItemRef) for a given category
@ -2437,7 +2445,7 @@ public:
/** /**
* @brief Get an iterator that delivers the const items (ItemRef) for a given cell and category * @brief Get an iterator that delivers the const items (ItemRef) for a given cell and category
*/ */
std::pair<const_item_ref_iterator, const_item_ref_iterator> items_by_cell_and_category (id_type cell_id, id_type category_id) const; std::pair<const_item_ref_iterator, const_item_ref_iterator> items_by_cell_and_category (id_type cell_id, id_type category_id) const;
/** /**
* @brief Get an iterator that delivers the non-const items (ItemRef) for a given cell and category * @brief Get an iterator that delivers the non-const items (ItemRef) for a given cell and category
@ -2455,7 +2463,7 @@ public:
/** /**
* @brief Reset the modified file * @brief Reset the modified file
*/ */
void reset_modified () void reset_modified ()
{ {
m_modified = false; m_modified = false;
} }
@ -2526,7 +2534,7 @@ private:
void clear (); void clear ();
void set_modified () void set_modified ()
{ {
m_modified = true; m_modified = true;
} }

View File

@ -816,7 +816,18 @@ TEST(13_ApplyIgnoreUnknownTag)
i2->values ().clear (); i2->values ().clear ();
i2->add_value (std::string ("xyz"), vtag22); i2->add_value (std::string ("xyz"), vtag22);
// values with incompatible tags are ignored -> tag2 is applied // values with incompatible tags are ignored, but vtag1 is a common tag.
// So far, nothing is applied as the we match abc[vtag1] vs. xyz[vtag2] which is both different value and tag-
db1.apply (db2);
EXPECT_EQ (i1->tag_str (), "");
// NOTE: don't do this at home
const_cast<rdb::Tags &> (db2.tags ()).remove_tag (vtag21);
// vtag1 is no longer a common tag -> we match abc[vtag1] vs. xyz[vtag2] where vtag1 is not known on the
// other side and vtag2 is not known on the self side.
// Hence, the values are ignored and the tag is applied.
db1.apply (db2); db1.apply (db2);
EXPECT_EQ (i1->tag_str (), "tag2"); EXPECT_EQ (i1->tag_str (), "tag2");