Fix errors in serializers and deserializers
[openflowplugin.git] / openflowplugin-impl / src / main / java / org / opendaylight / openflowplugin / impl / services / SalExperimenterMpMessageServiceImpl.java
1 /*
2  * Copyright (c) 2016 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;
10
11 import java.util.ArrayList;
12 import java.util.List;
13 import java.util.Objects;
14 import java.util.concurrent.Future;
15
16 import org.opendaylight.openflowjava.protocol.api.keys.MessageTypeKey;
17 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
18 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
19 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
20 import org.opendaylight.openflowplugin.extension.api.ConvertorMessageFromOFJava;
21 import org.opendaylight.openflowplugin.extension.api.ConvertorMessageToOFJava;
22 import org.opendaylight.openflowplugin.extension.api.TypeVersionKey;
23 import org.opendaylight.openflowplugin.extension.api.core.extension.ExtensionConverterProvider;
24 import org.opendaylight.openflowplugin.extension.api.exception.ConversionException;
25 import org.opendaylight.openflowplugin.extension.api.exception.ConverterNotFoundException;
26 import org.opendaylight.openflowplugin.extension.api.path.MessagePath;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.experimenter.mp.message.service.rev151020.SalExperimenterMpMessageService;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.experimenter.mp.message.service.rev151020.SendExperimenterMpRequestInput;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.experimenter.mp.message.service.rev151020.SendExperimenterMpRequestOutput;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.experimenter.mp.message.service.rev151020.SendExperimenterMpRequestOutputBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.experimenter.mp.message.service.rev151020.send.experimenter.mp.request.output.ExperimenterCoreMessageItem;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.experimenter.mp.message.service.rev151020.send.experimenter.mp.request.output.ExperimenterCoreMessageItemBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.experimenter.core.ExperimenterDataOfChoice;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyExperimenterCase;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.experimenter._case.MultipartReplyExperimenter;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestExperimenterCaseBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.multipart.request.experimenter._case.MultipartRequestExperimenterBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.experimenter.types.rev151020.experimenter.core.message.ExperimenterMessageOfChoice;
42 import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
43 import org.opendaylight.yangtools.yang.common.RpcResult;
44 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
45 import org.slf4j.Logger;
46
47 import com.google.common.util.concurrent.FutureCallback;
48 import com.google.common.util.concurrent.Futures;
49 import com.google.common.util.concurrent.ListenableFuture;
50 import com.google.common.util.concurrent.SettableFuture;
51
52 public class SalExperimenterMpMessageServiceImpl extends AbstractMultipartService<SendExperimenterMpRequestInput> implements SalExperimenterMpMessageService {
53     private final ExtensionConverterProvider extensionConverterProvider;
54     private static final Logger LOG = org.slf4j.LoggerFactory.getLogger(SalExperimenterMpMessageServiceImpl.class);
55
56     public SalExperimenterMpMessageServiceImpl(final RequestContextStack requestContextStack,
57                                                   final DeviceContext deviceContext,
58                                                   final ExtensionConverterProvider extensionConverterProvider) {
59         super(requestContextStack, deviceContext);
60         this.extensionConverterProvider = extensionConverterProvider;
61     }
62
63     @Override
64     public Future<RpcResult<SendExperimenterMpRequestOutput>> sendExperimenterMpRequest(SendExperimenterMpRequestInput input) {
65         final ListenableFuture<RpcResult<List<MultipartReply>>> multipartFuture = handleServiceCall(input);
66         final SettableFuture<RpcResult<SendExperimenterMpRequestOutput>> finalFuture = SettableFuture.create();
67
68         class CallBackImpl implements FutureCallback<RpcResult<List<MultipartReply>>> {
69             @Override
70             public void onSuccess(final RpcResult<List<MultipartReply>> result) {
71                 if (result.isSuccessful()) {
72                     final List<MultipartReply> multipartReplies = result.getResult();
73                     if (multipartReplies.isEmpty()) {
74                         LOG.warn("Multipart reply to Experimenter-Mp request shouldn't be empty list.");
75                         finalFuture.set(RpcResultBuilder.<SendExperimenterMpRequestOutput>failed().withError(ErrorType.RPC, "Multipart reply list is empty.").build());
76                     } else {
77                         LOG.debug(
78                                 "OnSuccess, rpc result successful, multipart response for rpc sendExperimenterMpRequest with xid {} obtained.",
79                                 multipartReplies.get(0).getXid());
80                         final SendExperimenterMpRequestOutputBuilder sendExpMpReqOutputBuilder = new SendExperimenterMpRequestOutputBuilder();
81                         final List<ExperimenterCoreMessageItem> expCoreMessageItem = new ArrayList<>();
82                         for(MultipartReply multipartReply : multipartReplies){
83                             final MultipartReplyExperimenterCase caseBody = (MultipartReplyExperimenterCase)multipartReply.getMultipartReplyBody();
84                             final MultipartReplyExperimenter replyBody = caseBody.getMultipartReplyExperimenter();
85                             final ExperimenterDataOfChoice vendorData = replyBody.getExperimenterDataOfChoice();
86                             final MessageTypeKey<? extends ExperimenterDataOfChoice> key = new MessageTypeKey<>(
87                                     getVersion(),
88                                     (Class<? extends ExperimenterDataOfChoice>) vendorData.getImplementedInterface());
89                             final ConvertorMessageFromOFJava<ExperimenterDataOfChoice, MessagePath> messageConverter =
90                                     extensionConverterProvider.getMessageConverter(key);
91                             if (messageConverter == null) {
92                                 LOG.warn("Custom converter for {}[OF:{}] not found",
93                                         vendorData.getImplementedInterface(),
94                                         getVersion());
95                                 finalFuture.set(RpcResultBuilder.<SendExperimenterMpRequestOutput>failed().withError(ErrorType.RPC, "Custom converter not found.").build());
96                                 return;
97                             }
98                             try {
99                                 final ExperimenterMessageOfChoice messageOfChoice = messageConverter.convert(vendorData, MessagePath.MPMESSAGE_RPC_OUTPUT);
100                                 final ExperimenterCoreMessageItemBuilder expCoreMessageItemBuilder = new ExperimenterCoreMessageItemBuilder();
101                                 expCoreMessageItemBuilder.setExperimenterMessageOfChoice(messageOfChoice);
102                                 expCoreMessageItem.add(expCoreMessageItemBuilder.build());
103                             } catch (final ConversionException e) {
104                                 LOG.error("Conversion of experimenter message reply failed. Exception: {}", e);
105                                 finalFuture.set(RpcResultBuilder.<SendExperimenterMpRequestOutput>failed().withError(ErrorType.RPC, "Conversion of experimenter rpc output failed.").build());
106                                 return;
107                             }
108                         }
109                         sendExpMpReqOutputBuilder.setExperimenterCoreMessageItem(expCoreMessageItem);
110                         finalFuture.set(RpcResultBuilder.success(sendExpMpReqOutputBuilder.build()).build());
111                     }
112                 } else {
113                     LOG.warn("OnSuccess, rpc result unsuccessful, multipart response for rpc sendExperimenterMpRequest was unsuccessful.");
114                     finalFuture.set(RpcResultBuilder.<SendExperimenterMpRequestOutput>failed().withRpcErrors(result.getErrors()).build());
115                 }
116             }
117
118             @Override
119             public void onFailure(final Throwable t) {
120                 LOG.warn("Failure multipart response for Experimenter-Mp request. Exception: {}", t);
121                 finalFuture.set(RpcResultBuilder.<SendExperimenterMpRequestOutput>failed().withError(ErrorType.RPC, "Future error", t).build());
122             }
123         }
124
125         Futures.addCallback(multipartFuture, new CallBackImpl());
126
127         return finalFuture;
128     }
129
130     @Override
131     @SuppressWarnings("unchecked")
132     protected OfHeader buildRequest(Xid xid, SendExperimenterMpRequestInput input) throws ServiceException {
133         final TypeVersionKey key = new TypeVersionKey(
134                 input.getExperimenterMessageOfChoice().getImplementedInterface(),
135                 getVersion());
136
137         final ConvertorMessageToOFJava<ExperimenterMessageOfChoice, ExperimenterDataOfChoice> messageConverter =
138                 extensionConverterProvider.getMessageConverter(key);
139
140         if (Objects.isNull(messageConverter)) {
141             throw new ServiceException(new ConverterNotFoundException(key.toString()));
142         }
143
144         try {
145             return RequestInputUtils
146                 .createMultipartHeader(MultipartType.OFPMPEXPERIMENTER, xid.getValue(), getVersion())
147                 .setMultipartRequestBody(new MultipartRequestExperimenterCaseBuilder()
148                         .setMultipartRequestExperimenter(new MultipartRequestExperimenterBuilder()
149                                 .setExperimenter(messageConverter.getExperimenterId())
150                                 .setExpType(messageConverter.getType())
151                                 .setExperimenterDataOfChoice(messageConverter
152                                         .convert(input.getExperimenterMessageOfChoice()))
153                                 .build())
154                         .build())
155                 .build();
156         } catch (final ConversionException e) {
157             throw new ServiceException(e);
158         }
159     }
160 }