Mantid
Loading...
Searching...
No Matches
CompositeValidator.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
8#include <algorithm>
9#include <sstream>
10#include <unordered_set>
11
12using namespace Mantid::Kernel;
13
14namespace Mantid::Kernel {
17 : IValidator(), m_children(), m_relation(relation) {}
18
21
27std::vector<std::string> CompositeValidator::allowedValues() const {
28 std::unordered_set<std::string> elem_unique;
29 std::unordered_multiset<std::string> elem_all;
30 // how many validators return non-empty list of allowed values
31 int n_combinations(0);
32 for (const auto &itr : m_children) {
33 std::vector<std::string> subs = itr->allowedValues();
34 if (subs.empty())
35 continue;
36 elem_unique.insert(subs.begin(), subs.end());
37 elem_all.insert(subs.begin(), subs.end());
38 n_combinations++;
39 }
40 // empty or single set of allowed values
41 if (n_combinations < 2)
42 return std::vector<std::string>(elem_unique.begin(), elem_unique.end());
43 // there is more then one combination and we have to identify its union;
44 for (const auto &its : elem_unique) {
45 auto im = elem_all.find(its);
46 elem_all.erase(im);
47 }
48 std::unordered_set<std::string> rez;
49 for (const auto &im : elem_all) {
50 rez.insert(im);
51 }
52 return std::vector<std::string>(rez.begin(), rez.end());
53}
54
60 std::shared_ptr<CompositeValidator> copy = std::make_shared<CompositeValidator>(m_relation);
61 for (const auto &itr : m_children) {
62 copy->add(itr->clone());
63 }
64 return copy;
65}
66
70void CompositeValidator::add(const Kernel::IValidator_sptr &child) { m_children.emplace_back(child); }
71
76std::string CompositeValidator::check(const boost::any &value) const {
77 switch (m_relation) {
79 return checkAll(value);
81 return checkAny(value);
82 default:
83 throw std::runtime_error("Unimplemented composite validator relation");
84 }
85}
86
87std::string CompositeValidator::checkAll(const boost::any &value) const {
88 for (const auto &validator : m_children) {
89 const auto error = validator->check(value);
90 // exit on the first error, to avoid passing doing more tests on invalid
91 // objects that could fail
92 if (!error.empty())
93 return error;
94 }
95 // there were no errors
96 return "";
97}
98
99std::string CompositeValidator::checkAny(const boost::any &value) const {
100 std::stringstream errorStream;
101
102 // Lambda to check if a validator is valid. If it is not valid then
103 // capture its error message to a stream so we can potentially print it out
104 // to the user if required.
105 const auto checkIfValid = [&errorStream, &value](const IValidator_sptr &validator) {
106 const auto errorMessage = validator->check(value);
107 if (errorMessage.empty()) {
108 return true;
109 } else {
110 // capture error message to possibly later.
111 errorStream << errorMessage << "\n";
112 return false;
113 }
114 };
115
116 const auto valid = std::any_of(m_children.begin(), m_children.end(), checkIfValid);
117 return buildErrorMessage(valid, errorStream.str());
118}
119
129std::string CompositeValidator::buildErrorMessage(const bool valid, const std::string &errors) const {
130 if (!valid) {
131 return "Invalid property. You must statisfy one of the following "
132 "conditions:\n" +
133 errors;
134 } else {
135 // there were no errors
136 return "";
137 }
138}
139
140} // namespace Mantid::Kernel
double value
The value of the point.
Definition: FitMW.cpp:51
double error
Definition: IndexPeaks.cpp:133
void add()
Add a validator based on a template type.
std::string buildErrorMessage(const bool valid, const std::string &errors) const
build an error message for OR relations
IValidator_sptr clone() const override
Clones this and the children into a new Validator.
std::string check(const boost::any &value) const override
Verify the value with the child validators.
CompositeValidator(const CompositeRelation &relation=CompositeRelation::AND)
Default constructor.
std::string checkAll(const boost::any &value) const
Verify the value with the child validators with logical "and" relationship.
std::vector< std::string > allowedValues() const override
Return the instersection of allowed values from children.
const CompositeRelation m_relation
Store what relationship child validators have.
std::list< IValidator_sptr > m_children
A container for the child validators.
std::string checkAny(const boost::any &value) const
Verify the value with the child validators with logical "or" relationship.
IValidator is the basic interface for all validators for properties.
Definition: IValidator.h:43
CompositeRelation
A composite validator that can combine any 2+ arbitrary validators together.
std::shared_ptr< IValidator > IValidator_sptr
A shared_ptr to an IValidator.
Definition: IValidator.h:26