From 5d4534fac483bce86e13a6ae724a7332a63b687c Mon Sep 17 00:00:00 2001 From: "Maarten L. Hekkelman" Date: Mon, 22 Jan 2024 15:15:11 +0100 Subject: [PATCH] Added rename_column Added item_alias Rename columns in reconstruct --- include/cif++/category.hpp | 3 +++ include/cif++/validate.hpp | 16 +++++++++++++++- src/category.cpp | 14 ++++++++++++++ src/dictionary_parser.cpp | 9 ++++++++- src/pdb/reconstruct.cpp | 20 +++++++++++++++++--- src/validate.cpp | 22 ++++++++++++++++++++++ 6 files changed, 79 insertions(+), 5 deletions(-) diff --git a/include/cif++/category.hpp b/include/cif++/category.hpp index 3ea6391..7d5922f 100644 --- a/include/cif++/category.hpp +++ b/include/cif++/category.hpp @@ -1041,6 +1041,9 @@ class category */ void remove_column(std::string_view column_name); + /** @brief Rename column @a from_name to @a to_name */ + void rename_column(std::string_view from_name, std::string_view to_name); + /// @brief Return whether a column with name @a name exists in this category /// @param name The name of the column /// @return True if the column exists diff --git a/include/cif++/validate.hpp b/include/cif++/validate.hpp index fd16299..54f9314 100644 --- a/include/cif++/validate.hpp +++ b/include/cif++/validate.hpp @@ -146,6 +146,16 @@ struct type_validator int compare(std::string_view a, std::string_view b) const; }; +/** @brief Item alias, items can be renamed over time + */ + +struct item_alias +{ + std::string m_name; ///< The alias_name + std::string m_dict; ///< The dictionary in which it was known + std::string m_vers; ///< The version of the dictionary +}; + /** * @brief An item_validator binds a type_validator to an item in * a category along with other information found in the dictionary. @@ -163,6 +173,7 @@ struct item_validator cif::iset m_enums; ///< If filled, the set of allowed values std::string m_default; ///< If filled, a default value for this item category_validator *m_category = nullptr; ///< The category_validator this item_validator belongs to + std::vector m_aliases; ///< The aliases for this item /// @brief Compare based on the name bool operator<(const item_validator &rhs) const @@ -191,7 +202,7 @@ struct category_validator { std::string m_name; ///< The name of the category std::vector m_keys; ///< The list of items that make up the key - cif::iset m_groups; ///< The category groups this category belongs to + cif::iset m_groups; ///< The category groups this category belongs to cif::iset m_mandatory_fields; ///< The mandatory fields for this category std::set m_item_validators; ///< The item validators for the items in this category @@ -206,6 +217,9 @@ struct category_validator /// @brief Return the item_validator for item @a tag, may return nullptr const item_validator *get_validator_for_item(std::string_view tag) const; + + /// @brief Return the item_validator for an item that has as alias name @a tag, may return nullptr + const item_validator *get_validator_for_aliased_item(std::string_view tag) const; }; /** diff --git a/src/category.cpp b/src/category.cpp index c798e6f..bba6c90 100644 --- a/src/category.cpp +++ b/src/category.cpp @@ -614,6 +614,20 @@ void category::remove_column(std::string_view column_name) } } +void category::rename_column(std::string_view from_name, std::string_view to_name) +{ + for (size_t ix = 0; ix < m_columns.size(); ++ix) + { + if (not iequals(from_name, m_columns[ix].m_name)) + continue; + + m_columns[ix].m_name = to_name; + m_columns[ix].m_validator = m_cat_validator ? m_cat_validator->get_validator_for_item(to_name) : nullptr; + + break; + } +} + iset category::get_columns() const { iset result; diff --git a/src/dictionary_parser.cpp b/src/dictionary_parser.cpp index 1b6a9d0..31fd912 100644 --- a/src/dictionary_parser.cpp +++ b/src/dictionary_parser.cpp @@ -224,6 +224,13 @@ class dictionary_parser : public parser // } // } + std::vector aliases; + for (const auto &[alias_name, dictionary, version] : + dict["item_aliases"].rows("alias_name", "dictionary", "version")) + { + aliases.emplace_back(alias_name, dictionary, version); + } + // collect the dict from our dataBlock and construct validators for (auto i : dict["item"]) { @@ -245,7 +252,7 @@ class dictionary_parser : public parser auto vi = find(ivs.begin(), ivs.end(), item_validator{ item_name }); if (vi == ivs.end()) - ivs.push_back(item_validator{ item_name, iequals(mandatory, "yes"), tv, ess, defaultValue /*, defaultIsNull*/ }); + ivs.push_back(item_validator{ item_name, iequals(mandatory, "yes"), tv, ess, defaultValue, nullptr, std::move(aliases) }); else { // need to update the itemValidator? diff --git a/src/pdb/reconstruct.cpp b/src/pdb/reconstruct.cpp index 58233be..4f6b52a 100644 --- a/src/pdb/reconstruct.cpp +++ b/src/pdb/reconstruct.cpp @@ -683,9 +683,6 @@ void comparePolySeqSchemes(datablock &db) } } } - - if (ndb_poly_seq_scheme.empty()) - db.erase(std::remove(db.begin(), db.end(), ndb_poly_seq_scheme), db.end()); } void reconstruct_pdbx(file &file, std::string_view dictionary) @@ -732,6 +729,23 @@ void reconstruct_pdbx(file &file, std::string_view dictionary) auto cv = validator.get_validator_for_category(cat.name()); if (not cv) continue; + + // Start by renaming columns that may have old names based on alias info + + for (auto tag : cat.get_columns()) + { + auto iv = cv->get_validator_for_item(tag); + if (iv) // know, must be OK then + continue; + + iv = cv->get_validator_for_aliased_item(tag); + if (not iv) + continue; + + if (cif::VERBOSE > 0) + std::clog << "Renaming " << tag << " to " << iv->m_tag << " in category " << cat.name() << '\n'; + cat.rename_column(tag, iv->m_tag); + } for (auto link : validator.get_links_for_child(cat.name())) { diff --git a/src/validate.cpp b/src/validate.cpp index 30c0514..dccd432 100644 --- a/src/validate.cpp +++ b/src/validate.cpp @@ -256,6 +256,28 @@ const item_validator *category_validator::get_validator_for_item(std::string_vie return result; } +const item_validator *category_validator::get_validator_for_aliased_item(std::string_view tag) const +{ + const item_validator *result = nullptr; + + for (auto &iv : m_item_validators) + { + for (auto &ai : iv.m_aliases) + { + const auto &[cat, name] = split_tag_name(ai.m_name); + if (name == tag and cat == m_name) + { + result = &iv; + break; + } + } + if (result) + break; + } + + return result; +} + // -------------------------------------------------------------------- void validator::add_type_validator(type_validator &&v)