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