Ember
Loading...
Searching...
No Matches
ParserProfile.cpp
Go to the documentation of this file.
2#include "Utils/Logger.h"
3#include <fstream>
4#include <iomanip>
5#include <sstream>
6
7namespace EmberCore {
8
12
16
18
20 config_ = config;
22}
23
24bool ParserProfile::Validate(std::vector<String> &errors) const {
25 errors.clear();
26
27 // Validate profile metadata
28 if (name_.empty()) {
29 errors.push_back("Profile name cannot be empty");
30 }
31
32 if (version_.empty()) {
33 errors.push_back("Profile version cannot be empty");
34 }
35
36 // Validate the underlying config
37 std::vector<String> config_errors;
38 if (!config_.Validate(config_errors)) {
39 errors.insert(errors.end(), config_errors.begin(), config_errors.end());
40 }
41
42 return errors.empty();
43}
44
45nlohmann::json ParserProfile::ToJson() const {
46 nlohmann::json json;
47
48 json["profile_name"] = name_;
49 json["description"] = description_;
50 json["version"] = version_;
51 json["author"] = author_;
52 json["created_timestamp"] = created_timestamp_;
53 json["modified_timestamp"] = modified_timestamp_;
54 json["config"] = config_.ToJson();
55
56 return json;
57}
58
59void ParserProfile::FromJson(const nlohmann::json &json) {
60 try {
61 // Validate required fields
62 if (!json.contains("profile_name")) {
63 throw std::runtime_error("Missing required field: profile_name");
64 }
65
66 if (!json.contains("config")) {
67 throw std::runtime_error("Missing required field: config");
68 }
69
70 // Validate that config is not empty and has required sections
71 const auto &config_json = json["config"];
72 if (config_json.empty()) {
73 throw std::runtime_error("Config object cannot be empty");
74 }
75
76 // Validate that config has minimum required sections
77 if (!config_json.contains("document") || !config_json.contains("tree") || !config_json.contains("node")) {
78 throw std::runtime_error("Config must contain minimum required sections: document, tree, and node");
79 }
80
81 // Load required fields
82 name_ = json["profile_name"].get<String>();
83 config_.FromJson(config_json);
84
85 // Load optional fields
86 if (json.contains("description")) {
87 description_ = json["description"].get<String>();
88 }
89 if (json.contains("version")) {
90 version_ = json["version"].get<String>();
91 }
92 if (json.contains("author")) {
93 author_ = json["author"].get<String>();
94 }
95 if (json.contains("created_timestamp")) {
96 created_timestamp_ = json["created_timestamp"].get<int64_t>();
97 }
98 if (json.contains("modified_timestamp")) {
99 modified_timestamp_ = json["modified_timestamp"].get<int64_t>();
100 }
101 } catch (const std::exception &e) {
102 LOG_ERROR("ParserProfile", "Error parsing JSON profile: " + std::string(e.what()));
103 throw;
104 }
105}
106
107bool ParserProfile::SaveToFile(const String &filepath) const {
108 try {
109 nlohmann::json json = ToJson();
110 std::ofstream file(filepath);
111
112 if (!file.is_open()) {
113 LOG_ERROR("ParserProfile", "Failed to open file for writing: " + filepath);
114 return false;
115 }
116
117 // Write with pretty formatting (4 space indent)
118 file << std::setw(4) << json << std::endl;
119 file.close();
120
121 LOG_INFO("ParserProfile", "Saved profile '" + name_ + "' to: " + filepath);
122 return true;
123 } catch (const std::exception &e) {
124 LOG_ERROR("ParserProfile", "Error saving profile to file: " + std::string(e.what()));
125 return false;
126 }
127}
128
129bool ParserProfile::LoadFromFile(const String &filepath) {
130 try {
131 std::ifstream file(filepath);
132
133 if (!file.is_open()) {
134 LOG_ERROR("ParserProfile", "Failed to open file for reading: " + filepath);
135 return false;
136 }
137
138 nlohmann::json json;
139 file >> json;
140 file.close();
141
142 FromJson(json);
143
144 LOG_INFO("ParserProfile", "Loaded profile '" + name_ + "' from: " + filepath);
145 return true;
146 } catch (const std::exception &e) {
147 LOG_ERROR("ParserProfile", "Error loading profile from file: " + std::string(e.what()));
148 return false;
149 }
150}
151
152std::shared_ptr<ParserProfile> ParserProfile::Clone(const String &new_name) const {
153 // Create new profile with cloned name
154 // If no new name provided, keep the same name
155 String cloned_name = new_name.empty() ? name_ : new_name;
156 auto cloned = std::make_shared<ParserProfile>(cloned_name, description_);
157
158 // Copy additional fields
159 cloned->SetVersion(version_);
160 cloned->SetAuthor(author_);
161 cloned->SetConfig(config_);
162
163 return cloned;
164}
165
166std::shared_ptr<ParserProfile> ParserProfile::CreateDefaultProfile() {
167 auto profile = std::make_shared<ParserProfile>("Default", "Default BehaviorTree.CPP format");
168 profile->SetVersion("1.0");
169 profile->SetAuthor("EmberForge");
170
171 // Config is already initialized with default values
173 profile->SetConfig(config);
174
175 return profile;
176}
177
178std::shared_ptr<ParserProfile> ParserProfile::CreateGenericProfile() {
179 auto profile =
180 std::make_shared<ParserProfile>("Generic", "Generic permissive format for various BT implementations");
181 profile->SetVersion("1.0");
182 profile->SetAuthor("EmberForge");
183
185 profile->SetConfig(config);
186
187 return profile;
188}
189
191 auto now = std::chrono::system_clock::now();
192 auto duration = now.time_since_epoch();
193 return std::chrono::duration_cast<std::chrono::seconds>(duration).count();
194}
195
196} // namespace EmberCore
#define LOG_ERROR(category, message)
Definition Logger.h:116
#define LOG_INFO(category, message)
Definition Logger.h:114
Configuration for XML parser behavior and element/attribute mappings.
static ParserConfig CreateDefault()
static ParserConfig CreateGeneric()
static std::shared_ptr< ParserProfile > CreateGenericProfile()
static int64_t GetCurrentTimestamp()
nlohmann::json ToJson() const
static std::shared_ptr< ParserProfile > CreateDefaultProfile()
bool LoadFromFile(const String &filepath)
bool Validate(std::vector< String > &errors) const
void SetConfig(const ParserConfig &config)
void FromJson(const nlohmann::json &json)
std::shared_ptr< ParserProfile > Clone(const String &new_name="") const
bool SaveToFile(const String &filepath) const
Main types header for EmberCore.
std::string String
Framework-agnostic string type.
Definition String.h:14