mirror of
https://github.com/PDB-REDO/libcifpp.git
synced 2026-06-04 13:54:25 +08:00
Update validation code, added pdbx_item_enumeration check and test case-sensitive when required.
This commit is contained in:
@@ -196,7 +196,7 @@ class validation_exception : public std::runtime_error
|
||||
public:
|
||||
// Constructors
|
||||
/// @cond
|
||||
|
||||
|
||||
validation_exception(validation_error err)
|
||||
: validation_exception(make_error_code(err))
|
||||
{
|
||||
@@ -337,7 +337,7 @@ struct item_validator
|
||||
std::string m_item_name; ///< The item name
|
||||
bool m_mandatory; ///< Flag indicating this item is mandatory
|
||||
const type_validator *m_type; ///< The type for this item
|
||||
cif::iset m_enums; ///< If filled, the set of allowed values
|
||||
std::set<std::string> m_enums; ///< If filled, the set of allowed values
|
||||
std::string m_default; ///< If filled, a default value for this item
|
||||
std::string m_category; ///< The category this item_validator belongs to
|
||||
std::vector<item_alias> m_aliases; ///< The aliases for this item
|
||||
@@ -502,15 +502,29 @@ class validator
|
||||
/// @brief Bottleneck function to report an error in validation
|
||||
void report_error(std::error_code ec, bool fatal = true) const;
|
||||
|
||||
/// @brief Bottleneck function to report an error in validation
|
||||
void report_error(validation_error err, std::string value, std::string_view category,
|
||||
std::string_view item, bool fatal = true) const
|
||||
{
|
||||
report_error(make_error_code(err), value, category, item, fatal);
|
||||
}
|
||||
|
||||
/// @brief Bottleneck function to report an error in validation
|
||||
void report_error(validation_error err, std::string_view category,
|
||||
std::string_view item, bool fatal = true) const
|
||||
{
|
||||
report_error(make_error_code(err), category, item, fatal);
|
||||
report_error(make_error_code(err), "", category, item, fatal);
|
||||
}
|
||||
|
||||
/// @brief Bottleneck function to report an error in validation
|
||||
void report_error(std::error_code ec, std::string_view category,
|
||||
std::string_view item, bool fatal = true) const
|
||||
{
|
||||
report_error(ec, "", category, item, fatal);
|
||||
}
|
||||
|
||||
/// @brief Bottleneck function to report an error in validation
|
||||
void report_error(std::error_code ec, std::string value, std::string_view category,
|
||||
std::string_view item, bool fatal = true) const;
|
||||
|
||||
/// @brief Write out the audit_conform data for this validator
|
||||
|
||||
3825
rsrc/mmcif_pdbx.dic
3825
rsrc/mmcif_pdbx.dic
File diff suppressed because it is too large
Load Diff
@@ -749,16 +749,38 @@ void category::set_validator(const validator *v, datablock &db)
|
||||
|
||||
bool number = type->m_primitive_type == DDL_PrimitiveType::Numb;
|
||||
if (number)
|
||||
continue;
|
||||
|
||||
for (auto row = m_head; row != nullptr; row = row->m_next)
|
||||
{
|
||||
if (cix >= row->size() or row->operator[](cix).empty())
|
||||
continue;
|
||||
for (auto row = m_head; row != nullptr; row = row->m_next)
|
||||
{
|
||||
if (cix >= row->size() or row->operator[](cix).empty())
|
||||
continue;
|
||||
|
||||
item_value &v = row->operator[](cix);
|
||||
if (v.is_number())
|
||||
v = v.str();
|
||||
item_value &v = row->operator[](cix);
|
||||
if (not v.is_number())
|
||||
{
|
||||
// Try cast the value to a number and throw in case of failure
|
||||
try
|
||||
{
|
||||
v.cast_to_int();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
v.cast_to_float();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (auto row = m_head; row != nullptr; row = row->m_next)
|
||||
{
|
||||
if (cix >= row->size() or row->operator[](cix).empty())
|
||||
continue;
|
||||
|
||||
item_value &v = row->operator[](cix);
|
||||
if (v.is_number())
|
||||
v = v.str();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -890,11 +912,13 @@ bool category::is_valid() const
|
||||
seen = true;
|
||||
std::error_code ec;
|
||||
|
||||
iv->validate_value(*ri->get(cix), ec);
|
||||
auto &v = *ri->get(cix);
|
||||
|
||||
iv->validate_value(v, ec);
|
||||
|
||||
if (ec != std::errc{})
|
||||
{
|
||||
m_validator->report_error(ec, m_name, m_items[cix].m_name, false);
|
||||
m_validator->report_error(ec, v.str(), m_name, m_items[cix].m_name, false);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
*/
|
||||
|
||||
#include "cif++/cif++.hpp"
|
||||
#include "cif++/text.hpp"
|
||||
#include "cif++/validate.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
#include <exception>
|
||||
@@ -103,7 +105,19 @@ class dictionary_parser : public parser
|
||||
error("Undefined category '" + iv.first);
|
||||
|
||||
for (auto &v : iv.second)
|
||||
{
|
||||
// enums, make lower case if needed
|
||||
auto tv = v.m_type;
|
||||
if (tv and tv->m_primitive_type == DDL_PrimitiveType::UChar)
|
||||
{
|
||||
std::set<std::string> es;
|
||||
for (auto &e : v.m_enums)
|
||||
es.emplace(cif::to_lower_copy(e));
|
||||
std::swap(es, v.m_enums);
|
||||
}
|
||||
|
||||
const_cast<category_validator *>(cv)->add_item_validator(std::move(v));
|
||||
}
|
||||
}
|
||||
|
||||
// check all item validators for having a typeValidator
|
||||
@@ -275,9 +289,11 @@ class dictionary_parser : public parser
|
||||
if (typeCode.has_value())
|
||||
tv = m_validator.get_validator_for_type(*typeCode);
|
||||
|
||||
iset ess;
|
||||
std::set<std::string> ess;
|
||||
for (auto e : dict["item_enumeration"])
|
||||
ess.insert(e["value"].get<std::string>());
|
||||
for (auto e : dict["pdbx_item_enumeration"])
|
||||
ess.insert(e["value"].get<std::string>());
|
||||
|
||||
std::string defaultValue;
|
||||
if (auto &cat = dict["item_default"]; not cat.empty())
|
||||
|
||||
@@ -2193,7 +2193,7 @@ void PDBFileParser::ParseRemarks()
|
||||
if (std::regex_match(line, m, rx))
|
||||
{
|
||||
models[0] = std::stoi(m[1].str());
|
||||
models[1] = stoi(m[2].str());
|
||||
models[1] = std::stoi(m[2].str());
|
||||
}
|
||||
else
|
||||
headerSeen = cif::contains(line, "RES C SSSEQI");
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "cif++/validate.hpp"
|
||||
|
||||
#include "cif++/cif++.hpp"
|
||||
#include "cif++/text.hpp"
|
||||
|
||||
#include <cassert>
|
||||
#include <charconv>
|
||||
@@ -245,8 +246,17 @@ bool item_validator::validate_value(const item_value &value, std::error_code &ec
|
||||
ec = make_error_code(validation_error::value_does_not_match_rx);
|
||||
}
|
||||
|
||||
if (ec == std::errc{} and not m_enums.empty() and m_enums.count(value.str()) == 0)
|
||||
ec = make_error_code(validation_error::value_is_not_in_enumeration_list);
|
||||
if (ec == std::errc{} and not m_enums.empty())
|
||||
{
|
||||
bool valid =
|
||||
m_type->m_primitive_type == DDL_PrimitiveType::UChar ? //
|
||||
m_enums.contains(cif::to_lower_copy(value.sv()))
|
||||
: //
|
||||
m_enums.contains(std::string{ value.sv() });
|
||||
|
||||
if (not valid)
|
||||
ec = make_error_code(validation_error::value_is_not_in_enumeration_list);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -436,8 +446,8 @@ void validator::report_error(std::error_code ec, bool fatal) const
|
||||
std::cerr << ec.message() << '\n';
|
||||
}
|
||||
|
||||
void validator::report_error(std::error_code ec, std::string_view category,
|
||||
std::string_view item, bool fatal) const
|
||||
void validator::report_error(std::error_code ec, std::string value,
|
||||
std::string_view category, std::string_view item, bool fatal) const
|
||||
{
|
||||
if (m_strict or fatal)
|
||||
{
|
||||
@@ -448,10 +458,19 @@ void validator::report_error(std::error_code ec, std::string_view category,
|
||||
}
|
||||
|
||||
if (VERBOSE > 0)
|
||||
std::cerr << ec.message()
|
||||
<< "; category: " << std::quoted(category)
|
||||
<< " item: " << std::quoted(item)
|
||||
<< '\n';
|
||||
{
|
||||
if (value.empty())
|
||||
std::cerr << ec.message()
|
||||
<< "; category: " << std::quoted(category)
|
||||
<< " item: " << std::quoted(item)
|
||||
<< '\n';
|
||||
else
|
||||
std::cerr << ec.message()
|
||||
<< "; value: " << std::quoted(value)
|
||||
<< "; category: " << std::quoted(category)
|
||||
<< " item: " << std::quoted(item)
|
||||
<< '\n';
|
||||
}
|
||||
}
|
||||
|
||||
void validator::fill_audit_conform(category &audit_conform) const
|
||||
|
||||
@@ -443,8 +443,6 @@ TEST_CASE("test_alternates_1")
|
||||
const std::filesystem::path example(gTestDir / ".." / "examples" / "1cbs.cif.gz");
|
||||
cif::file file(example.string());
|
||||
|
||||
auto &db = file.front();
|
||||
|
||||
cif::mm::structure s(file);
|
||||
|
||||
for (auto atom : s.atoms())
|
||||
|
||||
Reference in New Issue
Block a user