Eliminate RpcMethodInvoker
[mdsal.git] / binding / mdsal-binding-dom-adapter / src / main / java / org / opendaylight / mdsal / binding / dom / adapter / BindingDOMRpcProviderServiceAdapter.java
1 /*
2  * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.mdsal.binding.dom.adapter;
9
10 import com.google.common.annotations.VisibleForTesting;
11 import com.google.common.collect.ClassToInstanceMap;
12 import com.google.common.collect.ImmutableClassToInstanceMap;
13 import com.google.common.collect.ImmutableMap;
14 import com.google.common.collect.ImmutableSet;
15 import java.util.ArrayList;
16 import java.util.Collection;
17 import java.util.HashSet;
18 import java.util.Set;
19 import org.opendaylight.mdsal.binding.api.RpcProviderService;
20 import org.opendaylight.mdsal.binding.spec.reflect.BindingReflections;
21 import org.opendaylight.mdsal.dom.api.DOMRpcIdentifier;
22 import org.opendaylight.mdsal.dom.api.DOMRpcImplementation;
23 import org.opendaylight.mdsal.dom.api.DOMRpcProviderService;
24 import org.opendaylight.yangtools.concepts.ObjectRegistration;
25 import org.opendaylight.yangtools.concepts.Registration;
26 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
27 import org.opendaylight.yangtools.yang.binding.Rpc;
28 import org.opendaylight.yangtools.yang.binding.RpcService;
29 import org.opendaylight.yangtools.yang.common.QName;
30 import org.opendaylight.yangtools.yang.common.YangConstants;
31 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
32
33 @VisibleForTesting
34 public class BindingDOMRpcProviderServiceAdapter extends AbstractBindingAdapter<DOMRpcProviderService>
35         implements RpcProviderService {
36     private static final ImmutableSet<YangInstanceIdentifier> GLOBAL = ImmutableSet.of(YangInstanceIdentifier.empty());
37
38     public BindingDOMRpcProviderServiceAdapter(final AdapterContext adapterContext,
39             final DOMRpcProviderService domRpcRegistry) {
40         super(adapterContext, domRpcRegistry);
41     }
42
43     @Override
44     @Deprecated
45     public <R extends RpcService, I extends R> ObjectRegistration<I> registerRpcImplementation(final Class<R> type,
46             final I implementation) {
47         return register(currentSerializer(), type, implementation, GLOBAL);
48     }
49
50     @Override
51     @Deprecated
52     public <R extends RpcService, I extends R> ObjectRegistration<I> registerRpcImplementation(final Class<R> type,
53             final I implementation, final Set<InstanceIdentifier<?>> paths) {
54         final var serializer = currentSerializer();
55         return register(serializer, type, implementation, toYangInstanceIdentifiers(serializer, paths));
56     }
57
58     @Override
59     public Registration registerRpcImplementation(final Rpc<?, ?> implementation) {
60         return register(currentSerializer(), implementation, GLOBAL);
61     }
62
63     @Override
64     public Registration registerRpcImplementation(final Rpc<?, ?> implementation,
65             final Set<InstanceIdentifier<?>> paths) {
66         final var serializer = currentSerializer();
67         return register(serializer, implementation, toYangInstanceIdentifiers(serializer, paths));
68     }
69
70     @Override
71     public Registration registerRpcImplementations(final ClassToInstanceMap<Rpc<?, ?>> implementations) {
72         return register(currentSerializer(), implementations, GLOBAL);
73     }
74
75     @Override
76     public Registration registerRpcImplementations(final ClassToInstanceMap<Rpc<?, ?>> implementations,
77             final Set<InstanceIdentifier<?>> paths) {
78         final var serializer = currentSerializer();
79         return register(serializer, implementations, toYangInstanceIdentifiers(serializer, paths));
80     }
81
82     private <T extends Rpc<?, ?>> Registration register(final CurrentAdapterSerializer serializer,
83             final T implementation, final Collection<YangInstanceIdentifier> rpcContextPaths) {
84         @SuppressWarnings("unchecked")
85         final var type = (Class<T>) implementation.implementedInterface();
86         return register(serializer, ImmutableClassToInstanceMap.of(type, implementation), rpcContextPaths);
87     }
88
89     private Registration register(final CurrentAdapterSerializer serializer,
90             final ClassToInstanceMap<Rpc<?, ?>> implementations,
91             final Collection<YangInstanceIdentifier> rpcContextPaths) {
92         final var context = serializer.getRuntimeContext();
93         final var builder = ImmutableMap.<DOMRpcIdentifier, DOMRpcImplementation>builderWithExpectedSize(
94             implementations.size());
95         for (var entry : implementations.entrySet()) {
96             final var type = entry.getKey();
97             final var def = context.getRpcDefinition(type);
98             if (def == null) {
99                 throw new IllegalArgumentException("Cannot resolve YANG definition of " + type);
100             }
101             final var name = def.statement().argument();
102             final var impl = new BindingDOMRpcImplementationAdapter(adapterContext(), entry.getValue(), name);
103
104             for (var id : createDomRpcIdentifiers(Set.of(name), rpcContextPaths)) {
105                 builder.put(id, impl);
106             }
107         }
108
109         return getDelegate().registerRpcImplementations(builder.build());
110     }
111
112     @Deprecated
113     private <S extends RpcService, T extends S> ObjectRegistration<T> register(
114             final CurrentAdapterSerializer serializer, final Class<S> type, final T implementation,
115             final Collection<YangInstanceIdentifier> rpcContextPaths) {
116         // FIXME: do not use BindingReflections here
117         final var inputName = YangConstants.operationInputQName(BindingReflections.getQNameModule(type)).intern();
118         final var methodHandles = currentSerializer().getRpcMethods(type);
119         final var builder = ImmutableMap.<DOMRpcIdentifier, DOMRpcImplementation>builderWithExpectedSize(
120             methodHandles.size());
121         for (var entry : methodHandles.entrySet()) {
122             final var impl = new LegacyDOMRpcImplementationAdapter(adapterContext(), inputName,
123                 entry.getValue().bindTo(implementation));
124             for (var id : createDomRpcIdentifiers(Set.of(entry.getKey()), rpcContextPaths)) {
125                 builder.put(id, impl);
126             }
127         }
128
129         return new BindingRpcAdapterRegistration<>(implementation,
130             getDelegate().registerRpcImplementations(builder.build()));
131     }
132
133     private static Set<DOMRpcIdentifier> createDomRpcIdentifiers(final Set<QName> rpcs,
134             final Collection<YangInstanceIdentifier> paths) {
135         final Set<DOMRpcIdentifier> ret = new HashSet<>();
136         for (final YangInstanceIdentifier path : paths) {
137             for (final QName rpc : rpcs) {
138                 ret.add(DOMRpcIdentifier.create(rpc, path));
139             }
140         }
141         return ret;
142     }
143
144     private static Collection<YangInstanceIdentifier> toYangInstanceIdentifiers(
145             final CurrentAdapterSerializer serializer, final Set<InstanceIdentifier<?>> identifiers) {
146         final var ret = new ArrayList<YangInstanceIdentifier>(identifiers.size());
147         for (final InstanceIdentifier<?> binding : identifiers) {
148             ret.add(serializer.toCachedYangInstanceIdentifier(binding));
149         }
150         return ret;
151     }
152 }