Refactored function validators
This commit is contained in:
parent
e7fd7df154
commit
05fa2abbb0
|
@ -1,3 +1,4 @@
|
||||||
|
#include <algorithm>
|
||||||
#include "addressspace.h"
|
#include "addressspace.h"
|
||||||
|
|
||||||
namespace domain {
|
namespace domain {
|
||||||
|
|
|
@ -61,7 +61,7 @@ std::optional<ValidationError> ComdelValidator::validateRule(Rule rule, Validati
|
||||||
RuleContext ruleContext;
|
RuleContext ruleContext;
|
||||||
ruleContext.addressSpaces = context.addressSpaces;
|
ruleContext.addressSpaces = context.addressSpaces;
|
||||||
ruleContext.attributes = context.attributes;
|
ruleContext.attributes = context.attributes;
|
||||||
ruleContext.function = callbacks;
|
ruleContext.function = validators;
|
||||||
auto action = rule.evaluate(ruleContext);
|
auto action = rule.evaluate(ruleContext);
|
||||||
if (action) {
|
if (action) {
|
||||||
std::string message = this->populateMessage(action->getMessage(), context);
|
std::string message = this->populateMessage(action->getMessage(), context);
|
||||||
|
|
|
@ -29,14 +29,19 @@ public:
|
||||||
std::vector<ValidationError> validateAttribute(InstanceAttribute *attribute, ValidationContext context);
|
std::vector<ValidationError> validateAttribute(InstanceAttribute *attribute, ValidationContext context);
|
||||||
std::optional<ValidationError> validateRule(Rule rule, ValidationContext context);
|
std::optional<ValidationError> validateRule(Rule rule, ValidationContext context);
|
||||||
|
|
||||||
ComdelValidator(std::map<std::string, FunctionCallback> callbacks): callbacks(callbacks) {}
|
ComdelValidator(std::vector<FunctionValidator*> validators) {
|
||||||
|
for(auto* validator: validators) {
|
||||||
|
validator->clear();
|
||||||
|
this->validators.insert(std::make_pair(validator->getName(), validator));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::map<std::string, FunctionCallback> callbacks;
|
std::map<std::string, FunctionValidator*> validators;
|
||||||
|
|
||||||
std::string populateMessage(string basicString, ValidationContext context);
|
std::string populateMessage(string message, ValidationContext context);
|
||||||
|
|
||||||
string replacePlaceholder(string basicString, const string basicString1, Value value);
|
string replacePlaceholder(string message, const string name, Value value);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,45 +1,138 @@
|
||||||
|
#include <map>
|
||||||
#include "functionsignature.h"
|
#include "functionsignature.h"
|
||||||
|
|
||||||
namespace domain {
|
namespace domain {
|
||||||
|
|
||||||
FunctionSignature add(std::string name, std::vector<Value::ValueType> types, FunctionCallback callback) {
|
class DivisibleValidator: public FunctionValidator {
|
||||||
return {name, types, callback};
|
public:
|
||||||
|
DivisibleValidator(): FunctionValidator("divisible", {Value::INT, Value::INT}) {}
|
||||||
|
|
||||||
|
bool validate(std::vector<Value> values) override {
|
||||||
|
if(validateSignature(values)) {
|
||||||
|
long long first = values[0].asInt();
|
||||||
|
long long second = values[1].asInt();
|
||||||
|
return (first % second) == 0;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
void clear() override {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class LessThenValidator: public FunctionValidator {
|
||||||
|
public:
|
||||||
|
LessThenValidator(): FunctionValidator("less_then", {Value::INT, Value::INT}) {}
|
||||||
|
|
||||||
|
bool validate(std::vector<Value> values) override {
|
||||||
|
if(validateSignature(values)) {
|
||||||
|
long long first = values[0].asInt();
|
||||||
|
long long second = values[1].asInt();
|
||||||
|
return first < second;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
void clear() override {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class GreaterThenValidator: public FunctionValidator {
|
||||||
|
public:
|
||||||
|
GreaterThenValidator(): FunctionValidator("greater_then", {Value::INT, Value::INT}) {}
|
||||||
|
|
||||||
|
bool validate(std::vector<Value> values) override {
|
||||||
|
if(validateSignature(values)) {
|
||||||
|
long long first = values[0].asInt();
|
||||||
|
long long second = values[1].asInt();
|
||||||
|
return first > second;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
void clear() override {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class ContainsAddressValidator: public FunctionValidator {
|
||||||
|
public:
|
||||||
|
ContainsAddressValidator(): FunctionValidator("contains_address", {Value::ADDRESS_SPACE, Value::INT}) {}
|
||||||
|
|
||||||
|
bool validate(std::vector<Value> values) override {
|
||||||
|
if(validateSignature(values)) {
|
||||||
|
AddressSpace space = values[0].asAddressSpace();
|
||||||
|
long long address = values[1].asInt();
|
||||||
|
return space.contains(address);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
void clear() override {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class ContainsValidator: public FunctionValidator {
|
||||||
|
public:
|
||||||
|
ContainsValidator(): FunctionValidator("contains", {Value::ADDRESS_SPACE, Value::INT, Value::INT}) {}
|
||||||
|
|
||||||
|
bool validate(std::vector<Value> values) override {
|
||||||
|
if(validateSignature(values)) {
|
||||||
|
AddressSpace space = values[0].asAddressSpace();
|
||||||
|
long long start = values[1].asInt();
|
||||||
|
long long size = values[1].asInt();
|
||||||
|
return space.contains(start, start + size);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
void clear() override {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class UniqueValidator: public FunctionValidator {
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::map<std::string, std::vector<std::pair<long long int, long long int>>> spaces;
|
||||||
|
|
||||||
|
bool overlaps(long long int start1, long long int end1, long long int start2, long long int end2) {
|
||||||
|
return std::max((long long int)0, std::min(end1, end2) - std::max(start1, start2)) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
UniqueValidator(): FunctionValidator("unique", {Value::ADDRESS_SPACE, Value::INT, Value::INT}) {}
|
||||||
|
|
||||||
|
bool validate(std::vector<Value> values) override {
|
||||||
|
if(validateSignature(values)) {
|
||||||
|
std::string space = values[0].asAddressSpace().getName();
|
||||||
|
long long int start = values[1].asInt();
|
||||||
|
long long int end = start + values[2].asInt();
|
||||||
|
if(spaces.count(space) == 0) {
|
||||||
|
spaces.insert(std::make_pair(space, std::vector<std::pair<long long int, long long int>>{}));
|
||||||
|
}
|
||||||
|
for(auto& s: spaces[space]) {
|
||||||
|
if(overlaps(s.first, s.second, start, end)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
spaces[space].push_back(std::make_pair(start, end));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
void clear() override {
|
||||||
|
spaces.clear();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<FunctionValidator*> getSupportedValidators() {
|
||||||
|
std::vector<FunctionValidator*> validators;
|
||||||
|
|
||||||
|
validators.push_back(new DivisibleValidator());
|
||||||
|
validators.push_back(new LessThenValidator());
|
||||||
|
validators.push_back(new GreaterThenValidator());
|
||||||
|
validators.push_back(new ContainsAddressValidator());
|
||||||
|
validators.push_back(new ContainsValidator());
|
||||||
|
validators.push_back(new UniqueValidator());
|
||||||
|
|
||||||
|
return validators;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<FunctionSignature> getSupportedFunctions() {
|
|
||||||
std::vector<FunctionSignature> s;
|
|
||||||
s.push_back(add("divisible", std::vector<Value::ValueType>{Value::INT, Value::INT},[](std::vector<Value> values) {
|
|
||||||
long long first = values[0].asInt();
|
|
||||||
long long second = values[1].asInt();
|
|
||||||
return (first % second) == 0;
|
|
||||||
}));
|
|
||||||
s.push_back(add("less_then", std::vector<Value::ValueType>{Value::INT, Value::INT}, [](std::vector<Value> values) {
|
|
||||||
long long first = values[0].asInt();
|
|
||||||
long long second = values[1].asInt();
|
|
||||||
return first < second;
|
|
||||||
}));
|
|
||||||
s.push_back(add("greater_then", std::vector<Value::ValueType>{Value::INT, Value::INT}, [](std::vector<Value> values) {
|
|
||||||
long long first = values[0].asInt();
|
|
||||||
long long second = values[1].asInt();
|
|
||||||
return first > second;
|
|
||||||
}));
|
|
||||||
s.push_back(add("contains_address", std::vector<Value::ValueType>{Value::ADDRESS_SPACE, Value::INT}, [](std::vector<Value> values) {
|
|
||||||
AddressSpace space = values[0].asAddressSpace();
|
|
||||||
long long address = values[1].asInt();
|
|
||||||
return space.contains(address);
|
|
||||||
}));
|
|
||||||
s.push_back(add("contains", std::vector<Value::ValueType>{Value::ADDRESS_SPACE, Value::INT, Value::INT}, [](std::vector<Value> values) {
|
|
||||||
AddressSpace space = values[0].asAddressSpace();
|
|
||||||
long long start = values[1].asInt();
|
|
||||||
long long size = values[1].asInt();
|
|
||||||
return space.contains(start, start + size);
|
|
||||||
}));
|
|
||||||
s.push_back(add("unique", std::vector<Value::ValueType>{Value::ADDRESS_SPACE, Value::INT, Value::INT}, [](std::vector<Value> values) {
|
|
||||||
return true;
|
|
||||||
}));
|
|
||||||
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace domain
|
} // namespace domain
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#ifndef DOMAIN_FUNCTION_SIGNATURE_H
|
#ifndef DOMAIN_FUNCTION_VALIDATOR_H
|
||||||
#define DOMAIN_FUNCTION_SIGNATURE_H
|
#define DOMAIN_FUNCTION_VALIDATOR_H
|
||||||
|
|
||||||
#include<functional>
|
#include<functional>
|
||||||
#include<vector>
|
#include<vector>
|
||||||
|
@ -8,18 +8,46 @@
|
||||||
|
|
||||||
namespace domain {
|
namespace domain {
|
||||||
|
|
||||||
typedef std::function<bool (std::vector<Value>)> FunctionCallback;
|
class FunctionValidator {
|
||||||
|
private:
|
||||||
struct FunctionSignature {
|
|
||||||
std::string name;
|
std::string name;
|
||||||
std::vector<Value::ValueType> params;
|
std::vector<Value::ValueType> signature;
|
||||||
FunctionCallback callback;
|
|
||||||
|
|
||||||
FunctionSignature(std::string name, std::vector<Value::ValueType> params, FunctionCallback callback): name(name), params(params), callback(callback) {}
|
protected:
|
||||||
|
FunctionValidator(std::string name, std::vector<Value::ValueType> signature) {
|
||||||
|
this->name = name;
|
||||||
|
this->signature = signature;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
std::string getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<Value::ValueType> getSignature() {
|
||||||
|
return signature;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool validateSignature(std::vector<Value> signature) {
|
||||||
|
if(this->signature.size() != signature.size()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i=0; i<this->signature.size(); i++) {
|
||||||
|
if(this->signature[i] != signature[i].getType()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool validate(std::vector<Value> values) = 0;
|
||||||
|
virtual void clear() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<FunctionSignature> getSupportedFunctions();
|
std::vector<FunctionValidator*> getSupportedValidators();
|
||||||
|
|
||||||
} // namespace domain
|
} // namespace domain
|
||||||
|
|
||||||
#endif // DOMAIN_FUNCTIONSIGNATURE_H
|
#endif // DOMAIN_FUNCTION_VALIDATOR_H
|
||||||
|
|
|
@ -17,7 +17,7 @@ bool Condition::evaluate(RuleContext &context) {
|
||||||
request.push_back(params[i]);
|
request.push_back(params[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool result = context.function[function](request);
|
bool result = context.function[function]->validate(request);
|
||||||
return negated ? !result : result;
|
return negated ? !result : result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ namespace domain {
|
||||||
struct RuleContext {
|
struct RuleContext {
|
||||||
std::map<std::string, AddressSpace> addressSpaces;
|
std::map<std::string, AddressSpace> addressSpaces;
|
||||||
std::map<std::string, Value> attributes;
|
std::map<std::string, Value> attributes;
|
||||||
std::map<std::string, FunctionCallback> function;
|
std::map<std::string, FunctionValidator*> function;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Condition {
|
class Condition {
|
||||||
|
|
|
@ -102,8 +102,8 @@ Popup::PopupType toType(PopupNode::PopupType type)
|
||||||
return Popup::ON_DEMAND;
|
return Popup::ON_DEMAND;
|
||||||
}
|
}
|
||||||
|
|
||||||
SchemaCreator::SchemaCreator(std::vector<FunctionSignature> signatures)
|
SchemaCreator::SchemaCreator(std::vector<FunctionValidator*> validators)
|
||||||
: signatures(std::move(signatures))
|
: validators(std::move(validators))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
std::optional<Library> SchemaCreator::loadLibrary(LibraryNode node)
|
std::optional<Library> SchemaCreator::loadLibrary(LibraryNode node)
|
||||||
|
@ -736,19 +736,19 @@ std::optional<Condition> SchemaCreator::loadCondition(ConditionNode node)
|
||||||
{
|
{
|
||||||
std::string function = node.functionName.value;
|
std::string function = node.functionName.value;
|
||||||
|
|
||||||
for(auto & signature : signatures) {
|
for(auto & validator : validators) {
|
||||||
if(signature.name == function) {
|
if(validator->getName() == function) {
|
||||||
if(signature.params.size() == node.params.size()) {
|
if(validator->getSignature().size() == node.params.size()) {
|
||||||
std::vector<Value> params;
|
std::vector<Value> params;
|
||||||
for(uint j=0; j<signature.params.size(); j++) {
|
for(uint j=0; j<validator->getSignature().size(); j++) {
|
||||||
bool exists = false;
|
bool exists = false;
|
||||||
auto type = toType(node.params[j]);
|
auto type = toType(node.params[j]);
|
||||||
if (type.getType() == Value::UNDEFINED) {
|
if (type.getType() == Value::UNDEFINED) {
|
||||||
if(current().doesAttributeExists(type.asReference(), signature.params[j])) {
|
if(current().doesAttributeExists(type.asReference(), validator->getSignature()[j])) {
|
||||||
exists = true;
|
exists = true;
|
||||||
type = Value::fromReference(type.asReference(), Value::ATTRIBUTE_REFERENCE);
|
type = Value::fromReference(type.asReference(), Value::ATTRIBUTE_REFERENCE);
|
||||||
}
|
}
|
||||||
if(signature.params[j] == Value::ADDRESS_SPACE) {
|
if(validator->getSignature()[j] == Value::ADDRESS_SPACE) {
|
||||||
if(hasAddressSpace(type.asReference())) {
|
if(hasAddressSpace(type.asReference())) {
|
||||||
exists = true;
|
exists = true;
|
||||||
type = Value::fromReference(type.asReference(), Value::ADDRESS_SPACE_REFERENCE);
|
type = Value::fromReference(type.asReference(), Value::ADDRESS_SPACE_REFERENCE);
|
||||||
|
|
|
@ -61,7 +61,7 @@ class SchemaCreator
|
||||||
|
|
||||||
|
|
||||||
std::vector<SourceError> errors;
|
std::vector<SourceError> errors;
|
||||||
std::vector<FunctionSignature> signatures;
|
std::vector<FunctionValidator*> validators;
|
||||||
|
|
||||||
std::optional<AddressSpace> loadAddressSpace(AddressSpaceNode node);
|
std::optional<AddressSpace> loadAddressSpace(AddressSpaceNode node);
|
||||||
std::optional<Component> loadComponent(ComponentNode node);
|
std::optional<Component> loadComponent(ComponentNode node);
|
||||||
|
@ -130,7 +130,7 @@ class SchemaCreator
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SchemaCreator(std::vector<FunctionSignature> signatures);
|
SchemaCreator(std::vector<FunctionValidator*> validators);
|
||||||
|
|
||||||
std::vector<SourceError> getErrors() {
|
std::vector<SourceError> getErrors() {
|
||||||
return errors;
|
return errors;
|
||||||
|
|
|
@ -24,7 +24,7 @@ MainWindow::MainWindow(QWidget *parent)
|
||||||
setupUi();
|
setupUi();
|
||||||
|
|
||||||
// define allowed methods
|
// define allowed methods
|
||||||
signatures = domain::getSupportedFunctions();
|
validators = domain::getSupportedValidators();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::setupUi()
|
void MainWindow::setupUi()
|
||||||
|
@ -79,7 +79,7 @@ void MainWindow::onLoadLibrary() {
|
||||||
ParseContext parseContext;
|
ParseContext parseContext;
|
||||||
auto libraryNode = loadLibraryFromFile(&parseContext, filename.toStdString().c_str(), buffer);
|
auto libraryNode = loadLibraryFromFile(&parseContext, filename.toStdString().c_str(), buffer);
|
||||||
if(libraryNode) {
|
if(libraryNode) {
|
||||||
domain::SchemaCreator generator(signatures);
|
domain::SchemaCreator generator(validators);
|
||||||
library = generator.loadLibrary(*libraryNode);
|
library = generator.loadLibrary(*libraryNode);
|
||||||
|
|
||||||
for (auto& error : generator.getErrors()) {
|
for (auto& error : generator.getErrors()) {
|
||||||
|
@ -117,7 +117,7 @@ void MainWindow::onLoadSchema() {
|
||||||
auto schemaNode = loadSchemaFromFile(&parseContext, filename.toStdString().c_str(), buffer);
|
auto schemaNode = loadSchemaFromFile(&parseContext, filename.toStdString().c_str(), buffer);
|
||||||
|
|
||||||
if(schemaNode) {
|
if(schemaNode) {
|
||||||
domain::SchemaCreator generator(signatures);
|
domain::SchemaCreator generator(validators);
|
||||||
library = generator.loadLibrary(*schemaNode->library);
|
library = generator.loadLibrary(*schemaNode->library);
|
||||||
|
|
||||||
librarySource = schemaNode->source->value;
|
librarySource = schemaNode->source->value;
|
||||||
|
@ -190,13 +190,7 @@ void MainWindow::onValidateSchema(bool /*toggled*/) {
|
||||||
|
|
||||||
this->validationErrors.clear();
|
this->validationErrors.clear();
|
||||||
|
|
||||||
std::map<std::string, domain::FunctionCallback> callbacks;
|
domain::ComdelValidator validator{validators};
|
||||||
auto functions = domain::getSupportedFunctions();
|
|
||||||
for(auto &func: functions) {
|
|
||||||
callbacks[func.name] = func.callback;
|
|
||||||
}
|
|
||||||
|
|
||||||
domain::ComdelValidator validator{callbacks};
|
|
||||||
|
|
||||||
domain::ValidationContext context;
|
domain::ValidationContext context;
|
||||||
context.instance = nullptr;
|
context.instance = nullptr;
|
||||||
|
|
|
@ -30,7 +30,7 @@ public:
|
||||||
std::optional<domain::Library> library = std::nullopt;
|
std::optional<domain::Library> library = std::nullopt;
|
||||||
domain::Schema* schema = nullptr;
|
domain::Schema* schema = nullptr;
|
||||||
|
|
||||||
std::vector<domain::FunctionSignature> signatures;
|
std::vector<domain::FunctionValidator*> validators;
|
||||||
|
|
||||||
void setupUi();
|
void setupUi();
|
||||||
void clear();
|
void clear();
|
||||||
|
|
Loading…
Reference in New Issue