#include "comdelvalidator.h" namespace domain { std::vector ComdelValidator::validateSchema(Schema &schema, ValidationContext context) { std::vector errors; context.instance = nullptr; context.attribute = nullptr; for(auto &inst: schema.instances) { auto *instance = dynamic_cast(inst); if(instance) { auto result = validateComponent(instance, context); errors.insert(errors.end(), result.begin(), result.end()); } } return errors; } std::vector ComdelValidator::validateComponent(ComponentInstance *instance, ValidationContext context) { std::vector errors; context.instance = instance; context.attributes.clear(); for(auto &attribute: instance->attributes) { context.attributes[attribute->name] = attribute->value; } for(auto &rule: instance->component.getRules()) { auto result = validateRule(rule, context); if(result) { errors.push_back(*result); } } for(auto &attribute: instance->attributes) { auto result = validateAttribute(attribute, context); errors.insert(errors.end(), result.begin(), result.end()); } return errors; } std::vector ComdelValidator::validateAttribute(InstanceAttribute *attribute, ValidationContext context) { std::vector errors; if(attribute->attribute.getPopup()) { Popup popup = *attribute->attribute.getPopup(); context.attribute = attribute; context.attributes = std::map{{attribute->name, attribute->value}}; for(auto &rule: popup.getRules()) { auto result = validateRule(rule, context); if(result) { errors.push_back(*result); } } } return errors; } std::optional ComdelValidator::validateRule(Rule rule, ValidationContext context) { RuleContext ruleContext; ruleContext.addressSpaces = context.addressSpaces; ruleContext.attributes = context.attributes; ruleContext.function = callbacks; auto action = rule.evaluate(ruleContext); if (action) { std::string message = this->populateMessage(action->getMessage(), context); return ValidationError{context.instance, context.attribute, action->getType(), message}; } return nullopt; } std::string ComdelValidator::populateMessage(string source, ValidationContext context) { for(auto &[key, value]: context.attributes) { source = replacePlaceholder(source, key, value); } return source; } string ComdelValidator::replacePlaceholder(string source, string key, Value value) { key = "{" + key + "}"; auto placeholderValue = value.string(); auto found = source.find(key); while(found != string::npos) { source.replace(found, key.length(), placeholderValue); found = source.find(key); } return source; } }