#pragma once #include #include #include #include #include "IDataValue.h" namespace grove { /** * @brief Interface for a single node in the data tree * * Each node can have: * - Children nodes (tree navigation) * - Its own data blob (IDataValue) * - Properties accessible by name with type safety */ class IDataNode { public: virtual ~IDataNode() = default; // ======================================== // TREE NAVIGATION // ======================================== /** * @brief Get direct child by name (transfers ownership) * @param name Exact name of the child * @return Child node or nullptr if not found * @warning This removes the child from the tree. Use getChildReadOnly() for non-destructive reads. */ virtual std::unique_ptr getChild(const std::string& name) = 0; /** * @brief Get direct child by name (read-only, no ownership transfer) * @param name Exact name of the child * @return Raw pointer to child node or nullptr if not found * @note The returned pointer is valid as long as the parent node exists and the child isn't removed. */ virtual IDataNode* getChildReadOnly(const std::string& name) = 0; /** * @brief Get names of all direct children * @return Vector of child names */ virtual std::vector getChildNames() = 0; /** * @brief Check if this node has any children * @return true if children exist */ virtual bool hasChildren() = 0; /** * @brief Check if this node has a direct child with the given name * @param name Exact name of the child to check * @return true if child exists */ virtual bool hasChild(const std::string& name) const = 0; // ======================================== // EXACT SEARCH IN CHILDREN // ======================================== /** * @brief Find all children with exact name (direct children only) * @param name Exact name to search for * @return Vector of matching child nodes */ virtual std::vector getChildrenByName(const std::string& name) = 0; /** * @brief Check if any children have the exact name * @param name Exact name to search for * @return true if found */ virtual bool hasChildrenByName(const std::string& name) const = 0; /** * @brief Get first child with exact name * @param name Exact name to search for * @return First matching child or nullptr */ virtual IDataNode* getFirstChildByName(const std::string& name) = 0; // ======================================== // PATTERN MATCHING SEARCH (DEEP SEARCH IN WHOLE SUBTREE) // ======================================== /** * @brief Find all nodes in subtree matching pattern * @param pattern Pattern with wildcards (* supported) * @return Vector of matching nodes in entire subtree * * Examples: * - "component*" matches "component_armor", "component_engine" * - "*heavy*" matches "tank_heavy_mk1", "artillery_heavy" * - "model_*" matches "model_01", "model_02" */ virtual std::vector getChildrenByNameMatch(const std::string& pattern) = 0; /** * @brief Check if any nodes in subtree match pattern * @param pattern Pattern with wildcards * @return true if any matches found */ virtual bool hasChildrenByNameMatch(const std::string& pattern) const = 0; /** * @brief Get first node in subtree matching pattern * @param pattern Pattern with wildcards * @return First matching node or nullptr */ virtual IDataNode* getFirstChildByNameMatch(const std::string& pattern) = 0; // ======================================== // QUERY BY PROPERTIES // ======================================== /** * @brief Query nodes in subtree by property value * @param propName Property name to check * @param predicate Function to test property value * @return Vector of nodes where predicate returns true * * Example: * // Find all tanks with armor > 150 * queryByProperty("armor", [](const IDataValue& val) { * return val.isNumber() && val.asInt() > 150; * }); */ virtual std::vector queryByProperty(const std::string& propName, const std::function& predicate) = 0; // ======================================== // NODE'S OWN DATA // ======================================== /** * @brief Get this node's data blob * @return Data value or null if no data */ virtual std::unique_ptr getData() const = 0; /** * @brief Check if this node has data * @return true if data exists */ virtual bool hasData() const = 0; /** * @brief Set this node's data * @param data Data to set */ virtual void setData(std::unique_ptr data) = 0; // ======================================== // TYPED DATA ACCESS BY PROPERTY NAME // ======================================== /** * @brief Get string property from this node's data * @param name Property name * @param defaultValue Default if property not found or wrong type * @return Property value or default */ virtual std::string getString(const std::string& name, const std::string& defaultValue = "") const = 0; /** * @brief Get integer property from this node's data * @param name Property name * @param defaultValue Default if property not found or wrong type * @return Property value or default */ virtual int getInt(const std::string& name, int defaultValue = 0) const = 0; /** * @brief Get double property from this node's data * @param name Property name * @param defaultValue Default if property not found or wrong type * @return Property value or default */ virtual double getDouble(const std::string& name, double defaultValue = 0.0) const = 0; /** * @brief Get boolean property from this node's data * @param name Property name * @param defaultValue Default if property not found or wrong type * @return Property value or default */ virtual bool getBool(const std::string& name, bool defaultValue = false) const = 0; /** * @brief Check if property exists in this node's data * @param name Property name * @return true if property exists */ virtual bool hasProperty(const std::string& name) const = 0; // ======================================== // TYPED DATA MODIFICATION BY PROPERTY NAME // ======================================== /** * @brief Set string property in this node's data * @param name Property name * @param value Value to set * * Only works for data/ and runtime/ nodes. Config nodes are read-only. */ virtual void setString(const std::string& name, const std::string& value) = 0; /** * @brief Set integer property in this node's data * @param name Property name * @param value Value to set * * Only works for data/ and runtime/ nodes. Config nodes are read-only. */ virtual void setInt(const std::string& name, int value) = 0; /** * @brief Set double property in this node's data * @param name Property name * @param value Value to set * * Only works for data/ and runtime/ nodes. Config nodes are read-only. */ virtual void setDouble(const std::string& name, double value) = 0; /** * @brief Set boolean property in this node's data * @param name Property name * @param value Value to set * * Only works for data/ and runtime/ nodes. Config nodes are read-only. */ virtual void setBool(const std::string& name, bool value) = 0; // ======================================== // HASH SYSTEM FOR VALIDATION & SYNCHRO // ======================================== /** * @brief Get hash of this node's data only * @return SHA256 hash of data blob */ virtual std::string getDataHash() = 0; /** * @brief Get recursive hash of this node and all children * @return SHA256 hash of entire subtree */ virtual std::string getTreeHash() = 0; /** * @brief Get hash of specific child subtree * @param childPath Path to child from this node * @return SHA256 hash of child subtree */ virtual std::string getSubtreeHash(const std::string& childPath) = 0; // ======================================== // METADATA // ======================================== /** * @brief Get full path from root to this node * @return Path string (e.g., "vehicles/tanks/heavy/model5") */ virtual std::string getPath() const = 0; /** * @brief Get this node's name * @return Node name */ virtual std::string getName() const = 0; /** * @brief Get node type (extensible for templates/inheritance later) * @return Node type identifier */ virtual std::string getNodeType() const = 0; // ======================================== // TREE MODIFICATION (For data/ and runtime/ nodes) // ======================================== /** * @brief Add or update a child node * @param name Child name * @param node Child node to add/replace * * If a child with this name already exists, it will be replaced. * Only works for data/ and runtime/ nodes. Config nodes are read-only. */ virtual void setChild(const std::string& name, std::unique_ptr node) = 0; /** * @brief Remove a child node * @param name Child name to remove * @return true if child was found and removed * * Only works for data/ and runtime/ nodes. Config nodes are read-only. */ virtual bool removeChild(const std::string& name) = 0; /** * @brief Clear all children from this node * * Only works for data/ and runtime/ nodes. Config nodes are read-only. */ virtual void clearChildren() = 0; }; } // namespace grove