Add single layer deserialization support
[openflowplugin.git] / openflowplugin-impl / src / main / java / org / opendaylight / openflowplugin / impl / services / multilayer / MultiLayerExperimenterMultipartService.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
9 package org.opendaylight.openflowplugin.impl.services.multilayer;
10
11 import com.google.common.util.concurrent.FutureCallback;
12 import com.google.common.util.concurrent.Futures;
13 import com.google.common.util.concurrent.ListenableFuture;
14 import com.google.common.util.concurrent.SettableFuture;
15 import java.util.ArrayList;
16 import java.util.List;
17 import java.util.concurrent.Future;
18 import org.opendaylight.openflowjava.protocol.api.keys.MessageTypeKey;
19 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
20 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
21 import org.opendaylight.openflowplugin.extension.api.ConvertorMessageFromOFJava;
22 import org.opendaylight.openflowplugin.extension.api.core.extension.ExtensionConverterProvider;
23 import org.opendaylight.openflowplugin.extension.api.exception.ConversionException;
24 import org.opendaylight.openflowplugin.extension.api.path.MessagePath;
25 import org.opendaylight.openflowplugin.impl.services.AbstractExperimenterMultipartService;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.experimenter.mp.message.service.rev151020.SendExperimenterMpRequestInput;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.experimenter.mp.message.service.rev151020.SendExperimenterMpRequestOutput;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.experimenter.mp.message.service.rev151020.SendExperimenterMpRequestOutputBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.experimenter.mp.message.service.rev151020.send.experimenter.mp.request.output.ExperimenterCoreMessageItem;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.experimenter.mp.message.service.rev151020.send.experimenter.mp.request.output.ExperimenterCoreMessageItemBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.experimenter.core.ExperimenterDataOfChoice;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyExperimenterCase;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.experimenter._case.MultipartReplyExperimenter;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.experimenter.types.rev151020.experimenter.core.message.ExperimenterMessageOfChoice;
36 import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
37 import org.opendaylight.yangtools.yang.common.RpcResult;
38 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
39 import org.slf4j.Logger;
40
41 public class MultiLayerExperimenterMultipartService extends AbstractExperimenterMultipartService<MultipartReply> {
42
43     private static final Logger LOG = org.slf4j.LoggerFactory.getLogger(MultiLayerExperimenterMultipartService.class);
44
45     public MultiLayerExperimenterMultipartService(RequestContextStack requestContextStack, DeviceContext deviceContext,
46                                                   ExtensionConverterProvider extensionConverterProvider) {
47         super(requestContextStack, deviceContext, extensionConverterProvider);
48     }
49
50     @Override
51     @SuppressWarnings("unchecked")
52     public Future<RpcResult<SendExperimenterMpRequestOutput>> handleAndReply(SendExperimenterMpRequestInput input) {
53         final ListenableFuture<RpcResult<List<MultipartReply>>> multipartFuture = handleServiceCall(input);
54         final SettableFuture<RpcResult<SendExperimenterMpRequestOutput>> finalFuture = SettableFuture.create();
55
56         class CallBackImpl implements FutureCallback<RpcResult<List<MultipartReply>>> {
57             @Override
58             public void onSuccess(final RpcResult<List<MultipartReply>> result) {
59                 if (result.isSuccessful()) {
60                     final List<MultipartReply> multipartReplies = result.getResult();
61                     if (multipartReplies.isEmpty()) {
62                         LOG.warn("Multipart reply to Experimenter-Mp request shouldn't be empty list.");
63                         finalFuture.set(RpcResultBuilder.<SendExperimenterMpRequestOutput>failed().withError(ErrorType.RPC, "Multipart reply list is empty.").build());
64                     } else {
65                         LOG.debug(
66                                 "OnSuccess, rpc result successful, multipart response for rpc sendExperimenterMpRequest with xid {} obtained.",
67                                 multipartReplies.get(0).getXid());
68                         final SendExperimenterMpRequestOutputBuilder sendExpMpReqOutputBuilder = new SendExperimenterMpRequestOutputBuilder();
69                         final List<ExperimenterCoreMessageItem> expCoreMessageItem = new ArrayList<>();
70                         for(MultipartReply multipartReply : multipartReplies){
71                             final MultipartReplyExperimenterCase caseBody = (MultipartReplyExperimenterCase)multipartReply.getMultipartReplyBody();
72                             final MultipartReplyExperimenter replyBody = caseBody.getMultipartReplyExperimenter();
73                             final ExperimenterDataOfChoice vendorData = replyBody.getExperimenterDataOfChoice();
74                             final MessageTypeKey<? extends ExperimenterDataOfChoice> key = new MessageTypeKey<>(
75                                     getVersion(),
76                                     (Class<? extends ExperimenterDataOfChoice>) vendorData.getImplementedInterface());
77                             final ConvertorMessageFromOFJava<ExperimenterDataOfChoice, MessagePath> messageConverter =
78                                     getExtensionConverterProvider().getMessageConverter(key);
79                             if (messageConverter == null) {
80                                 LOG.warn("Custom converter for {}[OF:{}] not found",
81                                         vendorData.getImplementedInterface(),
82                                         getVersion());
83                                 finalFuture.set(RpcResultBuilder.<SendExperimenterMpRequestOutput>failed().withError(ErrorType.RPC, "Custom converter not found.").build());
84                                 return;
85                             }
86                             try {
87                                 final ExperimenterMessageOfChoice messageOfChoice = messageConverter.convert(vendorData, MessagePath.MPMESSAGE_RPC_OUTPUT);
88                                 final ExperimenterCoreMessageItemBuilder expCoreMessageItemBuilder = new ExperimenterCoreMessageItemBuilder();
89                                 expCoreMessageItemBuilder.setExperimenterMessageOfChoice(messageOfChoice);
90                                 expCoreMessageItem.add(expCoreMessageItemBuilder.build());
91                             } catch (final ConversionException e) {
92                                 LOG.error("Conversion of experimenter message reply failed. Exception: {}", e);
93                                 finalFuture.set(RpcResultBuilder.<SendExperimenterMpRequestOutput>failed().withError(ErrorType.RPC, "Conversion of experimenter rpc output failed.").build());
94                                 return;
95                             }
96                         }
97                         sendExpMpReqOutputBuilder.setExperimenterCoreMessageItem(expCoreMessageItem);
98                         finalFuture.set(RpcResultBuilder.success(sendExpMpReqOutputBuilder.build()).build());
99                     }
100                 } else {
101                     LOG.warn("OnSuccess, rpc result unsuccessful, multipart response for rpc sendExperimenterMpRequest was unsuccessful.");
102                     finalFuture.set(RpcResultBuilder.<SendExperimenterMpRequestOutput>failed().withRpcErrors(result.getErrors()).build());
103                 }
104             }
105
106             @Override
107             public void onFailure(final Throwable t) {
108                 LOG.warn("Failure multipart response for Experimenter-Mp request. Exception: {}", t);
109                 finalFuture.set(RpcResultBuilder.<SendExperimenterMpRequestOutput>failed().withError(ErrorType.RPC, "Future error", t).build());
110             }
111         }
112
113         Futures.addCallback(multipartFuture, new CallBackImpl());
114
115         return finalFuture;
116     }
117
118 }