Exemplo n.º 1
0
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;
      }
    }
  }
}