From: Jakub Toth Date: Tue, 20 Jun 2017 12:39:03 +0000 (+0200) Subject: Binding v2 runtime - adapters - impl - operations X-Git-Tag: release/carbon-sr1~13 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=refs%2Fchanges%2F49%2F59449%2F1;p=mdsal.git Binding v2 runtime - adapters - impl - operations Change-Id: I2d95df66996bff0ae340c2f7799e6399081af6ef Signed-off-by: Jakub Toth (cherry picked from commit 20e925231d9a4d8bec35fe328c0f92f79886837d) --- diff --git a/binding2/mdsal-binding2-api/src/main/java/org/opendaylight/mdsal/binding/javav2/api/RpcActionConsumerRegistry.java b/binding2/mdsal-binding2-api/src/main/java/org/opendaylight/mdsal/binding/javav2/api/RpcActionConsumerRegistry.java index 8da31d334e..860e0bcea0 100644 --- a/binding2/mdsal-binding2-api/src/main/java/org/opendaylight/mdsal/binding/javav2/api/RpcActionConsumerRegistry.java +++ b/binding2/mdsal-binding2-api/src/main/java/org/opendaylight/mdsal/binding/javav2/api/RpcActionConsumerRegistry.java @@ -12,6 +12,7 @@ import com.google.common.annotations.Beta; import org.opendaylight.mdsal.binding.javav2.spec.base.Action; import org.opendaylight.mdsal.binding.javav2.spec.base.ListAction; import org.opendaylight.mdsal.binding.javav2.spec.base.Rpc; +import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode; /** * Provides access to registered Remote Procedure Call (RPC) and Action service implementations. @@ -34,7 +35,7 @@ public interface RpcActionConsumerRegistry extends BindingService { * @param interface type * @return returns proxy for the requested RPC */ - T getRpcService(Class serviceInterface); + > T getRpcService(Class serviceInterface); /** * Returns an implementation of a requested Action service. @@ -47,7 +48,7 @@ public interface RpcActionConsumerRegistry extends BindingService { * @param interface type * @return returns proxy for the requested Action */ - T getActionService(Class serviceInterface); + > T getActionService(Class serviceInterface); /** * Returns an implementation of a requested ListAction service. @@ -60,6 +61,6 @@ public interface RpcActionConsumerRegistry extends BindingService { * @param interface type * @return returns proxy for the requested ListAction */ - T getListActionService(Class serviceInterface); + > T getListActionService(Class serviceInterface); } diff --git a/binding2/mdsal-binding2-api/src/main/java/org/opendaylight/mdsal/binding/javav2/api/RpcActionProviderService.java b/binding2/mdsal-binding2-api/src/main/java/org/opendaylight/mdsal/binding/javav2/api/RpcActionProviderService.java index 0db263235c..2002395730 100644 --- a/binding2/mdsal-binding2-api/src/main/java/org/opendaylight/mdsal/binding/javav2/api/RpcActionProviderService.java +++ b/binding2/mdsal-binding2-api/src/main/java/org/opendaylight/mdsal/binding/javav2/api/RpcActionProviderService.java @@ -33,7 +33,7 @@ public interface RpcActionProviderService { * @param service implementation type * @return returns class representing a RPC registration */ - ObjectRegistration registerRpcImplementation(Class type, + , T extends S> ObjectRegistration registerRpcImplementation(Class type, T implementation); /** @@ -45,7 +45,7 @@ public interface RpcActionProviderService { * @param service implementation type * @return returns class representing a RPC registration */ - ObjectRegistration registerRpcImplementation(Class type, + , T extends S> ObjectRegistration registerRpcImplementation(Class type, T implementation, Set> paths); /** @@ -58,7 +58,8 @@ public interface RpcActionProviderService { * @param service implementation type * @return returns class representing a Action registration */ - ObjectRegistration registerActionImplementation( + , T extends S, P extends TreeNode> ObjectRegistration + registerActionImplementation( Class type, InstanceIdentifier

parent, T implementation); /** @@ -72,6 +73,7 @@ public interface RpcActionProviderService { * @param service implementation type * @return returns class representing a ListAction registration */ - ObjectRegistration registerListActionImplementation( + , T extends S, P extends TreeNode, K> ObjectRegistration + registerListActionImplementation( Class type, KeyedInstanceIdentifier parent, T implementation); } diff --git a/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/extractor/ContextReferenceExtractor.java b/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/extractor/ContextReferenceExtractor.java index 20e2d788f0..a9bc0d65d0 100644 --- a/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/extractor/ContextReferenceExtractor.java +++ b/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/extractor/ContextReferenceExtractor.java @@ -84,14 +84,14 @@ public abstract class ContextReferenceExtractor { /** * Extract context-reference (Instance Identifier) from Binding TreeNode. * - * @param obj + * @param input * - TreeNode from which context reference should be extracted. * * @return Instance Identifier representing context reference or null, if tree node does not contain * context reference. */ @Nullable - public abstract InstanceIdentifier extract(TreeNode obj); + public abstract InstanceIdentifier extract(TreeNode input); /** * Method for return specific extractor of input object. diff --git a/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/BindingDOMOperationImplementationAdapter.java b/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/BindingDOMOperationImplementationAdapter.java new file mode 100644 index 0000000000..749a9ff1af --- /dev/null +++ b/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/BindingDOMOperationImplementationAdapter.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2017 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.binding.javav2.dom.adapter.impl.operation; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import com.google.common.util.concurrent.CheckedFuture; +import com.google.common.util.concurrent.JdkFutureAdapters; +import com.google.common.util.concurrent.ListenableFuture; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; +import java.util.concurrent.ExecutionException; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import org.opendaylight.mdsal.binding.javav2.dom.adapter.impl.operation.invoker.OperationServiceInvoker; +import org.opendaylight.mdsal.binding.javav2.dom.codec.impl.BindingNormalizedNodeCodecRegistry; +import org.opendaylight.mdsal.binding.javav2.dom.codec.serialized.LazySerializedContainerNode; +import org.opendaylight.mdsal.binding.javav2.runtime.reflection.BindingReflections; +import org.opendaylight.mdsal.binding.javav2.spec.base.Operation; +import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode; +import org.opendaylight.mdsal.dom.api.DOMRpcException; +import org.opendaylight.mdsal.dom.api.DOMRpcIdentifier; +import org.opendaylight.mdsal.dom.api.DOMRpcImplementation; +import org.opendaylight.mdsal.dom.api.DOMRpcResult; +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.data.api.schema.NormalizedNode; +import org.opendaylight.yangtools.yang.model.api.SchemaPath; + +/** + * Operation implementation adapter. + */ +@Beta +public class BindingDOMOperationImplementationAdapter implements DOMRpcImplementation { + + private static final Cache, OperationServiceInvoker> SERVICE_INVOKERS = + CacheBuilder.newBuilder().weakKeys().build(); + // Default implementations are 0, we need to perform some translation, hence we have a slightly higher + // cost + private static final int COST = 1; + + private final BindingNormalizedNodeCodecRegistry codec; + private final OperationServiceInvoker invoker; + private final Operation delegate; + private final QName inputQname; + + BindingDOMOperationImplementationAdapter(final BindingNormalizedNodeCodecRegistry codec, + final Class type, final Map localNameToMethod, final T delegate) { + try { + this.invoker = SERVICE_INVOKERS.get(type, () -> { + final Map map = new HashMap<>(); + for (final Entry e : localNameToMethod.entrySet()) { + map.put(e.getKey().getLastComponent(), e.getValue()); + } + + return OperationServiceInvoker.from(map); + }); + } catch (final ExecutionException e) { + throw new IllegalArgumentException("Failed to create invokers for type " + type, e); + } + + this.codec = Preconditions.checkNotNull(codec); + this.delegate = Preconditions.checkNotNull(delegate); + inputQname = QName.create(BindingReflections.getQNameModule(type), "input").intern(); + } + + @Nonnull + @Override + public CheckedFuture invokeRpc(@Nonnull final DOMRpcIdentifier rpc, + @Nullable final NormalizedNode input) { + + final SchemaPath schemaPath = rpc.getType(); + final TreeNode bindingInput = input != null ? deserialize(rpc.getType(), input) : null; + final ListenableFuture> bindingResult = invoke(schemaPath, bindingInput); + return transformResult(bindingResult); + } + + @Override + public long invocationCost() { + return COST; + } + + private TreeNode deserialize(final SchemaPath rpcPath, final NormalizedNode input) { + if (input instanceof LazySerializedContainerNode) { + return ((LazySerializedContainerNode) input).bindingData(); + } + final SchemaPath inputSchemaPath = rpcPath.createChild(inputQname); + return codec.fromNormalizedNodeOperationData(inputSchemaPath, (ContainerNode) input); + } + + private ListenableFuture> invoke(final SchemaPath schemaPath, final TreeNode input) { + return JdkFutureAdapters.listenInPoolThread(invoker.invoke(delegate, schemaPath.getLastComponent(), input)); + } + + private CheckedFuture + transformResult(final ListenableFuture> bindingResult) { + return LazyDOMOperationResultFuture.create(codec, bindingResult); + } +} diff --git a/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/BindingDOMOperationProviderServiceAdapter.java b/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/BindingDOMOperationProviderServiceAdapter.java new file mode 100644 index 0000000000..68a105f74e --- /dev/null +++ b/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/BindingDOMOperationProviderServiceAdapter.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2017 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.binding.javav2.dom.adapter.impl.operation; + +import com.google.common.annotations.Beta; +import com.google.common.collect.ImmutableSet; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import org.opendaylight.mdsal.binding.javav2.api.RpcActionProviderService; +import org.opendaylight.mdsal.binding.javav2.dom.adapter.registration.BindingDOMOperationAdapterRegistration; +import org.opendaylight.mdsal.binding.javav2.dom.codec.impl.BindingToNormalizedNodeCodec; +import org.opendaylight.mdsal.binding.javav2.spec.base.Action; +import org.opendaylight.mdsal.binding.javav2.spec.base.InstanceIdentifier; +import org.opendaylight.mdsal.binding.javav2.spec.base.KeyedInstanceIdentifier; +import org.opendaylight.mdsal.binding.javav2.spec.base.ListAction; +import org.opendaylight.mdsal.binding.javav2.spec.base.Rpc; +import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode; +import org.opendaylight.mdsal.dom.api.DOMRpcIdentifier; +import org.opendaylight.mdsal.dom.api.DOMRpcImplementationRegistration; +import org.opendaylight.mdsal.dom.api.DOMRpcProviderService; +import org.opendaylight.yangtools.concepts.ObjectRegistration; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; +import org.opendaylight.yangtools.yang.model.api.SchemaPath; + +//FIXME missing support of Action operation (dependence on support of Yang 1.1 in DOM part of MD-SAL) +/** + * Operation service provider adapter. + */ +@Beta +public class BindingDOMOperationProviderServiceAdapter implements RpcActionProviderService { + + private static final Set GLOBAL = ImmutableSet.of(YangInstanceIdentifier.builder().build()); + private final BindingToNormalizedNodeCodec codec; + private final DOMRpcProviderService domRpcRegistry; + + public BindingDOMOperationProviderServiceAdapter(final DOMRpcProviderService domRpcRegistry, + final BindingToNormalizedNodeCodec codec) { + this.codec = codec; + this.domRpcRegistry = domRpcRegistry; + } + + @Override + public , T extends S> ObjectRegistration registerRpcImplementation(final Class type, + final T implementation) { + return register(type, implementation, GLOBAL); + } + + @Override + public , T extends S> ObjectRegistration registerRpcImplementation(final Class type, + final T implementation, final Set> paths) { + return register(type, implementation, toYangInstanceIdentifiers(paths)); + } + + private , T extends S> ObjectRegistration register(final Class type, + final T implementation, final Collection rpcContextPaths) { + final Map rpcs = codec.getRPCMethodToSchemaPath(type).inverse(); + + final BindingDOMOperationImplementationAdapter adapter = + new BindingDOMOperationImplementationAdapter(codec.getCodecRegistry(), type, rpcs, implementation); + final Set domRpcs = createDomRpcIdentifiers(rpcs.keySet(), rpcContextPaths); + final DOMRpcImplementationRegistration domReg = domRpcRegistry.registerRpcImplementation(adapter, domRpcs); + return new BindingDOMOperationAdapterRegistration<>(implementation, domReg); + } + + private static Set createDomRpcIdentifiers(final Set rpcs, + final Collection paths) { + final Set ret = new HashSet<>(); + for (final YangInstanceIdentifier path : paths) { + for (final SchemaPath rpc : rpcs) { + ret.add(DOMRpcIdentifier.create(rpc, path)); + } + } + return ret; + } + + private Collection toYangInstanceIdentifiers(final Set> identifiers) { + final Collection ret = new ArrayList<>(identifiers.size()); + for (final InstanceIdentifier binding : identifiers) { + ret.add(codec.toYangInstanceIdentifierCached(binding)); + } + return ret; + } + + @Override + public , T extends S, P extends TreeNode> ObjectRegistration + registerActionImplementation(final Class type, final InstanceIdentifier

parent, + final T implementation) { + // TODO implement after improve DOM part of MD-SAL for support of Yang 1.1 + throw new UnsupportedOperationException(); + } + + @Override + public , T extends S, P extends TreeNode, K> ObjectRegistration + registerListActionImplementation(final Class type, final KeyedInstanceIdentifier parent, + final T implementation) { + // TODO implement after improve DOM part of MD-SAL for support of Yang 1.1 + throw new UnsupportedOperationException(); + } +} diff --git a/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/BindingDOMOperationServiceAdapter.java b/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/BindingDOMOperationServiceAdapter.java new file mode 100644 index 0000000000..c79a6ca4c9 --- /dev/null +++ b/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/BindingDOMOperationServiceAdapter.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2017 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.binding.javav2.dom.adapter.impl.operation; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; +import com.google.common.collect.ClassToInstanceMap; +import com.google.common.collect.ImmutableSet; +import java.util.Set; +import javax.annotation.Nonnull; +import org.opendaylight.mdsal.binding.javav2.api.RpcActionConsumerRegistry; +import org.opendaylight.mdsal.binding.javav2.dom.adapter.spi.builder.BindingDOMAdapterBuilder; +import org.opendaylight.mdsal.binding.javav2.dom.adapter.spi.builder.BindingDOMAdapterBuilder.Factory; +import org.opendaylight.mdsal.binding.javav2.dom.codec.impl.BindingToNormalizedNodeCodec; +import org.opendaylight.mdsal.binding.javav2.runtime.reflection.BindingReflections; +import org.opendaylight.mdsal.binding.javav2.spec.base.Action; +import org.opendaylight.mdsal.binding.javav2.spec.base.ListAction; +import org.opendaylight.mdsal.binding.javav2.spec.base.Operation; +import org.opendaylight.mdsal.binding.javav2.spec.base.Rpc; +import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode; +import org.opendaylight.mdsal.dom.api.DOMRpcService; +import org.opendaylight.mdsal.dom.api.DOMService; + +//FIXME implement after improve DOM part of MD-SAL for support of Yang 1.1 +/** + * Adapter for operation service. + */ +@Beta +public class BindingDOMOperationServiceAdapter implements RpcActionConsumerRegistry { + + public static final Factory BUILDER_FACTORY = Builder::new; + + private final DOMRpcService domService; + private final BindingToNormalizedNodeCodec codec; + private final LoadingCache, RpcServiceAdapter> proxies = CacheBuilder.newBuilder() + .weakKeys().build(new CacheLoader, RpcServiceAdapter>() { + + @SuppressWarnings("unchecked") + private RpcServiceAdapter createProxy(final Class key) { + Preconditions.checkArgument(BindingReflections.isBindingClass(key)); + Preconditions.checkArgument(key.isInterface(), + "Supplied Operation service type must be interface."); + if (Rpc.class.isAssignableFrom(key)) { + return new RpcServiceAdapter((Class>) key, codec, domService); + } + // TODO implement after improve DOM part of MD-SAL for support of Yang 1.1 + throw new UnsupportedOperationException(); + } + + @Nonnull + @Override + public RpcServiceAdapter load(@Nonnull final Class key) throws Exception { + return createProxy(key); + } + + }); + + public BindingDOMOperationServiceAdapter(final DOMRpcService domService, final BindingToNormalizedNodeCodec codec) { + this.domService = Preconditions.checkNotNull(domService); + this.codec = Preconditions.checkNotNull(codec); + } + + @SuppressWarnings("unchecked") + @Override + public > T getRpcService(final Class rpc) { + Preconditions.checkArgument(rpc != null, "Rpc needs to be specified."); + return (T) proxies.getUnchecked(rpc).getProxy(); + } + + private static final class Builder extends BindingDOMAdapterBuilder { + + @Override + protected RpcActionConsumerRegistry createInstance(final BindingToNormalizedNodeCodec codec, + final ClassToInstanceMap delegates) { + final DOMRpcService domRpc = delegates.getInstance(DOMRpcService.class); + return new BindingDOMOperationServiceAdapter(domRpc, codec); + } + + @Override + public Set> getRequiredDelegates() { + return ImmutableSet.of(DOMRpcService.class); + } + } + + @Override + public > T getActionService(final Class serviceInterface) { + // TODO implement after improve DOM part of MD-SAL for support of Yang 1.1 + throw new UnsupportedOperationException(); + } + + @Override + public > T getListActionService(final Class serviceInterface) { + // TODO implement after improve DOM part of MD-SAL for support of Yang 1.1 + throw new UnsupportedOperationException(); + } +} diff --git a/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/LazyDOMOperationResultFuture.java b/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/LazyDOMOperationResultFuture.java new file mode 100644 index 0000000000..878e8e9eb7 --- /dev/null +++ b/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/LazyDOMOperationResultFuture.java @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2017 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.binding.javav2.dom.adapter.impl.operation; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import com.google.common.base.Throwables; +import com.google.common.util.concurrent.CheckedFuture; +import com.google.common.util.concurrent.ListenableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import javax.annotation.Nonnull; +import org.opendaylight.mdsal.binding.javav2.dom.codec.impl.BindingNormalizedNodeCodecRegistry; +import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode; +import org.opendaylight.mdsal.dom.api.DOMRpcException; +import org.opendaylight.mdsal.dom.api.DOMRpcResult; +import org.opendaylight.mdsal.dom.spi.DefaultDOMRpcResult; +import org.opendaylight.yangtools.yang.binding.DataContainer; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; + +/** + * DOM operation result from Binding. + */ +@Beta +final class LazyDOMOperationResultFuture implements CheckedFuture { + + private final ListenableFuture> bindingFuture; + private final BindingNormalizedNodeCodecRegistry codec; + private volatile DOMRpcResult result; + + private LazyDOMOperationResultFuture(final ListenableFuture> delegate, + final BindingNormalizedNodeCodecRegistry codec) { + this.bindingFuture = Preconditions.checkNotNull(delegate, "delegate"); + this.codec = Preconditions.checkNotNull(codec, "codec"); + } + + static CheckedFuture create(final BindingNormalizedNodeCodecRegistry codec, + final ListenableFuture> bindingResult) { + return new LazyDOMOperationResultFuture(bindingResult, codec); + } + + ListenableFuture> getBindingFuture() { + return bindingFuture; + } + + @Override + public boolean cancel(final boolean mayInterruptIfRunning) { + return bindingFuture.cancel(mayInterruptIfRunning); + } + + @Override + public void addListener(@Nonnull final Runnable listener, @Nonnull final Executor executor) { + bindingFuture.addListener(listener, executor); + } + + @Override + public DOMRpcResult get() throws InterruptedException, ExecutionException { + if (result != null) { + return result; + } + return transformIfNecessary(bindingFuture.get()); + } + + @Override + public DOMRpcResult get(@Nonnull final long timeout, final TimeUnit unit) + throws InterruptedException, ExecutionException, TimeoutException { + if (result != null) { + return result; + } + return transformIfNecessary(bindingFuture.get(timeout, unit)); + } + + @Override + public DOMRpcResult checkedGet() throws DOMRpcException { + try { + return get(); + } catch (InterruptedException | ExecutionException e) { + // FIXME: Add exception mapping + throw Throwables.propagate(e); + } + } + + @Override + public DOMRpcResult checkedGet(@Nonnull final long timeout, final TimeUnit unit) + throws TimeoutException, DOMRpcException { + try { + return get(timeout, unit); + } catch (InterruptedException | ExecutionException e) { + // FIXME: Add exception mapping + throw Throwables.propagate(e); + } + } + + @Override + public boolean isCancelled() { + return bindingFuture.isCancelled(); + } + + @Override + public boolean isDone() { + return bindingFuture.isDone(); + } + + private synchronized DOMRpcResult transformIfNecessary(final RpcResult input) { + if (result == null) { + result = transform(input); + } + return result; + } + + private DOMRpcResult transform(final RpcResult input) { + if (input.isSuccessful()) { + final Object inputData = input.getResult(); + if (inputData instanceof DataContainer) { + return new DefaultDOMRpcResult(codec.toNormalizedNodeOperationData((TreeNode) inputData)); + } else { + return new DefaultDOMRpcResult((NormalizedNode) null); + } + } + return new DefaultDOMRpcResult(input.getErrors()); + } + +} \ No newline at end of file diff --git a/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/RpcServiceAdapter.java b/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/RpcServiceAdapter.java new file mode 100644 index 0000000000..e988616f28 --- /dev/null +++ b/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/RpcServiceAdapter.java @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2017 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.binding.javav2.dom.adapter.impl.operation; + +import com.google.common.annotations.Beta; +import com.google.common.base.Function; +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableMap; +import com.google.common.util.concurrent.CheckedFuture; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.Map.Entry; +import org.opendaylight.mdsal.binding.javav2.dom.adapter.extractor.ContextReferenceExtractor; +import org.opendaylight.mdsal.binding.javav2.dom.codec.impl.BindingNormalizedNodeCodecRegistry; +import org.opendaylight.mdsal.binding.javav2.dom.codec.impl.BindingToNormalizedNodeCodec; +import org.opendaylight.mdsal.binding.javav2.dom.codec.serialized.LazySerializedContainerNode; +import org.opendaylight.mdsal.binding.javav2.runtime.reflection.BindingReflections; +import org.opendaylight.mdsal.binding.javav2.spec.base.InstanceIdentifier; +import org.opendaylight.mdsal.binding.javav2.spec.base.Instantiable; +import org.opendaylight.mdsal.binding.javav2.spec.base.Rpc; +import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode; +import org.opendaylight.mdsal.dom.api.DOMRpcException; +import org.opendaylight.mdsal.dom.api.DOMRpcResult; +import org.opendaylight.mdsal.dom.api.DOMRpcService; +import org.opendaylight.mdsal.dom.spi.RpcRoutingStrategy; +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.YangInstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier; +import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode; +import org.opendaylight.yangtools.yang.data.api.schema.LeafNode; +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; +import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes; +import org.opendaylight.yangtools.yang.model.api.OperationDefinition; +import org.opendaylight.yangtools.yang.model.api.RpcDefinition; +import org.opendaylight.yangtools.yang.model.api.SchemaPath; + +@Beta +class RpcServiceAdapter implements InvocationHandler { + + private final ImmutableMap rpcNames; + private final Class> type; + private final BindingToNormalizedNodeCodec codec; + private final DOMRpcService delegate; + private final Rpc proxy; + + RpcServiceAdapter(final Class> type, final BindingToNormalizedNodeCodec codec, + final DOMRpcService domService) { + this.type = Preconditions.checkNotNull(type); + this.codec = Preconditions.checkNotNull(codec); + this.delegate = Preconditions.checkNotNull(domService); + final ImmutableMap.Builder rpcBuilder = ImmutableMap.builder(); + for (final Entry rpc : codec.getRPCMethodToSchema(type).entrySet()) { + rpcBuilder.put(rpc.getKey(), createStrategy(rpc.getKey(), (RpcDefinition) rpc.getValue())); + } + rpcNames = rpcBuilder.build(); + proxy = (Rpc) Proxy.newProxyInstance(type.getClassLoader(), new Class[] { type }, this); + } + + private RpcInvocationStrategy createStrategy(final Method method, final RpcDefinition schema) { + final RpcRoutingStrategy strategy = RpcRoutingStrategy.from(schema); + if (strategy.isContextBasedRouted()) { + return new RoutedStrategy(schema.getPath(), method, strategy.getLeaf()); + } + return new NonRoutedStrategy(schema.getPath()); + } + + Rpc getProxy() { + return proxy; + } + + @Override + public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable { + + final RpcInvocationStrategy rpc = rpcNames.get(method); + if (rpc != null) { + if (method.getParameterTypes().length == 0) { + return rpc.invokeEmpty(); + } + if (args.length != 1) { + throw new IllegalArgumentException("Input must be provided."); + } + return rpc.invoke((TreeNode) args[0]); + } + + if (isObjectMethod(method)) { + return callObjectMethod(proxy, method, args); + } + throw new UnsupportedOperationException("Method " + method.toString() + "is unsupported."); + } + + private static boolean isObjectMethod(final Method method) { + switch (method.getName()) { + case "toString": + return method.getReturnType().equals(String.class) && method.getParameterTypes().length == 0; + case "hashCode": + return method.getReturnType().equals(int.class) && method.getParameterTypes().length == 0; + case "equals": + return method.getReturnType().equals(boolean.class) && method.getParameterTypes().length == 1 + && method.getParameterTypes()[0] == Object.class; + default: + return false; + } + } + + private Object callObjectMethod(final Object self, final Method method, final Object[] args) { + switch (method.getName()) { + case "toString": + return type.getName() + "$Adapter{delegate=" + delegate.toString() + "}"; + case "hashCode": + return System.identityHashCode(self); + case "equals": + return self == args[0]; + default: + return null; + } + } + + private abstract class RpcInvocationStrategy { + + private final SchemaPath rpcName; + + protected RpcInvocationStrategy(final SchemaPath path) { + rpcName = path; + } + + final ListenableFuture> invoke(final TreeNode input) { + return invoke0(rpcName, serialize(input)); + } + + abstract NormalizedNode serialize(TreeNode input); + + final ListenableFuture> invokeEmpty() { + return invoke0(rpcName, null); + } + + final SchemaPath getRpcName() { + return rpcName; + } + + private ListenableFuture> invoke0(final SchemaPath schemaPath, final NormalizedNode input) { + final CheckedFuture result = delegate.invokeRpc(schemaPath, input); + + if (result instanceof LazyDOMOperationResultFuture) { + return ((LazyDOMOperationResultFuture) result).getBindingFuture(); + } + + return transformFuture(schemaPath, result, codec.getCodecFactory()); + } + + private ListenableFuture> transformFuture(final SchemaPath rpc, + final ListenableFuture domFuture, final BindingNormalizedNodeCodecRegistry codec) { + return Futures.transform(domFuture, (Function>) input -> { + final NormalizedNode domData = input.getResult(); + final TreeNode bindingResult; + if (domData != null) { + final SchemaPath rpcOutput = rpc.createChild(QName.create(rpc.getLastComponent(), "output")); + bindingResult = codec.fromNormalizedNodeOperationData(rpcOutput, (ContainerNode) domData); + } else { + bindingResult = null; + } + return RpcResult.class.cast(RpcResultBuilder.success(bindingResult).build()); + }); + } + + } + + private final class NonRoutedStrategy extends RpcInvocationStrategy { + + protected NonRoutedStrategy(final SchemaPath path) { + super(path); + } + + @Override + NormalizedNode serialize(final TreeNode input) { + return LazySerializedContainerNode.create(getRpcName(), input, codec.getCodecRegistry()); + } + + } + + private final class RoutedStrategy extends RpcInvocationStrategy { + + private final ContextReferenceExtractor refExtractor; + private final NodeIdentifier contextName; + + protected RoutedStrategy(final SchemaPath path, final Method rpcMethod, final QName leafName) { + super(path); + final Optional>> maybeInputType = + BindingReflections.resolveOperationInputClass(rpcMethod); + Preconditions.checkState(maybeInputType.isPresent(), "RPC method %s has no input", rpcMethod.getName()); + final Class> inputType = maybeInputType.get(); + refExtractor = ContextReferenceExtractor.from(inputType); + this.contextName = new NodeIdentifier(leafName); + } + + @SuppressWarnings("rawtypes") + @Override + NormalizedNode serialize(final TreeNode input) { + final InstanceIdentifier bindingII = refExtractor.extract(input); + if (bindingII != null) { + final YangInstanceIdentifier yangII = codec.toYangInstanceIdentifierCached(bindingII); + final LeafNode contextRef = ImmutableNodes.leafNode(contextName, yangII); + return LazySerializedContainerNode.withContextRef(getRpcName(), input, contextRef, + codec.getCodecRegistry()); + } + return LazySerializedContainerNode.create(getRpcName(), input, codec.getCodecRegistry()); + } + + } +} \ No newline at end of file diff --git a/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/invoker/AbstractMappedOperationInvoker.java b/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/invoker/AbstractMappedOperationInvoker.java index fe7068e551..f066898a42 100644 --- a/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/invoker/AbstractMappedOperationInvoker.java +++ b/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/invoker/AbstractMappedOperationInvoker.java @@ -18,8 +18,8 @@ import java.util.concurrent.Future; import javax.annotation.Nonnull; import javax.annotation.Nullable; import org.opendaylight.mdsal.binding.javav2.runtime.reflection.BindingReflections; -import org.opendaylight.mdsal.binding.javav2.spec.base.Instantiable; import org.opendaylight.mdsal.binding.javav2.spec.base.Operation; +import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.common.RpcResult; import org.slf4j.Logger; @@ -49,7 +49,7 @@ abstract class AbstractMappedOperationInvoker extends OperationServiceInvoker @Override public final Future> invoke(@Nonnull final I impl, - @Nonnull final QName operationName, @Nullable final Instantiable input) { + @Nonnull final QName operationName, @Nullable final TreeNode input) { Preconditions.checkNotNull(impl, "Implementation must be supplied"); diff --git a/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/invoker/OperationMethodInvoker.java b/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/invoker/OperationMethodInvoker.java index 17f4f817cb..c1549ad3ee 100644 --- a/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/invoker/OperationMethodInvoker.java +++ b/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/invoker/OperationMethodInvoker.java @@ -18,6 +18,7 @@ import java.util.concurrent.Future; import org.opendaylight.mdsal.binding.javav2.runtime.reflection.BindingReflections; import org.opendaylight.mdsal.binding.javav2.spec.base.Instantiable; import org.opendaylight.mdsal.binding.javav2.spec.base.Operation; +import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode; import org.opendaylight.yangtools.yang.common.RpcResult; @Beta @@ -25,7 +26,7 @@ abstract class OperationMethodInvoker { private static final Lookup LOOKUP = MethodHandles.publicLookup(); - protected abstract Future> invokeOn(T impl, Instantiable input); + protected abstract Future> invokeOn(T impl, TreeNode input); protected static OperationMethodInvoker from(final Method method) { final Optional>> input = BindingReflections.resolveOperationInputClass(method); diff --git a/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/invoker/OperationMethodInvokerWithInput.java b/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/invoker/OperationMethodInvokerWithInput.java index f1fa21b41a..d235e7a121 100644 --- a/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/invoker/OperationMethodInvokerWithInput.java +++ b/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/invoker/OperationMethodInvokerWithInput.java @@ -16,6 +16,7 @@ import org.opendaylight.mdsal.binding.javav2.spec.base.Instantiable; import org.opendaylight.mdsal.binding.javav2.spec.base.ListAction; import org.opendaylight.mdsal.binding.javav2.spec.base.Operation; import org.opendaylight.mdsal.binding.javav2.spec.base.Rpc; +import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode; import org.opendaylight.yangtools.yang.common.RpcResult; @Beta @@ -31,7 +32,7 @@ class OperationMethodInvokerWithInput extends OperationMethodInvoker { } @Override - public Future> invokeOn(final T impl, final Instantiable input) { + public Future> invokeOn(final T impl, final TreeNode input) { return invoking(handle, impl, input); } } diff --git a/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/invoker/OperationMethodInvokerWithoutInput.java b/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/invoker/OperationMethodInvokerWithoutInput.java index 7316fc7f80..e1d8f8b032 100644 --- a/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/invoker/OperationMethodInvokerWithoutInput.java +++ b/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/invoker/OperationMethodInvokerWithoutInput.java @@ -12,10 +12,10 @@ import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodType; import java.util.concurrent.Future; import org.opendaylight.mdsal.binding.javav2.spec.base.Action; -import org.opendaylight.mdsal.binding.javav2.spec.base.Instantiable; import org.opendaylight.mdsal.binding.javav2.spec.base.ListAction; import org.opendaylight.mdsal.binding.javav2.spec.base.Operation; import org.opendaylight.mdsal.binding.javav2.spec.base.Rpc; +import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode; import org.opendaylight.yangtools.yang.common.RpcResult; @Beta @@ -31,7 +31,7 @@ class OperationMethodInvokerWithoutInput extends OperationMethodInvoker { } @Override - public Future> invokeOn(final T impl, final Instantiable input) { + public Future> invokeOn(final T impl, final TreeNode input) { return invoking(handle, impl); } } diff --git a/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/invoker/OperationServiceInvoker.java b/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/invoker/OperationServiceInvoker.java index 52b473e12e..4167ba3dc9 100644 --- a/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/invoker/OperationServiceInvoker.java +++ b/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/invoker/OperationServiceInvoker.java @@ -14,8 +14,8 @@ import java.util.Map; import java.util.concurrent.Future; import javax.annotation.Nonnull; import javax.annotation.Nullable; -import org.opendaylight.mdsal.binding.javav2.spec.base.Instantiable; import org.opendaylight.mdsal.binding.javav2.spec.base.Operation; +import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.common.QNameModule; import org.opendaylight.yangtools.yang.common.RpcResult; @@ -27,7 +27,7 @@ import org.slf4j.LoggerFactory; * *

* Operation Service invoker provides common invocation interface for any subtype of operation. via - * {@link #invoke(Operation, QName, Instantiable)} method. + * {@link #invoke(Operation, QName, TreeNode)} method. */ @Beta public abstract class OperationServiceInvoker { @@ -87,5 +87,5 @@ public abstract class OperationServiceInvoker { * @return Future which will complete once operation processing is finished. */ public abstract Future> invoke(@Nonnull T impl, @Nonnull QName operationName, - @Nullable Instantiable input); + @Nullable TreeNode input); } diff --git a/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/spi/loader/BindingDOMAdapterLoader.java b/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/spi/loader/BindingDOMAdapterLoader.java index 447f60eb6e..fa2742586d 100644 --- a/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/spi/loader/BindingDOMAdapterLoader.java +++ b/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/spi/loader/BindingDOMAdapterLoader.java @@ -16,9 +16,11 @@ import org.opendaylight.mdsal.binding.javav2.api.BindingService; import org.opendaylight.mdsal.binding.javav2.api.DataBroker; import org.opendaylight.mdsal.binding.javav2.api.NotificationPublishService; import org.opendaylight.mdsal.binding.javav2.api.NotificationService; +import org.opendaylight.mdsal.binding.javav2.api.RpcActionConsumerRegistry; import org.opendaylight.mdsal.binding.javav2.dom.adapter.impl.data.BindingDOMDataBrokerAdapter; import org.opendaylight.mdsal.binding.javav2.dom.adapter.impl.notification.BindingDOMNotificationPublishServiceAdapter; import org.opendaylight.mdsal.binding.javav2.dom.adapter.impl.notification.BindingDOMNotificationServiceAdapter; +import org.opendaylight.mdsal.binding.javav2.dom.adapter.impl.operation.BindingDOMOperationServiceAdapter; import org.opendaylight.mdsal.binding.javav2.dom.adapter.spi.builder.AdapterBuilder; import org.opendaylight.mdsal.binding.javav2.dom.adapter.spi.builder.BindingDOMAdapterBuilder; import org.opendaylight.mdsal.binding.javav2.dom.adapter.spi.builder.BindingDOMAdapterBuilder.Factory; @@ -31,13 +33,13 @@ import org.opendaylight.mdsal.dom.api.DOMService; @Beta public abstract class BindingDOMAdapterLoader extends AdapterLoader { - // TODO add all factory of services @SuppressWarnings("checkstyle:GenericWhitespace") private static final Map, BindingDOMAdapterBuilder.Factory> FACTORIES = ImmutableMap., BindingDOMAdapterBuilder.Factory> builder() .put(DataBroker.class, BindingDOMDataBrokerAdapter.BUILDER_FACTORY) .put(NotificationPublishService.class, BindingDOMNotificationPublishServiceAdapter.BUILDER_FACTORY) .put(NotificationService.class, BindingDOMNotificationServiceAdapter.BUILDER_FACTORY) + .put(RpcActionConsumerRegistry.class, BindingDOMOperationServiceAdapter.BUILDER_FACTORY) .build(); private final BindingToNormalizedNodeCodec codec; diff --git a/binding2/mdsal-binding2-dom-adapter/src/test/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/invoker/ClassBaseOperationServiceInvokerTest.java b/binding2/mdsal-binding2-dom-adapter/src/test/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/invoker/ClassBaseOperationServiceInvokerTest.java new file mode 100644 index 0000000000..45023ea4ec --- /dev/null +++ b/binding2/mdsal-binding2-dom-adapter/src/test/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/invoker/ClassBaseOperationServiceInvokerTest.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2017 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.binding.javav2.dom.adapter.impl.operation.invoker; + +import static org.junit.Assert.assertNotNull; + +import org.junit.Test; +import org.opendaylight.mdsal.binding.javav2.spec.base.Action; +import org.opendaylight.mdsal.binding.javav2.spec.base.Rpc; +import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode; + +public class ClassBaseOperationServiceInvokerTest { + + @Test + public void rpcTest() { + final OperationServiceInvoker serviceInvoker = ClassBasedOperationServiceInvoker.instanceFor(DummyRpc.class); + assertNotNull(serviceInvoker); + } + + @Test + public void actionTest() { + final OperationServiceInvoker serviceInvoker = ClassBasedOperationServiceInvoker.instanceFor(DummyAction.class); + assertNotNull(serviceInvoker); + } + + @SuppressWarnings("rawtypes") + private interface DummyRpc extends Rpc, TreeNode { + } + + @SuppressWarnings("rawtypes") + private interface DummyAction extends Action, TreeNode { + } +} diff --git a/binding2/mdsal-binding2-dom-codec/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/codec/api/serializer/BindingNormalizedNodeSerializer.java b/binding2/mdsal-binding2-dom-codec/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/codec/api/serializer/BindingNormalizedNodeSerializer.java index 521af62321..6a81ed81d7 100644 --- a/binding2/mdsal-binding2-dom-codec/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/codec/api/serializer/BindingNormalizedNodeSerializer.java +++ b/binding2/mdsal-binding2-dom-codec/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/codec/api/serializer/BindingNormalizedNodeSerializer.java @@ -11,7 +11,6 @@ import java.util.Map.Entry; import javax.annotation.Nonnull; import javax.annotation.Nullable; import org.opendaylight.mdsal.binding.javav2.spec.base.InstanceIdentifier; -import org.opendaylight.mdsal.binding.javav2.spec.base.Instantiable; import org.opendaylight.mdsal.binding.javav2.spec.base.Notification; import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; @@ -128,5 +127,5 @@ public interface BindingNormalizedNodeSerializer { * @return NormalizedNode representation of operation data */ @Nonnull - ContainerNode toNormalizedNodeOperationData(@Nonnull Instantiable data); + ContainerNode toNormalizedNodeOperationData(@Nonnull TreeNode data); } diff --git a/binding2/mdsal-binding2-dom-codec/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/codec/impl/BindingNormalizedNodeCodecRegistry.java b/binding2/mdsal-binding2-dom-codec/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/codec/impl/BindingNormalizedNodeCodecRegistry.java index c2694d2930..2ec3aac1e2 100644 --- a/binding2/mdsal-binding2-dom-codec/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/codec/impl/BindingNormalizedNodeCodecRegistry.java +++ b/binding2/mdsal-binding2-dom-codec/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/codec/impl/BindingNormalizedNodeCodecRegistry.java @@ -169,16 +169,16 @@ public class BindingNormalizedNodeCodecRegistry implements TreeNodeSerializerReg @Nonnull @SuppressWarnings("unchecked") @Override - public ContainerNode toNormalizedNodeOperationData(@Nonnull final Instantiable data) { + public ContainerNode toNormalizedNodeOperationData(@Nonnull final TreeNode data) { final NormalizedNodeResult result = new NormalizedNodeResult(); // We create DOM stream writer which produces normalized nodes final NormalizedNodeStreamWriter domWriter = ImmutableNormalizedNodeStreamWriter.from(result); @SuppressWarnings("rawtypes") - final Class type = (Class) data.implementedInterface(); + final Class type = data.getClass(); final Class> instData = (Class>) data.getClass(); final BindingStreamEventWriter writer = newOperationWriter(instData, domWriter); try { - getSerializer(type).serialize((TreeNode) data, writer); + getSerializer(type).serialize(data, writer); } catch (final IOException e) { LOG.error("Unexpected failure while serializing data {}", data, e); throw new IllegalStateException("Failed to create normalized node", e); diff --git a/binding2/mdsal-binding2-dom-codec/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/codec/impl/BindingToNormalizedNodeCodec.java b/binding2/mdsal-binding2-dom-codec/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/codec/impl/BindingToNormalizedNodeCodec.java index 5a20cce332..2503507096 100644 --- a/binding2/mdsal-binding2-dom-codec/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/codec/impl/BindingToNormalizedNodeCodec.java +++ b/binding2/mdsal-binding2-dom-codec/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/codec/impl/BindingToNormalizedNodeCodec.java @@ -36,7 +36,6 @@ import org.opendaylight.mdsal.binding.javav2.generator.impl.GeneratedClassLoadin import org.opendaylight.mdsal.binding.javav2.runtime.context.BindingRuntimeContext; import org.opendaylight.mdsal.binding.javav2.runtime.reflection.BindingReflections; import org.opendaylight.mdsal.binding.javav2.spec.base.InstanceIdentifier; -import org.opendaylight.mdsal.binding.javav2.spec.base.Instantiable; import org.opendaylight.mdsal.binding.javav2.spec.base.Notification; import org.opendaylight.mdsal.binding.javav2.spec.base.TreeArgument; import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode; @@ -228,7 +227,7 @@ public final class BindingToNormalizedNodeCodec @Nonnull @Override - public ContainerNode toNormalizedNodeOperationData(@Nonnull final Instantiable data) { + public ContainerNode toNormalizedNodeOperationData(@Nonnull final TreeNode data) { return codecRegistry.toNormalizedNodeOperationData(data); } diff --git a/binding2/mdsal-binding2-dom-codec/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/codec/serialized/LazySerializedContainerNode.java b/binding2/mdsal-binding2-dom-codec/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/codec/serialized/LazySerializedContainerNode.java index 6b543ccf60..0e49aac617 100644 --- a/binding2/mdsal-binding2-dom-codec/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/codec/serialized/LazySerializedContainerNode.java +++ b/binding2/mdsal-binding2-dom-codec/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/codec/serialized/LazySerializedContainerNode.java @@ -12,7 +12,7 @@ import java.util.Collection; import java.util.Map; import javax.annotation.Nonnull; import org.opendaylight.mdsal.binding.javav2.dom.codec.impl.BindingNormalizedNodeCodecRegistry; -import org.opendaylight.mdsal.binding.javav2.spec.base.Instantiable; +import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument; @@ -28,12 +28,12 @@ import org.opendaylight.yangtools.yang.model.api.SchemaPath; public class LazySerializedContainerNode implements ContainerNode { private final NodeIdentifier identifier; - private final Instantiable bindingData; + private final TreeNode bindingData; private BindingNormalizedNodeCodecRegistry registry; private ContainerNode domData; - private LazySerializedContainerNode(final QName identifier, final Instantiable binding, + private LazySerializedContainerNode(final QName identifier, final TreeNode binding, final BindingNormalizedNodeCodecRegistry registry) { this.identifier = NodeIdentifier.create(identifier); this.bindingData = binding; @@ -52,7 +52,7 @@ public class LazySerializedContainerNode implements ContainerNode { * - specifc codec for operation * @return instance of lazy serialized container node */ - public static NormalizedNode create(final SchemaPath operationName, final Instantiable data, + public static NormalizedNode create(final SchemaPath operationName, final TreeNode data, final BindingNormalizedNodeCodecRegistry codec) { return new LazySerializedContainerNode(operationName.getLastComponent(), data, codec); } @@ -71,7 +71,7 @@ public class LazySerializedContainerNode implements ContainerNode { * - specific codec * @return insntance of lazy serialized container node with pre-cached serialized leaf */ - public static NormalizedNode withContextRef(final SchemaPath operationName, final Instantiable data, + public static NormalizedNode withContextRef(final SchemaPath operationName, final TreeNode data, final LeafNode contextRef, final BindingNormalizedNodeCodecRegistry codec) { return new WithContextRef(operationName.getLastComponent(), data, contextRef, codec); } @@ -120,7 +120,7 @@ public class LazySerializedContainerNode implements ContainerNode { * * @return binding data. */ - public final Instantiable bindingData() { + public final TreeNode bindingData() { return bindingData; } @@ -132,7 +132,7 @@ public class LazySerializedContainerNode implements ContainerNode { private final LeafNode contextRef; - private WithContextRef(final QName identifier, final Instantiable binding, final LeafNode contextRef, + private WithContextRef(final QName identifier, final TreeNode binding, final LeafNode contextRef, final BindingNormalizedNodeCodecRegistry registry) { super(identifier, binding, registry); this.contextRef = contextRef;