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;
      }
    }
  }
}
Exemplo n.º 2
0
rw_yang_netconf_op_status_t XMLDocMerger::do_delete(
                YangNode* child_ynode,
                XMLNode* new_node,
                XMLNode* new_child,
                XMLNode* delta_child)
{
  rw_yang_netconf_op_status_t status = RW_YANG_NETCONF_OP_STATUS_OK;
  
  // The deletion of last case node should add default-case default-values
  // This is taken care by fill_defaults()

  XMLNode* remove_node = new_child;
  xml_data_presence_t data_presence = check_if_data_exists(child_ynode,
                                              new_node, delta_child, &remove_node);
  switch(data_presence) {
    case XML_DATA_MISSING: {
      if (current_operation_ == XML_EDIT_OP_DELETE) {
        std::string const error_msg = "Node ("
                                      + new_node->get_local_name()
                                      + ") has missing data";
        report_error(delta_child, RW_YANG_NETCONF_OP_STATUS_DATA_MISSING, error_msg.c_str());
        return RW_YANG_NETCONF_OP_STATUS_DATA_MISSING;
      }
      return status;
    }
    case XML_DATA_EXISTS: {
      // If a leaf node has default value and is deleted, then don't report it,
      // just delete the node, the default value will added when fill_defaults
      // is invoked.
      if (child_ynode->get_default_value() == nullptr) {
        // Neither a leaf nor a leaf with default value
        report_delete(remove_node);
      } else {
        // has default value, if it is part of a case and is the last node, and
        // is not part of the default case then report deletion
        YangNode* ycase = child_ynode->get_case();
        YangNode* ychoice = child_ynode->get_choice();
        if (ychoice && ycase != ychoice->get_default_case()) {
          bool found = false;
          // Iterate thru the subtree to find if any node in the existing case
          // exists. If so, don't report
          for (XMLNodeIter it = new_node->child_begin();
               it != new_node->child_end(); ++it) {
            XMLNode* xnode = &(*it);
            if (xnode != remove_node && 
                xnode->get_yang_node()->get_case() == ycase) {
              found = true;
            }
          }
          if (!found) {
            report_delete(remove_node);
          }
        }
      }
      new_node->remove_child(remove_node);
      break;
    }
    case XML_DATA_LIST_EXISTS: {
      // remove all the data with the list name
      for (XMLNode* xchild = new_node->get_first_child(); xchild; ) {
        if (xchild->get_local_name() == child_ynode->get_name() &&
            xchild->get_name_space() == child_ynode->get_ns()) {
          XMLNode* next_node = xchild->get_next_sibling();

          // Multiple keyspecs, report the deletion and remove it from dom
          report_delete(xchild);
          new_node->remove_child(xchild);
          xchild = next_node;
        } else {
          xchild = xchild->get_next_sibling();
        }
      }
      break;
    }
  }

  return status;
}