org.opendaylight.controller.sal.binding.impl.connect.dom.RpcInvocationStrategy.java Source code

Java tutorial

Introduction

Here is the source code for org.opendaylight.controller.sal.binding.impl.connect.dom.RpcInvocationStrategy.java

Source

/*
 ** Copyright (c) 2014 Brocade Communications Systems, Inc. and others.  All rights reserved.
 **
 ** This program and the accompanying materials are made available under the
 ** terms of the Eclipse Public License v1.0 which accompanies this distribution,
 ** and is available at http://www.eclipse.org/legal/epl-v10.html
 **/

package org.opendaylight.controller.sal.binding.impl.connect.dom;

import java.lang.ref.WeakReference;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.concurrent.Future;

import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
import org.opendaylight.yangtools.yang.binding.DataContainer;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.RpcService;
import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.common.RpcResult;
import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
import org.opendaylight.yangtools.yang.data.api.Node;
import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;

import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;

/*
 * RPC's can have both input, output, one or the other, or neither.
 *
 * This class handles the permutations and provides two means of invocation:
 * 1. forwardToDomBroker
 * 2.
 *
 * Weak References to the input and output classes are used to allow these classes to
 * be from another OSGi bundle/class loader which may come and go.
 *
 */
public class RpcInvocationStrategy {

    private final BindingIndependentMappingService mappingService;
    private final RpcProvisionRegistry biRpcRegistry;
    protected final Method targetMethod;
    protected final QName rpc;

    @SuppressWarnings("rawtypes")
    private final WeakReference<Class> inputClass;

    @SuppressWarnings("rawtypes")
    private final WeakReference<Class> outputClass;

    @SuppressWarnings({ "rawtypes" })
    public RpcInvocationStrategy(final QName rpc, final Method targetMethod,
            final BindingIndependentMappingService mappingService, final RpcProvisionRegistry biRpcRegistry) {

        this.targetMethod = targetMethod;
        this.rpc = rpc;

        Optional<Class<?>> outputClassOption = BindingReflections.resolveRpcOutputClass(targetMethod);
        Optional<Class<? extends DataContainer>> inputClassOption = BindingReflections
                .resolveRpcInputClass(targetMethod);

        if (outputClassOption != null && outputClassOption.isPresent()) {
            this.outputClass = new WeakReference(outputClassOption.get());
        } else {
            this.outputClass = null;
        }
        if (inputClassOption != null && inputClassOption.isPresent()) {
            this.inputClass = new WeakReference(inputClassOption.get());
        } else {
            this.inputClass = null;
        }

        this.mappingService = mappingService;
        this.biRpcRegistry = biRpcRegistry;
    }

    @SuppressWarnings({ "unchecked" })
    public ListenableFuture<RpcResult<?>> forwardToDomBroker(final DataObject input) {

        if (biRpcRegistry == null) {
            return Futures.<RpcResult<?>>immediateFuture(RpcResultBuilder.failed().build());
        }

        CompositeNode inputXml = null;
        if (input != null) {
            CompositeNode xml = mappingService.toDataDom(input);
            inputXml = ImmutableCompositeNode.create(rpc, ImmutableList.<Node<?>>of(xml));
        } else {
            inputXml = ImmutableCompositeNode.create(rpc, Collections.<Node<?>>emptyList());
        }

        Function<RpcResult<CompositeNode>, RpcResult<?>> transformationFunction = new Function<RpcResult<CompositeNode>, RpcResult<?>>() {
            @SuppressWarnings("rawtypes")
            @Override
            public RpcResult<?> apply(RpcResult<CompositeNode> result) {

                Object output = null;

                if (getOutputClass() != null) {
                    if (result.getResult() != null) {
                        output = mappingService.dataObjectFromDataDom(getOutputClass().get(), result.getResult());
                    }
                }

                return RpcResultBuilder.from((RpcResult) result).withResult(output).build();
            }
        };

        return Futures.transform(biRpcRegistry.invokeRpc(rpc, inputXml), transformationFunction);
    }

    @SuppressWarnings("unchecked")
    private RpcResult<CompositeNode> uncheckedInvoke(final RpcService rpcService, final CompositeNode domInput)
            throws Exception {

        Future<RpcResult<?>> futureResult = null;

        if (inputClass != null) {
            DataContainer bindingInput = mappingService.dataObjectFromDataDom(inputClass.get(), domInput);
            futureResult = (Future<RpcResult<?>>) targetMethod.invoke(rpcService, bindingInput);

        } else {
            futureResult = (Future<RpcResult<?>>) targetMethod.invoke(rpcService);
        }

        if (futureResult == null) {
            return RpcResultBuilder.<CompositeNode>failed().build();
        }

        @SuppressWarnings("rawtypes")
        RpcResult bindingResult = futureResult.get();

        final Object resultObj = bindingResult.getResult();
        Object output = null;
        if (resultObj instanceof DataObject) {
            output = mappingService.toDataDom((DataObject) resultObj);
        }
        return RpcResultBuilder.from(bindingResult).withResult(output).build();
    }

    public RpcResult<CompositeNode> invokeOn(final RpcService rpcService, final CompositeNode domInput)
            throws Exception {
        return uncheckedInvoke(rpcService, domInput);
    }

    @SuppressWarnings("rawtypes")
    public WeakReference<Class> getOutputClass() {
        return outputClass;
    }
}