示例#1
0
// ATTN: This function seriously needs re-organization, will be done
// shortly.
rw_yang_netconf_op_status_t XMLDocMerger::do_edit(XMLNode* new_node, 
                XMLNode* delta_node,
                XMLNode* update_node,
                bool* update_required)
{
  rw_yang_netconf_op_status_t status = RW_YANG_NETCONF_OP_STATUS_OK;
  YangNode* ynode = new_node->get_descend_yang_node();
  XMLEditDefaultOperation parent_op = current_operation_;

  for(XMLNodeIter it = delta_node->child_begin();
      it != delta_node->child_end(); ++it)
  {
    XMLNode* delta_child = &(*it);
    std::string child_name = delta_child->get_local_name();
    std::string child_ns = delta_child->get_name_space();

    YangNode* child_ynode = ynode->search_child(child_name.c_str(), 
                                                child_ns.c_str());
    if (child_ynode == nullptr) {
      // Incoming node is not in our model and thus is an error
      std::string const err_msg = "Cannot find child ("+child_name+") of node ("+delta_node->get_local_name()+")";
      report_error(delta_node, RW_YANG_NETCONF_OP_STATUS_INVALID_VALUE, err_msg.c_str());
      return RW_YANG_NETCONF_OP_STATUS_INVALID_VALUE;
    }

    // Set the current node operation (default=merge)
    status = set_current_operation(delta_child);
    if (status !=  RW_YANG_NETCONF_OP_STATUS_OK) {
      return status;
    }

    bool subtree_update = false;

    XMLNode* new_child = new_node->find(child_name.c_str(), child_ns.c_str());
    if (new_child == nullptr) {
      // Node not found in existing config, edit-config on new node
      status = do_edit_new(child_ynode, new_node, delta_child, 
                           update_node, &subtree_update);
    } else {
      status = do_edit_existing(child_ynode, new_node, new_child, delta_child,
                           update_node, &subtree_update);
    }

    *update_required = (*update_required || subtree_update);

    if (status !=  RW_YANG_NETCONF_OP_STATUS_OK) {
      return status;
    }
    current_operation_ = parent_op;
  }

  if (current_operation_ == XML_EDIT_OP_REPLACE) {
    // Iterate thru the config dom node and find the elements not in delta
    // Those are marked for deletion.
    do_delete_missing(new_node, delta_node);
  }

  // Add defaults
  fill_defaults(ynode, new_node, update_node, update_required);

  if (!(*update_required)) {
    // No updates on this subtree. Either it is delete/remove operation or
    // the config is not changed. So remove the update subtree. 
    XMLNode* parent = update_node->get_parent();
    if (parent) {
      parent->remove_child(update_node);
    }
  }

  if (new_node->get_first_child() == nullptr &&
      ynode->get_stmt_type() == RW_YANG_STMT_TYPE_CONTAINER &&
      !ynode->is_presence()) {
    // No children for a non-presence container, they are only present to
    // maintain hierarchy. Remove it
    XMLNode* parent = new_node->get_parent();
    if (parent) {
      parent->remove_child(new_node);
    }
  }

  return status;
}
示例#2
0
rw_tree_walker_status_t add_xml_child (XMLNode *parent,
                                       rw_confd_value_t *confd,
                                       XMLNode*& child)
{
  confd_cs_node *cs_node = confd->cs_node;
  confd_value_t *child_src = confd->value;
  const char *name = confd_hash2str (confd->cs_node->tag);
  const char *ns = confd_hash2str (confd->cs_node->ns);

  YangNode *child_yn = nullptr;
  child = nullptr;

  YangNode *yn = parent->get_yang_node();
  if (!yn) {
    return RW_TREE_WALKER_FAILURE;
  }

  child_yn = yn->search_child (name, ns);
  if (!child_yn) {
    return RW_TREE_WALKER_FAILURE;
  }

  if (!child_yn->is_leafy()) {
    child = parent->add_child(child_yn);
    if (child) {
      return RW_TREE_WALKER_SUCCESS;
    }

    return RW_TREE_WALKER_FAILURE;
  }

  char value[1024];
  char *val_p = nullptr;
  
  switch (child_src->type) {
    default:
    case C_QNAME: 
    case C_DATETIME: 
    case C_DATE: 
    case C_TIME: 
    case C_DURATION:
    case C_NOEXISTS:
    case C_STR:
    case C_SYMBOL:
    case C_BIT32: 
    case C_BIT64:
    case C_XMLBEGIN:  
    case C_XMLEND: 
    case C_OBJECTREF: 
    case C_UNION: 
    case C_PTR: 
    case C_CDBBEGIN: 
    case C_OID: 
    case C_DEFAULT: 
    case C_IDENTITYREF: 
    case C_XMLBEGINDEL: 
    case C_DQUAD: 
    case C_HEXSTR: 

      RW_CRASH();
    break;
    
    case C_XMLTAG:
      break;

    case C_BUF: 
    case C_INT8: 
    case C_INT16: 
    case C_INT32: 
    case C_INT64: 
    case C_UINT8: 
    case C_UINT16: 
    case C_UINT32: 
    case C_UINT64: 
    case C_DOUBLE: 
    case C_BOOL: 
    case C_ENUM_VALUE:
    case C_BINARY: 
    case C_DECIMAL64: 
    case C_IPV4: 
    case C_IPV6: 
    case C_IPV4PREFIX:
    case C_IPV4_AND_PLEN: 
    case C_IPV6_AND_PLEN: 
    case C_IPV6PREFIX: {

      struct confd_type *ct = cs_node->info.type;
      
      int len = confd_val2str (ct, child_src, value, sizeof (value));
      if (len < 0) {
        return RW_TREE_WALKER_FAILURE;
      }
      val_p = &value[0];
    }
      
      break;
    case C_LIST: {
      
      // ATTN: ATTN:
      // This code is inefficient. TAIL-F has been asked what the best method
      // for doing this is. Once TAILF responds, change this code.

      // ATTN: ATTN:
      // This also needs to change when protobuf representation of a leaf list
      // transitions to becoming a list of single elements
      

      struct confd_type *ct = confd_get_leaf_list_type (cs_node);
      RW_ASSERT(ct);
      
      int len = confd_val2str (ct, child_src, value, sizeof (value));
      if (len < 0) {
        return RW_TREE_WALKER_FAILURE;
      }
      val_p = &value[0];
    }
      break;
  }
  child = parent->add_child (child_yn, val_p);
  if (child) {
    return RW_TREE_WALKER_SUCCESS;
  }

  return RW_TREE_WALKER_FAILURE;
}