Merge "Cleanup MeterMessageSerializer"
[openflowplugin.git] / openflowplugin-impl / src / main / java / org / opendaylight / openflowplugin / impl / common / MultipartReplyTranslatorUtil.java
1 /*
2  * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.common;
9
10 import java.util.ArrayList;
11 import java.util.List;
12 import java.util.Optional;
13 import java.util.stream.Collectors;
14 import org.eclipse.jdt.annotation.Nullable;
15 import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
16 import org.opendaylight.openflowplugin.api.openflow.device.MessageTranslator;
17 import org.opendaylight.openflowplugin.api.openflow.device.TranslatorLibrary;
18 import org.opendaylight.openflowplugin.api.openflow.md.core.TranslatorKey;
19 import org.opendaylight.openflowplugin.api.openflow.md.util.OpenflowVersion;
20 import org.opendaylight.openflowplugin.extension.api.path.MatchPath;
21 import org.opendaylight.openflowplugin.impl.util.GroupUtil;
22 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
23 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.data.FlowStatsResponseConvertorData;
24 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.data.VersionConvertorData;
25 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.data.VersionDatapathIdConvertorData;
26 import org.opendaylight.openflowplugin.openflow.md.util.InventoryDataServiceUtil;
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Counter32;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Counter64;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.multipart.reply.multipart.reply.body.MultipartReplyDescBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.flow.and.statistics.map.list.FlowAndStatisticsMapList;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.multipart.reply.multipart.reply.body.MultipartReplyFlowAggregateStats;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.multipart.reply.multipart.reply.body.MultipartReplyFlowAggregateStatsBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.multipart.reply.multipart.reply.body.MultipartReplyFlowStats;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.multipart.reply.multipart.reply.body.MultipartReplyFlowStatsBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.flow.table.and.statistics.map.FlowTableAndStatisticsMap;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.flow.table.and.statistics.map.FlowTableAndStatisticsMapBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.multipart.reply.multipart.reply.body.MultipartReplyFlowTableStats;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.multipart.reply.multipart.reply.body.MultipartReplyFlowTableStatsBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.multipart.reply.multipart.reply.body.MultipartReplyPortDesc;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.multipart.reply.multipart.reply.body.MultipartReplyPortDescBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.multipart.reply.multipart.reply.body.multipart.reply.port.desc.PortsBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.queue.rev130925.QueueId;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.multipart.reply.multipart.reply.body.MultipartReplyGroupDescBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.multipart.reply.multipart.reply.body.MultipartReplyGroupFeaturesBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.multipart.reply.multipart.reply.body.MultipartReplyGroupStats;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.multipart.reply.multipart.reply.body.MultipartReplyGroupStatsBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.Chaining;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.ChainingChecks;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupAll;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupCapability;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupFf;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupIndirect;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupSelect;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupType;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.SelectLiveness;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.SelectWeight;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.desc.stats.reply.GroupDescStats;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.statistics.reply.GroupStats;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.multipart.reply.multipart.reply.body.MultipartReplyMeterConfigBuilder;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.multipart.reply.multipart.reply.body.MultipartReplyMeterFeaturesBuilder;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.multipart.reply.multipart.reply.body.MultipartReplyMeterStats;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.multipart.reply.multipart.reply.body.MultipartReplyMeterStatsBuilder;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterBand;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterBandDrop;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterBandDscpRemark;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterBurst;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterCapability;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterKbps;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterPktps;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterStats;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.config.stats.reply.MeterConfigStats;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.duration.DurationBuilder;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.node.connector.statistics.BytesBuilder;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.node.connector.statistics.PacketsBuilder;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.multipart.types.rev170112.multipart.reply.MultipartReplyBody;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortGrouping;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyAggregateCase;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyDescCase;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyFlowCase;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyGroupCase;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyGroupDescCase;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyGroupFeaturesCase;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyMeterCase;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyMeterConfigCase;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyMeterFeaturesCase;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyPortDescCase;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyPortStatsCase;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyQueueCase;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyTableCase;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyTableFeaturesCase;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.aggregate._case.MultipartReplyAggregate;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.desc._case.MultipartReplyDesc;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.group._case.MultipartReplyGroup;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.group.desc._case.MultipartReplyGroupDesc;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.group.features._case.MultipartReplyGroupFeatures;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.meter._case.MultipartReplyMeter;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.meter.config._case.MultipartReplyMeterConfig;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.meter.features._case.MultipartReplyMeterFeatures;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.port.stats._case.MultipartReplyPortStats;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.port.stats._case.multipart.reply.port.stats.PortStats;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.queue._case.MultipartReplyQueue;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.queue._case.multipart.reply.queue.QueueStats;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.table._case.MultipartReplyTable;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.table._case.multipart.reply.table.TableStats;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.table.features._case.MultipartReplyTableFeatures;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.multipart.reply.multipart.reply.body.MultipartReplyPortStatsBuilder;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.node.connector.statistics.and.port.number.map.NodeConnectorStatisticsAndPortNumberMap;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.node.connector.statistics.and.port.number.map.NodeConnectorStatisticsAndPortNumberMapBuilder;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.multipart.reply.multipart.reply.body.MultipartReplyQueueStats;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.multipart.reply.multipart.reply.body.MultipartReplyQueueStatsBuilder;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.queue.id.and.statistics.map.QueueIdAndStatisticsMap;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.queue.id.and.statistics.map.QueueIdAndStatisticsMapBuilder;
116 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.TableId;
117 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.multipart.reply.multipart.reply.body.MultipartReplyTableFeaturesBuilder;
118 import org.opendaylight.yangtools.yang.common.Uint64;
119 import org.slf4j.Logger;
120 import org.slf4j.LoggerFactory;
121
122 /**
123  * Class converts multipart reply messages to the objects that can be then written to datastore using
124  * multipart writers.
125  */
126 public final class MultipartReplyTranslatorUtil {
127     private static final Logger LOG = LoggerFactory.getLogger(MultipartReplyTranslatorUtil.class);
128
129     private MultipartReplyTranslatorUtil() {
130         // Hidden on purpose
131     }
132
133     public static Optional<? extends MultipartReplyBody> translate(final OfHeader message, final DeviceInfo deviceInfo,
134             final @Nullable ConvertorExecutor convertorExecutor, final @Nullable TranslatorLibrary translatorLibrary) {
135
136         if (message instanceof MultipartReply) {
137             final MultipartReply msg = (MultipartReply) message;
138             final OpenflowVersion ofVersion = OpenflowVersion.get(deviceInfo.getVersion());
139             final VersionDatapathIdConvertorData data = new VersionDatapathIdConvertorData(deviceInfo.getVersion());
140             data.setDatapathId(deviceInfo.getDatapathId());
141
142             switch (msg.getType()) {
143                 case OFPMPFLOW:
144                     return translateFlow(msg, data, convertorExecutor);
145                 case OFPMPAGGREGATE:
146                     return Optional.of(translateAggregate(msg));
147                 case OFPMPPORTSTATS:
148                     return Optional.of(translatePortStats(msg, ofVersion, deviceInfo.getDatapathId()));
149                 case OFPMPGROUP:
150                     return translateGroup(msg, data, convertorExecutor);
151                 case OFPMPGROUPDESC:
152                     return translateGroupDesc(msg, data, convertorExecutor);
153                 case OFPMPGROUPFEATURES:
154                     return Optional.of(translateGroupFeatures(msg));
155                 case OFPMPMETER:
156                     return translateMeter(msg, data, convertorExecutor);
157                 case OFPMPMETERCONFIG:
158                     return translateMeterConfig(msg, data, convertorExecutor);
159                 case OFPMPMETERFEATURES:
160                     return Optional.of(translateMeterFeatures(msg));
161                 case OFPMPTABLE:
162                     return Optional.of(translateTable(msg));
163                 case OFPMPQUEUE:
164                     return Optional.of(translateQueue(msg, ofVersion, deviceInfo.getDatapathId()));
165                 case OFPMPDESC:
166                     return Optional.of(translateDesc(msg));
167                 case OFPMPTABLEFEATURES:
168                     return translateTableFeatures(msg, deviceInfo.getVersion(), convertorExecutor);
169                 case OFPMPPORTDESC:
170                     return translatePortDesc(msg, deviceInfo, translatorLibrary);
171                 default:
172                     // TODO: log something?
173                     break;
174             }
175         } else if (message instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.multipart.types.rev170112
176             .MultipartReply) {
177             return Optional.of(((org.opendaylight.yang.gen.v1.urn.opendaylight.multipart.types.rev170112
178                 .MultipartReply) message).getMultipartReplyBody());
179         }
180
181         LOG.debug("Failed to translate {} for node {}.", message.implementedInterface(), deviceInfo);
182         return Optional.empty();
183     }
184
185     private static Optional<MultipartReplyPortDesc> translatePortDesc(final MultipartReply msg,
186             final DeviceInfo deviceInfo, final TranslatorLibrary translatorLibrary) {
187         if (translatorLibrary == null) {
188             return Optional.empty();
189         }
190
191         return Optional.of(new MultipartReplyPortDescBuilder()
192             .setPorts(((MultipartReplyPortDescCase) msg.getMultipartReplyBody())
193                 .getMultipartReplyPortDesc().nonnullPorts().stream()
194                 .map(port -> {
195                     final MessageTranslator<PortGrouping, FlowCapableNodeConnector> translator =
196                         translatorLibrary .lookupTranslator(new TranslatorKey(deviceInfo.getVersion(),
197                             PortGrouping.class.getName()));
198
199                     return new PortsBuilder(translator.translate(port, deviceInfo, null)).build();
200                 })
201                 .collect(Collectors.toList()))
202             .build());
203     }
204
205     private static Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.multipart.reply
206             .multipart.reply.body.MultipartReplyTableFeatures> translateTableFeatures(final MultipartReply msg,
207                     final short version, final ConvertorExecutor convertorExecutor) {
208         if (convertorExecutor == null) {
209             return Optional.empty();
210         }
211
212         final MultipartReplyTableFeatures multipartReplyTableFeatures =
213             ((MultipartReplyTableFeaturesCase) msg.getMultipartReplyBody()).getMultipartReplyTableFeatures();
214         final Optional<List<org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features
215             .TableFeatures>> tableFeaturesList = convertorExecutor
216             .convert(multipartReplyTableFeatures, new VersionConvertorData(version));
217
218         return Optional.of(new MultipartReplyTableFeaturesBuilder()
219             .setTableFeatures(tableFeaturesList.orElse(List.of()))
220             .build());
221     }
222
223     private static org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.multipart.reply.multipart
224             .reply.body.MultipartReplyDesc translateDesc(final MultipartReply msg) {
225         final MultipartReplyDesc desc = ((MultipartReplyDescCase) msg.getMultipartReplyBody()).getMultipartReplyDesc();
226
227         return new MultipartReplyDescBuilder()
228             .setDescription(desc.getDpDesc())
229             .setHardware(desc.getHwDesc())
230             .setManufacturer(desc.getMfrDesc())
231             .setSoftware(desc.getSwDesc())
232             .setSerialNumber(desc.getSerialNum())
233             .build();
234     }
235
236     private static Optional<MultipartReplyFlowStats> translateFlow(final MultipartReply msg,
237             final VersionDatapathIdConvertorData data, final ConvertorExecutor convertor) {
238         if (convertor == null) {
239             return Optional.empty();
240         }
241
242         final FlowStatsResponseConvertorData flowData = new FlowStatsResponseConvertorData(data.getVersion());
243         flowData.setDatapathId(data.getDatapathId());
244         flowData.setMatchPath(MatchPath.FLOWS_STATISTICS_UPDATE_MATCH);
245
246         final MultipartReplyFlowCase caseBody = (MultipartReplyFlowCase) msg.getMultipartReplyBody();
247         final Optional<List<FlowAndStatisticsMapList>> flowAndStatisticsMapLists =
248             convertor.convert(caseBody.getMultipartReplyFlow().getFlowStats(), flowData);
249
250         return Optional.of(new MultipartReplyFlowStatsBuilder()
251             .setFlowAndStatisticsMapList(flowAndStatisticsMapLists.orElse(List.of()))
252             .build());
253     }
254
255     private static MultipartReplyFlowAggregateStats translateAggregate(final MultipartReply msg) {
256         final MultipartReplyAggregate replyBody = ((MultipartReplyAggregateCase) msg.getMultipartReplyBody())
257             .getMultipartReplyAggregate();
258
259         return new MultipartReplyFlowAggregateStatsBuilder()
260             .setByteCount(new Counter64(replyBody.getByteCount()))
261             .setPacketCount(new Counter64(replyBody.getPacketCount()))
262             .setFlowCount(new Counter32(replyBody.getFlowCount()))
263             .build();
264     }
265
266     private static org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.multipart.reply.multipart
267             .reply.body.MultipartReplyPortStats translatePortStats(final MultipartReply msg,
268                     final OpenflowVersion ofVersion, final Uint64 datapathId) {
269         MultipartReplyPortStatsCase caseBody = (MultipartReplyPortStatsCase) msg.getMultipartReplyBody();
270         MultipartReplyPortStats replyBody = caseBody.getMultipartReplyPortStats();
271
272         List<NodeConnectorStatisticsAndPortNumberMap> statsMap = new ArrayList<>();
273         for (PortStats portStats : replyBody.nonnullPortStats()) {
274             final DurationBuilder durationBuilder = new DurationBuilder();
275             if (portStats.getDurationSec() != null) {
276                 durationBuilder.setSecond(new Counter32(portStats.getDurationSec()));
277             }
278             if (portStats.getDurationNsec() != null) {
279                 durationBuilder.setNanosecond(new Counter32(portStats.getDurationNsec()));
280             }
281
282             statsMap.add(new NodeConnectorStatisticsAndPortNumberMapBuilder()
283                 .setNodeConnectorId(InventoryDataServiceUtil.nodeConnectorIdfromDatapathPortNo(datapathId,
284                     portStats.getPortNo(), ofVersion))
285                 .setBytes(new BytesBuilder()
286                     .setReceived(portStats.getRxBytes())
287                     .setTransmitted(portStats.getTxBytes())
288                     .build())
289                 .setPackets(new PacketsBuilder()
290                     .setReceived(portStats.getRxPackets())
291                     .setTransmitted(portStats.getTxPackets())
292                     .build())
293                 .setDuration(durationBuilder.build())
294                 .setCollisionCount(portStats.getCollisions())
295                 .setReceiveCrcError(portStats.getRxCrcErr())
296                 .setReceiveDrops(portStats.getRxDropped())
297                 .setReceiveErrors(portStats.getRxErrors())
298                 .setReceiveFrameError(portStats.getRxFrameErr())
299                 .setReceiveOverRunError(portStats.getRxOverErr())
300                 .setTransmitDrops(portStats.getTxDropped())
301                 .setTransmitErrors(portStats.getTxErrors())
302                 .build());
303         }
304
305         return new MultipartReplyPortStatsBuilder()
306             .setNodeConnectorStatisticsAndPortNumberMap(statsMap)
307             .build();
308     }
309
310     private static Optional<MultipartReplyGroupStats> translateGroup(final MultipartReply msg,
311             final VersionDatapathIdConvertorData data, final ConvertorExecutor convertorExecutor) {
312         if (convertorExecutor == null) {
313             return Optional.empty();
314         }
315
316         final MultipartReplyGroup replyBody = ((MultipartReplyGroupCase) msg.getMultipartReplyBody())
317             .getMultipartReplyGroup();
318         final Optional<List<GroupStats>> groupStatsList = convertorExecutor.convert(
319             replyBody.getGroupStats(), data);
320
321         return Optional.of(new MultipartReplyGroupStatsBuilder()
322             .setGroupStats(groupStatsList.orElse(List.of()))
323             .build());
324     }
325
326     private static Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.multipart.reply
327             .multipart.reply.body.MultipartReplyGroupDesc> translateGroupDesc(final MultipartReply msg,
328                     final VersionDatapathIdConvertorData data, final ConvertorExecutor convertorExecutor) {
329         if (convertorExecutor == null) {
330             return Optional.empty();
331         }
332
333         MultipartReplyGroupDescCase caseBody = (MultipartReplyGroupDescCase) msg.getMultipartReplyBody();
334         MultipartReplyGroupDesc replyBody = caseBody.getMultipartReplyGroupDesc();
335
336         final Optional<List<GroupDescStats>> groupDescStatsList = convertorExecutor.convert(
337             replyBody.getGroupDesc(), data);
338
339         return Optional.of(new MultipartReplyGroupDescBuilder()
340             .setGroupDescStats(groupDescStatsList.orElse(List.of()))
341             .build());
342     }
343
344     private static org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.multipart.reply.multipart
345             .reply.body.MultipartReplyGroupFeatures translateGroupFeatures(final MultipartReply msg) {
346         final MultipartReplyGroupFeatures replyBody = ((MultipartReplyGroupFeaturesCase) msg.getMultipartReplyBody())
347             .getMultipartReplyGroupFeatures();
348         final List<Class<? extends GroupType>> supportedGroups = new ArrayList<>();
349         if (replyBody.getTypes().getOFPGTALL()) {
350             supportedGroups.add(GroupAll.class);
351         }
352         if (replyBody.getTypes().getOFPGTSELECT()) {
353             supportedGroups.add(GroupSelect.class);
354         }
355         if (replyBody.getTypes().getOFPGTINDIRECT()) {
356             supportedGroups.add(GroupIndirect.class);
357         }
358         if (replyBody.getTypes().getOFPGTFF()) {
359             supportedGroups.add(GroupFf.class);
360         }
361
362         List<Class<? extends GroupCapability>> supportedCapabilities = new ArrayList<>();
363         if (replyBody.getCapabilities().getOFPGFCCHAINING()) {
364             supportedCapabilities.add(Chaining.class);
365         }
366         if (replyBody.getCapabilities().getOFPGFCCHAININGCHECKS()) {
367             supportedCapabilities.add(ChainingChecks.class);
368         }
369         if (replyBody.getCapabilities().getOFPGFCSELECTLIVENESS()) {
370             supportedCapabilities.add(SelectLiveness.class);
371         }
372         if (replyBody.getCapabilities().getOFPGFCSELECTWEIGHT()) {
373             supportedCapabilities.add(SelectWeight.class);
374         }
375
376         return new MultipartReplyGroupFeaturesBuilder()
377             .setGroupTypesSupported(supportedGroups)
378             .setMaxGroups(replyBody.getMaxGroups())
379             .setGroupCapabilitiesSupported(supportedCapabilities)
380             .setActions(GroupUtil.extractGroupActionsSupportBitmap(replyBody.getActionsBitmap()))
381             .build();
382     }
383
384     private static Optional<MultipartReplyMeterStats> translateMeter(final MultipartReply msg,
385             final VersionDatapathIdConvertorData data, final ConvertorExecutor convertorExecutor) {
386         if (convertorExecutor == null) {
387             return Optional.empty();
388         }
389
390         final MultipartReplyMeter replyBody = ((MultipartReplyMeterCase) msg.getMultipartReplyBody())
391             .getMultipartReplyMeter();
392         final Optional<List<
393             org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.statistics.reply.MeterStats>>
394                 meterStatsList = convertorExecutor.convert(replyBody.getMeterStats(), data);
395
396         return Optional.of(new MultipartReplyMeterStatsBuilder()
397             .setMeterStats(meterStatsList.orElse(List.of()))
398             .build());
399     }
400
401     private static Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.multipart.reply
402             .multipart.reply.body.MultipartReplyMeterConfig> translateMeterConfig(final MultipartReply msg,
403                     final VersionDatapathIdConvertorData data, final ConvertorExecutor convertorExecutor) {
404         if (convertorExecutor == null) {
405             return Optional.empty();
406         }
407
408         MultipartReplyMeterConfigCase caseBody = (MultipartReplyMeterConfigCase) msg.getMultipartReplyBody();
409         MultipartReplyMeterConfig replyBody = caseBody.getMultipartReplyMeterConfig();
410         final Optional<List<MeterConfigStats>> meterConfigStatsList
411                 = convertorExecutor.convert(replyBody.getMeterConfig(), data);
412
413         return Optional.of(new MultipartReplyMeterConfigBuilder()
414             .setMeterConfigStats(meterConfigStatsList.orElse(List.of()))
415             .build());
416     }
417
418     private static org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.multipart.reply.multipart
419             .reply.body.MultipartReplyMeterFeatures translateMeterFeatures(final MultipartReply msg) {
420         MultipartReplyMeterFeaturesCase caseBody = (MultipartReplyMeterFeaturesCase) msg.getMultipartReplyBody();
421         MultipartReplyMeterFeatures replyBody = caseBody.getMultipartReplyMeterFeatures();
422
423         final List<Class<? extends MeterCapability>> supportedCapabilities = new ArrayList<>();
424         if (replyBody.getCapabilities().getOFPMFBURST()) {
425             supportedCapabilities.add(MeterBurst.class);
426         }
427         if (replyBody.getCapabilities().getOFPMFKBPS()) {
428             supportedCapabilities.add(MeterKbps.class);
429         }
430         if (replyBody.getCapabilities().getOFPMFPKTPS()) {
431             supportedCapabilities.add(MeterPktps.class);
432         }
433         if (replyBody.getCapabilities().getOFPMFSTATS()) {
434             supportedCapabilities.add(MeterStats.class);
435         }
436
437         final List<Class<? extends MeterBand>> supportedMeterBand = new ArrayList<>();
438         if (replyBody.getBandTypes().getOFPMBTDROP()) {
439             supportedMeterBand.add(MeterBandDrop.class);
440         }
441         if (replyBody.getBandTypes().getOFPMBTDSCPREMARK()) {
442             supportedMeterBand.add(MeterBandDscpRemark.class);
443         }
444
445         return new MultipartReplyMeterFeaturesBuilder()
446             .setMaxBands(replyBody.getMaxBands())
447             .setMaxColor(replyBody.getMaxColor())
448             .setMaxMeter(new Counter32(replyBody.getMaxMeter()))
449             .setMeterCapabilitiesSupported(supportedCapabilities)
450             .setMeterBandSupported(supportedMeterBand)
451             .build();
452     }
453
454     private static MultipartReplyFlowTableStats translateTable(final MultipartReply msg) {
455         MultipartReplyTableCase caseBody = (MultipartReplyTableCase) msg.getMultipartReplyBody();
456         MultipartReplyTable replyBody = caseBody.getMultipartReplyTable();
457
458         List<FlowTableAndStatisticsMap> salFlowStats = new ArrayList<>();
459         //TODO: Duplicate code: look at OpendaylightFlowTableStatisticsServiceImpl method transformToNotification
460         for (TableStats swTableStats : replyBody.nonnullTableStats()) {
461             salFlowStats.add(new FlowTableAndStatisticsMapBuilder()
462                 .setActiveFlows(new Counter32(swTableStats.getActiveCount()))
463                 .setPacketsLookedUp(new Counter64(swTableStats.getLookupCount()))
464                 .setPacketsMatched(new Counter64(swTableStats.getMatchedCount()))
465                 .setTableId(new TableId(swTableStats.getTableId()))
466                 .build());
467         }
468
469         return new MultipartReplyFlowTableStatsBuilder()
470             .setFlowTableAndStatisticsMap(salFlowStats)
471             .build();
472     }
473
474     private static MultipartReplyQueueStats translateQueue(final MultipartReply msg,
475                                                            final OpenflowVersion ofVersion,
476                                                            final Uint64 datapathId) {
477         MultipartReplyQueueCase caseBody = (MultipartReplyQueueCase) msg.getMultipartReplyBody();
478         MultipartReplyQueue replyBody = caseBody.getMultipartReplyQueue();
479
480         List<QueueIdAndStatisticsMap> statsMap = new ArrayList<>();
481         for (QueueStats queueStats : replyBody.nonnullQueueStats()) {
482             statsMap.add(new QueueIdAndStatisticsMapBuilder()
483                 .setNodeConnectorId(InventoryDataServiceUtil.nodeConnectorIdfromDatapathPortNo(datapathId,
484                     queueStats.getPortNo(), ofVersion))
485                 .setQueueId(new QueueId(queueStats.getQueueId()))
486                 .setTransmissionErrors(new Counter64(queueStats.getTxErrors()))
487                 .setTransmittedBytes(new Counter64(queueStats.getTxBytes()))
488                 .setTransmittedPackets(new Counter64(queueStats.getTxPackets()))
489                 .setDuration(new DurationBuilder()
490                     .setSecond(new Counter32(queueStats.getDurationSec()))
491                     .setNanosecond(new Counter32(queueStats.getDurationNsec()))
492                     .build())
493                 .build());
494         }
495
496         return new MultipartReplyQueueStatsBuilder()
497             .setQueueIdAndStatisticsMap(statsMap)
498             .build();
499     }
500 }