requires org.opendaylight.mdsal.dom.spi;
requires org.opendaylight.yangtools.concepts;
requires org.opendaylight.yangtools.yang.common;
+ requires org.opendaylight.yangtools.yang.data.api;
requires org.opendaylight.yangtools.yang.data.spi;
requires org.opendaylight.yangtools.yang.model.api;
requires org.slf4j;
import static org.opendaylight.yangtools.yang.common.YangConstants.operationInputQName;
import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.MoreExecutors;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.mdsal.binding.api.ActionSpec;
import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
-import org.opendaylight.mdsal.dom.api.DOMActionResult;
import org.opendaylight.mdsal.dom.api.DOMActionService;
import org.opendaylight.mdsal.dom.api.DOMDataTreeIdentifier;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
final var input = (RpcInput) requireNonNull(args[1]);
final var serializer = currentSerializer();
- final ListenableFuture<? extends DOMActionResult> future = getDelegate().invokeAction(actionPath,
+ final var future = getDelegate().invokeAction(actionPath,
DOMDataTreeIdentifier.of(LogicalDatastoreType.OPERATIONAL,
serializer.toYangInstanceIdentifier(path)),
serializer.toLazyNormalizedNodeActionInput(spec.type(), inputName, input));
return bindingAware.getBindingFuture();
}
- return Futures.transform(future,
- dom -> RpcResultUtil.rpcResultFromDOM(dom.getErrors(), dom.getOutput()
- .map(output -> serializer.fromNormalizedNodeActionOutput(spec.type(), output))
- .orElse(null)),
- MoreExecutors.directExecutor());
+ final var specType = spec.type();
+ return Futures.transform(future, dom -> {
+ final var value = dom.value();
+ return RpcResultUtil.rpcResultFromDOM(dom.errors(), value == null ? null
+ : serializer.fromNormalizedNodeActionOutput(specType, value));
+ }, MoreExecutors.directExecutor());
}
break;
default:
import com.google.common.collect.ImmutableSet;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
-import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.opendaylight.mdsal.dom.api.DOMActionImplementation;
import org.opendaylight.mdsal.dom.api.DOMActionInstance;
import org.opendaylight.mdsal.dom.api.DOMActionProviderService;
-import org.opendaylight.mdsal.dom.api.DOMActionResult;
import org.opendaylight.mdsal.dom.api.DOMDataTreeIdentifier;
+import org.opendaylight.mdsal.dom.api.DOMRpcResult;
import org.opendaylight.mdsal.dom.api.DOMService;
-import org.opendaylight.mdsal.dom.spi.SimpleDOMActionResult;
+import org.opendaylight.mdsal.dom.spi.DefaultDOMRpcResult;
import org.opendaylight.yangtools.concepts.Registration;
import org.opendaylight.yangtools.yang.binding.Action;
import org.opendaylight.yangtools.yang.binding.DataObject;
@Override
@SuppressWarnings({ "rawtypes", "unchecked" })
- public ListenableFuture<? extends DOMActionResult> invokeAction(final Absolute type,
+ public ListenableFuture<? extends DOMRpcResult> invokeAction(final Absolute type,
final DOMDataTreeIdentifier path, final ContainerNode input) {
final CurrentAdapterSerializer codec = adapterContext.currentSerializer();
final InstanceIdentifier<DataObject> instance = codec.fromYangInstanceIdentifier(path.path());
if (instance == null) {
// Not representable: return an error
LOG.debug("Path {} is not representable in binding, rejecting invocation", path);
- return Futures.immediateFuture(new SimpleDOMActionResult(List.of(RpcResultBuilder.newError(
- ErrorType.APPLICATION, ErrorTag.INVALID_VALUE, "Supplied path cannot be represented"))));
+ return Futures.immediateFuture(new DefaultDOMRpcResult(RpcResultBuilder.newError(
+ ErrorType.APPLICATION, ErrorTag.INVALID_VALUE, "Supplied path cannot be represented")));
}
if (instance.isWildcarded()) {
// A wildcard path: return an error
LOG.debug("Path {} maps to a wildcard {}, rejecting invocation", path, instance);
- return Futures.immediateFuture(new SimpleDOMActionResult(List.of(RpcResultBuilder.newError(
+ return Futures.immediateFuture(new DefaultDOMRpcResult(RpcResultBuilder.newError(
ErrorType.APPLICATION, ErrorTag.INVALID_VALUE,
- "Supplied path does not identify a concrete instance"))));
+ "Supplied path does not identify a concrete instance")));
}
final ListenableFuture<RpcResult<?>> userFuture = implementation.invoke(instance,
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.MoreExecutors;
import java.util.concurrent.ExecutionException;
-import org.opendaylight.mdsal.dom.api.DOMActionResult;
-import org.opendaylight.mdsal.dom.spi.SimpleDOMActionResult;
+import org.opendaylight.mdsal.dom.api.DOMRpcResult;
+import org.opendaylight.mdsal.dom.spi.DefaultDOMRpcResult;
import org.opendaylight.yangtools.yang.binding.Action;
import org.opendaylight.yangtools.yang.binding.RpcOutput;
import org.opendaylight.yangtools.yang.common.RpcResult;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
-final class BindingOperationFluentFuture<O extends RpcOutput> extends AbstractFuture<DOMActionResult>
+final class BindingOperationFluentFuture<O extends RpcOutput> extends AbstractFuture<DOMRpcResult>
implements BindingRpcFutureAware {
private final ListenableFuture<RpcResult<O>> userFuture;
private final Class<? extends Action<?, ?, O>> action;
@SuppressWarnings("checkstyle:illegalCatch")
private void userFutureCompleted() {
- final DOMActionResult domResult;
+ final DOMRpcResult domResult;
try {
- final RpcResult<O> bindingResult = Futures.getDone(userFuture);
- if (bindingResult.getResult() != null) {
- domResult = new SimpleDOMActionResult(adapterContext.currentSerializer()
- .toLazyNormalizedNodeActionOutput(action, identifier, bindingResult.getResult()),
- bindingResult.getErrors());
- } else {
- domResult = new SimpleDOMActionResult(bindingResult.getErrors());
- }
+ final var bindingResult = Futures.getDone(userFuture);
+ final var bindingValue = bindingResult.getResult();
+ domResult = new DefaultDOMRpcResult(bindingValue == null ? null
+ : adapterContext.currentSerializer().toLazyNormalizedNodeActionOutput(action, identifier, bindingValue),
+ bindingResult.getErrors());
} catch (ExecutionException e) {
adapterContext = null;
setException(e.getCause());
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.MoreExecutors;
import org.eclipse.jdt.annotation.NonNull;
-import org.opendaylight.mdsal.binding.dom.codec.api.BindingNormalizedNodeSerializer;
-import org.opendaylight.mdsal.dom.api.DOMRpcResult;
-import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.RpcInput;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.common.RpcResult;
}
final ListenableFuture<RpcResult<?>> invoke(final RpcInput input) {
- return invoke(serialize(inputIdentifier, adapter.currentSerializer(), input));
+ final var serializer = adapter.currentSerializer();
+ return invoke(serializer, serialize(inputIdentifier, serializer, input));
}
- private ListenableFuture<RpcResult<?>> invoke(final ContainerNode input) {
+ private ListenableFuture<RpcResult<?>> invoke(final @NonNull CurrentAdapterSerializer serializer,
+ final ContainerNode input) {
final var domFuture = adapter.delegate().invokeRpc(outputPath.firstNodeIdentifier(), input);
if (ENABLE_CODEC_SHORTCUT && domFuture instanceof BindingRpcFutureAware bindingAware) {
return bindingAware.getBindingFuture();
}
- return transformFuture(domFuture, adapter.currentSerializer());
+ return Futures.transform(domFuture, dom -> {
+ final var value = dom.value();
+ return RpcResultUtil.rpcResultFromDOM(dom.errors(), value == null ? null
+ : serializer.fromNormalizedNodeRpcData(outputPath, value));
+ }, MoreExecutors.directExecutor());
}
ContainerNode serialize(final @NonNull NodeIdentifier identifier,
final @NonNull CurrentAdapterSerializer serializer, final RpcInput input) {
return LazySerializedContainerNode.create(inputIdentifier, input, serializer);
}
-
- private ListenableFuture<RpcResult<?>> transformFuture(final ListenableFuture<? extends DOMRpcResult> domFuture,
- final BindingNormalizedNodeSerializer resultCodec) {
- return Futures.transform(domFuture, input -> {
- final ContainerNode domData = input.value();
- final DataObject bindingResult;
- if (domData != null) {
- bindingResult = resultCodec.fromNormalizedNodeRpcData(outputPath, domData);
- } else {
- bindingResult = null;
- }
-
- return RpcResultUtil.rpcResultFromDOM(input.errors(), bindingResult);
- }, MoreExecutors.directExecutor());
- }
}
\ No newline at end of file
import java.util.Collection;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
-import org.opendaylight.mdsal.dom.api.DOMActionResult;
import org.opendaylight.mdsal.dom.api.DOMRpcResult;
import org.opendaylight.yangtools.yang.common.ErrorSeverity;
import org.opendaylight.yangtools.yang.common.RpcError;
import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
/**
- * Utility methods for converting {@link RpcResult} to/from {@link DOMActionResult} and {@link DOMRpcResult}.
+ * Utility methods for converting {@link RpcResult} to/from {@link DOMRpcResult}.
*/
@NonNullByDefault
final class RpcResultUtil {
private RpcResultUtil() {
-
+ // Hidden on purpose
}
/**
*/
static <T> RpcResult<T> rpcResultFromDOM(final Collection<? extends RpcError> errors, final @Nullable T result) {
return RpcResultBuilder.<T>status(errors.stream().noneMatch(err -> err.getSeverity() == ErrorSeverity.ERROR))
- .withResult(result).withRpcErrors(errors).build();
+ .withResult(result)
+ .withRpcErrors(errors)
+ .build();
}
}
import org.mockito.junit.MockitoJUnitRunner;
import org.opendaylight.mdsal.binding.api.ActionService;
import org.opendaylight.mdsal.binding.api.ActionSpec;
-import org.opendaylight.mdsal.dom.api.DOMActionResult;
import org.opendaylight.mdsal.dom.api.DOMActionService;
-import org.opendaylight.mdsal.dom.spi.SimpleDOMActionResult;
+import org.opendaylight.mdsal.dom.api.DOMRpcResult;
+import org.opendaylight.mdsal.dom.spi.DefaultDOMRpcResult;
import org.opendaylight.yang.gen.v1.urn.odl.actions.norev.Cont;
import org.opendaylight.yang.gen.v1.urn.odl.actions.norev.Lstio;
import org.opendaylight.yang.gen.v1.urn.odl.actions.norev.LstioKey;
import org.opendaylight.yang.gen.v1.urn.odl.actions.norev.cont.Foo;
import org.opendaylight.yang.gen.v1.urn.odl.actions.norev.lstio.Fooio;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
@RunWith(MockitoJUnitRunner.StrictStubs.class)
public class ActionServiceAdapterTest extends AbstractActionAdapterTest {
private ActionService service;
- private SettableFuture<DOMActionResult> domResult;
+ private SettableFuture<DOMRpcResult> domResult;
@Override
@Before
final var future = handle.invoke(InstanceIdentifier.create(Cont.class), BINDING_FOO_INPUT);
assertNotNull(future);
assertFalse(future.isDone());
- domResult.set(new SimpleDOMActionResult(DOM_FOO_OUTPUT, List.of()));
+ domResult.set(new DefaultDOMRpcResult(DOM_FOO_OUTPUT));
final var bindingResult = Futures.getDone(future);
assertEquals(List.of(), bindingResult.getErrors());
@Test
public void testKeyedInvocation() throws ExecutionException {
final var handle = service.getActionHandle(ActionSpec.builder(Lstio.class).build(Fooio.class));
- final var future = handle.invoke((KeyedInstanceIdentifier<Lstio, LstioKey>)
- InstanceIdentifier.builder(Lstio.class, new LstioKey("test")).build(),
+ final var future = handle.invoke(InstanceIdentifier.builder(Lstio.class, new LstioKey("test")).build(),
BINDING_LSTIO_INPUT);
assertNotNull(future);
assertFalse(future.isDone());
- domResult.set(new SimpleDOMActionResult(DOM_FOO_OUTPUT, List.of()));
+ domResult.set(new DefaultDOMRpcResult(DOM_FOO_OUTPUT));
final var bindingResult = Futures.getDone(future);
assertEquals(List.of(), bindingResult.getErrors());
/**
* Base class for failures that can occur during operation invocation. This covers transport and protocol-level
- * failures, not implementation-reported errors, which are part of {@link DOMActionResult}.
- *
- * @author Robert Varga
+ * failures, not implementation-reported errors, which are part of {@link DOMRpcResult}.
*/
+// FIXME: remove this exception and rename DOMRpcException to DOMOperationException
@Beta
+@Deprecated
@NonNullByDefault
public abstract class DOMActionException extends Exception {
+ @java.io.Serial
private static final long serialVersionUID = 1L;
/**
*/
package org.opendaylight.mdsal.dom.api;
-import com.google.common.annotations.Beta;
import com.google.common.util.concurrent.ListenableFuture;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
/**
* Interface implemented by an individual operation implementation. This API allows for dispatch implementations, e.g.
* an individual object handling a multitude of operations.
- *
- * @author Robert Varga
*/
-@Beta
@FunctionalInterface
@NonNullByDefault
-public interface DOMActionImplementation {
+public non-sealed interface DOMActionImplementation extends DOMOperationImplementation {
/**
* Initiate invocation of the action. Implementations of this method are expected to not block.
*
* instantiated on top of the conceptual {@link StoreTreeNode}.
* @param path {@link DOMDataTreeIdentifier} of parent data node which action attached to.
* @param input Input arguments
- * @return A FluentFuture which completes with the result of invocation
+ * @return A {@link ListenableFuture} which completes with the result of invocation
* @throws NullPointerException if any of the arguments is null
*/
- ListenableFuture<? extends DOMActionResult> invokeAction(Absolute type, DOMDataTreeIdentifier path,
- ContainerNode input);
-
- /**
- * Return the relative invocation cost of this implementation. Default implementation returns 0.
- *
- * @return Non-negative cost of invoking this implementation.
- */
- default long invocationCost() {
- return 0;
- }
+ ListenableFuture<? extends DOMRpcResult> invokeAction(Absolute type, DOMDataTreeIdentifier path,
+ ContainerNode input);
}
+++ /dev/null
-/*
- * Copyright (c) 2018 Pantheon Technologies, s.r.o. 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.mdsal.dom.api;
-
-import com.google.common.annotations.Beta;
-import java.util.Collection;
-import java.util.Optional;
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.opendaylight.yangtools.yang.common.RpcError;
-import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
-
-/**
- * Interface defining a result of an operation invocation.
- *
- * @author Robert Varga
- */
-@Beta
-@NonNullByDefault
-public interface DOMActionResult {
- /**
- * Returns a set of errors and warnings which occurred during processing the call.
- *
- * @return a Collection of {@link RpcError}, guaranteed to be non-null. In case no errors are reported, an empty
- * collection is returned.
- */
- Collection<RpcError> getErrors();
-
- /**
- * Returns the value result of the call.
- *
- * @return Invocation result,.empty if the operation has not produced a result. This might be the case if the
- * operation does not produce a result, or if it failed.
- */
- Optional<ContainerNode> getOutput();
-}
*/
package org.opendaylight.mdsal.dom.api;
-import com.google.common.annotations.Beta;
import com.google.common.util.concurrent.ListenableFuture;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
* A {@link DOMService} which allows clients to invoke Actions. The conceptual model of this service is that
* of a dynamic router, where the set of available Action services can change dynamically.
*/
-@Beta
@NonNullByDefault
public interface DOMActionService extends DOMService<DOMActionService, DOMActionService.Extension> {
/**
* instantiated on top of the conceptual {@link StoreTreeNode}.
* @param path {@link DOMDataTreeIdentifier} of parent data node which action attached to.
* @param input Input argument
- * @return A FluentFuture which completes with the result of invocation
+ * @return A {@link ListenableFuture} which completes with the result of invocation
* @throws NullPointerException if any of the arguments is null
* @throws IllegalArgumentException if {@code path} is empty
*/
- ListenableFuture<? extends DOMActionResult> invokeAction(Absolute type, DOMDataTreeIdentifier path,
+ ListenableFuture<? extends DOMRpcResult> invokeAction(Absolute type, DOMDataTreeIdentifier path,
ContainerNode input);
}
--- /dev/null
+/*
+ * Copyright (c) 2024 PANTHEON.tech, s.r.o. 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.mdsal.dom.api;
+
+/**
+ * Common interface between {@link DOMActionImplementation} and {@link DOMRpcImplementation}.
+ */
+public sealed interface DOMOperationImplementation permits DOMActionImplementation, DOMRpcImplementation {
+ /**
+ * Return the relative invocation cost of this implementation. Default implementation returns 0.
+ *
+ * @return Non-negative cost of invoking this implementation.
+ */
+ default long invocationCost() {
+ return 0;
+ }
+}
* Base class for failures that can occur during RPC invocation. This covers
* transport and protocol-level failures.
*/
+// FIXME: remove this exception to DOMOperationException and remove DOMActionException
public abstract class DOMRpcException extends Exception {
+ @java.io.Serial
private static final long serialVersionUID = 1L;
/**
* Interface implemented by an individual RPC implementation. This API allows for dispatch
* implementations, e.g. an individual object handling a multitude of RPCs.
*/
-public interface DOMRpcImplementation {
+public non-sealed interface DOMRpcImplementation extends DOMOperationImplementation {
/**
* Initiate invocation of the RPC. Implementations of this method are
* expected to not block on external resources.
*/
@NonNull ListenableFuture<? extends DOMRpcResult> invokeRpc(@NonNull DOMRpcIdentifier rpc,
@NonNull ContainerNode input);
-
- /**
- * Return the relative invocation cost of this implementation. Default implementation return 0.
- *
- * @return Non-negative cost of invoking this implementation.
- */
- default long invocationCost() {
- return 0;
- }
}
/**
* Interface defining a result of an RPC call.
*/
+// FIXME: rename to DOMOperationResult
@NonNullByDefault
public interface DOMRpcResult {
/**
import org.opendaylight.mdsal.dom.api.DOMActionInstance;
import org.opendaylight.mdsal.dom.api.DOMActionNotAvailableException;
import org.opendaylight.mdsal.dom.api.DOMActionProviderService;
-import org.opendaylight.mdsal.dom.api.DOMActionResult;
import org.opendaylight.mdsal.dom.api.DOMActionService;
import org.opendaylight.mdsal.dom.api.DOMDataTreeIdentifier;
import org.opendaylight.mdsal.dom.api.DOMRpcAvailabilityListener;
}
@Override
- public ListenableFuture<? extends DOMActionResult> invokeAction(final Absolute type,
+ public ListenableFuture<? extends DOMRpcResult> invokeAction(final Absolute type,
final DOMDataTreeIdentifier path, final ContainerNode input) {
final YangInstanceIdentifier pathRoot = path.path();
checkArgument(!pathRoot.isEmpty(), "Action path must not be empty");
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import org.opendaylight.mdsal.dom.api.DOMActionNotAvailableException;
-import org.opendaylight.mdsal.dom.api.DOMActionResult;
import org.opendaylight.mdsal.dom.api.DOMDataTreeIdentifier;
import org.opendaylight.mdsal.dom.api.DOMRpcIdentifier;
import org.opendaylight.mdsal.dom.api.DOMRpcImplementationNotAvailableException;
// hidden on purpose
}
- static ListenableFuture<? extends DOMActionResult> invoke(final DOMActionRoutingTableEntry entry,
+ static ListenableFuture<? extends DOMRpcResult> invoke(final DOMActionRoutingTableEntry entry,
final Absolute type, final DOMDataTreeIdentifier path, final ContainerNode input) {
var impls = entry.getImplementations(path);
if (impls == null) {
import org.opendaylight.mdsal.dom.api.DOMActionImplementation;
import org.opendaylight.mdsal.dom.api.DOMActionInstance;
import org.opendaylight.mdsal.dom.api.DOMActionNotAvailableException;
-import org.opendaylight.mdsal.dom.api.DOMActionResult;
import org.opendaylight.mdsal.dom.api.DOMActionService;
import org.opendaylight.mdsal.dom.api.DOMDataTreeIdentifier;
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.DOMSchemaService;
-import org.opendaylight.mdsal.dom.spi.SimpleDOMActionResult;
+import org.opendaylight.mdsal.dom.spi.DefaultDOMRpcResult;
import org.opendaylight.yangtools.concepts.Registration;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
new NodeIdentifier(Actions.FOO), NodeIdentifierWithPredicates.of(Actions.FOO, Actions.BAR, "good"));
private static final DOMActionImplementation IMPL =
- (type, path, input) -> Futures.immediateFuture(new SimpleDOMActionResult(
+ (type, path, input) -> Futures.immediateFuture(new DefaultDOMRpcResult(
ImmutableNodes.newContainerBuilder().withNodeIdentifier(new NodeIdentifier(Actions.OUTPUT)).build()));
@Test
public void registerRpcImplementation() {
- try (DOMRpcRouter rpcRouter = rpcsRouter()) {
+ try (var rpcRouter = rpcsRouter()) {
assertOperationKeys(rpcRouter);
- final Registration fooReg = rpcRouter.rpcProviderService().registerRpcImplementation(
+ final var fooReg = rpcRouter.rpcProviderService().registerRpcImplementation(
getTestRpcImplementation(), DOMRpcIdentifier.create(Rpcs.FOO, null));
assertOperationKeys(rpcRouter, Rpcs.FOO);
- final Registration barReg = rpcRouter.rpcProviderService().registerRpcImplementation(
+ final var barReg = rpcRouter.rpcProviderService().registerRpcImplementation(
getTestRpcImplementation(), DOMRpcIdentifier.create(Rpcs.BAR, null));
assertOperationKeys(rpcRouter, Rpcs.FOO, Rpcs.BAR);
@Test
public void registerRpcImplementations() {
- try (DOMRpcRouter rpcRouter = rpcsRouter()) {
+ try (var rpcRouter = rpcsRouter()) {
assertOperationKeys(rpcRouter);
- final Registration fooReg = rpcRouter.rpcProviderService().registerRpcImplementations(
+ final var fooReg = rpcRouter.rpcProviderService().registerRpcImplementations(
Map.of(DOMRpcIdentifier.create(Rpcs.FOO, null), getTestRpcImplementation()));
assertOperationKeys(rpcRouter, Rpcs.FOO);
- final Registration barReg = rpcRouter.rpcProviderService().registerRpcImplementations(
+ final var barReg = rpcRouter.rpcProviderService().registerRpcImplementations(
Map.of(
DOMRpcIdentifier.create(Rpcs.BAR, null), getTestRpcImplementation(),
DOMRpcIdentifier.create(Rpcs.BAZ, null), getTestRpcImplementation()));
public void testClose() {
final var reg = mock(Registration.class);
doNothing().when(reg).close();
- final DOMSchemaService schema = mock(DOMSchemaService.class);
+ final var schema = mock(DOMSchemaService.class);
doReturn(reg).when(schema).registerSchemaContextListener(any());
final var rpcRouter = new DOMRpcRouter(schema);
private static void assertAvailable(final DOMActionService actionService, final YangInstanceIdentifier path)
throws ExecutionException {
- final DOMActionResult result = Futures.getDone(invokeBaz(actionService, path));
- assertEquals(List.of(), result.getErrors());
+ final var result = Futures.getDone(invokeBaz(actionService, path));
+ assertEquals(List.of(), result.errors());
}
private static void assertUnavailable(final DOMActionService actionService, final YangInstanceIdentifier path) {
- final ListenableFuture<? extends DOMActionResult> future = invokeBaz(actionService, path);
- final ExecutionException ex = assertThrows(ExecutionException.class, () -> Futures.getDone(future));
+ final var future = invokeBaz(actionService, path);
+ final var ex = assertThrows(ExecutionException.class, () -> Futures.getDone(future));
assertThat(ex.getCause(), instanceOf(DOMActionNotAvailableException.class));
}
- private static ListenableFuture<? extends DOMActionResult> invokeBaz(final DOMActionService actionService,
+ private static ListenableFuture<? extends DOMRpcResult> invokeBaz(final DOMActionService actionService,
final YangInstanceIdentifier path) {
return actionService.invokeAction(Actions.BAZ_TYPE,
DOMDataTreeIdentifier.of(LogicalDatastoreType.OPERATIONAL, path),
import static java.util.Objects.requireNonNull;
import com.google.common.annotations.Beta;
+import com.google.common.base.MoreObjects;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
-import java.io.Serial;
import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import org.eclipse.jdt.annotation.Nullable;
import org.opendaylight.mdsal.dom.api.DOMRpcResult;
import org.opendaylight.yangtools.concepts.Immutable;
+import org.opendaylight.yangtools.yang.common.ErrorTag;
+import org.opendaylight.yangtools.yang.common.ErrorType;
import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
/**
@Beta
@NonNullByDefault
public final class DefaultDOMRpcResult implements DOMRpcResult, Immutable, Serializable {
- @Serial
+ @java.io.Serial
private static final long serialVersionUID = 1L;
@SuppressFBWarnings(value = "SE_BAD_FIELD", justification = "Interfaces do not specify Serializable")
- private final @Nullable ContainerNode result;
+ private final @Nullable ContainerNode value;
// FIXME: a plain Collection is bad for equality
private final Collection<? extends RpcError> errors;
- public DefaultDOMRpcResult(final ContainerNode value, final RpcError... errors) {
- this(value, List.of(errors));
+ public DefaultDOMRpcResult(final RpcError error) {
+ this(null, List.of(error));
}
public DefaultDOMRpcResult(final RpcError... errors) {
this(result, List.of());
}
- public DefaultDOMRpcResult(final @Nullable ContainerNode value, final Collection<? extends RpcError> errors) {
- result = value;
+ public DefaultDOMRpcResult(final ContainerNode value, final RpcError error) {
+ this(value, List.of(error));
+ }
+
+ public DefaultDOMRpcResult(final ContainerNode value, final RpcError... errors) {
+ this(value, List.of(errors));
+ }
+
+ public DefaultDOMRpcResult(final @Nullable ContainerNode result, final Collection<? extends RpcError> errors) {
+ value = result;
this.errors = requireNonNull(errors);
}
this(null, errors);
}
+ // As per RFC7950 page 80 (top)
+ public static DOMRpcResult ofMalformedMessage(final Exception cause) {
+ return new DefaultDOMRpcResult(RpcResultBuilder.newError(ErrorType.RPC, ErrorTag.MALFORMED_MESSAGE,
+ cause.getMessage(), null, null, requireNonNull(cause)));
+ }
+
@Override
public Collection<? extends RpcError> errors() {
return errors;
@Override
public @Nullable ContainerNode value() {
- return result;
+ return value;
}
@Override
public int hashCode() {
int ret = errors.hashCode();
- if (result != null) {
- ret = 31 * ret + result.hashCode();
+ final var local = value;
+ if (local != null) {
+ ret = 31 * ret + local.hashCode();
}
return ret;
}
@Override
public boolean equals(final @Nullable Object obj) {
return this == obj || obj instanceof DefaultDOMRpcResult other && errors.equals(other.errors)
- && Objects.equals(result, other.result);
+ && Objects.equals(value, other.value);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this).omitNullValues()
+ .add("value", value)
+ .add("errors", errors.isEmpty() ? null : errors)
+ .toString();
}
}
import com.google.common.util.concurrent.ListenableFuture;
import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.opendaylight.mdsal.dom.api.DOMActionResult;
import org.opendaylight.mdsal.dom.api.DOMActionService;
import org.opendaylight.mdsal.dom.api.DOMDataTreeIdentifier;
+import org.opendaylight.mdsal.dom.api.DOMRpcResult;
import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute;
public abstract class ForwardingDOMActionService
extends ForwardingDOMService<DOMActionService, DOMActionService.Extension> implements DOMActionService {
@Override
- public ListenableFuture<? extends DOMActionResult> invokeAction(final Absolute type,
- final DOMDataTreeIdentifier path, final ContainerNode input) {
+ public ListenableFuture<? extends DOMRpcResult> invokeAction(final Absolute type, final DOMDataTreeIdentifier path,
+ final ContainerNode input) {
return delegate().invokeAction(type, path, input);
}
}
+++ /dev/null
-/*
- * Copyright (c) 2018 Pantheon Technologies, s.r.o. 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.mdsal.dom.spi;
-
-import static java.util.Objects.requireNonNull;
-
-import com.google.common.annotations.Beta;
-import com.google.common.base.MoreObjects;
-import com.google.common.collect.ImmutableList;
-import java.util.Collection;
-import java.util.Optional;
-import org.eclipse.jdt.annotation.NonNull;
-import org.eclipse.jdt.annotation.Nullable;
-import org.opendaylight.mdsal.dom.api.DOMActionResult;
-import org.opendaylight.yangtools.concepts.Immutable;
-import org.opendaylight.yangtools.yang.common.ErrorTag;
-import org.opendaylight.yangtools.yang.common.ErrorType;
-import org.opendaylight.yangtools.yang.common.RpcError;
-import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
-import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
-
-@Beta
-public final class SimpleDOMActionResult implements DOMActionResult, Immutable {
- private final @NonNull Collection<RpcError> errors;
- private final @Nullable ContainerNode output;
-
- private SimpleDOMActionResult(final @NonNull Collection<RpcError> errors, final @Nullable ContainerNode output) {
- this.errors = ImmutableList.copyOf(errors);
- this.output = output;
- }
-
- public SimpleDOMActionResult(final @NonNull ContainerNode output) {
- errors = ImmutableList.of();
- this.output = requireNonNull(output);
- }
-
- public SimpleDOMActionResult(final @NonNull Collection<RpcError> errors) {
- this(errors, null);
- }
-
- public SimpleDOMActionResult(final @NonNull ContainerNode output, final @NonNull Collection<RpcError> errors) {
- this(errors, requireNonNull(output));
- }
-
- // As per RFC7950 page 80 (top)
- public static @NonNull SimpleDOMActionResult ofMalformedMessage(final @NonNull Exception cause) {
- return new SimpleDOMActionResult(ImmutableList.of(RpcResultBuilder.newError(ErrorType.RPC,
- ErrorTag.MALFORMED_MESSAGE, cause.getMessage(), null, null, requireNonNull(cause))), null);
- }
-
- @Override
- public Collection<RpcError> getErrors() {
- return errors;
- }
-
- @Override
- public Optional<ContainerNode> getOutput() {
- return Optional.ofNullable(output);
- }
-
- @Override
- public String toString() {
- final var helper = MoreObjects.toStringHelper(this).omitNullValues().add("output", output);
- if (!errors.isEmpty()) {
- helper.add("errors", errors);
- }
- return helper.toString();
- }
-}