@@ -13,6 +13,21 @@ namespace tesseract_common
1313{
1414namespace property_type
1515{
16+ /* *
17+ * @brief A utility for constructing the list type
18+ * @param type The type assoicated with the list
19+ * @return The string representation of the std::vector<type>, aka. type[]
20+ */
21+ std::string createList (std::string_view type);
22+
23+ /* *
24+ * @brief A utility for constructing the map type
25+ * @param key_type The type assoicated with the map key
26+ * @param value_type The type assoicated with the map value
27+ * @return The string representation of the std::make<key_type, value_type>, aka. {key_type : value_type}
28+ */
29+ std::string createMap (std::string_view key_type, std::string_view value_type);
30+
1631// Integral Types
1732constexpr std::string_view BOOL{ " bool" };
1833constexpr std::string_view CHAR{ " char" };
@@ -26,11 +41,11 @@ constexpr std::string_view DOUBLE{ "double" };
2641
2742// Eigen Types
2843constexpr std::string_view EIGEN_ISOMETRY_3D{ " Eigen::Isometry3d" };
29- constexpr std::string_view EIGEN_MATRIX_XD{ " Eigen::MatrixXd" };
44+ // constexpr std::string_view EIGEN_MATRIX_XD{ "Eigen::MatrixXd" };
3045constexpr std::string_view EIGEN_VECTOR_XD{ " Eigen::VectorXd" };
31- constexpr std::string_view EIGEN_MATRIX_2D{ " Eigen::Matrix2d" };
46+ // constexpr std::string_view EIGEN_MATRIX_2D{ "Eigen::Matrix2d" };
3247constexpr std::string_view EIGEN_VECTOR_2D{ " Eigen::Vector2d" };
33- constexpr std::string_view EIGEN_MATRIX_3D{ " Eigen::Matrix3d" };
48+ // constexpr std::string_view EIGEN_MATRIX_3D{ "Eigen::Matrix3d" };
3449constexpr std::string_view EIGEN_VECTOR_3D{ " Eigen::Vector3d" };
3550} // namespace property_type
3651
@@ -77,21 +92,22 @@ class PropertyTree
7792 PropertyTree () = default ;
7893
7994 /* *
80- * @brief Merge schema metadata into this node.
81- *
82- * Copies attributes from the schema, applies defaults for non-required
83- * properties, registers schema validators, and recursively merges children.
84- * @param schema PropertyTree containing schema definitions.
95+ * @brief Given that *this* is purely a schema tree, merge in the
96+ * user’s YAML config to populate all values (and apply defaults).
97+ * @param config The user-supplied YAML::Node (possibly null).
98+ * @param allow_extra_properties If false, “extra” keys in config will be flagged.
8599 */
86- void mergeSchema (const PropertyTree& schema );
100+ void mergeConfig (const YAML::Node& config, bool allow_extra_properties = false );
87101
88102 /* *
89103 * @brief Validate the tree using registered validators.
90104 *
91105 * Recursively invokes all validators on this node and its children.
92106 * Throws on the first error encountered.
107+ *
108+ * @param allow_extra_properties Indicate if extra properties are allowed
93109 */
94- void validate () const ;
110+ void validate (bool allow_extra_properties = false ) const ;
95111
96112 /* *
97113 * @brief Register a custom validator for this node.
@@ -139,6 +155,12 @@ class PropertyTree
139155 */
140156 bool isNull () const ;
141157
158+ /* *
159+ * @brief Check if property is a container of child properties
160+ * @return True if container, otherwise false
161+ */
162+ bool isContainer () const ;
163+
142164 /* *
143165 * @brief List all immediate child keys.
144166 * @return Vector of child key strings.
@@ -204,11 +226,19 @@ class PropertyTree
204226
205227private:
206228 YAML::Node value_; /* *< Value stored at this node */
229+ YAML::Node follow_; /* *< Follow stored at this node */
207230 std::map<std::string, YAML::Node> attributes_; /* *< Metadata attributes */
208231 std::map<std::string, PropertyTree> children_; /* *< Nested child nodes */
209232 std::vector<ValidatorFn> validators_; /* *< Validators to invoke */
210233};
211234
235+ /* *
236+ * @brief Check if type is a sequence
237+ * @param type The type to check
238+ * @return If it is a sequence the underlying type is returned
239+ */
240+ std::optional<std::string> isSequenceType (std::string_view type);
241+
212242/* *
213243 * @brief Validator: ensure 'required' attribute is present and non-null.
214244 * @param node Node to validate.
@@ -217,18 +247,86 @@ class PropertyTree
217247void validateRequired (const PropertyTree& node);
218248
219249/* *
220- * @brief Validator: enforce 'minimum'/'maximum' range constraints .
250+ * @brief Validator: enforce that node's value is in 'enum' list .
221251 * @param node Node to validate.
222- * @throws runtime_error if out of range.
252+ * @throws runtime_error if not found.
253+ */
254+ void validateEnum (const PropertyTree& node);
255+
256+ /* *
257+ * @brief Validtor: ensure node value is of type YAML::NodeType::Map
258+ * @param node Node to validate.
259+ * @throws runtime_error if not correct type.
223260 */
224- void validateRange (const PropertyTree& node);
261+ void validateMap (const PropertyTree& node);
225262
226263/* *
227- * @brief Validator: enforce that node's value is in 'enum' list.
264+ * @brief Validtor: ensure node value is of type YAML::NodeType::Sequence
265+ * @param node Node to validate.
266+ * @throws runtime_error if not correct type.
267+ */
268+ void validateSequence (const PropertyTree& node);
269+
270+ void validateCustomType (const PropertyTree& node);
271+
272+ /* *
273+ * @brief Validate that the node’s value can be interpreted as the provided type.
274+ * @param node PropertyTree node whose value to validate.
275+ * @throws std::runtime_error or YAML::BadConversion if the value is not a valid type.
276+ */
277+ template <typename T>
278+ void validateTypeCast (const PropertyTree& node)
279+ {
280+ try
281+ {
282+ node.getValue ().as <T>();
283+ }
284+ catch (const std::exception& e)
285+ {
286+ std::throw_with_nested (e);
287+ }
288+ }
289+
290+ /* *
291+ * @brief Validator: type cast and enforce 'minimum'/'maximum' range constraints.
228292 * @param node Node to validate.
229- * @throws runtime_error if not found .
293+ * @throws runtime_error if out of range .
230294 */
231- void validateEnum (const PropertyTree& node);
295+ template <typename T>
296+ void validateTypeCastWithRange (const PropertyTree& node)
297+ {
298+ // Get value
299+ const T val = [&]() {
300+ try
301+ {
302+ return node.getValue ().as <T>();
303+ }
304+ catch (const std::exception& e)
305+ {
306+ std::throw_with_nested (e);
307+ }
308+ }();
309+
310+ // If minimum attribute exist, validate
311+ auto min_attr = node.getAttribute (property_attribute::MINIMUM);
312+ if (min_attr)
313+ {
314+ const auto minv = min_attr->as <T>();
315+ if (val < minv)
316+ std::throw_with_nested (std::runtime_error (" Property value " + std::to_string (val) + " is less than minimum " +
317+ std::to_string (minv)));
318+ }
319+
320+ // If maximum attribute exist, validate
321+ auto max_attr = node.getAttribute (property_attribute::MAXIMUM);
322+ if (max_attr)
323+ {
324+ const auto maxv = max_attr->as <T>();
325+ if (val > maxv)
326+ std::throw_with_nested (std::runtime_error (" Property value " + std::to_string (val) + " is greater than maximum " +
327+ std::to_string (maxv)));
328+ }
329+ }
232330
233331} // namespace tesseract_common
234332
0 commit comments