@@ -193,6 +193,12 @@ void A2uiValidator::check_component_integrity(const std::optional<std::string>&
193193 throw std::runtime_error (" Missing root component: No component has id='" + *root_id + " '" );
194194 }
195195
196+ auto check_ref = [&](const std::string& comp_id, const std::string& ref_id, const std::string& field_name) {
197+ if (ids.find (ref_id) == ids.end ()) {
198+ throw std::runtime_error (" Component '" + comp_id + " ' references non-existent component '" + ref_id + " ' in field '" + field_name + " '" );
199+ }
200+ };
201+
196202 for (const auto & comp : components) {
197203 if (comp.contains (" component" ) && comp[" component" ].is_object ()) {
198204 auto comp_def = comp[" component" ];
@@ -222,76 +228,134 @@ void A2uiValidator::check_component_integrity(const std::optional<std::string>&
222228 }
223229 }
224230
225- if (!skip_root_check && root_id.has_value ()) {
226- auto check_ref = [&](const std::string& ref_id, const std::string& field_name) {
227- if (ids.find (ref_id) == ids.end ()) {
228- throw std::runtime_error (" Component '" + comp.value (" id" , " " ) + " ' references non-existent component '" + ref_id + " ' in field '" + field_name + " '" );
229- }
230- };
231+ std::string comp_id = comp.value (" id" , " unknown" );
231232
232- if (comp.contains (" child" ) && comp[" child" ].is_string ()) {
233- check_ref (comp[" child" ].get <std::string>(), " child" );
233+ if (comp.contains (" child" )) {
234+ if (!comp[" child" ].is_string ()) {
235+ throw std::runtime_error (" Validation failed: 'child' must be a string" );
234236 }
235- if (comp.contains (" children" )) {
236- const auto & children = comp[" children" ];
237- if (children.is_array ()) {
238- for (const auto & item : children) {
239- if (item.is_string ()) {
240- check_ref (item.get <std::string>(), " children" );
237+ if (!skip_root_check && root_id.has_value ()) {
238+ check_ref (comp_id, comp[" child" ].get <std::string>(), " child" );
239+ }
240+ }
241+ if (comp.contains (" children" )) {
242+ const auto & children = comp[" children" ];
243+ if (children.is_array ()) {
244+ for (const auto & item : children) {
245+ if (item.is_string ()) {
246+ if (!skip_root_check && root_id.has_value ()) {
247+ check_ref (comp_id, item.get <std::string>(), " children" );
241248 }
249+ } else {
250+ throw std::runtime_error (" Validation failed: 'children' array items must be strings" );
242251 }
243- } else if (children.is_object ()) {
244- if (children.contains (" explicitList" ) && children[" explicitList" ].is_array ()) {
245- for (const auto & item : children[" explicitList" ]) {
246- if (item.is_string ()) {
247- check_ref (item.get <std::string>(), " children.explicitList" );
252+ }
253+ } else if (children.is_object ()) {
254+ if (children.contains (" explicitList" )) {
255+ if (!children[" explicitList" ].is_array ()) {
256+ throw std::runtime_error (" Validation failed: 'explicitList' must be an array" );
257+ }
258+ for (const auto & item : children[" explicitList" ]) {
259+ if (item.is_string ()) {
260+ if (!skip_root_check && root_id.has_value ()) {
261+ check_ref (comp_id, item.get <std::string>(), " children.explicitList" );
248262 }
263+ } else {
264+ throw std::runtime_error (" Validation failed: 'explicitList' array items must be strings" );
249265 }
250266 }
251- if (children.contains (" template" ) && children[" template" ].is_object ()) {
252- const auto & temp = children[" template" ];
253- if (temp.contains (" componentId" ) && temp[" componentId" ].is_string ()) {
254- check_ref (temp[" componentId" ].get <std::string>(), " children.template.componentId" );
267+ }
268+ if (children.contains (" template" )) {
269+ if (!children[" template" ].is_object ()) {
270+ throw std::runtime_error (" Validation failed: 'template' must be an object" );
271+ }
272+ const auto & temp = children[" template" ];
273+ if (temp.contains (" componentId" )) {
274+ if (!temp[" componentId" ].is_string ()) {
275+ throw std::runtime_error (" Validation failed: 'componentId' must be a string" );
276+ }
277+ if (!skip_root_check && root_id.has_value ()) {
278+ check_ref (comp_id, temp[" componentId" ].get <std::string>(), " children.template.componentId" );
255279 }
256280 }
257- if (children.contains (" componentId" ) && children[" componentId" ].is_string ()) {
258- check_ref (children[" componentId" ].get <std::string>(), " children.componentId" );
281+ }
282+ if (children.contains (" componentId" )) {
283+ if (!children[" componentId" ].is_string ()) {
284+ throw std::runtime_error (" Validation failed: 'componentId' must be a string" );
285+ }
286+ if (!skip_root_check && root_id.has_value ()) {
287+ check_ref (comp_id, children[" componentId" ].get <std::string>(), " children.componentId" );
259288 }
260289 }
290+ } else {
291+ throw std::runtime_error (" Validation failed: 'children' must be an array or object" );
261292 }
262- if (comp.contains (" component" ) && comp[" component" ].is_object ()) {
263- for (auto it = comp[" component" ].begin (); it != comp[" component" ].end (); ++it) {
264- if (it.value ().is_object ()) {
265- auto props = it.value ();
266- if (props.contains (" child" ) && props[" child" ].is_string ()) {
267- check_ref (props[" child" ].get <std::string>(), " child" );
293+ }
294+
295+ if (comp.contains (" component" ) && comp[" component" ].is_object ()) {
296+ for (auto it = comp[" component" ].begin (); it != comp[" component" ].end (); ++it) {
297+ if (it.value ().is_object ()) {
298+ auto props = it.value ();
299+ if (props.contains (" child" )) {
300+ if (!props[" child" ].is_string ()) {
301+ throw std::runtime_error (" Validation failed: 'child' must be a string" );
268302 }
269- if (props.contains (" children" )) {
270- const auto & children = props[" children" ];
271- if (children.is_array ()) {
272- for (const auto & item : children) {
273- if (item.is_string ()) {
274- check_ref (item.get <std::string>(), " children" );
303+ if (!skip_root_check && root_id.has_value ()) {
304+ check_ref (comp_id, props[" child" ].get <std::string>(), " child" );
305+ }
306+ }
307+
308+ if (props.contains (" children" )) {
309+ const auto & children = props[" children" ];
310+ if (children.is_array ()) {
311+ for (const auto & item : children) {
312+ if (item.is_string ()) {
313+ if (!skip_root_check && root_id.has_value ()) {
314+ check_ref (comp_id, item.get <std::string>(), " children" );
275315 }
316+ } else {
317+ throw std::runtime_error (" Validation failed: 'children' array items must be strings" );
276318 }
277- } else if (children.is_object ()) {
278- if (children.contains (" explicitList" ) && children[" explicitList" ].is_array ()) {
279- for (const auto & item : children[" explicitList" ]) {
280- if (item.is_string ()) {
281- check_ref (item.get <std::string>(), " children.explicitList" );
319+ }
320+ } else if (children.is_object ()) {
321+ if (children.contains (" explicitList" )) {
322+ if (!children[" explicitList" ].is_array ()) {
323+ throw std::runtime_error (" Validation failed: 'explicitList' must be an array" );
324+ }
325+ for (const auto & item : children[" explicitList" ]) {
326+ if (item.is_string ()) {
327+ if (!skip_root_check && root_id.has_value ()) {
328+ check_ref (comp_id, item.get <std::string>(), " children.explicitList" );
282329 }
330+ } else {
331+ throw std::runtime_error (" Validation failed: 'explicitList' array items must be strings" );
283332 }
284333 }
285- if (children.contains (" template" ) && children[" template" ].is_object ()) {
286- const auto & temp = children[" template" ];
287- if (temp.contains (" componentId" ) && temp[" componentId" ].is_string ()) {
288- check_ref (temp[" componentId" ].get <std::string>(), " children.template.componentId" );
334+ }
335+ if (children.contains (" template" )) {
336+ if (!children[" template" ].is_object ()) {
337+ throw std::runtime_error (" Validation failed: 'template' must be an object" );
338+ }
339+ const auto & temp = children[" template" ];
340+ if (temp.contains (" componentId" )) {
341+ if (!temp[" componentId" ].is_string ()) {
342+ throw std::runtime_error (" Validation failed: 'componentId' must be a string" );
343+ }
344+ if (!skip_root_check && root_id.has_value ()) {
345+ check_ref (comp_id, temp[" componentId" ].get <std::string>(), " children.template.componentId" );
289346 }
290347 }
291- if (children.contains (" componentId" ) && children[" componentId" ].is_string ()) {
292- check_ref (children[" componentId" ].get <std::string>(), " children.componentId" );
348+ }
349+ if (children.contains (" componentId" )) {
350+ if (!children[" componentId" ].is_string ()) {
351+ throw std::runtime_error (" Validation failed: 'componentId' must be a string" );
352+ }
353+ if (!skip_root_check && root_id.has_value ()) {
354+ check_ref (comp_id, children[" componentId" ].get <std::string>(), " children.componentId" );
293355 }
294356 }
357+ } else {
358+ throw std::runtime_error (" Validation failed: 'children' must be an array or object" );
295359 }
296360 }
297361 }
0 commit comments