Adjust to yangtools-2.0.0/odlparent-3.0.0 changes
[netconf.git] / restconf / restconf-nb-rfc8040 / src / main / java / org / opendaylight / restconf / nb / rfc8040 / handlers / SchemaContextHandler.java
1 /*
2  * Copyright (c) 2016 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 package org.opendaylight.restconf.nb.rfc8040.handlers;
9
10 import com.google.common.base.Preconditions;
11 import java.util.Collection;
12 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
13 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
14 import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
15 import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
16 import org.opendaylight.restconf.nb.rfc8040.RestConnectorProvider;
17 import org.opendaylight.restconf.nb.rfc8040.Rfc8040.IetfYangLibrary;
18 import org.opendaylight.restconf.nb.rfc8040.Rfc8040.MonitoringModule;
19 import org.opendaylight.restconf.nb.rfc8040.utils.mapping.RestconfMappingNodeUtil;
20 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
21 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
22 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
23 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
24 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
25 import org.opendaylight.yangtools.yang.data.api.schema.tree.ConflictingModificationAppliedException;
26 import org.opendaylight.yangtools.yang.model.api.Module;
27 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
30
31 /**
32  * Implementation of {@link SchemaContextHandler}.
33  *
34  */
35 public class SchemaContextHandler implements SchemaContextListenerHandler {
36
37     private static final Logger LOG = LoggerFactory.getLogger(SchemaContextHandler.class);
38
39     private final TransactionChainHandler transactionChainHandler;
40     private SchemaContext context;
41     private static SchemaContext actualSchemaContext;
42
43     private int moduleSetId;
44
45     /**
46      * Set module-set-id on initial value - 0.
47      *
48      * @param transactionChainHandler Transaction chain handler
49      */
50     public SchemaContextHandler(final TransactionChainHandler transactionChainHandler) {
51         this.transactionChainHandler = transactionChainHandler;
52         this.moduleSetId = 0;
53         actualSchemaContext = null;
54     }
55
56     @Override
57     @SuppressWarnings("checkstyle:hiddenField")
58     public void onGlobalContextUpdated(final SchemaContext context) {
59         Preconditions.checkNotNull(context);
60         this.context = null;
61         this.context = context;
62
63         actualSchemaContext = context;
64
65         this.moduleSetId++;
66         final Module ietfYangLibraryModule =
67                 context.findModule(IetfYangLibrary.MODULE_QNAME).orElse(null);
68         NormalizedNode<NodeIdentifier, Collection<DataContainerChild<? extends PathArgument, ?>>> normNode =
69                 RestconfMappingNodeUtil.mapModulesByIetfYangLibraryYang(context.getModules(), ietfYangLibraryModule,
70                         context, String.valueOf(this.moduleSetId));
71         putData(normNode);
72
73         final Module monitoringModule =
74                 this.context.findModule(MonitoringModule.MODULE_QNAME).orElse(null);
75         normNode = RestconfMappingNodeUtil.mapCapabilites(monitoringModule);
76         putData(normNode);
77     }
78
79     @Override
80     public SchemaContext get() {
81         return this.context;
82     }
83
84     public static SchemaContext getActualSchemaContext() {
85         return actualSchemaContext;
86     }
87
88     public static void setActualSchemaContext(final SchemaContext schemaContext) {
89         actualSchemaContext = schemaContext;
90     }
91
92     private void putData(
93             final NormalizedNode<NodeIdentifier, Collection<DataContainerChild<? extends PathArgument, ?>>> normNode) {
94         final DOMDataWriteTransaction wTx = this.transactionChainHandler.get().newWriteOnlyTransaction();
95         wTx.put(LogicalDatastoreType.OPERATIONAL,
96                 YangInstanceIdentifier.create(NodeIdentifier.create(normNode.getNodeType())), normNode);
97         try {
98             wTx.submit().checkedGet();
99         } catch (final TransactionCommitFailedException e) {
100             if (!(e.getCause() instanceof ConflictingModificationAppliedException)) {
101                 throw new RestconfDocumentedException("Problem occurred while putting data to DS.", e);
102             }
103
104             /*
105               Ignore error when another cluster node is already putting the same data to DS.
106               We expect that cluster is homogeneous and that node was going to write the same data
107               (that means no retry is needed). Transaction chain reset must be invoked to be able
108               to continue writing data with another transaction after failed transaction.
109               This is workaround for bug:
110               https://bugs.opendaylight.org/show_bug.cgi?id=7728
111             */
112             LOG.warn("Ignoring that another cluster node is already putting the same data to DS.", e);
113             RestConnectorProvider.resetTransactionChainForAdapaters(this.transactionChainHandler.get());
114         }
115     }
116 }