Commit afc541b9 by Maarten L. Hekkelman

Merge remote-tracking branch 'github/develop-cif2fasta' into develop

parents 22537c0e 7e4d2ffb
......@@ -70,6 +70,26 @@ class duplicate_key_error : public std::runtime_error
}
};
/// @brief A missing_key_error is thrown when an attempt is made
/// to create an index when one of the key fields is missing.
class missing_key_error : public std::runtime_error
{
public:
/**
* @brief Construct a new duplicate key error object
*/
missing_key_error(const std::string &msg, const std::string &key)
: std::runtime_error(msg)
, m_key(key)
{
}
const std::string &get_key() const noexcept { return m_key; }
private:
std::string m_key;
};
/// @brief A multiple_results_error is throw when you request a single
/// row using a query but the query contains more than exactly one row.
class multiple_results_error : public std::runtime_error
......@@ -516,7 +536,7 @@ class category
/// @param column The name of the column to return the value for
/// @return The value found
template <typename T>
T find1(condition &&cond, const char *column) const
T find1(condition &&cond, std::string_view column) const
{
return find1<T>(cbegin(), std::move(cond), column);
}
......@@ -530,7 +550,7 @@ class category
/// @param column The name of the column to return the value for
/// @return The value found
template <typename T, std::enable_if_t<not is_optional_v<T>, int> = 0>
T find1(const_iterator pos, condition &&cond, const char *column) const
T find1(const_iterator pos, condition &&cond, std::string_view column) const
{
auto h = find<T>(pos, std::move(cond), column);
......@@ -549,7 +569,7 @@ class category
/// @param column The name of the column to return the value for
/// @return The value found, can be empty if no row matches the condition
template <typename T, std::enable_if_t<is_optional_v<T>, int> = 0>
T find1(const_iterator pos, condition &&cond, const char *column) const
T find1(const_iterator pos, condition &&cond, std::string_view column) const
{
auto h = find<typename T::value_type>(pos, std::move(cond), column);
......@@ -644,7 +664,7 @@ class category
/// @param column The column for which the value should be returned
/// @return The value found or a default constructed value if not found
template <typename T>
T find_first(condition &&cond, const char *column) const
T find_first(condition &&cond, std::string_view column) const
{
return find_first<T>(cbegin(), std::move(cond), column);
}
......@@ -657,7 +677,7 @@ class category
/// @param column The column for which the value should be returned
/// @return The value found or a default constructed value if not found
template <typename T>
T find_first(const_iterator pos, condition &&cond, const char *column) const
T find_first(const_iterator pos, condition &&cond, std::string_view column) const
{
auto h = find<T>(pos, std::move(cond), column);
......@@ -701,7 +721,7 @@ class category
/// @param cond The condition to search for
/// @return The value found or the minimal value for the type
template <typename T, std::enable_if_t<std::is_arithmetic_v<T>, int> = 0>
T find_max(const char *column, condition &&cond) const
T find_max(std::string_view column, condition &&cond) const
{
T result = std::numeric_limits<T>::min();
......@@ -719,7 +739,7 @@ class category
/// @param column The column to use for the value
/// @return The value found or the minimal value for the type
template <typename T, std::enable_if_t<std::is_arithmetic_v<T>, int> = 0>
T find_max(const char *column) const
T find_max(std::string_view column) const
{
return find_max<T>(column, all());
}
......@@ -730,7 +750,7 @@ class category
/// @param cond The condition to search for
/// @return The value found or the maximum value for the type
template <typename T, std::enable_if_t<std::is_arithmetic_v<T>, int> = 0>
T find_min(const char *column, condition &&cond) const
T find_min(std::string_view column, condition &&cond) const
{
T result = std::numeric_limits<T>::max();
......@@ -748,7 +768,7 @@ class category
/// @param column The column to use for the value
/// @return The value found or the maximum value for the type
template <typename T, std::enable_if_t<std::is_arithmetic_v<T>, int> = 0>
T find_min(const char *column) const
T find_min(std::string_view column) const
{
return find_min<T>(column, all());
}
......@@ -756,8 +776,17 @@ class category
/// @brief Return whether a row exists that matches condition @a cond
/// @param cond The condition to match
/// @return True if a row exists
[[deprecated("Use contains instead")]]
bool exists(condition &&cond) const
{
return contains(std::move(cond));
}
/// @brief Return whether a row exists that matches condition @a cond
/// @param cond The condition to match
/// @return True if a row exists
bool contains(condition &&cond) const
{
bool result = false;
if (cond)
......@@ -922,6 +951,11 @@ class category
{ return prefix + std::to_string(nr + 1); });
}
/// @brief Generate a new, unique value for a item named @a tag
/// @param tag The name of the item
/// @return a new unique value
std::string get_unique_value(std::string_view tag);
// --------------------------------------------------------------------
/// \brief Update a single column named @a tag in the rows that match \a cond to value \a value
......
......@@ -934,6 +934,16 @@ struct key
{
}
/**
* @brief Construct a new key object using @a itemTag as name
*
* @param itemTag
*/
explicit key(std::string_view itemTag)
: m_item_tag(itemTag)
{
}
key(const key &) = delete;
key &operator=(const key &) = delete;
......
......@@ -556,7 +556,7 @@ struct item_handle::item_value_as<T, std::enable_if_t<std::is_arithmetic_v<T> an
auto txt = ref.text();
if (txt.empty())
if (ref.empty())
result = 1;
else
{
......
......@@ -562,22 +562,23 @@ class conditional_iterator_proxy
reference operator*()
{
return *mBegin;
return *m_begin;
}
pointer operator->()
{
return &*mBegin;
m_current = *m_begin;
return &m_current;
}
conditional_iterator_impl &operator++()
{
while (mBegin != mEnd)
while (m_begin != m_end)
{
if (++mBegin == mEnd)
if (++m_begin == m_end)
break;
if (m_condition->operator()(mBegin))
if (m_condition->operator()(m_begin))
break;
}
......@@ -591,18 +592,22 @@ class conditional_iterator_proxy
return result;
}
bool operator==(const conditional_iterator_impl &rhs) const { return mBegin == rhs.mBegin; }
bool operator!=(const conditional_iterator_impl &rhs) const { return mBegin != rhs.mBegin; }
bool operator==(const conditional_iterator_impl &rhs) const { return m_begin == rhs.m_begin; }
bool operator!=(const conditional_iterator_impl &rhs) const { return m_begin != rhs.m_begin; }
bool operator==(const row_iterator &rhs) const { return m_begin == rhs; }
bool operator!=(const row_iterator &rhs) const { return m_begin != rhs; }
template <typename IRowType, typename... ITs>
bool operator==(const iterator_impl<IRowType, ITs...> &rhs) const { return mBegin == rhs; }
bool operator==(const iterator_impl<IRowType, ITs...> &rhs) const { return m_begin == rhs; }
template <typename IRowType, typename... ITs>
bool operator!=(const iterator_impl<IRowType, ITs...> &rhs) const { return mBegin != rhs; }
bool operator!=(const iterator_impl<IRowType, ITs...> &rhs) const { return m_begin != rhs; }
private:
CategoryType *mCat;
base_iterator mBegin, mEnd;
CategoryType *m_cat;
base_iterator m_begin, m_end;
value_type m_current;
const condition *m_condition;
};
......@@ -673,13 +678,13 @@ iterator_proxy<Category, Ts...>::iterator_proxy(Category &cat, row_iterator pos,
template <typename Category, typename... Ts>
conditional_iterator_proxy<Category, Ts...>::conditional_iterator_impl::conditional_iterator_impl(
Category &cat, row_iterator pos, const condition &cond, const std::array<uint16_t, N> &cix)
: mCat(&cat)
, mBegin(pos, cix)
, mEnd(cat.end(), cix)
: m_cat(&cat)
, m_begin(pos, cix)
, m_end(cat.end(), cix)
, m_condition(&cond)
{
if (m_condition == nullptr or m_condition->empty())
mBegin = mEnd;
m_begin = m_end;
}
template <typename Category, typename... Ts>
......
......@@ -202,7 +202,7 @@ struct category_validator
}
/// @brief Add item_validator @a v to the list of item validators
void addItemValidator(item_validator &&v);
void add_item_validator(item_validator &&v);
/// @brief Return the item_validator for item @a tag, may return nullptr
const item_validator *get_validator_for_item(std::string_view tag) const;
......
......@@ -672,7 +672,7 @@ void category::set_validator(const validator *v, datablock &db)
std::ostringstream msg;
msg << "Cannot construct index since the key field" << (missing.size() > 1 ? "s" : "") << " "
<< cif::join(missing, ", ") << " in " << m_name << " " << (missing.size() == 1 ? "is" : "are") << " missing\n";
throw std::runtime_error(msg.str());
throw missing_key_error(msg.str(), *missing.begin());
}
}
}
......@@ -860,7 +860,7 @@ bool category::validate_links() const
auto cond = get_parents_condition(r, *parent);
if (not cond)
continue;
if (not parent->exists(std::move(cond)))
if (not parent->contains(std::move(cond)))
{
++missing;
if (VERBOSE and first_missing_rows.size() < 5)
......@@ -997,7 +997,7 @@ bool category::has_children(row_handle r) const
for (auto &&[childCat, link] : m_child_links)
{
if (not childCat->exists(get_children_condition(r, *childCat)))
if (not childCat->contains(get_children_condition(r, *childCat)))
continue;
result = true;
......@@ -1013,7 +1013,7 @@ bool category::has_parents(row_handle r) const
for (auto &&[parentCat, link] : m_parent_links)
{
if (not parentCat->exists(get_parents_condition(r, *parentCat)))
if (not parentCat->contains(get_parents_condition(r, *parentCat)))
continue;
result = true;
......@@ -1214,7 +1214,7 @@ void category::erase_orphans(condition &&cond, category &parent)
if (not cond(r))
continue;
if (parent.exists(get_parents_condition(r, parent)))
if (parent.contains(get_parents_condition(r, parent)))
continue;
if (VERBOSE > 1)
......@@ -1263,7 +1263,7 @@ std::string category::get_unique_id(std::function<std::string(int)> generator)
{
for (;;)
{
if (not exists(key(id_tag) == result))
if (not contains(key(id_tag) == result))
break;
result = generator(static_cast<int>(m_last_unique_num++));
......@@ -1273,6 +1273,36 @@ std::string category::get_unique_id(std::function<std::string(int)> generator)
return result;
}
std::string category::get_unique_value(std::string_view tag)
{
std::string result;
if (m_validator and m_cat_validator)
{
auto iv = m_cat_validator->get_validator_for_item(tag);
if (iv and iv->m_type and iv->m_type->m_primitive_type == DDL_PrimitiveType::Numb)
{
uint64_t v = find_max<uint64_t>(tag);
result = std::to_string(v + 1);
}
}
if (result.empty())
{
// brain-dead implementation
for (size_t ix = 0; ix < size(); ++ix)
{
// result = m_name + "-" + std::to_string(ix);
result = cif_id_for_number(ix);
if (not contains(key(tag) == result))
break;
}
}
return result;
}
void category::update_value(const std::vector<row_handle> &rows, std::string_view tag, std::string_view value)
{
using namespace std::literals;
......@@ -1376,7 +1406,7 @@ void category::update_value(const std::vector<row_handle> &rows, std::string_vie
check = std::move(check) && key(ck) == parent[pk].text();
}
if (childCat->exists(std::move(check))) // phew..., narrow escape
if (childCat->contains(std::move(check))) // phew..., narrow escape
continue;
// create the actual copy, if we can...
......@@ -1405,7 +1435,7 @@ void category::update_value(const std::vector<row_handle> &rows, std::string_vie
void category::update_value(row *row, uint16_t column, std::string_view value, bool updateLinked, bool validate)
{
// make sure we have an index, if possible
if (m_index == nullptr and m_cat_validator != nullptr)
if ((updateLinked or validate) and m_index == nullptr and m_cat_validator != nullptr)
m_index = new category_index(*this);
auto &col = m_columns[column];
......@@ -1444,7 +1474,7 @@ void category::update_value(row *row, uint16_t column, std::string_view value, b
if (not value.empty())
row->append(column, { value });
if (reinsert)
if (reinsert and m_index != nullptr)
m_index->insert(*this, row);
// see if we need to update any child categories that depend on this value
......
......@@ -87,7 +87,7 @@ class dictionary_parser : public parser
error("Undefined category '" + iv.first);
for (auto &v : iv.second)
const_cast<category_validator *>(cv)->addItemValidator(std::move(v));
const_cast<category_validator *>(cv)->add_item_validator(std::move(v));
}
// check all item validators for having a typeValidator
......
......@@ -1783,7 +1783,7 @@ atom &structure::emplace_atom(atom &&atom)
std::string symbol = atom.get_property("type_symbol");
using namespace cif::literals;
if (not atom_type.exists("symbol"_key == symbol))
if (not atom_type.contains("symbol"_key == symbol))
atom_type.emplace({ { "symbol", symbol } });
return m_atoms.emplace_back(std::move(atom));
......@@ -1969,7 +1969,7 @@ void structure::change_residue(residue &res, const std::string &newCompound,
// create rest
auto &chemComp = m_db["chem_comp"];
if (not chemComp.exists(key("id") == newCompound))
if (not chemComp.contains(key("id") == newCompound))
{
chemComp.emplace({{"id", newCompound},
{"name", compound->name()},
......@@ -2702,7 +2702,7 @@ void structure::cleanup_empty_categories()
for (auto chemComp : chem_comp)
{
std::string compID = chemComp["id"].as<std::string>();
if (atomSite.exists("label_comp_id"_key == compID or "auth_comp_id"_key == compID))
if (atomSite.contains("label_comp_id"_key == compID or "auth_comp_id"_key == compID))
continue;
obsoleteChemComps.push_back(chemComp);
......@@ -2719,7 +2719,7 @@ void structure::cleanup_empty_categories()
for (auto entity : entities)
{
std::string entityID = entity["id"].as<std::string>();
if (atomSite.exists("label_entity_id"_key == entityID))
if (atomSite.contains("label_entity_id"_key == entityID))
continue;
obsoleteEntities.push_back(entity);
......
......@@ -183,7 +183,7 @@ bool is_valid_pdbx_file(const file &file, std::string_view dictionary)
"label_asym_id"_key == asym_id and
"label_seq_id"_key == seq_id and not std::move(cond);
if (atom_site.exists(std::move(cond)))
if (atom_site.contains(std::move(cond)))
throw validation_error("An atom_site record exists that has no parent in the poly seq scheme categories");
}
}
......
......@@ -233,7 +233,7 @@ void item_validator::operator()(std::string_view value) const
// --------------------------------------------------------------------
void category_validator::addItemValidator(item_validator &&v)
void category_validator::add_item_validator(item_validator &&v)
{
if (v.m_mandatory)
m_mandatory_fields.insert(v.m_tag);
......
......@@ -568,7 +568,7 @@ _test.value
auto &test = db["test"];
REQUIRE(test.size() == 5);
REQUIRE(test.exists("value"_key == cif::null));
REQUIRE(test.contains("value"_key == cif::null));
REQUIRE(test.find("value"_key == cif::null).size() == 2);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment