Skip to content

Commit

Permalink
Merge pull request #236 from singnet/issue-209-link-create-template-p…
Browse files Browse the repository at this point in the history
…arser

[#209] Link Create Template parser
  • Loading branch information
eddiebrissow authored Feb 7, 2025
2 parents c62ab5e + 8ae90af commit c916290
Show file tree
Hide file tree
Showing 4 changed files with 606 additions and 22 deletions.
4 changes: 2 additions & 2 deletions src/cpp/link_creation_agent/agent.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <sstream>

#include "RemoteIterator.h"
#include "link_create_template.h"

using namespace std;
using namespace link_creation_agent;
Expand Down Expand Up @@ -165,7 +166,7 @@ LinkCreationAgentRequest* LinkCreationAgent::create_request(vector<string> reque
bool is_link_create = false;
for (string arg : request) {
cursor++;
is_link_create = (arg == "LINK_CREATE") ^ is_link_create;
is_link_create = (arg == "LINK_CREATE") || is_link_create;
if (!is_link_create) {
lca_request->query.push_back(arg);
}
Expand All @@ -186,7 +187,6 @@ LinkCreationAgentRequest* LinkCreationAgent::create_request(vector<string> reque
}
}
lca_request->infinite = (lca_request->repeat == -1);

return lca_request;
} catch (exception& e) {
cout << "Error parsing request: " << e.what() << endl;
Expand Down
244 changes: 244 additions & 0 deletions src/cpp/link_creation_agent/link_create_template.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,244 @@
#include "link_create_template.h"

#include <algorithm>
#include <iostream>
#include <stdexcept>

using namespace link_creation_agent;

// TODO move this to a utils file
static bool is_number(const std::string& s) {
return !s.empty() &&
std::find_if(s.begin(), s.end(), [](unsigned char c) { return !std::isdigit(c); }) == s.end();
}
// TODO move this to a utils file
static int string_to_int(const std::string& s) {
if (!is_number(s)) {
throw std::invalid_argument("Can not convert string to int: Invalid arguments");
}
return std::stoi(s);
}
// TODO move this to a utils file
static std::string get_token(std::vector<std::string>& link_template, int cursor) {
if (cursor >= link_template.size()) {
throw std::invalid_argument("Can not get token: Invalid arguments");
}
return link_template[cursor];
}

CustomField::CustomField(std::vector<std::string>& custom_fields) {
if (get_token(custom_fields, 0) != "CUSTOM_FIELD")
throw std::invalid_argument("Can not create Custom Field: Invalid arguments");

int cursor = 0;
std::string custom_field_name = get_token(custom_fields, 1);
this->name = custom_field_name;
cursor += 3;
while (cursor < custom_fields.size()) {
if (get_token(custom_fields, cursor) == "CUSTOM_FIELD") {
std::vector<std::string> custom_field_args;
int sub_custom_field_size = string_to_int(get_token(custom_fields, cursor + 2));
std::string sub_custom_field_name = get_token(custom_fields, cursor + 1);
custom_field_args.push_back(get_token(custom_fields, cursor)); // CUSTOM_FIELD
custom_field_args.push_back(get_token(custom_fields, cursor + 1)); // field name
custom_field_args.push_back(get_token(custom_fields, cursor + 2)); // field size
cursor += 3;
while (cursor < custom_fields.size()) {
if (sub_custom_field_size == 0) {
break;
}

custom_field_args.push_back(get_token(custom_fields, cursor));
if (get_token(custom_fields, cursor) == "CUSTOM_FIELD") {
sub_custom_field_size += string_to_int(get_token(custom_fields, cursor + 2));
custom_field_args.push_back(get_token(custom_fields, cursor + 1)); // field name
custom_field_args.push_back(get_token(custom_fields, cursor + 2)); // field size
cursor += 3;
sub_custom_field_size--;
} else {
custom_field_args.push_back(get_token(custom_fields, cursor + 1));
cursor += 2;
sub_custom_field_size--;
}
}
CustomField custom_field = CustomField(custom_field_args);
this->values.push_back(
std::make_tuple(sub_custom_field_name, std::make_shared<CustomField>(custom_field)));
} else {
this->values.push_back(
std::make_tuple(get_token(custom_fields, cursor), get_token(custom_fields, cursor + 1)));
cursor += 2;
}
}
}

CustomField::~CustomField() {}

std::string CustomField::get_name() { return this->name; }

std::vector<std::tuple<std::string, CustomFieldTypes>> CustomField::get_values() { return this->values; }

std::vector<std::string> parse_sub_custom_field(std::vector<std::string>& link_template,
size_t& cursor) {
if (get_token(link_template, cursor) != "CUSTOM_FIELD" || link_template.size() < cursor + 3)
throw std::invalid_argument("Can not create Custom Field: Invalid arguments");
std::vector<std::string> custom_field_args;
int custom_field_size = string_to_int(get_token(link_template, cursor + 2));
custom_field_args.push_back(get_token(link_template, cursor)); // CUSTOM_FIELD
custom_field_args.push_back(get_token(link_template, cursor + 1)); // field name
custom_field_args.push_back(get_token(link_template, cursor + 2)); // field size
cursor += 3;
while (cursor < link_template.size()) {
if (custom_field_size == 0) {
break;
}
custom_field_args.push_back(get_token(link_template, cursor));
if (get_token(link_template, cursor) == "CUSTOM_FIELD") {
custom_field_args.push_back(get_token(link_template, cursor + 1));
custom_field_args.push_back(get_token(link_template, cursor + 2));
custom_field_size += string_to_int(get_token(link_template, cursor + 2));
custom_field_size--;
cursor += 3;
} else {
custom_field_args.push_back(get_token(link_template, cursor + 1));
custom_field_size--;
cursor += 2;
}
}
return custom_field_args;
}

std::vector<std::string> parse_sub_link_template(std::vector<std::string>& link_template,
size_t& cursor) {
if (get_token(link_template, cursor) != "LINK_CREATE" || link_template.size() < cursor + 4)
throw std::invalid_argument("Can not create Link Template: Invalid arguments");
int sub_link_template_size = string_to_int(get_token(link_template, cursor + 2));
int sub_link_custom_field_size = string_to_int(get_token(link_template, cursor + 3));
int custom_field_value_size = 0;
std::vector<std::string> sub_link_template;
int current_ptr = 0; // link create default size
sub_link_template.push_back(get_token(link_template, cursor)); // LINK_CREATE
sub_link_template.push_back(get_token(link_template, cursor + 1)); // link type
sub_link_template.push_back(get_token(link_template, cursor + 2)); // link size
sub_link_template.push_back(get_token(link_template, cursor + 3)); // custom field size
cursor += 4;
while (cursor < link_template.size()) {
if (sub_link_template_size == 0 && current_ptr == 0 && sub_link_custom_field_size == 0 &&
custom_field_value_size == 0) {
break;
}
sub_link_template.push_back(get_token(link_template, cursor));

if (get_token(link_template, cursor) == "NODE") {
current_ptr = 3;
sub_link_template_size--;
}
if (get_token(link_template, cursor) == "VARIABLE") {
current_ptr = 2;
sub_link_template_size--;
}
if (get_token(link_template, cursor) == "LINK_CREATE") {
current_ptr = 4;
sub_link_template_size += string_to_int(get_token(link_template, cursor + 2));
sub_link_custom_field_size = string_to_int(get_token(link_template, cursor + 3));
sub_link_template_size--;
}
if (sub_link_custom_field_size > 0 && get_token(link_template, cursor) == "CUSTOM_FIELD") {
current_ptr = 3 + (string_to_int(get_token(link_template, cursor + 2)) * 2);
sub_link_custom_field_size--;
}

current_ptr--;
cursor++;
}
return sub_link_template;
}

LinkCreateTemplate::LinkCreateTemplate(std::vector<std::string>& link_template) {
int starting_pos = 0;
if (get_token(link_template, 0) == "LINK_CREATE") {
starting_pos = 1;
}

this->link_type = get_token(link_template, starting_pos);
std::size_t cursor = starting_pos;
std::size_t link_template_size = string_to_int(get_token(link_template, starting_pos + 1));
std::size_t custom_field_size = string_to_int(get_token(link_template, starting_pos + 2));
while (cursor < link_template.size()) {
if (get_token(link_template, cursor) == "NODE") {
Node node;
node.type = get_token(link_template, cursor + 1);
node.value = get_token(link_template, cursor + 2);
this->targets.push_back(node);
cursor += 2;
} else if (get_token(link_template, cursor) == "VARIABLE") {
Variable var;
var.name = get_token(link_template, cursor + 1);
this->targets.push_back(var);
cursor += 1;
} else if (get_token(link_template, cursor) == "LINK_CREATE") {
std::vector<std::string> sub_link_template = parse_sub_link_template(link_template, cursor);
LinkCreateTemplateTypes sub_link = std::make_shared<LinkCreateTemplate>(sub_link_template);
this->targets.push_back(sub_link);
} else if (get_token(link_template, cursor) == "CUSTOM_FIELD") {
std::vector<std::string> sub_custom_field = parse_sub_custom_field(link_template, cursor);
CustomField custom_field = CustomField(sub_custom_field);
this->custom_fields.push_back(custom_field);
} else {
cursor++;
}
}
if (this->targets.size() != link_template_size || this->custom_fields.size() != custom_field_size) {
throw std::invalid_argument("Can not create Link Template: Invalid arguments");
}
}

LinkCreateTemplate::~LinkCreateTemplate() {}

std::string LinkCreateTemplate::get_link_type() { return this->link_type; }

std::vector<LinkCreateTemplateTypes> LinkCreateTemplate::get_targets() { return this->targets; }

std::vector<CustomField> LinkCreateTemplate::get_custom_fields() { return this->custom_fields; }

std::string LinkCreateTemplate::to_string() {
std::string link_template = "LINK_CREATE " + this->link_type + " " +
std::to_string(this->targets.size()) + " " +
std::to_string(this->custom_fields.size()) + " ";
for (auto target : this->targets) {
if (std::holds_alternative<Node>(target)) {
Node node = std::get<Node>(target);
link_template += "NODE " + node.type + " " + node.value;
} else if (std::holds_alternative<Variable>(target)) {
Variable var = std::get<Variable>(target);
link_template += "VARIABLE " + var.name;
} else if (std::holds_alternative<std::shared_ptr<LinkCreateTemplate>>(target)) {
std::shared_ptr<LinkCreateTemplate> sub_link =
std::get<std::shared_ptr<LinkCreateTemplate>>(target);
link_template += sub_link->to_string();
}
link_template += " ";
}
for (auto custom_field : this->custom_fields) {
link_template += custom_field.to_string();
}
link_template = link_template.substr(0, link_template.size() - 1);
return link_template;
}

std::string CustomField::to_string() {
std::string custom_field =
"CUSTOM_FIELD " + this->name + " " + std::to_string(this->values.size()) + " ";
for (auto value : this->values) {
CustomFieldTypes field_value = std::get<1>(value);
if (std::holds_alternative<std::string>(field_value)) {
custom_field += std::get<0>(value) + " ";
custom_field += std::get<std::string>(field_value) + " ";
} else {
std::shared_ptr<CustomField> sub_custom_field =
std::get<std::shared_ptr<CustomField>>(field_value);
custom_field += sub_custom_field->to_string();
}
}
return custom_field;
}
Loading

0 comments on commit c916290

Please sign in to comment.