4877a735b14edbc1e16c0931ff52a511f85a7c8f
[netconf.git] / netconf / messagebus-netconf / src / main / java / org / opendaylight / netconf / messagebus / eventsources / netconf / NetconfEventSourceManager.java
1 /*
2  * Copyright (c) 2015 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.netconf.messagebus.eventsources.netconf;
9
10 import com.google.common.base.Preconditions;
11 import java.util.Collection;
12 import java.util.Map;
13 import java.util.concurrent.ConcurrentHashMap;
14 import org.opendaylight.controller.messagebus.spi.EventSourceRegistry;
15 import org.opendaylight.mdsal.binding.api.DataBroker;
16 import org.opendaylight.mdsal.binding.api.DataObjectModification;
17 import org.opendaylight.mdsal.binding.api.DataTreeChangeListener;
18 import org.opendaylight.mdsal.binding.api.DataTreeIdentifier;
19 import org.opendaylight.mdsal.binding.api.DataTreeModification;
20 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
21 import org.opendaylight.mdsal.dom.api.DOMMountPointService;
22 import org.opendaylight.mdsal.dom.api.DOMNotificationPublishService;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.network.topology.topology.topology.types.TopologyNetconf;
25 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
26 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
27 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
28 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
29 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
30 import org.opendaylight.yangtools.concepts.ListenerRegistration;
31 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
34
35 /**
36  * NetconfEventSourceManager implements DataChangeListener. On topology changes, it manages creation,
37  * updating and removing registrations of event sources.
38  */
39 public final class NetconfEventSourceManager implements DataTreeChangeListener<Node>, AutoCloseable {
40
41     private static final Logger LOG = LoggerFactory.getLogger(NetconfEventSourceManager.class);
42     private static final TopologyKey NETCONF_TOPOLOGY_KEY = new TopologyKey(
43             new TopologyId(TopologyNetconf.QNAME.getLocalName()));
44     private static final InstanceIdentifier<Node> NETCONF_DEVICE_PATH = InstanceIdentifier.create(NetworkTopology.class)
45             .child(Topology.class, NETCONF_TOPOLOGY_KEY).child(Node.class);
46
47     private Map<String, String> streamMap;
48     private final ConcurrentHashMap<InstanceIdentifier<?>, NetconfEventSourceRegistration> registrationMap =
49             new ConcurrentHashMap<>();
50     private final DOMNotificationPublishService publishService;
51     private final DOMMountPointService domMounts;
52     private ListenerRegistration<NetconfEventSourceManager> listenerRegistration;
53     private final EventSourceRegistry eventSourceRegistry;
54     private final DataBroker dataBroker;
55
56     public NetconfEventSourceManager(final DataBroker dataBroker,
57                                      final DOMNotificationPublishService domPublish,
58                                      final DOMMountPointService domMount,
59                                      final EventSourceRegistry eventSourceRegistry) {
60         Preconditions.checkNotNull(dataBroker);
61         Preconditions.checkNotNull(domPublish);
62         Preconditions.checkNotNull(domMount);
63         Preconditions.checkNotNull(eventSourceRegistry);
64         this.dataBroker = dataBroker;
65         this.domMounts = domMount;
66         this.publishService = domPublish;
67         this.eventSourceRegistry = eventSourceRegistry;
68     }
69
70     /**
71      * Invoked by blueprint.
72      */
73     public void initialize() {
74         Preconditions.checkNotNull(dataBroker);
75         listenerRegistration = dataBroker.registerDataTreeChangeListener(DataTreeIdentifier.create(
76                 LogicalDatastoreType.OPERATIONAL, NETCONF_DEVICE_PATH), this);
77         LOG.info("NetconfEventSourceManager initialized.");
78     }
79
80     @Override
81     public void onDataTreeChanged(final Collection<DataTreeModification<Node>> changes) {
82         for (DataTreeModification<Node> change: changes) {
83             LOG.debug("DataTreeModification: {}", change);
84             final DataObjectModification<Node> rootNode = change.getRootNode();
85             final InstanceIdentifier<Node> identifier = change.getRootPath().getRootIdentifier();
86             switch (rootNode.getModificationType()) {
87                 case WRITE:
88                 case SUBTREE_MODIFIED:
89                     nodeCreated(identifier, rootNode.getDataAfter());
90                     break;
91                 case DELETE:
92                     nodeRemoved(identifier);
93                     break;
94                 default:
95                     break;
96             }
97         }
98     }
99
100     private void nodeCreated(final InstanceIdentifier<?> key, final Node node) {
101         Preconditions.checkNotNull(key);
102         if (!validateNode(node)) {
103             LOG.warn("NodeCreated event : Node [{}] is null or not valid.", key.toString());
104             return;
105         }
106         LOG.info("Netconf event source [{}] is creating...", key.toString());
107         NetconfEventSourceRegistration nesr = NetconfEventSourceRegistration.create(key, node, this);
108         if (nesr != null) {
109             NetconfEventSourceRegistration nesrOld = registrationMap.put(key, nesr);
110             if (nesrOld != null) {
111                 nesrOld.close();
112             }
113         }
114     }
115
116     private void nodeRemoved(final InstanceIdentifier<?> key) {
117         Preconditions.checkNotNull(key);
118         LOG.info("Netconf event source [{}] is removing...", key.toString());
119         NetconfEventSourceRegistration nesr = registrationMap.remove(key);
120         if (nesr != null) {
121             nesr.close();
122         }
123     }
124
125     private static boolean validateNode(final Node node) {
126         return node == null ? false : isNetconfNode(node);
127     }
128
129     Map<String, String> getStreamMap() {
130         return streamMap;
131     }
132
133     DOMNotificationPublishService getPublishService() {
134         return publishService;
135     }
136
137     DOMMountPointService getDomMounts() {
138         return domMounts;
139     }
140
141     EventSourceRegistry getEventSourceRegistry() {
142         return eventSourceRegistry;
143     }
144
145     /**
146      * Invoked by blueprint.
147      *
148      * @param streamMap Stream map
149      */
150     public void setStreamMap(final Map<String, String> streamMap) {
151         this.streamMap = streamMap;
152     }
153
154     private static boolean isNetconfNode(final Node node) {
155         return node.augmentation(NetconfNode.class) != null;
156     }
157
158     @Override
159     public void close() {
160         listenerRegistration.close();
161         for (final NetconfEventSourceRegistration reg : registrationMap.values()) {
162             reg.close();
163         }
164         registrationMap.clear();
165     }
166 }