void XMLDocMerger::fill_defaults( YangNode* ynode, XMLNode* new_node, XMLNode* update_node, bool* update_required ) { YangNode* yn = nullptr; XMLNode* xchild = nullptr; for (YangNodeIter it = ynode->child_begin(); it != ynode->child_end(); ++it) { yn = &(*it); const char* default_val = yn->get_default_value(); if (!default_val && !yn->has_default()) { // Only default values or containers with default leaf descendents continue; } // Default values may be within a choice/case. Check if the choice has // another case. If the same case is present YangNode* ychoice = yn->get_choice(); YangNode* ycase = yn->get_case(); YangNode* other_choice = nullptr; YangNode* other_case = nullptr; bool add_default = true; bool subtree_update = false; if (ychoice && ycase && (ychoice->get_default_case() != ycase)) { add_default = false; } for (XMLNodeIter xit = new_node->child_begin(); xit != new_node->child_end(); ++xit) { xchild = &(*xit); if (xchild->get_local_name() == yn->get_name() && xchild->get_name_space() == yn->get_ns()) { if (yn->get_stmt_type() == RW_YANG_STMT_TYPE_CONTAINER) { // The container has a default descendant node XMLNode* update_child = nullptr; bool created = false; if ((update_child = update_node->find( yn->get_name(), yn->get_ns())) == nullptr) { update_child = update_node->add_child(yn); created = true; } fill_defaults(yn, xchild, update_child, &subtree_update); if (!subtree_update && created) { update_node->remove_child(update_child); } *update_required = (*update_required || subtree_update); } // Default node already present in the new-dom add_default = false; break; } if (!ychoice) { // Not part of a choice continue; } other_choice = xchild->get_yang_node()->get_choice(); if (!other_choice || (other_choice != ychoice)) { // Other node is not a choice, or not the same choice, not conflicting continue; } other_case = xchild->get_yang_node()->get_case(); if (other_case && (ycase != other_case)) { // There is a node with conflicting case. Hence no default add_default = false; break; } // Same case, in-case the case is not default, some-other node in the same // case is set. Then add this default, unless the same node is found in // the new-dom. add_default = true; } if (add_default) { XMLNode* xn = new_node->add_child(yn, default_val); RW_ASSERT(xn); XMLNode* un = update_node->add_child(yn, default_val); if (yn->get_stmt_type() == RW_YANG_STMT_TYPE_CONTAINER) { // The container has a default descendant node fill_defaults(yn, xn, un, &subtree_update); if (!subtree_update) { new_node->remove_child(xn); update_node->remove_child(un); } *update_required = (*update_required || subtree_update); } else { *update_required = true; } } } }
rw_status_t get_confd_case ( rw_yang::XMLNode *root, confd_hkeypath_t *keypath, confd_value_t *choice, confd_value_t *case_val) { RW_ASSERT (case_val); rw_yang::XMLNode *node = get_node_by_hkeypath (root, keypath, 0); if (nullptr == node) { return RW_STATUS_FAILURE; } XMLNodeList::uptr_t children(node->get_children()); for (size_t i = 0; i < children->length(); i++) { XMLNode* child = children->at(i); YangNode *yn = child->get_descend_yang_node(); if (nullptr == yn) { continue; } YangNode *yn_case = yn->get_case(); if (nullptr == yn_case) { continue; } // The comparision starts with the choice.. YangNode *yn_choice = yn_case->get_choice(); RW_ASSERT (yn_choice); while (choice->type != C_NOEXISTS) { RW_ASSERT (choice->type == C_XMLTAG); const char * tag = confd_hash2str (choice->val.xmltag.tag); int n_s = choice->val.xmltag.ns; const char *ns = confd_hash2str (n_s); if (strcmp (tag, yn_choice->get_name()) || strcmp (ns, yn_choice->get_ns())) { break; } // The case matches - check if choice exists choice++; if (C_NOEXISTS == choice->type) { case_val->type = C_XMLTAG; case_val->val.xmltag.ns = n_s; case_val->val.xmltag.tag = confd_str2hash (yn_case->get_name()); return RW_STATUS_SUCCESS; } RW_ASSERT (choice->type == C_XMLTAG); yn_case = yn_choice->get_case(); // Can this be null?? RW_ASSERT (yn_case); tag = confd_hash2str (choice->val.xmltag.tag); ns = confd_hash2str (choice->val.xmltag.ns); if (strcmp (tag, yn_case->get_name()) || strcmp (ns, yn_case->get_ns())) { break; } } } return RW_STATUS_FAILURE; }