8e356b5c5dbef28fe96e13e1e34a910c4e62e6a4
[bgpcep.git] / graph / graph-impl / src / main / java / org / opendaylight / graph / impl / ConnectedGraphImpl.java
1 /*
2  * Copyright (c) 2019 Orange. 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
9 package org.opendaylight.graph.impl;
10
11 import static com.google.common.base.Preconditions.checkArgument;
12
13 import java.util.ArrayList;
14 import java.util.HashMap;
15 import java.util.List;
16 import org.eclipse.jdt.annotation.NonNull;
17 import org.opendaylight.graph.ConnectedEdge;
18 import org.opendaylight.graph.ConnectedGraph;
19 import org.opendaylight.graph.ConnectedVertex;
20 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
22 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
23 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev191125.graph.topology.Graph;
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.EdgeKey;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev191125.graph.topology.graph.Prefix;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev191125.graph.topology.graph.Vertex;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev191125.graph.topology.graph.VertexKey;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32
33 /**
34  * This Class implements the Connected Graph for path computation algorithms.
35  *
36  * @author Olivier Dugeon
37  * @author Philippe Niger
38  */
39
40
41 public class ConnectedGraphImpl implements ConnectedGraph {
42
43     private static final Logger LOG = LoggerFactory.getLogger(ConnectedGraphImpl.class);
44
45     /* List of Connected Vertics that composed this Connected Graph */
46     private final HashMap<Long, ConnectedVertexImpl> vertices = new HashMap<>();
47
48     /* List of Connected Edges that composed this Connected Graph */
49     private final HashMap<Long, ConnectedEdgeImpl> edges = new HashMap<>();
50
51     /* List of IP prefix attached to Vertices */
52     private final HashMap<IpPrefix, Prefix> prefixes = new HashMap<>();
53
54     /* Reference to the non connected Graph stored in DataStore */
55     private Graph graph;
56
57     /* Reference to Graph Model Server to store corresponding graph in DataStore */
58     private final ConnectedGraphServer connectedGraphServer;
59
60     public ConnectedGraphImpl(Graph newGraph, ConnectedGraphServer server) {
61         this.graph = newGraph;
62         createConnectedGraph();
63         this.connectedGraphServer = server;
64     }
65
66     /**
67      * Transform the associated Graph in a Connected Graph. This method will automatically create associated Connected
68      * Vertices, from the Graph Vertices, Connected Edges, from the Graph Edges and Prefix from the Graph Prefix.
69      *
70      */
71     private void createConnectedGraph() {
72         if (this.graph == null) {
73             return;
74         }
75         /* Add all vertices */
76         if (this.graph.getVertex() != null) {
77             for (Vertex vertex : this.graph.getVertex()) {
78                 ConnectedVertexImpl cvertex = new ConnectedVertexImpl(vertex);
79                 vertices.put(cvertex.getKey(), cvertex);
80             }
81         }
82         /* Add all edges */
83         if (this.graph.getEdge() != null) {
84             for (Edge edge : this.graph.getEdge()) {
85                 ConnectedEdgeImpl cedge = new ConnectedEdgeImpl(edge);
86                 edges.put(cedge.getKey(), cedge);
87             }
88         }
89         /* Add all prefixes */
90         if (this.graph.getPrefix() != null) {
91             for (Prefix prefix : this.graph.getPrefix()) {
92                 ConnectedVertexImpl cvertex = vertices.get(prefix.getVertexId().longValue());
93                 if (cvertex != null) {
94                     cvertex.addPrefix(prefix);
95                 }
96                 prefixes.putIfAbsent(prefix.getPrefix(), prefix);
97             }
98         }
99     }
100
101     /**
102      * Return Connected Vertex if it exists or create a new one.
103      *
104      * @param  key   Unique Vertex Key identifier
105      * @return new or existing Connected Vertex
106      */
107     private ConnectedVertexImpl updateConnectedVertex(@NonNull Long key) {
108         checkArgument(key != 0, "Provided Vertex Key must not be equal to 0");
109         ConnectedVertexImpl vertex = vertices.get(key);
110         if (vertex == null) {
111             vertex = new ConnectedVertexImpl(key);
112             vertices.put(key, vertex);
113         }
114         return vertex;
115     }
116
117     /**
118      * Return Connected Edge if it exist or create a new one.
119      *
120      * @param key   Unique Edge Key identifier
121      * @return new or existing Connected Edge
122      */
123     private ConnectedEdgeImpl updateConnectedEdge(@NonNull Long key) {
124         checkArgument(key != 0, "Provided Edge Key must not be equal to 0");
125         ConnectedEdgeImpl edge = edges.get(key);
126         if (edge == null) {
127             edge = new ConnectedEdgeImpl(key);
128             edges.put(edge.getKey(), edge);
129         }
130         return edge;
131     }
132
133     /**
134      * Connect source and destination Connected Vertices with the given Connected Edge.
135      *
136      * @param srcVertex Source Connected Vertex
137      * @param dstVertex Destination Connected Vertex
138      * @param edge      Connected Edge
139      */
140     private void connectVertices(ConnectedVertexImpl srcVertex, ConnectedVertexImpl dstVertex, ConnectedEdgeImpl edge) {
141         if (edge != null) {
142             edge.setSource(srcVertex);
143             edge.setDestination(dstVertex);
144         }
145         if (srcVertex != null) {
146             srcVertex.addOutput(edge);
147         }
148         if (dstVertex != null) {
149             dstVertex.addInput(edge);
150         }
151     }
152
153     @Override
154     public Graph getGraph() {
155         return this.graph;
156     }
157
158     @Override
159     public List<ConnectedVertex> getVertices() {
160         return new ArrayList<ConnectedVertex>(this.vertices.values());
161     }
162
163     @Override
164     public ConnectedVertex getConnectedVertex(@NonNull Long key) {
165         return vertices.get(key);
166     }
167
168     @Override
169     public ConnectedVertex getConnectedVertex(IpAddress address) {
170         IpPrefix prefix = null;
171         if (address.getIpv4Address() != null) {
172             prefix = new IpPrefix(new Ipv4Prefix(address.getIpv4Address().getValue() + "/32"));
173         }
174         if (address.getIpv6Address() != null) {
175             prefix = new IpPrefix(new Ipv6Prefix(address.getIpv6Address().getValue() + "/128"));
176         }
177         if (prefix != null && prefixes.containsKey(prefix)) {
178             long key = prefixes.get(prefix).getVertexId().longValue();
179             return vertices.get(key);
180         } else {
181             return null;
182         }
183     }
184
185     @Override
186     public int getVerticesSize() {
187         return vertices.size();
188     }
189
190     @Override
191     public List<ConnectedEdge> getEdges() {
192         return new ArrayList<ConnectedEdge>(this.edges.values());
193     }
194
195     @Override
196     public ConnectedEdge getConnectedEdge(@NonNull Long key) {
197         return edges.get(key);
198     }
199
200     @Override
201     public ConnectedEdge getConnectedEdge(IpAddress address) {
202         for (ConnectedEdge cedge : edges.values()) {
203             if (cedge.getEdge() == null) {
204                 continue;
205             }
206             if (cedge.getEdge().getEdgeAttributes().getLocalAddress().equals(address)) {
207                 return cedge;
208             }
209         }
210         return null;
211     }
212
213     @Override
214     public int getEdgesSize() {
215         return edges.size();
216     }
217
218     @Override
219     public List<Prefix> getPrefixes() {
220         return new ArrayList<Prefix>(this.prefixes.values());
221     }
222
223     @Override
224     public Prefix getPrefix(IpPrefix prefix) {
225         return this.prefixes.get(prefix);
226     }
227
228     @Override
229     public ConnectedVertex addVertex(Vertex vertex) {
230         checkArgument(vertex != null, "Provided Vertex is a null object");
231         ConnectedVertexImpl cvertex = updateConnectedVertex(vertex.getVertexId().longValue());
232         Vertex old = cvertex.getVertex();
233         this.connectedGraphServer.addVertex(this.graph, vertex, old);
234         cvertex.setVertex(vertex);
235         return cvertex;
236     }
237
238     @Override
239     public void deleteVertex(VertexKey key) {
240         checkArgument(key != null, "Provided Vertex Key is a null object");
241         ConnectedVertexImpl cvertex = vertices.get(key.getVertexId().longValue());
242         if (cvertex != null) {
243             cvertex.disconnect();
244             vertices.remove(cvertex.getKey());
245             this.connectedGraphServer.deleteVertex(this.graph, cvertex.getVertex());
246             cvertex.setVertex(null);
247         }
248     }
249
250     @Override
251     public ConnectedEdge addEdge(Edge edge) {
252         checkArgument(edge != null, "Provided Edge is a null object");
253         ConnectedEdgeImpl cedge = updateConnectedEdge(edge.getEdgeId().longValue());
254         Edge old = cedge.getEdge();
255         if (old == null) {
256             ConnectedVertexImpl source = null;
257             ConnectedVertexImpl destination = null;
258             if (edge.getLocalVertexId() != null) {
259                 source = updateConnectedVertex(edge.getLocalVertexId().longValue());
260             }
261             if (edge.getRemoteVertexId() != null) {
262                 destination = updateConnectedVertex(edge.getRemoteVertexId().longValue());
263             }
264             connectVertices(source, destination, cedge);
265         }
266         this.connectedGraphServer.addEdge(this.graph, edge, old);
267         cedge.setEdge(edge);
268         return cedge;
269     }
270
271     @Override
272     public void deleteEdge(EdgeKey key) {
273         checkArgument(key != null, "Provided Edge Key is a null object");
274         ConnectedEdgeImpl cedge = edges.get(key.getEdgeId().longValue());
275         if (cedge != null) {
276             this.connectedGraphServer.deleteEdge(this.graph, cedge.getEdge());
277             cedge.disconnect();
278             edges.remove(cedge.getKey());
279             cedge.setEdge(null);
280         }
281     }
282
283     @Override
284     public void addPrefix(Prefix prefix) {
285         checkArgument(prefix != null, "Provided Prefix is a null object");
286         ConnectedVertexImpl cvertex = updateConnectedVertex(prefix.getVertexId().longValue());
287         cvertex.addPrefix(prefix);
288         prefixes.putIfAbsent(prefix.getPrefix(), prefix);
289         this.connectedGraphServer.addPrefix(this.graph, prefix);
290     }
291
292     @Override
293     public void deletePrefix(IpPrefix ippfx) {
294         checkArgument(ippfx != null, "Provided Prefix is a null object");
295         Prefix prefix = prefixes.get(ippfx);
296         if (prefix != null) {
297             ConnectedVertexImpl cvertex = vertices.get(prefix.getVertexId().longValue());
298             if (cvertex != null) {
299                 cvertex.removePrefix(prefix);
300             }
301             prefixes.remove(prefix.getPrefix());
302             this.connectedGraphServer.deletePrefix(this.graph, prefix);
303         }
304     }
305
306     @Override
307     public void clear() {
308         LOG.info("Reset Connected Graph({})", graph.getName());
309         this.vertices.clear();
310         this.edges.clear();
311         this.prefixes.clear();
312         this.connectedGraphServer.clearGraph(this.graph);
313         this.graph = null;
314     }
315
316     @Override
317     public String getSummary() {
318         return vertices.size() + "/" + edges.size() + "/" + prefixes.size();
319     }
320
321     /**
322      * Returns the name of the associated Graph.
323      *
324      * @return Graph name
325      */
326     @Override
327     public String toString() {
328         return this.graph.getName();
329     }
330 }