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