Bug 6820 - Implement SalExperimenterMpMessageService
[openflowplugin.git] / openflowplugin-impl / src / main / java / org / opendaylight / openflowplugin / impl / services / SalExperimenterMpMessageServiceImpl.java
old mode 100644 (file)
new mode 100755 (executable)
index 9797ece..fa67972
@@ -8,36 +8,50 @@
 
 package org.opendaylight.openflowplugin.impl.services;
 
-import com.google.common.base.Function;
-import com.google.common.util.concurrent.Futures;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
 import java.util.concurrent.Future;
-import javax.annotation.Nullable;
+
+import org.opendaylight.openflowjava.protocol.api.keys.MessageTypeKey;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
+import org.opendaylight.openflowplugin.extension.api.ConvertorMessageFromOFJava;
 import org.opendaylight.openflowplugin.extension.api.ConvertorMessageToOFJava;
 import org.opendaylight.openflowplugin.extension.api.TypeVersionKey;
 import org.opendaylight.openflowplugin.extension.api.core.extension.ExtensionConverterProvider;
 import org.opendaylight.openflowplugin.extension.api.exception.ConversionException;
 import org.opendaylight.openflowplugin.extension.api.exception.ConverterNotFoundException;
+import org.opendaylight.openflowplugin.extension.api.path.MessagePath;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.experimenter.mp.message.service.rev151020.SalExperimenterMpMessageService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.experimenter.mp.message.service.rev151020.SendExperimenterMpRequestInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.experimenter.mp.message.service.rev151020.SendExperimenterMpRequestOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.experimenter.mp.message.service.rev151020.SendExperimenterMpRequestOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.experimenter.mp.message.service.rev151020.send.experimenter.mp.request.output.ExperimenterCoreMessageItem;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.experimenter.mp.message.service.rev151020.send.experimenter.mp.request.output.ExperimenterCoreMessageItemBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.experimenter.core.ExperimenterDataOfChoice;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyExperimenterCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.experimenter._case.MultipartReplyExperimenter;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestExperimenterCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.multipart.request.experimenter._case.MultipartRequestExperimenterBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.experimenter.types.rev151020.experimenter.core.message.ExperimenterMessageOfChoice;
+import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+import org.slf4j.Logger;
+
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.SettableFuture;
 
 public class SalExperimenterMpMessageServiceImpl extends AbstractMultipartService<SendExperimenterMpRequestInput> implements SalExperimenterMpMessageService {
     private final ExtensionConverterProvider extensionConverterProvider;
+    private static final Logger LOG = org.slf4j.LoggerFactory.getLogger(SalExperimenterMpMessageServiceImpl.class);
 
     public SalExperimenterMpMessageServiceImpl(final RequestContextStack requestContextStack,
                                                   final DeviceContext deviceContext,
@@ -48,21 +62,69 @@ public class SalExperimenterMpMessageServiceImpl extends AbstractMultipartServic
 
     @Override
     public Future<RpcResult<SendExperimenterMpRequestOutput>> sendExperimenterMpRequest(SendExperimenterMpRequestInput input) {
-        return Futures.lazyTransform(handleServiceCall(input), new Function<RpcResult<List<MultipartReply>>, RpcResult<SendExperimenterMpRequestOutput>>() {
-            @Nullable
+        final ListenableFuture<RpcResult<List<MultipartReply>>> multipartFuture = handleServiceCall(input);
+        final SettableFuture<RpcResult<SendExperimenterMpRequestOutput>> finalFuture = SettableFuture.create();
+
+        class CallBackImpl implements FutureCallback<RpcResult<List<MultipartReply>>> {
             @Override
-            public RpcResult<SendExperimenterMpRequestOutput> apply(final RpcResult<List<MultipartReply>> result) {
-                return result.isSuccessful()
-                        ? RpcResultBuilder
-                                .success(new SendExperimenterMpRequestOutputBuilder()
-                                        .setExperimenterMessageOfChoice(input.getExperimenterMessageOfChoice()))
-                                .build()
-                        : RpcResultBuilder
-                                .<SendExperimenterMpRequestOutput>failed()
-                                .withRpcErrors(result.getErrors())
-                                .build();
+            public void onSuccess(final RpcResult<List<MultipartReply>> result) {
+                if (result.isSuccessful()) {
+                    final List<MultipartReply> multipartReplies = result.getResult();
+                    if (multipartReplies.isEmpty()) {
+                        LOG.warn("Multipart reply to Experimenter-Mp request shouldn't be empty list.");
+                        finalFuture.set(RpcResultBuilder.<SendExperimenterMpRequestOutput>failed().withError(ErrorType.RPC, "Multipart reply list is empty.").build());
+                    } else {
+                        LOG.debug(
+                                "OnSuccess, rpc result successful, multipart response for rpc sendExperimenterMpRequest with xid {} obtained.",
+                                multipartReplies.get(0).getXid());
+                        final SendExperimenterMpRequestOutputBuilder sendExpMpReqOutputBuilder = new SendExperimenterMpRequestOutputBuilder();
+                        final List<ExperimenterCoreMessageItem> expCoreMessageItem = new ArrayList<>();
+                        for(MultipartReply multipartReply : multipartReplies){
+                            final MultipartReplyExperimenterCase caseBody = (MultipartReplyExperimenterCase)multipartReply.getMultipartReplyBody();
+                            final MultipartReplyExperimenter replyBody = caseBody.getMultipartReplyExperimenter();
+                            final ExperimenterDataOfChoice vendorData = replyBody.getExperimenterDataOfChoice();
+                            final MessageTypeKey<? extends ExperimenterDataOfChoice> key = new MessageTypeKey<>(
+                                    getVersion(),
+                                    (Class<? extends ExperimenterDataOfChoice>) vendorData.getImplementedInterface());
+                            final ConvertorMessageFromOFJava<ExperimenterDataOfChoice, MessagePath> messageConverter =
+                                    extensionConverterProvider.getMessageConverter(key);
+                            if (messageConverter == null) {
+                                LOG.warn("Custom converter for {}[OF:{}] not found",
+                                        vendorData.getImplementedInterface(),
+                                        getVersion());
+                                finalFuture.set(RpcResultBuilder.<SendExperimenterMpRequestOutput>failed().withError(ErrorType.RPC, "Custom converter not found.").build());
+                                return;
+                            }
+                            try {
+                                final ExperimenterMessageOfChoice messageOfChoice = messageConverter.convert(vendorData, MessagePath.MPMESSAGE_RPC_OUTPUT);
+                                final ExperimenterCoreMessageItemBuilder expCoreMessageItemBuilder = new ExperimenterCoreMessageItemBuilder();
+                                expCoreMessageItemBuilder.setExperimenterMessageOfChoice(messageOfChoice);
+                                expCoreMessageItem.add(expCoreMessageItemBuilder.build());
+                            } catch (final ConversionException e) {
+                                LOG.error("Conversion of experimenter message reply failed. Exception: {}", e);
+                                finalFuture.set(RpcResultBuilder.<SendExperimenterMpRequestOutput>failed().withError(ErrorType.RPC, "Conversion of experimenter rpc output failed.").build());
+                                return;
+                            }
+                        }
+                        sendExpMpReqOutputBuilder.setExperimenterCoreMessageItem(expCoreMessageItem);
+                        finalFuture.set(RpcResultBuilder.success(sendExpMpReqOutputBuilder.build()).build());
+                    }
+                } else {
+                    LOG.warn("OnSuccess, rpc result unsuccessful, multipart response for rpc sendExperimenterMpRequest was unsuccessful.");
+                    finalFuture.set(RpcResultBuilder.<SendExperimenterMpRequestOutput>failed().withRpcErrors(result.getErrors()).build());
+                }
             }
-        });
+
+            @Override
+            public void onFailure(final Throwable t) {
+                LOG.warn("Failure multipart response for Experimenter-Mp request. Exception: {}", t);
+                finalFuture.set(RpcResultBuilder.<SendExperimenterMpRequestOutput>failed().withError(ErrorType.RPC, "Future error", t).build());
+            }
+        }
+
+        Futures.addCallback(multipartFuture, new CallBackImpl());
+
+        return finalFuture;
     }
 
     @Override