Merge "Rename restconf-binding-parent -> restconf-parent"
[netconf.git] / netconf / mdsal-netconf-connector / src / main / java / org / opendaylight / netconf / mdsal / connector / ops / CopyConfig.java
1 /*
2  * Copyright (c) 2018 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.netconf.mdsal.connector.ops;
10
11 import com.google.common.base.Optional;
12 import org.opendaylight.controller.config.util.xml.DocumentedException;
13 import org.opendaylight.controller.config.util.xml.DocumentedException.ErrorSeverity;
14 import org.opendaylight.controller.config.util.xml.DocumentedException.ErrorTag;
15 import org.opendaylight.controller.config.util.xml.DocumentedException.ErrorType;
16 import org.opendaylight.controller.config.util.xml.XmlElement;
17 import org.opendaylight.controller.config.util.xml.XmlUtil;
18 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
19 import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
20 import org.opendaylight.netconf.api.xml.XmlNetconfConstants;
21 import org.opendaylight.netconf.mdsal.connector.CurrentSchemaContext;
22 import org.opendaylight.netconf.mdsal.connector.TransactionProvider;
23 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
24 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
25 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
26 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
27 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNormalizedNodeStreamWriter;
28 import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeResult;
29 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
30 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
31 import org.w3c.dom.Document;
32 import org.w3c.dom.Element;
33
34 public final class CopyConfig extends AbstractEdit {
35     private static final String OPERATION_NAME = "copy-config";
36     private static final String CONFIG_KEY = "config";
37     private static final String SOURCE_KEY = "source";
38
39     // Top-level "data" node without child nodes
40     private static final ContainerNode EMPTY_ROOT_NODE = Builders.containerBuilder()
41         .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(SchemaContext.NAME)).build();
42
43     private final TransactionProvider transactionProvider;
44
45     public CopyConfig(final String netconfSessionIdForReporting, final CurrentSchemaContext schemaContext,
46                       final TransactionProvider transactionProvider) {
47         super(netconfSessionIdForReporting, schemaContext);
48         this.transactionProvider = transactionProvider;
49     }
50
51     @Override
52     protected Element handleWithNoSubsequentOperations(final Document document, final XmlElement operationElement)
53             throws DocumentedException {
54         final Datastore targetDatastore = extractTargetParameter(operationElement, OPERATION_NAME);
55         if (targetDatastore == Datastore.running) {
56             throw new DocumentedException("edit-config on running datastore is not supported",
57                     ErrorType.PROTOCOL,
58                     ErrorTag.OPERATION_NOT_SUPPORTED,
59                     ErrorSeverity.ERROR);
60         }
61         final XmlElement configElement = extractConfigParameter(operationElement);
62
63         // <copy-config>, unlike <edit-config>, always replaces entire configuration,
64         // so remove old configuration first:
65         final DOMDataReadWriteTransaction rwTx = transactionProvider.getOrCreateTransaction();
66         rwTx.put(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier.EMPTY, EMPTY_ROOT_NODE);
67
68         // Then create nodes present in the <config> element:
69         for (final XmlElement element : configElement.getChildElements()) {
70             final String ns = element.getNamespace();
71             final DataSchemaNode schemaNode = getSchemaNodeFromNamespace(ns, element);
72             final NormalizedNodeResult resultHolder = new NormalizedNodeResult();
73             parseIntoNormalizedNode(schemaNode, element, ImmutableNormalizedNodeStreamWriter.from(resultHolder));
74             final NormalizedNode<?, ?> data = resultHolder.getResult();
75             final YangInstanceIdentifier path = YangInstanceIdentifier.create(data.getIdentifier());
76             // Doing merge instead of put to support top-level list:
77             rwTx.merge(LogicalDatastoreType.CONFIGURATION, path, data);
78         }
79         return XmlUtil.createElement(document, XmlNetconfConstants.OK, Optional.absent());
80     }
81
82     private static XmlElement extractConfigParameter(final XmlElement operationElement) throws DocumentedException {
83         final XmlElement source = getElement(operationElement, SOURCE_KEY);
84         return getElement(source, CONFIG_KEY);
85     }
86
87     @Override
88     protected String getOperationName() {
89         return OPERATION_NAME;
90     }
91 }