Ember
Loading...
Searching...
No Matches
LibXMLBehaviorTreeParser.h
Go to the documentation of this file.
1#pragma once
2
14
18#include <condition_variable>
19#include <libxml/parser.h>
20#include <libxml/threads.h>
21#include <libxml/tree.h>
22#include <map>
23#include <memory>
24#include <mutex>
25#include <queue>
26#include <set>
27#include <thread>
28#include <vector>
29
30// Forward declarations
31namespace EmberCore {
32class BehaviorTree;
33class Node;
34class Blackboard;
35class BlackboardEntry;
37} // namespace EmberCore
38
39namespace EmberCore {
40
56 public:
86
90 struct ParseResult {
91 std::shared_ptr<BehaviorTree> tree;
93 std::vector<ParseError> errors;
94 bool success;
95
96 ParseResult() : success(false) {}
97 };
98
105 bool has_behavior_trees = false;
106 bool has_blackboards = false;
107 int tree_count = 0;
109 std::vector<String> tree_ids;
110 std::vector<String> blackboard_ids;
111 std::vector<String> subtree_refs;
112 std::vector<String> blackboard_includes;
113 std::vector<String> errors;
114 std::vector<String> warnings;
115 };
116
124 bool success = false;
125 std::map<EmberCore::String, std::shared_ptr<BehaviorTree>> parsed_trees;
126 std::map<EmberCore::String, std::shared_ptr<Blackboard>> parsed_blackboards;
127 std::map<EmberCore::String, TreeImplementationStatus> tree_statuses;
128 std::vector<FileParseInfo> file_infos; // Per-file detailed info
129 std::vector<ParseError> errors;
130 std::vector<EmberCore::String> warnings;
131 std::vector<EmberCore::String> unimplemented_references;
132 std::vector<EmberCore::String> unresolved_blackboard_includes;
133 std::vector<EmberCore::String> duplicate_tree_ids;
134 std::vector<EmberCore::String> duplicate_blackboard_ids;
135 std::vector<EmberCore::String> circular_references;
136 std::map<EmberCore::String, std::vector<EmberCore::String>> blackboard_includes_map;
138
139 bool HasUnimplementedReferences() const { return !unimplemented_references.empty(); }
140 int GetImplementedTreeCount() const;
141 int GetTotalTreeCount() const;
142 };
143
144 public:
146 explicit LibXMLBehaviorTreeParser(const ParserConfig &config);
148
149 // Main parsing methods (same interface as XMLBehaviorTreeParser)
150 std::shared_ptr<BehaviorTree> ParseFromFile(const EmberCore::String &filepath);
151 std::shared_ptr<BehaviorTree> ParseFromString(const EmberCore::String &xml_content);
152
153 // Batch parsing method (sequential processing)
154 std::vector<ParseResult> ParseMultipleFiles(const std::vector<EmberCore::String> &filepaths);
155
156 // Project parsing method - parses all files and tracks cross-file references
157 ProjectParseResult ParseProject(BehaviorTreeProject *project);
158
159 // Parse multiple files with shared tree registry (for cross-file references)
160 ProjectParseResult ParseFilesWithSharedRegistry(const std::vector<EmberCore::String> &filepaths);
161
162 // Progress callback (thread-safe)
164
165 // Get tree implementation status (populated after project parsing)
166 const std::map<EmberCore::String, TreeImplementationStatus> &GetTreeImplementationStatuses() const {
168 }
169
170 // Check if a specific tree is implemented
171 bool IsTreeImplemented(const EmberCore::String &tree_id) const;
172
173 // Get list of unimplemented tree references
174 std::vector<EmberCore::String> GetUnimplementedReferences() const;
175
176 // Error handling (thread-safe)
177 bool HasErrors() const;
178 const std::vector<ParseError> &GetErrors() const;
179 void ClearErrors();
180
181 // Get parsed tree information
183 const std::map<EmberCore::String, std::shared_ptr<BehaviorTree>> &GetParsedTrees() const { return parsed_trees_; }
184
185 // Thread safety and performance
186 void SetMaxThreads(size_t max_threads) { max_threads_ = max_threads; }
187 size_t GetMaxThreads() const { return max_threads_; }
188 bool IsThreadSafe() const { return thread_safe_; }
189
190 // Configuration management
191 const ParserConfig &GetConfig() const { return config_; }
192 void SetConfig(const ParserConfig &config) { config_ = config; }
193
194 private:
195 // Core parsing methods
196 bool ParseXMLDocument(xmlDocPtr doc, const EmberCore::String &source_path = "");
197 std::shared_ptr<BehaviorTree> ParseBehaviorTree(xmlNodePtr tree_node);
198 std::unique_ptr<Node> ParseNode(xmlNodePtr xml_node);
199
200 // Node type specific parsing
201 std::unique_ptr<Node> ParseControlNode(xmlNodePtr xml_node);
202 std::unique_ptr<Node> ParseActionNode(xmlNodePtr xml_node);
203 std::unique_ptr<Node> ParseConditionNode(xmlNodePtr xml_node);
204 std::unique_ptr<Node> ParseDecoratorNode(xmlNodePtr xml_node);
205 std::unique_ptr<Node> ParseSubTreeNode(xmlNodePtr xml_node);
206
207 // Blackboard parsing
208 std::unique_ptr<Blackboard> ParseBlackboard(xmlNodePtr blackboard_node);
209 std::unique_ptr<BlackboardEntry> ParseBlackboardEntry(xmlNodePtr entry_node);
210
211 // Helper methods
212 void SetNodeAttributes(Node *node, xmlNodePtr xml_node);
213 void ParseChildNodes(Node *parent, xmlNodePtr xml_parent);
214
215 // Comment and formatting capture
216 void CaptureComments(xmlNodePtr parent, BehaviorTree *tree, Node *node = nullptr);
217
218 // SubTree expansion (two-pass system)
220 bool ExpandSubTreePlaceholder(Node *node);
221
222 // Project-aware SubTree expansion (tracks unimplemented references)
225
226 // Track SubTree references for implementation status
227 void CollectSubTreeReferences(Node *node, std::set<EmberCore::String> &references);
228
229 // Error handling (thread-safe)
230 void AddError(ParseError::Type type, const EmberCore::String &message, xmlNodePtr node = nullptr,
231 const EmberCore::String &context = "");
232 EmberCore::String GetNodePath(xmlNodePtr node);
233
234 // Validation
235 bool ValidateRequiredAttribute(xmlNodePtr node, const EmberCore::String &attr_name);
236
237 // Thread-safe progress reporting
238 bool ReportProgress(const EmberCore::String &message, int current = 0, int total = 0);
239
240 // libxml2 specific helpers
241 EmberCore::String GetNodeName(xmlNodePtr node);
242 EmberCore::String GetNodeAttribute(xmlNodePtr node, const EmberCore::String &attr_name);
243 void InitializeLibXML2();
244
245 private:
246 // Configuration
248
249 // Thread-safe data members
250 mutable std::mutex errors_mutex_;
251 std::vector<ParseError> errors_;
253 std::map<EmberCore::String, std::shared_ptr<BehaviorTree>> parsed_trees_;
254 std::map<EmberCore::String, std::unique_ptr<Blackboard>> parsed_blackboards_;
255 std::set<EmberCore::String> expanded_subtree_cache_;
256 std::set<EmberCore::String> expansion_stack_; // Track currently expanding subtrees for circular reference detection
257 std::set<EmberCore::String> circular_references_; // Track detected circular references
260
261 // Tree implementation tracking for project parsing
262 std::map<EmberCore::String, TreeImplementationStatus> tree_implementation_statuses_;
263 std::set<EmberCore::String> unimplemented_references_;
264 bool project_parsing_mode_; // When true, don't error on missing subtrees
265
266 // Threading support
270
271 // Static thread-safe initialization
272 static std::once_flag libxml2_init_flag_;
274
275 // Static mutex for serializing parser destruction (prevents libxml2 race conditions)
276 static std::mutex destruction_mutex_;
277};
278
279} // namespace EmberCore
Represents a BehaviorTree project containing multiple XML resources.
Represents a complete behavior tree data structure.
Represents a single entry in a behavior tree blackboard.
Represents a blackboard containing multiple entries.
Callback interface for reporting parsing progress.
std::unique_ptr< Node > ParseNode(xmlNodePtr xml_node)
std::shared_ptr< BehaviorTree > ParseFromString(const EmberCore::String &xml_content)
std::vector< EmberCore::String > GetUnimplementedReferences() const
ProjectParseResult ParseFilesWithSharedRegistry(const std::vector< EmberCore::String > &filepaths)
std::set< EmberCore::String > unimplemented_references_
const std::map< EmberCore::String, TreeImplementationStatus > & GetTreeImplementationStatuses() const
std::set< EmberCore::String > circular_references_
std::unique_ptr< Node > ParseSubTreeNode(xmlNodePtr xml_node)
std::map< EmberCore::String, TreeImplementationStatus > tree_implementation_statuses_
std::unique_ptr< Node > ParseActionNode(xmlNodePtr xml_node)
void ParseChildNodes(Node *parent, xmlNodePtr xml_parent)
void SetProgressCallback(IParseProgressCallback *callback)
void SetConfig(const ParserConfig &config)
bool ParseXMLDocument(xmlDocPtr doc, const EmberCore::String &source_path="")
void AddError(ParseError::Type type, const EmberCore::String &message, xmlNodePtr node=nullptr, const EmberCore::String &context="")
std::unique_ptr< BlackboardEntry > ParseBlackboardEntry(xmlNodePtr entry_node)
std::unique_ptr< Node > ParseConditionNode(xmlNodePtr xml_node)
void CaptureComments(xmlNodePtr parent, BehaviorTree *tree, Node *node=nullptr)
std::set< EmberCore::String > expansion_stack_
void CollectSubTreeReferences(Node *node, std::set< EmberCore::String > &references)
std::unique_ptr< Node > ParseControlNode(xmlNodePtr xml_node)
std::map< EmberCore::String, std::shared_ptr< BehaviorTree > > parsed_trees_
const std::vector< ParseError > & GetErrors() const
EmberCore::String GetNodeAttribute(xmlNodePtr node, const EmberCore::String &attr_name)
EmberCore::String GetNodePath(xmlNodePtr node)
std::unique_ptr< Blackboard > ParseBlackboard(xmlNodePtr blackboard_node)
EmberCore::String GetNodeName(xmlNodePtr node)
ProjectParseResult ParseProject(BehaviorTreeProject *project)
void SetNodeAttributes(Node *node, xmlNodePtr xml_node)
std::shared_ptr< BehaviorTree > ParseFromFile(const EmberCore::String &filepath)
bool IsTreeImplemented(const EmberCore::String &tree_id) const
std::set< EmberCore::String > expanded_subtree_cache_
std::shared_ptr< BehaviorTree > ParseBehaviorTree(xmlNodePtr tree_node)
std::map< EmberCore::String, std::unique_ptr< Blackboard > > parsed_blackboards_
std::unique_ptr< Node > ParseDecoratorNode(xmlNodePtr xml_node)
std::vector< ParseResult > ParseMultipleFiles(const std::vector< EmberCore::String > &filepaths)
bool ReportProgress(const EmberCore::String &message, int current=0, int total=0)
bool ValidateRequiredAttribute(xmlNodePtr node, const EmberCore::String &attr_name)
const std::map< EmberCore::String, std::shared_ptr< BehaviorTree > > & GetParsedTrees() const
Represents a node in a behavior tree structure.
Definition Node.h:20
Configuration for XML parser behavior and element/attribute mappings.
Main types header for EmberCore.
std::string String
Framework-agnostic string type.
Definition String.h:14
Per-file parsing information for project validation.
ParseError(Type t, const EmberCore::String &msg, const EmberCore::String &path="", int line=-1, int col=-1)
std::map< EmberCore::String, std::vector< EmberCore::String > > blackboard_includes_map
std::map< EmberCore::String, TreeImplementationStatus > tree_statuses
std::map< EmberCore::String, std::shared_ptr< BehaviorTree > > parsed_trees
std::map< EmberCore::String, std::shared_ptr< Blackboard > > parsed_blackboards