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
9 package org.opendaylight.graph.impl;
11 import static com.google.common.base.Preconditions.checkState;
13 import java.util.Collection;
14 import org.opendaylight.graph.ConnectedGraph;
15 import org.opendaylight.graph.ConnectedGraphProvider;
16 import org.opendaylight.mdsal.binding.api.DataBroker;
17 import org.opendaylight.mdsal.binding.api.DataObjectModification;
18 import org.opendaylight.mdsal.binding.api.DataTreeChangeListener;
19 import org.opendaylight.mdsal.binding.api.DataTreeIdentifier;
20 import org.opendaylight.mdsal.binding.api.DataTreeModification;
21 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev191125.GraphTopology;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev191125.graph.topology.Graph;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev191125.graph.topology.GraphKey;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev191125.graph.topology.graph.Edge;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev191125.graph.topology.graph.Prefix;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev191125.graph.topology.graph.Vertex;
28 import org.opendaylight.yangtools.concepts.ListenerRegistration;
29 import org.opendaylight.yangtools.yang.binding.DataObject;
30 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
35 * This Class Implements the DataStoreService interface providing the methods required to manage the network
36 * representation elements in the Data Store.
39 * @author Olivier Dugeon
40 * @author Philippe Niger
43 public class GraphListener implements DataTreeChangeListener<Graph> {
45 private static final Logger LOG = LoggerFactory.getLogger(GraphListener.class);
46 private final DataBroker dataBroker;
47 private final InstanceIdentifier<Graph> graphIdentifier;
48 private final ConnectedGraphProvider graphProvider;
49 private ListenerRegistration<GraphListener> listenerRegistration = null;
51 public GraphListener(final DataBroker dataBroker, final ConnectedGraphProvider provider) {
52 this.dataBroker = dataBroker;
53 this.graphIdentifier = InstanceIdentifier.builder(GraphTopology.class).child(Graph.class).build();
54 this.graphProvider = provider;
55 LOG.info("Graph Model Listener started");
59 * Initialization of the Graph Topology Listener. This method is called through the blueprint.
62 checkState(this.listenerRegistration == null, "Graph Listener has been registered before");
63 final DataTreeIdentifier<Graph> treeId = DataTreeIdentifier.create(LogicalDatastoreType.CONFIGURATION,
65 this.listenerRegistration = this.dataBroker.registerDataTreeChangeListener(treeId, this);
66 LOG.info("Registered listener {} on Graph Model at {}", this, this.graphIdentifier);
70 * Close this Listener.
73 if (this.listenerRegistration != null) {
74 LOG.debug("Unregistered listener {} on Graph", this);
75 this.listenerRegistration.close();
76 this.listenerRegistration = null;
81 * Parse Sub Tree modification. This method is called with the Modified Children from
82 * the Data Tree Modification root.This method is necessary as the getModificationType() method returns
83 * SUBTREE_MODIFIED only when Data Object is already present in the Data Store. Thus, this is indication is only
84 * relevant for deletion not for insertion where WRITE modification type is return even if it concerns a child.
86 * @param cgraph Connected Graph where children Data Object must insert or remove
87 * @param children List of children (Vertex, Edge or Prefix)
89 private void parseSubTree(ConnectedGraph cgraph,
90 Collection<? extends DataObjectModification<? extends DataObject>> children) {
91 for (DataObjectModification<? extends DataObject> child : children) {
93 switch (child.getModificationType()) {
95 value = child.getDataBefore();
96 if (value instanceof Vertex) {
97 cgraph.deleteVertex(((Vertex )value).key());
99 if (value instanceof Edge) {
100 cgraph.deleteEdge(((Edge )value).key());
102 if (value instanceof Prefix) {
103 cgraph.deletePrefix(((Prefix )value).getPrefix());
106 case SUBTREE_MODIFIED:
108 value = child.getDataAfter();
109 if (value instanceof Vertex) {
110 cgraph.addVertex((Vertex )value);
112 if (value instanceof Edge) {
113 cgraph.addEdge((Edge )value);
115 if (value instanceof Prefix) {
116 cgraph.addPrefix((Prefix )value);
126 public void onDataTreeChanged(final Collection<DataTreeModification<Graph>> changes) {
127 for (DataTreeModification<Graph> change : changes) {
128 DataObjectModification<Graph> root = change.getRootNode();
129 GraphKey key = change.getRootPath().getRootIdentifier().firstKeyOf(Graph.class);
130 switch (root.getModificationType()) {
132 graphProvider.deleteGraph(key);
134 case SUBTREE_MODIFIED:
135 /* getModificationType() returns SUBTREE_MODIFIED only when Data Object is already present in the
136 * Data Store, thus, only for deletion. Thus, to insert children, we must used parseSubTree()
137 * method (See above). This method is called only when the graph already exists.
140 /* First look if the Graph was not already configured */
141 ConnectedGraph cgraph = this.graphProvider.getConnectedGraph(key);
142 if (cgraph == null) {
143 graphProvider.addGraph(root.getDataAfter());
145 /* Graph exist, process Children */
146 parseSubTree(cgraph, root.getModifiedChildren());