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