2022-05-30 21:11:06 +00:00
|
|
|
#include <set>
|
2022-05-27 06:18:17 +00:00
|
|
|
#include "comdel_validator.h"
|
|
|
|
#include "library.h"
|
2022-06-19 18:10:44 +00:00
|
|
|
#include "message_source.h"
|
2022-05-27 06:18:17 +00:00
|
|
|
|
|
|
|
namespace domain {
|
|
|
|
|
|
|
|
std::vector<ValidationError> ComdelValidator::validateSchema(Schema &schema, ValidationContext context) {
|
|
|
|
std::vector<ValidationError> errors;
|
|
|
|
|
|
|
|
context.instance = nullptr;
|
|
|
|
context.attribute = nullptr;
|
|
|
|
|
|
|
|
for (auto &instance: schema.componentInstances) {
|
|
|
|
auto result = validateComponent(instance.get(), context);
|
|
|
|
errors.insert(errors.end(), result.begin(), result.end());
|
|
|
|
}
|
|
|
|
return errors;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<ValidationError>
|
|
|
|
ComdelValidator::validateInstanceCount(Schema &schema, Library &library, ValidationContext context) {
|
|
|
|
std::vector<ValidationError> errors;
|
|
|
|
|
|
|
|
// validate instance count
|
|
|
|
std::map<std::string, int> instanceMap;
|
|
|
|
for (auto &inst: schema.componentInstances) {
|
|
|
|
instanceMap[inst->component.getName()]++;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (auto comp: library.getComponents()) {
|
|
|
|
int count = instanceMap[comp.getName()];
|
|
|
|
|
2022-06-19 18:10:44 +00:00
|
|
|
context.attributes["componentName"] = Value::fromString(comp.getDisplayName());
|
2022-05-27 06:18:17 +00:00
|
|
|
context.attributes["min"] = Value::fromInt(comp.getCount().first);
|
|
|
|
context.attributes["max"] = Value::fromInt(comp.getCount().second);
|
|
|
|
context.attributes["count"] = Value::fromInt(count);
|
|
|
|
|
|
|
|
if (count < comp.getCount().first) {
|
2022-06-19 18:10:44 +00:00
|
|
|
auto message = MESSAGE_PARAM("msg_validators_component_min_count", context.map());
|
2022-05-30 21:11:06 +00:00
|
|
|
errors.emplace_back(Action::ERROR, message);
|
2022-05-27 06:18:17 +00:00
|
|
|
} else if (count > comp.getCount().second) {
|
2022-06-19 18:10:44 +00:00
|
|
|
auto message = MESSAGE_PARAM("msg_validators_component_max_count", context.map());
|
2022-05-30 21:11:06 +00:00
|
|
|
errors.emplace_back(Action::ERROR, message);
|
2022-05-27 06:18:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// validate bus instance count
|
|
|
|
std::map<std::string, int> busInstanceMap;
|
|
|
|
for (auto &inst: schema.busInstances) {
|
|
|
|
busInstanceMap[inst->bus.getName()]++;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (auto bus: library.getBuses()) {
|
|
|
|
int count = busInstanceMap[bus.getName()];
|
|
|
|
|
2022-06-19 18:10:44 +00:00
|
|
|
context.attributes["busName"] = Value::fromString(bus.getDisplayName());
|
2022-05-27 06:18:17 +00:00
|
|
|
context.attributes["min"] = Value::fromInt(bus.getCount().first);
|
|
|
|
context.attributes["max"] = Value::fromInt(bus.getCount().second);
|
|
|
|
context.attributes["count"] = Value::fromInt(count);
|
|
|
|
|
|
|
|
if (count < bus.getCount().first) {
|
2022-06-19 18:10:44 +00:00
|
|
|
auto message = MESSAGE_PARAM("msg_validators_bus_min_count", context.map());
|
2022-05-30 21:11:06 +00:00
|
|
|
errors.emplace_back(Action::ERROR, message);
|
2022-05-27 06:18:17 +00:00
|
|
|
} else if (count > bus.getCount().second) {
|
2022-06-19 18:10:44 +00:00
|
|
|
auto message = MESSAGE_PARAM("msg_validators_bus_max_count", context.map());
|
2022-05-30 21:11:06 +00:00
|
|
|
errors.emplace_back(Action::ERROR, message);
|
2022-05-27 06:18:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return errors;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<ValidationError>
|
|
|
|
ComdelValidator::validatePinConnections(Schema &schema, Library &library, ValidationContext context) {
|
|
|
|
std::vector<ValidationError> errors;
|
|
|
|
|
|
|
|
for (auto &inst: schema.componentInstances) {
|
|
|
|
for (auto &pin: inst->component.getPins()) {
|
2022-06-12 22:48:12 +00:00
|
|
|
if (pin.getConnection().has_value()) {
|
2022-05-27 06:18:17 +00:00
|
|
|
if (!connectionExists(schema, inst, pin)) {
|
|
|
|
context.instance = inst.get();
|
2022-06-19 18:10:44 +00:00
|
|
|
auto message = MESSAGE_PARAM(pin.getConnection().value(), context.map());
|
|
|
|
errors.emplace_back(context.instance, nullptr, Action::ERROR, message);
|
2022-05-27 06:18:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return errors;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<ValidationError>
|
|
|
|
ComdelValidator::validateComponent(ComponentInstance *instance, ValidationContext context) {
|
|
|
|
std::vector<ValidationError> 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<ValidationError>
|
|
|
|
ComdelValidator::validateAttribute(InstanceAttribute *attribute, ValidationContext context) {
|
|
|
|
std::vector<ValidationError> errors;
|
|
|
|
if (attribute->attribute.getPopup()) {
|
|
|
|
Popup popup = *attribute->attribute.getPopup();
|
|
|
|
context.attribute = attribute;
|
|
|
|
context.attributes = std::map<std::string, Value>{{attribute->name, attribute->value}};
|
|
|
|
|
|
|
|
for (auto &rule: popup.getRules()) {
|
|
|
|
auto result = validateRule(rule, context);
|
|
|
|
if (result) {
|
|
|
|
errors.push_back(*result);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return errors;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::optional<ValidationError> ComdelValidator::validateRule(Rule rule, ValidationContext context) {
|
|
|
|
RuleContext ruleContext;
|
|
|
|
ruleContext.addressSpaces = context.addressSpaces;
|
|
|
|
ruleContext.attributes = context.attributes;
|
|
|
|
ruleContext.function = validators;
|
|
|
|
auto action = rule.evaluate(ruleContext);
|
|
|
|
if (action) {
|
2022-06-19 18:10:44 +00:00
|
|
|
auto message = MESSAGE_PARAM(action->getMessage(), context.map());
|
2022-05-27 06:18:17 +00:00
|
|
|
return ValidationError{context.instance, context.attribute, action->getType(), message};
|
|
|
|
}
|
|
|
|
return nullopt;
|
|
|
|
}
|
|
|
|
|
2022-06-01 23:37:14 +00:00
|
|
|
|
|
|
|
std::vector<ValidationError>
|
|
|
|
ComdelValidator::validateMemoryReferences(Schema &schema, Library &library, ValidationContext context) {
|
|
|
|
std::set<std::string> memoryInstances;
|
|
|
|
for(auto& component: schema.componentInstances) {
|
|
|
|
if(component->component.getType() == Component::MEMORY) {
|
|
|
|
memoryInstances.insert(component->name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<ValidationError> errors;
|
|
|
|
for(auto& component: schema.componentInstances) {
|
|
|
|
if(component->component.getType() == Component::PROCESSOR) {
|
|
|
|
for(auto& attribute: component->attributes) {
|
|
|
|
if(attribute.value.isType(Value::MEMORY_REFERENCE)) {
|
|
|
|
auto memoryReference = attribute.value.asMemoryReference();
|
|
|
|
if(memoryReference != nullopt) {
|
|
|
|
if(memoryInstances.count(*memoryReference) == 0) {
|
|
|
|
context.attributes["memoryReference"] = domain::Value::fromString(memoryReference.value());
|
2022-06-19 18:10:44 +00:00
|
|
|
auto message = MESSAGE_PARAM("msg_validators_memory_not_found", context.map());
|
2022-06-01 23:37:14 +00:00
|
|
|
errors.emplace_back(component.get(), nullptr, Action::ERROR, message);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return errors;
|
|
|
|
}
|
|
|
|
|
2022-05-30 21:11:06 +00:00
|
|
|
std::vector<ValidationError>
|
|
|
|
ComdelValidator::validateInstanceNames(Schema &schema, Library &library, ValidationContext context) {
|
|
|
|
std::set<std::string> names;
|
|
|
|
std::vector<ValidationError> errors;
|
|
|
|
|
|
|
|
for(auto& component: schema.componentInstances) {
|
|
|
|
if(names.find(component->name) != names.end()) {
|
2022-06-19 18:10:44 +00:00
|
|
|
context.instance = component.get();
|
|
|
|
auto message = MESSAGE_PARAM("msg_validators_duplicates_found", context.map());
|
2022-05-30 21:11:06 +00:00
|
|
|
errors.emplace_back(Action::ERROR, message);
|
|
|
|
}
|
|
|
|
names.insert(component->name);
|
|
|
|
}
|
|
|
|
return errors;
|
|
|
|
}
|
|
|
|
|
2022-05-27 06:18:17 +00:00
|
|
|
bool ComdelValidator::connectionExists(Schema &schema, shared_ptr<ComponentInstance> &component, Pin &pin) {
|
|
|
|
for (auto conn: schema.connections) {
|
|
|
|
auto busConnection = dynamic_cast<BusConnectionInstance *>(conn.get());
|
|
|
|
if (busConnection != nullptr) {
|
|
|
|
if (busConnection->instance->name == component->name &&
|
|
|
|
busConnection->connection.getComponent().pin == pin.getName()) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
auto directConnection = dynamic_cast<DirectConnectionInstance *>(conn.get());
|
|
|
|
if (directConnection != nullptr) {
|
2022-06-19 18:10:44 +00:00
|
|
|
if ((directConnection->instance->name == component->name && directConnection->connection.getComponent().pin == pin.getName()) ||
|
|
|
|
(directConnection->secondInstance->name == component->name) && directConnection->connection.getSecondComponent()->pin == pin.getName()) {
|
|
|
|
return directConnection->connection.isConnecting({component->component.getName(), pin.getName()});
|
2022-05-27 06:18:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
ComdelValidator::ComdelValidator(std::vector<FunctionValidator *> validators) {
|
|
|
|
for (auto *validator: validators) {
|
|
|
|
validator->clear();
|
|
|
|
this->validators.insert(std::make_pair(validator->getName(), validator));
|
|
|
|
}
|
|
|
|
}
|
2022-06-19 18:10:44 +00:00
|
|
|
|
|
|
|
std::map<std::string, std::string> ValidationContext::map() {
|
|
|
|
std::map<std::string, std::string> parametars;
|
|
|
|
if(instance != nullptr) {
|
|
|
|
parametars["instanceName"] = instance->name;
|
|
|
|
parametars["componentName"] = instance->component.getDisplayName();
|
|
|
|
}
|
|
|
|
if(attribute != nullptr) {
|
|
|
|
parametars["attributeName"] = attribute->name;
|
|
|
|
parametars["attribute"] = attribute->value.string();
|
|
|
|
}
|
|
|
|
for(auto [key, value]: attributes) {
|
|
|
|
parametars[key] = value.string();
|
|
|
|
}
|
|
|
|
return parametars;
|
|
|
|
}
|
2022-05-27 06:18:17 +00:00
|
|
|
}
|