2 * Copyright (c) 2019 Orange. All rights reserved.
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
8 package org.opendaylight.graph.impl;
10 import static java.util.Objects.requireNonNull;
12 import java.util.Collection;
13 import javax.annotation.PreDestroy;
14 import javax.inject.Inject;
15 import javax.inject.Singleton;
16 import org.opendaylight.graph.ConnectedGraph;
17 import org.opendaylight.graph.ConnectedGraphProvider;
18 import org.opendaylight.mdsal.binding.api.DataBroker;
19 import org.opendaylight.mdsal.binding.api.DataObjectModification;
20 import org.opendaylight.mdsal.binding.api.DataTreeChangeListener;
21 import org.opendaylight.mdsal.binding.api.DataTreeIdentifier;
22 import org.opendaylight.mdsal.binding.api.DataTreeModification;
23 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev220720.GraphTopology;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev220720.graph.topology.Graph;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev220720.graph.topology.GraphKey;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev220720.graph.topology.graph.Edge;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev220720.graph.topology.graph.Prefix;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev220720.graph.topology.graph.Vertex;
30 import org.opendaylight.yangtools.concepts.ListenerRegistration;
31 import org.opendaylight.yangtools.yang.binding.DataObject;
32 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
33 import org.osgi.service.component.annotations.Activate;
34 import org.osgi.service.component.annotations.Component;
35 import org.osgi.service.component.annotations.Deactivate;
36 import org.osgi.service.component.annotations.Reference;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
41 * This Class Implements the DataStoreService interface providing the methods required to manage the network
42 * representation elements in the Data Store.
44 * @author Olivier Dugeon
45 * @author Philippe Niger
47 @Component(service = {})
49 public final class GraphListener implements DataTreeChangeListener<Graph>, AutoCloseable {
50 private static final Logger LOG = LoggerFactory.getLogger(GraphListener.class);
52 private final ConnectedGraphProvider graphProvider;
54 private ListenerRegistration<GraphListener> listenerRegistration;
58 public GraphListener(@Reference final DataBroker dataBroker, @Reference final ConnectedGraphProvider provider) {
59 graphProvider = requireNonNull(provider);
61 final var graphIdentifier = InstanceIdentifier.builder(GraphTopology.class).child(Graph.class).build();
63 listenerRegistration = dataBroker.registerDataTreeChangeListener(
64 DataTreeIdentifier.create(LogicalDatastoreType.CONFIGURATION, graphIdentifier), this);
65 LOG.info("Registered listener {} on Graph Model at {}", this, graphIdentifier);
69 * Close this Listener.
75 if (listenerRegistration != null) {
76 LOG.debug("Unregistered listener {} on Graph", this);
77 listenerRegistration.close();
78 listenerRegistration = null;
83 * Parse Sub Tree modification. This method is called with the Modified Children from
84 * the Data Tree Modification root.This method is necessary as the getModificationType() method returns
85 * SUBTREE_MODIFIED only when Data Object is already present in the Data Store. Thus, this is indication is only
86 * relevant for deletion not for insertion where WRITE modification type is return even if it concerns a child.
88 * @param cgraph Connected Graph where children Data Object must insert or remove
89 * @param children List of children (Vertex, Edge or Prefix)
91 private static void parseSubTree(final ConnectedGraph cgraph,
92 final Collection<? extends DataObjectModification<? extends DataObject>> children) {
93 for (var child : children) {
94 final DataObject value;
95 switch (child.getModificationType()) {
97 value = child.getDataBefore();
98 if (value instanceof Vertex vertex) {
99 cgraph.deleteVertex(vertex.key());
101 if (value instanceof Edge edge) {
102 cgraph.deleteEdge(edge.key());
104 if (value instanceof Prefix prefix) {
105 cgraph.deletePrefix(prefix.getPrefix());
108 case SUBTREE_MODIFIED:
110 value = child.getDataAfter();
111 if (value instanceof Vertex vertex) {
112 cgraph.addVertex(vertex);
114 if (value instanceof Edge edge) {
115 cgraph.addEdge(edge);
117 if (value instanceof Prefix prefix) {
118 cgraph.addPrefix(prefix);
128 public void onDataTreeChanged(final Collection<DataTreeModification<Graph>> changes) {
129 for (DataTreeModification<Graph> change : changes) {
130 DataObjectModification<Graph> root = change.getRootNode();
131 GraphKey key = change.getRootPath().getRootIdentifier().firstKeyOf(Graph.class);
132 switch (root.getModificationType()) {
134 graphProvider.deleteGraph(key);
136 case SUBTREE_MODIFIED:
137 /* getModificationType() returns SUBTREE_MODIFIED only when Data Object is already present in the
138 * Data Store, thus, only for deletion. Thus, to insert children, we must used parseSubTree()
139 * method (See above). This method is called only when the graph already exists.
142 /* First look if the Graph was not already configured */
143 ConnectedGraph cgraph = graphProvider.getConnectedGraph(key);
144 if (cgraph == null) {
145 graphProvider.addGraph(root.getDataAfter());
147 /* Graph exist, process Children */
148 parseSubTree(cgraph, root.getModifiedChildren());