Walk the tables directly
[controller.git] / opendaylight / md-sal / compatibility / sal-compatibility / src / main / java / org / opendaylight / controller / sal / compatibility / InventoryAndReadAdapter.xtend
1 /*
2  * Copyright (c) 2014 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.controller.sal.compatibility
9
10 import java.util.ArrayList
11 import java.util.Collections
12 import java.util.List
13 import java.util.Set
14 import java.util.concurrent.CopyOnWriteArrayList;
15 import org.opendaylight.controller.sal.binding.api.data.DataBrokerService
16 import org.opendaylight.controller.sal.binding.api.data.DataProviderService
17 import org.opendaylight.controller.sal.core.Edge
18 import org.opendaylight.controller.sal.core.Node
19 import org.opendaylight.controller.sal.core.NodeTable
20 import org.opendaylight.controller.sal.core.UpdateType
21 import org.opendaylight.controller.sal.flowprogrammer.Flow
22 import org.opendaylight.controller.sal.inventory.IPluginInInventoryService
23 import org.opendaylight.controller.sal.inventory.IPluginOutInventoryService
24 import org.opendaylight.controller.sal.reader.FlowOnNode
25 import org.opendaylight.controller.sal.reader.IPluginInReadService
26 import org.opendaylight.controller.sal.reader.IPluginOutReadService
27 import org.opendaylight.controller.sal.reader.NodeConnectorStatistics
28 import org.opendaylight.controller.sal.reader.NodeDescription
29 import org.opendaylight.controller.sal.reader.NodeTableStatistics
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.AggregateFlowStatisticsUpdate
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowStatisticsData
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowsStatisticsUpdate
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAllFlowsStatisticsFromAllFlowTablesInputBuilder
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetFlowStatisticsFromFlowTableInputBuilder
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.OpendaylightFlowStatisticsListener
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.OpendaylightFlowStatisticsService
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.flow.and.statistics.map.list.FlowAndStatisticsMapList
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.FlowTableStatisticsData
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.FlowTableStatisticsUpdate
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.GetFlowTablesStatisticsInputBuilder
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.OpendaylightFlowTableStatisticsListener
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.OpendaylightFlowTableStatisticsService
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.flow.table.statistics.FlowTableStatistics
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.topology.discovery.rev130819.FlowTopologyDiscoveryService
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.topology.discovery.rev130819.Link
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRemoved
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorUpdated
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRemoved
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeUpdated
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.OpendaylightInventoryListener
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.FlowCapableNodeConnectorStatistics
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.FlowCapableNodeConnectorStatisticsData
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.GetAllNodeConnectorsStatisticsInputBuilder
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.GetNodeConnectorStatisticsInputBuilder
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.NodeConnectorStatisticsUpdate
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.OpendaylightPortStatisticsListener
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.OpendaylightPortStatisticsService
70 import org.opendaylight.yangtools.yang.binding.DataObject
71 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
72 import org.slf4j.LoggerFactory
73
74 import static extension org.opendaylight.controller.sal.common.util.Arguments.*
75 import static extension org.opendaylight.controller.sal.compatibility.NodeMapping.*
76 import org.opendaylight.controller.md.sal.binding.util.TypeSafeDataReader
77 import java.util.concurrent.ConcurrentHashMap
78 import java.util.Map
79
80 class InventoryAndReadAdapter implements IPluginInReadService,
81                                                                                          IPluginInInventoryService,
82                                                                                          OpendaylightInventoryListener,
83                                                                                          OpendaylightFlowStatisticsListener,
84                                                                                          OpendaylightFlowTableStatisticsListener,
85                                                                                          OpendaylightPortStatisticsListener {
86
87     private static val LOG = LoggerFactory.getLogger(InventoryAndReadAdapter);
88
89         private static val OPENFLOWV10_TABLE_ID = new Integer(0).shortValue;
90     @Property
91     DataBrokerService dataService;
92
93     @Property
94     DataProviderService dataProviderService;
95
96     @Property
97     OpendaylightFlowStatisticsService flowStatisticsService;
98
99     @Property
100     OpendaylightPortStatisticsService nodeConnectorStatisticsService;
101     
102     @Property
103     OpendaylightFlowTableStatisticsService flowTableStatisticsService;
104
105     @Property
106     FlowTopologyDiscoveryService topologyDiscovery;
107     
108     @Property
109     List<IPluginOutReadService> statisticsPublisher = new CopyOnWriteArrayList<IPluginOutReadService>();
110
111     @Property
112     List<IPluginOutInventoryService> inventoryPublisher = new CopyOnWriteArrayList<IPluginOutInventoryService>();
113
114         def setInventoryPublisher(IPluginOutInventoryService listener){
115         inventoryPublisher.add(listener);
116         }
117
118         def unsetInventoryPublisher(IPluginOutInventoryService listener){
119         inventoryPublisher.remove(listener);
120         }
121
122     def setReadPublisher(IPluginOutReadService listener) {
123         statisticsPublisher.add(listener);
124     }
125     
126     def unsetReadPublisher (IPluginOutReadService listener) {
127         if( listener != null)
128                 statisticsPublisher.remove(listener);
129     }
130
131     protected def startChange() {
132         return dataProviderService.beginTransaction;
133     }
134
135     override getTransmitRate(org.opendaylight.controller.sal.core.NodeConnector connector) {
136         val nodeConnector = readFlowCapableNodeConnector(connector.toNodeConnectorRef);
137         return nodeConnector.currentSpeed
138     }
139
140     override readAllFlow(Node node, boolean cached) {
141
142         val output = new ArrayList<FlowOnNode>();
143                 val tableRef = InstanceIdentifier.builder(Nodes)
144                                                                                 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node, InventoryMapping.toNodeKey(node))
145                                                         .augmentation(FlowCapableNode).child(Table, new TableKey(OPENFLOWV10_TABLE_ID)).toInstance();
146                 
147                 val it = this.startChange();
148                 
149                 val table= it.readConfigurationData(tableRef) as Table;
150                 
151                 if(table != null){
152                         LOG.trace("Number of flows installed in table 0 of node {} : {}",node,table.flow.size);
153                         
154                         for(flow : table.flow){
155                                 
156                                 val adsalFlow = ToSalConversionsUtils.toFlow(flow,node);
157                                 val statsFromDataStore = flow.getAugmentation(FlowStatisticsData);
158                                 
159                                 if(statsFromDataStore != null){
160                                         val it = new FlowOnNode(adsalFlow);
161                                         byteCount =  statsFromDataStore.flowStatistics.byteCount.value.longValue;
162                                         packetCount = statsFromDataStore.flowStatistics.packetCount.value.longValue;
163                                         durationSeconds = statsFromDataStore.flowStatistics.duration.second.value.intValue;
164                                         durationNanoseconds = statsFromDataStore.flowStatistics.duration.nanosecond.value.intValue;
165                                         
166                                         output.add(it);
167                                 }
168                         }
169                 }
170         
171         //TODO (main): Shell we send request to the switch? It will make async request to the switch.
172         // Once plugin receive response, it will let adaptor know through onFlowStatisticsUpdate()
173         // If we assume that md-sal statistics manager will always be running, then its not required
174         // But if not, then sending request will collect the latest data for adaptor atleast.
175         val input = new GetAllFlowsStatisticsFromAllFlowTablesInputBuilder;
176         input.setNode(node.toNodeRef);
177         flowStatisticsService.getAllFlowsStatisticsFromAllFlowTables(input.build)
178         
179         return output;
180     }
181
182     override readAllNodeConnector(Node node, boolean cached) {
183         
184         val ret = new ArrayList<NodeConnectorStatistics>();
185                 val nodeRef = InstanceIdentifier.builder(Nodes)
186                                                                         .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node, InventoryMapping.toNodeKey(node))
187                                                                         .toInstance();
188                 
189                 val provider = this.startChange();
190                 
191                 val dsNode= provider.readConfigurationData(nodeRef) as org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
192                 
193                 if(dsNode != null){
194                         
195                         for (dsNodeConnector : dsNode.nodeConnector){
196                                 val nodeConnectorRef = InstanceIdentifier.builder(Nodes)
197                                                                         .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node, InventoryMapping.toNodeKey(node))
198                                                                         .child(NodeConnector, dsNodeConnector.key)
199                                                                         .toInstance();
200                                 
201                                 val nodeConnectorFromDS = provider.readConfigurationData(nodeConnectorRef) as NodeConnector;
202                                 
203                                 if(nodeConnectorFromDS != null){
204                                         val nodeConnectorStatsFromDs = nodeConnectorFromDS.getAugmentation(FlowCapableNodeConnectorStatisticsData) as FlowCapableNodeConnectorStatistics;
205                                         
206                                         ret.add(toNodeConnectorStatistics(nodeConnectorStatsFromDs.flowCapableNodeConnectorStatistics,dsNode.id,dsNodeConnector.id));
207                                 }
208                         }
209                 }
210
211                 //TODO: Refer TODO (main)
212         val input = new GetAllNodeConnectorsStatisticsInputBuilder();
213         input.setNode(node.toNodeRef);
214         nodeConnectorStatisticsService.getAllNodeConnectorsStatistics(input.build());
215         return ret;
216     }
217
218     override readAllNodeTable(Node node, boolean cached) {
219         val ret = new ArrayList<NodeTableStatistics>();
220         
221                 val dsFlowCapableNode= readFlowCapableNode(node.toNodeRef)
222                 
223                 if(dsFlowCapableNode != null){
224                         
225                         for (table : dsFlowCapableNode.table){
226                                 
227                                 val tableStats = table.getAugmentation(FlowTableStatisticsData);
228                                 
229                                 if(tableStats != null){
230                                         ret.add(toNodeTableStatistics(tableStats.flowTableStatistics,table.id,node));
231                                 }
232                         }
233                 }
234
235                 //TODO: Refer TODO (main)
236         val input = new GetFlowTablesStatisticsInputBuilder();
237         input.setNode(node.toNodeRef);
238         flowTableStatisticsService.getFlowTablesStatistics(input.build);
239         return ret;
240     }
241
242     override readDescription(Node node, boolean cached) {
243         return toNodeDescription(node.toNodeRef);
244         }
245
246     override readFlow(Node node, Flow targetFlow, boolean cached) {
247                 var FlowOnNode ret= null;
248                 
249                 val tableRef = InstanceIdentifier.builder(Nodes)
250                                                                                 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node, InventoryMapping.toNodeKey(node))
251                                                         .augmentation(FlowCapableNode).child(Table, new TableKey(OPENFLOWV10_TABLE_ID)).toInstance();
252                 
253                 val it = this.startChange();
254                 
255                 val table= it.readConfigurationData(tableRef) as Table;
256                 
257                 if(table != null){
258                         LOG.trace("Number of flows installed in table 0 of node {} : {}",node,table.flow.size);
259                         
260                         for(mdsalFlow : table.flow){
261                                 if(FromSalConversionsUtils.flowEquals(mdsalFlow, MDFlowMapping.toMDSalflow(targetFlow))){
262                                         val statsFromDataStore = mdsalFlow.getAugmentation(FlowStatisticsData);
263                                         
264                                         if(statsFromDataStore != null){
265                                                 LOG.debug("Found matching flow in the data store flow table ");
266                                                 val it = new FlowOnNode(targetFlow);
267                                                 byteCount =  statsFromDataStore.flowStatistics.byteCount.value.longValue;
268                                                 packetCount = statsFromDataStore.flowStatistics.packetCount.value.longValue;
269                                                 durationSeconds = statsFromDataStore.flowStatistics.duration.second.value.intValue;
270                                                 durationNanoseconds = statsFromDataStore.flowStatistics.duration.nanosecond.value.intValue;
271                                                 
272                                                 ret = it;
273                                         }
274                                 }                       
275                         }
276                 }
277         
278         //TODO: Refer TODO (main)
279         val input = new GetFlowStatisticsFromFlowTableInputBuilder;
280         input.setNode(node.toNodeRef);
281         input.fieldsFrom(MDFlowMapping.toMDSalflow(targetFlow));
282         flowStatisticsService.getFlowStatisticsFromFlowTable(input.build)
283         
284         return ret;
285         
286     }
287
288     override readNodeConnector(org.opendaylight.controller.sal.core.NodeConnector connector, boolean cached) {
289         var NodeConnectorStatistics  nodeConnectorStatistics = null;
290         
291                 val nodeConnectorRef = InstanceIdentifier.builder(Nodes)
292                                                                         .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node, InventoryMapping.toNodeKey(connector.node))
293                                                                         .child(NodeConnector, InventoryMapping.toNodeConnectorKey(connector))
294                                                                         .toInstance();
295                 val provider = this.startChange();
296                                 
297                 val nodeConnectorFromDS = provider.readConfigurationData(nodeConnectorRef) as NodeConnector;
298                                 
299                 if(nodeConnectorFromDS != null){
300                         val nodeConnectorStatsFromDs = nodeConnectorFromDS.getAugmentation(FlowCapableNodeConnectorStatisticsData) as FlowCapableNodeConnectorStatistics;
301                         if(nodeConnectorStatsFromDs != null) {
302                                 nodeConnectorStatistics = toNodeConnectorStatistics(nodeConnectorStatsFromDs.flowCapableNodeConnectorStatistics,
303                                                                                                                                                 InventoryMapping.toNodeKey(connector.node).id,
304                                                                                                                                                 InventoryMapping.toNodeConnectorKey(connector).id);
305                         }
306                 }
307
308                 //TODO: Refer TODO (main)
309         val input = new GetNodeConnectorStatisticsInputBuilder();
310         input.setNode(connector.node.toNodeRef);
311         input.setNodeConnectorId(InventoryMapping.toNodeConnectorKey(connector).id);
312         nodeConnectorStatisticsService.getNodeConnectorStatistics(input.build());
313         return nodeConnectorStatistics;
314     }
315
316     override readNodeTable(NodeTable nodeTable, boolean cached) {
317         var NodeTableStatistics nodeStats = null
318         
319         val tableRef = InstanceIdentifier.builder(Nodes)
320                                                                                 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node, InventoryMapping.toNodeKey(nodeTable.node))
321                                                         .augmentation(FlowCapableNode).child(Table, new TableKey(nodeTable.ID as Short)).toInstance();
322                 
323                 val it = this.startChange();
324                 
325                 val table= it.readConfigurationData(tableRef) as Table;
326                 
327                 if(table != null){
328                         val tableStats = table.getAugmentation(FlowTableStatisticsData);
329                                 
330                         if(tableStats != null){
331                                 nodeStats =  toNodeTableStatistics(tableStats.flowTableStatistics,table.id,nodeTable.node);
332                         }
333                 }
334
335                 //TODO: Refer TODO (main)
336         val input = new GetFlowTablesStatisticsInputBuilder();
337         input.setNode(nodeTable.node.toNodeRef);
338         flowTableStatisticsService.getFlowTablesStatistics(input.build);
339         
340         return nodeStats;
341     }
342
343     override onNodeConnectorRemoved(NodeConnectorRemoved update) {
344         // NOOP
345     }
346
347     override onNodeRemoved(NodeRemoved notification) {
348         val properties = Collections.<org.opendaylight.controller.sal.core.Property>emptySet();
349
350         publishNodeUpdate(notification.nodeRef.toADNode, UpdateType.REMOVED, properties);
351     }
352
353     override onNodeConnectorUpdated(NodeConnectorUpdated update) {
354         var updateType = UpdateType.CHANGED;
355         if ( this._dataService.readOperationalData(update.nodeConnectorRef.value as InstanceIdentifier<? extends DataObject>) == null ){
356             updateType = UpdateType.ADDED;
357         }
358
359         var nodeConnector = update.nodeConnectorRef.toADNodeConnector
360
361         publishNodeConnectorUpdate(nodeConnector , updateType , update.toADNodeConnectorProperties);
362     }
363
364     override onNodeUpdated(NodeUpdated notification) {
365         val InstanceIdentifier<? extends DataObject> identifier = notification.nodeRef.value  as InstanceIdentifier<? extends DataObject>;
366
367         var updateType = UpdateType.CHANGED;
368         if ( this._dataService.readOperationalData(identifier) == null ){
369             updateType = UpdateType.ADDED;
370         }
371         publishNodeUpdate(notification.nodeRef.toADNode, updateType, notification.toADNodeProperties);
372         
373                 //Notify the listeners of IPluginOutReadService
374         
375         for (statsPublisher : statisticsPublisher){
376                         val nodeRef = InstanceIdentifier.builder(Nodes).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node,new NodeKey(notification.id)).toInstance;
377             val description = notification.nodeRef.toNodeDescription
378             if(description != null) {
379                           statsPublisher.descriptionStatisticsUpdated(nodeRef.toADNode,description);
380                         }
381                 }
382     }
383
384     override getNodeProps() {
385         val props = new ConcurrentHashMap<Node, Map<String, org.opendaylight.controller.sal.core.Property>>()
386         
387         val nodes = readAllMDNodes()
388         for (node : nodes.node ) {
389             val fcn = node.getAugmentation(FlowCapableNode)
390             if(fcn != null) {
391                 val perNodeProps = fcn.toADNodeProperties(node.id)
392                 val perNodePropMap = new ConcurrentHashMap<String, org.opendaylight.controller.sal.core.Property>
393                 if(perNodeProps != null ) {
394                     for(perNodeProp : perNodeProps) {
395                         perNodePropMap.put(perNodeProp.name,perNodeProp)
396                     }
397                 }
398                 props.put(new Node(MD_SAL_TYPE, node.id.toADNodeId),perNodePropMap)
399             }
400         }
401         return props;
402     }
403     
404     private def readAllMDNodes() {
405         val nodesRef = InstanceIdentifier.builder(Nodes)
406             .toInstance
407         val reader = TypeSafeDataReader.forReader(dataService)
408         return reader.readOperationalData(nodesRef)
409     }
410     
411     private def readAllMDNodeConnectors(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node node) {
412         val nodeRef = InstanceIdentifier.builder(Nodes)
413             .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node,new NodeKey(node.id))
414             .toInstance
415         val reader = TypeSafeDataReader.forReader(dataService)
416         return reader.readOperationalData(nodeRef).nodeConnector
417     }
418
419     override getNodeConnectorProps(Boolean refresh) {
420         // Note, because the MD-SAL has a unified data store, we can ignore the Boolean refresh, as we have no secondary 
421         // data store to refresh from
422         val props = new ConcurrentHashMap<org.opendaylight.controller.sal.core.NodeConnector, Map<String, org.opendaylight.controller.sal.core.Property>>()
423         val nodes = readAllMDNodes()
424         for (node : nodes.node) {
425             val ncs = node.readAllMDNodeConnectors
426             if(ncs != null) {
427                 for( nc : ncs ) {
428                     val fcnc = nc.getAugmentation(FlowCapableNodeConnector)
429                     if(fcnc != null) {
430                         val ncps = fcnc.toADNodeConnectorProperties
431                         val ncpsm = new ConcurrentHashMap<String, org.opendaylight.controller.sal.core.Property>
432                         if(ncps != null) {
433                             for(p : ncps) {
434                                 ncpsm.put(p.name,p)
435                             }
436                         }  
437                         props.put(nc.id.toADNodeConnector(node.id),ncpsm)
438                     }
439                 }
440             }
441         }
442         return props
443     }
444
445     private def FlowCapableNode readFlowCapableNode(NodeRef ref) {
446         val dataObject = dataService.readOperationalData(ref.value as InstanceIdentifier<? extends DataObject>);
447         if(dataObject != null) {
448             val node = dataObject.checkInstanceOf(
449                 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node);
450             return node.getAugmentation(FlowCapableNode);
451         }
452         return null;
453     }
454
455     private def FlowCapableNodeConnector readFlowCapableNodeConnector(NodeConnectorRef ref) {
456         val dataObject = dataService.readOperationalData(ref.value as InstanceIdentifier<? extends DataObject>);
457         val node = dataObject.checkInstanceOf(
458             NodeConnector);
459         return node.getAugmentation(FlowCapableNodeConnector);
460     }
461
462     private def toNodeConnectorStatistics(
463         org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.NodeConnectorStatistics nodeConnectorStatistics, NodeId nodeId, NodeConnectorId nodeConnectorId) {
464                 
465                         val it = new NodeConnectorStatistics();
466                         
467                         receivePacketCount = nodeConnectorStatistics.packets.received.longValue;
468                         transmitPacketCount = nodeConnectorStatistics.packets.transmitted.longValue;
469                         
470                         receiveByteCount = nodeConnectorStatistics.bytes.received.longValue;
471                         transmitByteCount = nodeConnectorStatistics.bytes.transmitted.longValue;
472                         
473                         receiveDropCount = nodeConnectorStatistics.receiveDrops.longValue;
474                         transmitDropCount = nodeConnectorStatistics.transmitDrops.longValue;
475                         
476                         receiveErrorCount = nodeConnectorStatistics.receiveErrors.longValue;
477                         transmitErrorCount = nodeConnectorStatistics.transmitErrors.longValue;
478                         
479                         receiveFrameErrorCount = nodeConnectorStatistics.receiveFrameError.longValue;
480                         receiveOverRunErrorCount = nodeConnectorStatistics.receiveOverRunError.longValue;
481                         receiveCRCErrorCount = nodeConnectorStatistics.receiveCrcError.longValue;
482                         collisionCount = nodeConnectorStatistics.collisionCount.longValue;
483                         
484                         val nodeConnectorRef = InstanceIdentifier.builder(Nodes)
485                                                                 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node,new NodeKey(nodeId))
486                                                                 .child(NodeConnector,new NodeConnectorKey(nodeConnectorId)).toInstance;
487                         
488                         nodeConnector = NodeMapping.toADNodeConnector(new NodeConnectorRef(nodeConnectorRef));
489                         
490                         return it;
491     }
492
493         private def toNodeTableStatistics(
494                 FlowTableStatistics tableStats,
495                 Short tableId,Node node){
496                 var it = new NodeTableStatistics();
497                 
498                 activeCount = tableStats.activeFlows.value.intValue;
499                 lookupCount = tableStats.packetsLookedUp.value.intValue;
500                 matchedCount = tableStats.packetsMatched.value.intValue;
501                 name = tableId.toString;
502                 nodeTable = new NodeTable(NodeMapping.MD_SAL_TYPE,tableId,node);
503                 return it;
504         }
505         
506         private def toNodeDescription(NodeRef nodeRef){
507                 val capableNode = readFlowCapableNode(nodeRef);
508         if(capableNode !=null) {
509             val it = new NodeDescription()
510             manufacturer = capableNode.manufacturer
511             serialNumber = capableNode.serialNumber
512             software = capableNode.software
513             description = capableNode.description
514             
515             return it;
516          }
517          return null;
518         }
519     
520     
521     def Edge toADEdge(Link link) {
522         new Edge(link.source.toADNodeConnector,link.destination.toADNodeConnector)
523     }
524         
525         /*
526          * OpendaylightFlowStatisticsListener interface implementation
527          */
528         override onAggregateFlowStatisticsUpdate(AggregateFlowStatisticsUpdate notification) {
529         //Ignoring this notification as there does not seem to be a way to bubble this up to AD-SAL
530         }
531         
532         override onFlowsStatisticsUpdate(FlowsStatisticsUpdate notification) {
533                 
534                 val adsalFlowsStatistics = new ArrayList<FlowOnNode>();
535                 val nodeRef = InstanceIdentifier.builder(Nodes).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node,new NodeKey(notification.id)).toInstance;
536                 
537                 for(flowStats : notification.flowAndStatisticsMapList){
538                         if(flowStats.tableId == 0)
539                                 adsalFlowsStatistics.add(toFlowOnNode(flowStats,nodeRef.toADNode));
540                 }
541                 
542                 for (statsPublisher : statisticsPublisher){
543                         statsPublisher.nodeFlowStatisticsUpdated(nodeRef.toADNode,adsalFlowsStatistics);
544                 }
545                 
546         }
547         /*
548          * OpendaylightFlowTableStatisticsListener interface implementation
549          */     
550         override onFlowTableStatisticsUpdate(FlowTableStatisticsUpdate notification) {
551                 var adsalFlowTableStatistics = new ArrayList<NodeTableStatistics>();
552                 
553                 for(stats : notification.flowTableAndStatisticsMap){
554                         if (stats.tableId.value == 0){
555                                 val it = new NodeTableStatistics();
556                                 activeCount = stats.activeFlows.value.intValue;
557                                 lookupCount = stats.packetsLookedUp.value.longValue;
558                                 matchedCount = stats.packetsMatched.value.longValue;
559                                 
560                                 adsalFlowTableStatistics.add(it);
561                         }
562                 }
563                 for (statsPublisher : statisticsPublisher){
564                         val nodeRef = InstanceIdentifier.builder(Nodes).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node,new NodeKey(notification.id)).toInstance;
565                         statsPublisher.nodeTableStatisticsUpdated(nodeRef.toADNode,adsalFlowTableStatistics);
566                 }
567         }
568         
569         /*
570          * OpendaylightPortStatisticsUpdate interface implementation
571          */
572         override onNodeConnectorStatisticsUpdate(NodeConnectorStatisticsUpdate notification) {
573                 
574                 val adsalPortStatistics  = new ArrayList<NodeConnectorStatistics>();
575                 
576                 for(nodeConnectorStatistics : notification.nodeConnectorStatisticsAndPortNumberMap){
577                         adsalPortStatistics.add(toNodeConnectorStatistics(nodeConnectorStatistics,notification.id,nodeConnectorStatistics.nodeConnectorId));
578                 }
579                 
580                 for (statsPublisher : statisticsPublisher){
581                         val nodeRef = InstanceIdentifier.builder(Nodes).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node,new NodeKey(notification.id)).toInstance;
582                         statsPublisher.nodeConnectorStatisticsUpdated(nodeRef.toADNode,adsalPortStatistics);
583                 }
584                 
585         }
586         
587         private static def toFlowOnNode (FlowAndStatisticsMapList flowAndStatsMap,Node node){
588                 
589                 val it = new FlowOnNode(ToSalConversionsUtils.toFlow(flowAndStatsMap,node));
590                 
591                 byteCount = flowAndStatsMap.byteCount.value.longValue;
592                 packetCount = flowAndStatsMap.packetCount.value.longValue;
593                 durationSeconds = flowAndStatsMap.duration.second.value.intValue;
594                 durationNanoseconds = flowAndStatsMap.duration.nanosecond.value.intValue;
595                 
596                 return it;
597         }
598
599         override  getConfiguredNotConnectedNodes() {
600         return Collections.emptySet();
601         }
602
603
604         private def publishNodeUpdate(Node node, UpdateType updateType, Set<org.opendaylight.controller.sal.core.Property> properties){
605             for( publisher : inventoryPublisher){
606                 publisher.updateNode(node, updateType, properties);
607             }
608         }
609
610         private def publishNodeConnectorUpdate(org.opendaylight.controller.sal.core.NodeConnector nodeConnector, UpdateType updateType, Set<org.opendaylight.controller.sal.core.Property> properties){
611             for( publisher : inventoryPublisher){
612                 publisher.updateNodeConnector(nodeConnector, updateType, properties);
613             }
614         }
615 }