9#include <boost/circular_buffer.hpp>
10#include <boost/fusion/container.hpp>
93 template<
typename... ACCESSORTYPES>
95 const std::string& errorMessage,
const std::function<
bool(
void)>& isValidFunction, ACCESSORTYPES&... accessors);
101 template<std::ranges::input_range R>
103 void add(
const std::string& errorMessage,
const std::function<
bool(
void)>& isValidFunction,
const R& accessors);
113 template<
typename UserType,
template<
typename>
typename Accessor>
114 void setFallback(Accessor<UserType>& accessor, UserType value);
116 template<
typename UserType,
template<
typename>
typename Accessor>
117 void setFallback(Accessor<UserType>& accessor, std::vector<UserType> value);
124 void setErrorFunction(
const std::function<
void(
const std::string&)>& errorFunction);
145 bool validate(
const ChimeraTK::TransferElementID& change);
194 template<
typename UserType,
template<
typename>
typename Accessor>
207 template<
typename UserType,
template<
typename>
typename Accessor>
241 Validator*
addValidator(
const std::function<
bool(
void)>& isValidFunction,
const std::string& errorMessage);
243 template<
typename UserType,
template<
typename>
typename Accessor>
250 std::map<ChimeraTK::TransferElementID, std::shared_ptr<VariableBase>>
_variableMap;
253 std::map<ChimeraTK::TransferElementID, std::vector<Validator*>>
_validatorMap;
269 template<
typename UserType,
template<
typename>
typename Accessor>
277 template<
typename... ACCESSORTYPES>
279 const std::string& errorMessage,
const std::function<
bool(
void)>& isValidFunction, ACCESSORTYPES&... accessors) {
280 boost::fusion::list<ACCESSORTYPES&...> accessorList{accessors...};
281 static_assert(boost::fusion::size(accessorList) > 0,
"Must specify at least one accessor!");
282 assert(isValidFunction !=
nullptr);
284 auto* validator =
addValidator(isValidFunction, errorMessage);
292 template<std::ranges::input_range R>
295 const std::string& errorMessage,
const std::function<
bool(
void)>& isValidFunction,
const R& accessors) {
296 assert(isValidFunction !=
nullptr);
299 _validators.emplace_back(isValidFunction, errorMessage);
302 for(
auto& accessor : accessors) {
310 template<
typename UserType,
template<
typename>
typename Accessor>
313 auto pv = std::dynamic_pointer_cast<Variable<UserType, Accessor>>(
_variableMap.at(accessor.getId()));
314 assert(pv !=
nullptr);
315 if(pv->fallbackValue.size() != 1) {
316 throw ChimeraTK::logic_error(
317 "UserInputValidator::setFallback() with scalar value called for array-typed accessor '" + accessor.getName() +
320 pv->fallbackValue[0] = value;
325 template<
typename UserType,
template<
typename>
typename Accessor>
328 auto pv = std::dynamic_pointer_cast<Variable<UserType, Accessor>>(
_variableMap.at(accessor.getId()));
329 assert(pv !=
nullptr);
330 if(pv->fallbackValue.size() != value.size()) {
331 throw ChimeraTK::logic_error(
332 "UserInputValidator::setFallback() with called with mismatching array length for accessor '" +
333 accessor.getName() +
"'.");
335 pv->fallbackValue = value;
339 template<
typename UserType,
template<
typename>
typename Accessor>
349 _variableMap[accessor.getId()] = std::make_shared<Variable<UserType, Accessor>>(accessor);
352 auto hook = boost::dynamic_pointer_cast<AccessorHook>(accessor.getImpl());
354 hook->onAddValidator(*
this);
360 template<
typename UserType,
template<
typename>
typename Accessor>
362 : accessor(validatedAccessor) {
366 throw ChimeraTK::logic_error(
"UserInputValidator can only be used with push-type inputs.");
380 template<
typename UserType,
template<
typename>
typename Accessor>
382 if(type == RejectionType::downstream && !lastAcceptedValue.empty()) {
383 lastAcceptedValue.pop_back();
386 if(lastAcceptedValue.empty()) {
387 accessor = fallbackValue[0];
390 accessor = lastAcceptedValue.back()[0];
394 if(lastAcceptedValue.empty()) {
395 accessor = fallbackValue;
398 accessor = lastAcceptedValue.back();
403 auto hook = boost::dynamic_pointer_cast<AccessorHook>(accessor.getImpl());
408 if(accessor.isWriteable()) {
414 template<
typename UserType,
template<
typename>
typename Accessor>
417 auto savedValue = std::vector<UserType>(1);
418 savedValue[0] = accessor;
419 lastAcceptedValue.push_back(savedValue);
422 auto savedValue = std::vector<UserType>(accessor.getNElements());
423 savedValue = accessor;
424 lastAcceptedValue.push_back(savedValue);
428 auto hook = boost::dynamic_pointer_cast<AccessorHook>(accessor.getImpl());
435 template<
typename UserType,
template<
typename>
typename Accessor>
437 historyLength = 3 * size;
438 lastAcceptedValue.set_capacity(historyLength);
LifeCycleState getLifeCycleState() const
Get the current LifeCycleState of the application.
static Application & getInstance()
Obtain instance of the application.
void addTag(const std::string &tag)
Add a tag to all Application-type nodes inside this group.
Base class for ApplicationModule and DeviceModule, to have a common interface for these module types.
Accessor for scalar variables (i.e.
Class describing a node of a variable network.
InvalidityTracer application module.
@ initialisation
Initialisation phase including ApplicationModule::prepare().
Logger::StreamProxy logger(Logger::Severity severity, std::string context)
Convenience function to obtain the logger stream.