/* * Copyright (c) 2014 Cisco 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.netconf.sal.connect.netconf.sal; import static java.util.Objects.requireNonNull; import com.google.common.collect.Collections2; 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.MoreExecutors; import com.google.common.util.concurrent.SettableFuture; import org.opendaylight.mdsal.dom.api.DOMRpcAvailabilityListener; import org.opendaylight.mdsal.dom.api.DOMRpcIdentifier; import org.opendaylight.mdsal.dom.api.DOMRpcImplementationNotAvailableException; import org.opendaylight.mdsal.dom.api.DOMRpcResult; import org.opendaylight.mdsal.dom.api.DefaultDOMRpcException; import org.opendaylight.netconf.api.NetconfMessage; import org.opendaylight.netconf.sal.connect.api.RemoteDeviceCommunicator; import org.opendaylight.netconf.sal.connect.api.RemoteDeviceServices.Rpcs; import org.opendaylight.netconf.sal.connect.api.RpcTransformer; import org.opendaylight.yangtools.concepts.ListenerRegistration; import org.opendaylight.yangtools.concepts.NoOpListenerRegistration; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.common.RpcResult; import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode; import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext; /** * Invokes RPC by sending netconf message via listener. Also transforms result from NetconfMessage to * {@link ContainerNode}. */ public final class NetconfDeviceRpc implements Rpcs.Normalized { private final RemoteDeviceCommunicator communicator; private final RpcTransformer transformer; private final EffectiveModelContext modelContext; public NetconfDeviceRpc(final EffectiveModelContext modelContext, final RemoteDeviceCommunicator communicator, final RpcTransformer transformer) { this.modelContext = requireNonNull(modelContext); this.communicator = communicator; this.transformer = transformer; } @Override @SuppressWarnings("checkstyle:IllegalCatch") public ListenableFuture invokeRpc(final QName type, final ContainerNode input) { final ListenableFuture> delegateFuture = communicator.sendRequest( transformer.toRpcRequest(type, input), type); final SettableFuture ret = SettableFuture.create(); Futures.addCallback(delegateFuture, new FutureCallback>() { @Override public void onSuccess(final RpcResult result) { final DOMRpcResult rpcResult; try { rpcResult = transformer.toRpcResult(result, type); } catch (Exception cause) { ret.setException(new DefaultDOMRpcException( "Unable to parse rpc reply. type: " + type + " input: " + input, cause)); return; } ret.set(rpcResult); } @Override public void onFailure(final Throwable cause) { ret.setException(new DOMRpcImplementationNotAvailableException(cause, "Unable to invoke rpc %s", type)); } }, MoreExecutors.directExecutor()); return ret; } @Override public ListenerRegistration registerRpcListener(final T listener) { listener.onRpcAvailable(Collections2.transform(modelContext.getOperations(), input -> DOMRpcIdentifier.create(input.getQName()))); // NOOP, no rpcs appear and disappear in this implementation return NoOpListenerRegistration.of(listener); } }