From 0f833da652c82c3f52889144626b56c52bb98f4c Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 17 Aug 2024 22:03:00 +0200 Subject: [PATCH] Consolidated solution for RDB merge ('apply'). Potentially one bug fixed (tag mapping) --- src/rdb/rdb/rdb.cc | 136 +++++++++++---------- src/rdb/rdb/rdb.h | 208 +++++++++++++++++---------------- src/rdb/unit_tests/rdbTests.cc | 13 ++- 3 files changed, 196 insertions(+), 161 deletions(-) diff --git a/src/rdb/rdb/rdb.cc b/src/rdb/rdb/rdb.cc index 8e624f78c..289c21d68 100644 --- a/src/rdb/rdb/rdb.cc +++ b/src/rdb/rdb/rdb.cc @@ -278,7 +278,7 @@ template <> RDB_PUBLIC bool Value::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. 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 -std::string +std::string ValueWrapper::to_string () const { std::string r; @@ -437,14 +437,14 @@ ValueWrapper::to_string () const return r; } -void +void ValueWrapper::from_string (const std::string &s) { tl::Extractor ex (s.c_str ()); from_string (ex); } -void +void ValueWrapper::from_string (tl::Extractor &ex) { id_type tag_id = 0; @@ -453,7 +453,7 @@ ValueWrapper::from_string (tl::Extractor &ex) bool user_tag = ex.test ("#"); - std::string tn; + std::string tn; ex.read_word_or_quoted (tn); tag_id = rdb::Tags::id_for_name (tn, user_tag); @@ -482,11 +482,11 @@ Values::compare (const Values &other, const std::set &common_tags) cons Values::const_iterator a = begin (), b = other.begin (); while (a != end () && b != other.end ()) { - id_type t12 = 0; + id_type t1 = 0; while (a != end () && a->tag_id () != 0) { auto j = common_tags.find (a->tag_id ()); if (j != common_tags.end ()) { - t12 = a->tag_id (); + t1 = a->tag_id (); break; } ++a; @@ -506,8 +506,8 @@ Values::compare (const Values &other, const std::set &common_tags) cons return b != other.end (); } - if (t12 != t2) { - return t12 < t2; + if (t1 != t2) { + return t1 < t2; } if (a->get () && b->get ()) { @@ -528,7 +528,7 @@ Values::compare (const Values &other, const std::set &common_tags) cons return b != other.end (); } -std::string +std::string Values::to_string () const { std::string r; @@ -547,7 +547,7 @@ Values::to_string () const return r; } -void +void Values::from_string (const std::string &s) { tl::Extractor ex (s.c_str ()); @@ -567,7 +567,7 @@ Values::from_string (const std::string &s) // ------------------------------------------------------------------------------------------ // Cell implementation -void +void Cells::import_cell (const Cell &c) { Cell *cell; @@ -582,7 +582,7 @@ Cells::import_cell (const Cell &c) cell->references ().insert (*r); } } - + // ------------------------------------------------------------------------------------------ // Cell implementation @@ -615,7 +615,7 @@ Cell::~Cell () // .. nothing yet .. } -std::pair +std::pair Cell::path_to (id_type parent_cell_id, const Database *db) const { if (parent_cell_id == id ()) { @@ -626,7 +626,7 @@ Cell::path_to (id_type parent_cell_id, const Database *db) const } } -std::pair +std::pair Cell::path_to (id_type parent_cell_id, const Database *db, std::set &visited, const db::DCplxTrans &trans) const { 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 &v return std::pair (false, db::DCplxTrans ()); } -void +void Cell::import_references (const References &references) { for (References::const_iterator r = references.begin (); r != references.end (); ++r) { m_references.insert (*r); } } - -std::string + +std::string Cell::qname () const { if (m_variant.empty ()) { @@ -687,7 +687,7 @@ References::References (Cell *cell) // .. nothing yet .. } -void +void References::set_database (Database *database) { mp_database = database; @@ -705,20 +705,20 @@ Reference::Reference (References *references) // .. nothing yet .. } -void +void Reference::set_trans_str (const std::string &s) { tl::Extractor ex (s.c_str ()); ex.read (m_trans); } -std::string +std::string Reference::trans_str () const { return m_trans.to_string (); } -void +void Reference::set_parent_cell_qname (const std::string &qname) { tl_assert (mp_database != 0); @@ -729,7 +729,7 @@ Reference::set_parent_cell_qname (const std::string &qname) m_parent_cell_id = cell->id (); } -std::string +std::string Reference::parent_cell_qname () const { tl_assert (mp_database != 0); @@ -787,7 +787,7 @@ Category::sub_categories () return *mp_sub_categories; } -std::string +std::string Category::path () const { std::vector path_elements; @@ -810,7 +810,7 @@ Category::path () const return r; } -void +void Category::import_sub_categories (Categories *categories) { if (mp_sub_categories) { @@ -826,7 +826,7 @@ Category::import_sub_categories (Categories *categories) } } -void +void Category::set_database (Database *database) { mp_database = database; @@ -838,14 +838,14 @@ Category::set_database (Database *database) // ------------------------------------------------------------------------------------------ // Categories implementation -void +void Categories::clear () { m_categories.clear (); m_categories_by_name.clear (); } -void +void Categories::add_category (Category *cat) { 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)); } -void +void Categories::set_database (Database *database) { mp_database = database; @@ -863,7 +863,7 @@ Categories::set_database (Database *database) } Category * -Categories::category_by_name (const char *path) +Categories::category_by_name (const char *path) { std::string component; tl::Extractor ex (path); @@ -881,7 +881,7 @@ Categories::category_by_name (const char *path) return 0; } -void +void Categories::import_category (Category *category) { Category *cat; @@ -945,13 +945,31 @@ Tags::Tags () // .. nothing yet .. } -void +void Tags::clear () { m_tags_per_id.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 & 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 ()); } -bool +bool 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 (); @@ -1043,31 +1061,31 @@ Item &Item::operator= (const Item &d) return *this; } -void +void Item::add_tag (id_type tag_id) { m_tag_ids.insert (tag_id); } -void +void Item::remove_tag (id_type tag_id) { m_tag_ids.erase (tag_id); } -void +void Item::remove_tags () { m_tag_ids.clear (); } -bool +bool Item::has_tag (id_type tag_id) const { return m_tag_ids.find (tag_id) != m_tag_ids.end (); } -std::string +std::string Item::cell_qname () const { tl_assert (mp_database != 0); @@ -1076,7 +1094,7 @@ Item::cell_qname () const return cell->qname (); } -void +void Item::set_cell_qname (const std::string &qname) { tl_assert (mp_database != 0); @@ -1096,7 +1114,7 @@ Item::category_name () const return category->path (); } -void +void Item::set_category_name (const std::string &path) { tl_assert (mp_database != 0); @@ -1107,7 +1125,7 @@ Item::set_category_name (const std::string &path) m_category_id = category->id (); } -std::string +std::string Item::tag_str () const { tl_assert (mp_database != 0); @@ -1135,7 +1153,7 @@ Item::tag_str () const return r; } -void +void Item::set_tag_str (const std::string &tags) { tl_assert (mp_database != 0); @@ -1153,7 +1171,7 @@ Item::set_tag_str (const std::string &tags) } #if defined(HAVE_QT) -void +void Item::set_image (const QImage &image) { if (image.isNull ()) { @@ -1341,7 +1359,7 @@ Database::import_tags (const Tags &tags) } } -void +void Database::import_categories (Categories *categories) { set_modified (); @@ -1352,7 +1370,7 @@ Database::import_categories (Categories *categories) mp_categories->set_database (this); } -void +void Database::import_cells (const Cells &cells) { set_modified (); @@ -1399,13 +1417,13 @@ Database::create_category (Categories *container, const std::string &name) } 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 ()); } Category * -Database::category_by_id_non_const (id_type id) +Database::category_by_id_non_const (id_type id) { std::map ::const_iterator c = m_categories_by_id.find (id); if (c != m_categories_by_id.end ()) { @@ -1460,7 +1478,7 @@ Database::create_cell (const std::string &name, const std::string &variant, cons } else { new_cell = new Cell (++m_next_id, name, std::string (), layout_name); - + } 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)); } else { - + new_cell = new Cell (++m_next_id, name, variant, layout_name); m_cells.add_cell (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)); - + 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) { set_modified (); tags_non_const ().tag (tag_id).set_description (description); } -void +void Database::add_item_tag (const Item *item, id_type tag) { set_modified (); const_cast (item)->add_tag (tag); } -void +void Database::remove_item_tag (const Item *item, id_type tag) { set_modified (); @@ -1571,7 +1589,7 @@ Database::set_item_comment (const Item *item, const std::string &comment) } #if defined(HAVE_QT) -void +void Database::set_item_image (const Item *item, const QImage &image) { set_modified (); @@ -1586,14 +1604,14 @@ Database::set_item_image_str (const Item *item, const std::string &image_str) const_cast (item)->set_image_str (image_str); } -void +void Database::set_item_multiplicity (const Item *item, size_t n) { set_modified (); const_cast (item)->set_multiplicity (n); } -void +void Database::set_item_visited (const Item *item_c, bool visited) { if (visited != item_c->visited ()) { @@ -1654,7 +1672,7 @@ Database::create_item (id_type cell_id, id_type category_id) static std::list empty_list; -std::pair +std::pair Database::items_by_cell_and_category (id_type cell_id, id_type category_id) const { std::map , std::list >::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 { std::map , 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 cell2cell; std::map cat2cat; - std::map tag2tag; - std::map rev_tag2tag; for (auto c = other.cells ().begin (); c != other.cells ().end (); ++c) { // TODO: do we have a consistent scheme of naming variants? What requirements diff --git a/src/rdb/rdb/rdb.h b/src/rdb/rdb/rdb.h index 7f0e2e339..3747ada65 100644 --- a/src/rdb/rdb/rdb.h +++ b/src/rdb/rdb/rdb.h @@ -68,10 +68,10 @@ class Items; /** * @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 * 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. * * 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. */ - void set_id (id_type id) + void set_id (id_type 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. */ - void set_name (const std::string &d) + void set_name (const std::string &d) { m_name = d; } @@ -155,7 +155,7 @@ public: /** * @brief The description string (setter) */ - void set_description (const std::string &d) + void set_description (const std::string &d) { m_description = d; } @@ -181,7 +181,7 @@ public: /** * @brief The parent (owner) of this category (getter) */ - Category *parent () + Category *parent () { return mp_parent; } @@ -192,7 +192,7 @@ public: * 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. */ - void import_sub_categories (Categories *categories); + void import_sub_categories (Categories *categories); /** * @brief Report the number of items @@ -242,7 +242,7 @@ private: * @brief Default constructor * * 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 (const std::string &name); @@ -262,9 +262,9 @@ private: { 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) { @@ -279,7 +279,7 @@ private: m_num_items = 0; m_num_items_visited = 0; } - + /** * @brief Set the database reference */ @@ -293,10 +293,10 @@ private: /** * @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. */ -class RDB_PUBLIC Categories +class RDB_PUBLIC Categories { public: typedef tl::shared_collection::const_iterator const_iterator; @@ -327,39 +327,39 @@ public: /** * @brief Iterate the categories inside this collection (begin iterator) */ - const_iterator begin () const - { - return m_categories.begin (); + const_iterator begin () const + { + return m_categories.begin (); } /** * @brief Iterate the categories inside this collection (end iterator) */ - const_iterator end () const - { - return m_categories.end (); + const_iterator end () const + { + return m_categories.end (); } /** * @brief Iterate the categories inside this collection (begin iterator) */ - iterator begin () - { - return m_categories.begin (); + iterator begin () + { + return m_categories.begin (); } /** * @brief Iterate the categories inside this collection (end iterator) */ - iterator end () - { - return m_categories.end (); + iterator end () + { + return m_categories.end (); } /** * @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'. * If no such category can be found, 0 is returned. */ @@ -371,7 +371,7 @@ public: /** * @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'. * 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 will take over ownership over the category. */ - void import_category (Category *category); + void import_category (Category *category); /** * @brief Gets the database reference @@ -403,7 +403,7 @@ public: friend class Category; tl::shared_collection m_categories; - std::map m_categories_by_name; + std::map m_categories_by_name; tl::weak_ptr mp_database; Categories () @@ -422,7 +422,7 @@ public: * 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. */ -class RDB_PUBLIC ValueBase +class RDB_PUBLIC ValueBase { public: ValueBase () @@ -496,14 +496,14 @@ public: return m_value; } - C &value () + C &value () { return m_value; } - int type_index () const - { - return type_index_of (); + int type_index () const + { + return type_index_of (); } 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 */ -class RDB_PUBLIC ValueWrapper +class RDB_PUBLIC ValueWrapper { public: /** @@ -592,7 +592,7 @@ public: /** * @brief Get the pointer */ - ValueBase *get () + ValueBase *get () { 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; @@ -672,19 +672,16 @@ public: } /** - * @brief Assignment + * @brief Assignment */ Values &operator= (const Values &d); /** * @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). - * Values with tags not listed in the tag map will not be compared. + * This compare function will use the tags provide in "common_tags". Tags outside this set are ignored. * 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. */ bool compare (const Values &other, const std::set &common_tags) const; @@ -708,7 +705,7 @@ public: /** * @brief The non-const iterator (begin) */ - iterator begin () + iterator 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; @@ -774,8 +771,8 @@ private: /** * @brief A report item * - * A report item is one information item in the report. - * The value of a report item is manyfold. Values can be keyed, + * A report item is one information item in the report. + * The value of a report item is manyfold. Values can be keyed, * 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. */ @@ -789,12 +786,12 @@ public: Item (Items *items); /** - * @brief Copy constructor + * @brief Copy constructor */ Item (const Item &d); /** - * @brief Assignment + * @brief Assignment */ 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. */ - void set_cell_id (id_type id) + void set_cell_id (id_type 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. */ - void set_category_id (id_type id) + void set_category_id (id_type 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-> * overloads. */ @@ -1141,7 +1138,7 @@ public: /** * @brief Construct an item list with a database reference */ - Items (Database *database) + Items (Database *database) : mp_database (database) { // .. nothing yet .. @@ -1150,33 +1147,33 @@ public: /** * @brief Iterate the items inside this collection (begin iterator) */ - const_iterator begin () const - { - return m_items.begin (); + const_iterator begin () const + { + return m_items.begin (); } /** * @brief Iterate the items inside this collection (end iterator) */ - const_iterator end () const - { - return m_items.end (); + const_iterator end () const + { + return m_items.end (); } /** * @brief Iterate the items inside this collection (non-const begin iterator) */ iterator begin () - { - return m_items.begin (); + { + return m_items.begin (); } /** * @brief Iterate the items inside this collection (non-const end iterator) */ 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. */ - Item &back () + Item &back () { return m_items.back (); } @@ -1203,7 +1200,7 @@ public: /** * @brief Get the database reference */ - Database *database () + Database *database () { return mp_database; } @@ -1350,7 +1347,7 @@ private: }; /** - * @brief A collection of references + * @brief A collection of references */ class RDB_PUBLIC References { @@ -1393,7 +1390,7 @@ public: /** * @brief Begin iterator (non-const) */ - iterator begin () + iterator begin () { return m_references.begin (); } @@ -1401,7 +1398,7 @@ public: /** * @brief End iterator (non-const) */ - iterator end () + iterator end () { return m_references.end (); } @@ -1417,7 +1414,7 @@ public: /** * @brief Get the database reference */ - Database *database () + Database *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. */ - void set_id (id_type id) + void set_id (id_type 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. */ - void set_name (const std::string &d) + void set_name (const std::string &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. */ - void set_variant (const std::string &v) + void set_variant (const std::string &v) { m_variant = v; } @@ -1591,7 +1588,7 @@ public: /** * @brief The reference collection (non-const) */ - References &references () + References &references () { return m_references; } @@ -1604,10 +1601,10 @@ public: 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 - * 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 * true. */ @@ -1616,7 +1613,7 @@ public: /** * @brief Get the database reference */ - Database *database () + Database *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) { @@ -1669,7 +1666,7 @@ private: m_num_items = 0; m_num_items_visited = 0; } - + /** * @brief Set the database reference */ @@ -1683,7 +1680,7 @@ private: }; /** - * @brief A collection of cells + * @brief A collection of cells */ class RDB_PUBLIC Cells { @@ -1743,7 +1740,7 @@ public: /** * @brief Begin iterator (non-const) */ - iterator begin () + iterator begin () { return m_cells.begin (); } @@ -1751,7 +1748,7 @@ public: /** * @brief End iterator (non-const) */ - iterator end () + iterator end () { return m_cells.end (); } @@ -1784,7 +1781,7 @@ public: /** * @brief Get the database reference (non-const) */ - Database *database () + Database *database () { 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 - * + * * 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. */ bool is_user_tag () const @@ -1863,7 +1860,7 @@ public: * * See \is_user_tag for details. */ - void set_user_tag (bool user) + void set_user_tag (bool 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. */ - void set_id (id_type id) + void set_id (id_type 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. * Otherwise, the tag collection becomes inconsistent. */ - void set_name (const std::string &name) + void set_name (const std::string &name) { m_name = name; } @@ -1921,7 +1918,7 @@ public: 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. */ @@ -1972,16 +1969,27 @@ public: * @brief Import a tag * * 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. */ void import_tag (const Tag &tag); /** * @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 (); + /** + * @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 * @@ -2013,7 +2021,7 @@ private: /** * @brief The database object */ -class RDB_PUBLIC Database +class RDB_PUBLIC Database : public gsi::ObjectBase, 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) { @@ -2179,17 +2187,17 @@ public: 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); /** - * @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); /** - * @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 * under normal circumstances. It is provided as a internal method and @@ -2268,7 +2276,7 @@ public: * @brief Create a cell variant and register it * * 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. * * "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 */ - std::pair items_by_cell (id_type cell_id) const; + std::pair items_by_cell (id_type cell_id) const; /** * @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 */ - std::pair items_by_category (id_type category_id) const; + std::pair items_by_category (id_type category_id) const; /** * @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 */ - std::pair items_by_cell_and_category (id_type cell_id, id_type category_id) const; + std::pair 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 @@ -2455,7 +2463,7 @@ public: /** * @brief Reset the modified file */ - void reset_modified () + void reset_modified () { m_modified = false; } @@ -2526,7 +2534,7 @@ private: void clear (); - void set_modified () + void set_modified () { m_modified = true; } diff --git a/src/rdb/unit_tests/rdbTests.cc b/src/rdb/unit_tests/rdbTests.cc index 88b48676e..247b9c1c0 100644 --- a/src/rdb/unit_tests/rdbTests.cc +++ b/src/rdb/unit_tests/rdbTests.cc @@ -816,7 +816,18 @@ TEST(13_ApplyIgnoreUnknownTag) i2->values ().clear (); 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 (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); EXPECT_EQ (i1->tag_str (), "tag2");