1 package org.opendaylight.controller.sal.binding.impl.connect.dom;
3 import java.lang.ref.WeakReference;
4 import java.lang.reflect.Method;
5 import java.util.Collection;
6 import java.util.Collections;
7 import java.util.HashSet;
9 import java.util.Map.Entry;
11 import java.util.WeakHashMap;
12 import java.util.concurrent.Callable;
13 import java.util.concurrent.ConcurrentHashMap;
14 import java.util.concurrent.ConcurrentMap;
15 import java.util.concurrent.ExecutionException;
16 import java.util.concurrent.Future;
18 import org.opendaylight.controller.md.sal.common.api.RegistrationListener;
19 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
20 import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
21 import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction;
22 import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandlerRegistration;
23 import org.opendaylight.controller.md.sal.common.api.data.DataModification;
24 import org.opendaylight.controller.md.sal.common.api.data.DataReader;
25 import org.opendaylight.controller.md.sal.common.api.routing.RouteChange;
26 import org.opendaylight.controller.md.sal.common.api.routing.RouteChangeListener;
27 import org.opendaylight.controller.md.sal.common.api.routing.RouteChangePublisher;
28 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
29 import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
30 import org.opendaylight.controller.sal.binding.api.data.RuntimeDataProvider;
31 import org.opendaylight.controller.sal.binding.api.rpc.RpcRouter;
32 import org.opendaylight.controller.sal.binding.impl.RpcProviderRegistryImpl;
33 import org.opendaylight.controller.sal.binding.api.rpc.RpcContextIdentifier;
34 import org.opendaylight.controller.sal.common.util.CommitHandlerTransactions;
35 import org.opendaylight.controller.sal.common.util.Rpcs;
36 import org.opendaylight.controller.sal.core.api.Provider;
37 import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
38 import org.opendaylight.controller.sal.core.api.RpcImplementation;
39 import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
40 import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
41 import org.opendaylight.yangtools.concepts.ListenerRegistration;
42 import org.opendaylight.yangtools.concepts.Registration;
43 import org.opendaylight.yangtools.concepts.util.ClassLoaderUtils;
44 import org.opendaylight.yangtools.yang.binding.Augmentable;
45 import org.opendaylight.yangtools.yang.binding.Augmentation;
46 import org.opendaylight.yangtools.yang.binding.BaseIdentity;
47 import org.opendaylight.yangtools.yang.binding.BindingMapping;
48 import org.opendaylight.yangtools.yang.binding.DataContainer;
49 import org.opendaylight.yangtools.yang.binding.DataObject;
50 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
51 import org.opendaylight.yangtools.yang.binding.RpcService;
52 import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
53 import org.opendaylight.yangtools.yang.common.QName;
54 import org.opendaylight.yangtools.yang.common.RpcError;
55 import org.opendaylight.yangtools.yang.common.RpcResult;
56 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
57 import org.slf4j.Logger;
58 import org.slf4j.LoggerFactory;
60 import com.google.common.base.Function;
61 import com.google.common.base.Optional;
62 import com.google.common.collect.FluentIterable;
63 import com.google.common.collect.ImmutableSet;
65 import static com.google.common.base.Preconditions.*;
67 public class BindingIndependentConnector implements //
68 RuntimeDataProvider, //
72 private final Logger LOG = LoggerFactory.getLogger(BindingIndependentConnector.class);
74 private static final InstanceIdentifier<? extends DataObject> ROOT = InstanceIdentifier.builder().toInstance();
76 private static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier ROOT_BI = org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
77 .builder().toInstance();
79 private BindingIndependentMappingService mappingService;
81 private org.opendaylight.controller.sal.core.api.data.DataProviderService biDataService;
83 private DataProviderService baDataService;
85 private ConcurrentMap<Object, BindingToDomTransaction> domOpenedTransactions = new ConcurrentHashMap<>();
86 private ConcurrentMap<Object, DomToBindingTransaction> bindingOpenedTransactions = new ConcurrentHashMap<>();
88 private BindingToDomCommitHandler bindingToDomCommitHandler = new BindingToDomCommitHandler();
89 private DomToBindingCommitHandler domToBindingCommitHandler = new DomToBindingCommitHandler();
91 private Registration<DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject>> baCommitHandlerRegistration;
93 private Registration<DataCommitHandler<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode>> biCommitHandlerRegistration;
95 private RpcProvisionRegistry biRpcRegistry;
96 private RpcProviderRegistry baRpcRegistry;
98 private ListenerRegistration<DomToBindingRpcForwardingManager> domToBindingRpcManager;
99 // private ListenerRegistration<BindingToDomRpcForwardingManager>
100 // bindingToDomRpcManager;
102 private Function<InstanceIdentifier<?>, org.opendaylight.yangtools.yang.data.api.InstanceIdentifier> toDOMInstanceIdentifier = new Function<InstanceIdentifier<?>, org.opendaylight.yangtools.yang.data.api.InstanceIdentifier>() {
105 public org.opendaylight.yangtools.yang.data.api.InstanceIdentifier apply(InstanceIdentifier<?> input) {
106 return mappingService.toDataDom(input);
111 private Registration<DataReader<InstanceIdentifier<? extends DataObject>, DataObject>> baDataReaderRegistration;
113 private boolean rpcForwarding = false;
115 private boolean dataForwarding = false;
117 private boolean notificationForwarding = false;
120 public DataObject readOperationalData(InstanceIdentifier<? extends DataObject> path) {
122 org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biPath = mappingService.toDataDom(path);
123 CompositeNode result = biDataService.readOperationalData(biPath);
124 return potentialAugmentationRead(path,biPath,result);
125 } catch (DeserializationException e) {
126 throw new IllegalStateException(e);
130 private DataObject potentialAugmentationRead(InstanceIdentifier<? extends DataObject> path, org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biPath, CompositeNode result) throws DeserializationException {
131 Class<? extends DataObject> targetType = path.getTargetType();
132 if (Augmentation.class.isAssignableFrom(targetType)) {
133 path = mappingService.fromDataDom(biPath);
134 Class<? extends Augmentation<?>> augmentType = (Class<? extends Augmentation<?>>) targetType;
135 DataObject parentTo = mappingService.dataObjectFromDataDom(path, result);
136 if (parentTo instanceof Augmentable<?>) {
137 return (DataObject) ((Augmentable) parentTo).getAugmentation(augmentType);
140 return mappingService.dataObjectFromDataDom(path, result);
144 public DataObject readConfigurationData(InstanceIdentifier<? extends DataObject> path) {
146 org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biPath = mappingService.toDataDom(path);
147 CompositeNode result = biDataService.readConfigurationData(biPath);
148 return potentialAugmentationRead(path,biPath,result);
149 } catch (DeserializationException e) {
150 throw new IllegalStateException(e);
154 private DataModificationTransaction createBindingToDomTransaction(
155 DataModification<InstanceIdentifier<? extends DataObject>, DataObject> source) {
156 DataModificationTransaction target = biDataService.beginTransaction();
157 for (Entry<InstanceIdentifier<? extends DataObject>, DataObject> entry : source.getUpdatedConfigurationData()
159 Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> biEntry = mappingService
161 target.putConfigurationData(biEntry.getKey(), biEntry.getValue());
163 for (Entry<InstanceIdentifier<? extends DataObject>, DataObject> entry : source.getUpdatedOperationalData()
165 Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> biEntry = mappingService
167 target.putOperationalData(biEntry.getKey(), biEntry.getValue());
169 for (InstanceIdentifier<? extends DataObject> entry : source.getRemovedConfigurationData()) {
170 org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biEntry = mappingService.toDataDom(entry);
171 target.removeConfigurationData(biEntry);
173 for (InstanceIdentifier<? extends DataObject> entry : source.getRemovedOperationalData()) {
174 org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biEntry = mappingService.toDataDom(entry);
175 target.removeOperationalData(biEntry);
180 private org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction createDomToBindingTransaction(
181 DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> source) {
182 org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction target = baDataService
184 for (Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> entry : source
185 .getUpdatedConfigurationData().entrySet()) {
187 InstanceIdentifier<?> baKey = mappingService.fromDataDom(entry.getKey());
188 DataObject baData = mappingService.dataObjectFromDataDom(baKey, entry.getValue());
189 target.putConfigurationData(baKey, baData);
190 } catch (DeserializationException e) {
191 LOG.error("Ommiting from BA transaction: {}.", entry.getKey(), e);
194 for (Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> entry : source
195 .getUpdatedOperationalData().entrySet()) {
198 InstanceIdentifier<?> baKey = mappingService.fromDataDom(entry.getKey());
199 DataObject baData = mappingService.dataObjectFromDataDom(baKey, entry.getValue());
200 target.putOperationalData(baKey, baData);
201 } catch (DeserializationException e) {
202 LOG.error("Ommiting from BA transaction: {}.", entry.getKey(), e);
205 for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier entry : source.getRemovedConfigurationData()) {
208 InstanceIdentifier<?> baEntry = mappingService.fromDataDom(entry);
209 target.removeConfigurationData(baEntry);
210 } catch (DeserializationException e) {
211 LOG.error("Ommiting from BA transaction: {}.", entry, e);
214 for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier entry : source.getRemovedOperationalData()) {
217 InstanceIdentifier<?> baEntry = mappingService.fromDataDom(entry);
218 target.removeOperationalData(baEntry);
219 } catch (DeserializationException e) {
220 LOG.error("Ommiting from BA transaction: {}.", entry, e);
226 public org.opendaylight.controller.sal.core.api.data.DataProviderService getBiDataService() {
227 return biDataService;
230 protected void setDomDataService(org.opendaylight.controller.sal.core.api.data.DataProviderService biDataService) {
231 this.biDataService = biDataService;
234 public DataProviderService getBaDataService() {
235 return baDataService;
238 protected void setBindingDataService(DataProviderService baDataService) {
239 this.baDataService = baDataService;
242 public RpcProviderRegistry getRpcRegistry() {
243 return baRpcRegistry;
246 protected void setBindingRpcRegistry(RpcProviderRegistry rpcRegistry) {
247 this.baRpcRegistry = rpcRegistry;
250 public void startDataForwarding() {
251 checkState(!dataForwarding, "Connector is already forwarding data.");
252 baDataReaderRegistration = baDataService.registerDataReader(ROOT, this);
253 baCommitHandlerRegistration = baDataService.registerCommitHandler(ROOT, bindingToDomCommitHandler);
254 biCommitHandlerRegistration = biDataService.registerCommitHandler(ROOT_BI, domToBindingCommitHandler);
255 baDataService.registerCommitHandlerListener(domToBindingCommitHandler);
256 dataForwarding = true;
259 public void startRpcForwarding() {
260 if (baRpcRegistry != null && biRpcRegistry != null && baRpcRegistry instanceof RouteChangePublisher<?, ?>) {
261 checkState(!rpcForwarding,"Connector is already forwarding RPCs");
262 domToBindingRpcManager = baRpcRegistry.registerRouteChangeListener(new DomToBindingRpcForwardingManager());
263 rpcForwarding = true;
267 public void startNotificationForwarding() {
268 checkState(!notificationForwarding, "Connector is already forwarding notifications.");
269 notificationForwarding = true;
272 protected void setMappingService(BindingIndependentMappingService mappingService) {
273 this.mappingService = mappingService;
277 public Collection<ProviderFunctionality> getProviderFunctionality() {
278 return Collections.emptyList();
282 public void onSessionInitiated(ProviderSession session) {
283 setDomDataService(session.getService(org.opendaylight.controller.sal.core.api.data.DataProviderService.class));
284 setDomRpcRegistry(session.getService(RpcProvisionRegistry.class));
288 public <T extends RpcService> void onRpcRouterCreated(Class<T> serviceType, RpcRouter<T> router) {
292 public void setDomRpcRegistry(RpcProvisionRegistry registry) {
293 biRpcRegistry = registry;
297 public void close() throws Exception {
298 if (baCommitHandlerRegistration != null) {
299 baCommitHandlerRegistration.close();
301 if (biCommitHandlerRegistration != null) {
302 biCommitHandlerRegistration.close();
307 private class DomToBindingTransaction implements
308 DataCommitTransaction<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> {
310 private final org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction backing;
311 private final DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> modification;
313 public DomToBindingTransaction(
314 org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction backing,
315 DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> modification) {
317 this.backing = backing;
318 this.modification = modification;
319 bindingOpenedTransactions.put(backing.getIdentifier(), this);
323 public DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> getModification() {
328 public RpcResult<Void> rollback() throws IllegalStateException {
330 return Rpcs.<Void> getRpcResult(true, null, Collections.<RpcError> emptySet());
334 public RpcResult<Void> finish() throws IllegalStateException {
335 Future<RpcResult<TransactionStatus>> result = backing.commit();
337 RpcResult<TransactionStatus> baResult = result.get();
338 return Rpcs.<Void> getRpcResult(baResult.isSuccessful(), null, baResult.getErrors());
339 } catch (InterruptedException e) {
340 throw new IllegalStateException("", e);
341 } catch (ExecutionException e) {
342 throw new IllegalStateException("", e);
347 private class BindingToDomTransaction implements
348 DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject> {
350 private DataModificationTransaction backing;
351 private DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification;
353 public BindingToDomTransaction(DataModificationTransaction backing,
354 DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification) {
355 this.backing = backing;
356 this.modification = modification;
357 domOpenedTransactions.put(backing.getIdentifier(), this);
361 public DataModification<InstanceIdentifier<? extends DataObject>, DataObject> getModification() {
366 public RpcResult<Void> finish() throws IllegalStateException {
367 Future<RpcResult<TransactionStatus>> result = backing.commit();
369 RpcResult<TransactionStatus> biResult = result.get();
370 return Rpcs.<Void> getRpcResult(biResult.isSuccessful(), null, biResult.getErrors());
371 } catch (InterruptedException e) {
372 throw new IllegalStateException("", e);
373 } catch (ExecutionException e) {
374 throw new IllegalStateException("", e);
376 domOpenedTransactions.remove(backing.getIdentifier());
381 public RpcResult<Void> rollback() throws IllegalStateException {
382 domOpenedTransactions.remove(backing.getIdentifier());
383 return Rpcs.<Void> getRpcResult(true, null, Collections.<RpcError> emptySet());
387 private class BindingToDomCommitHandler implements
388 DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject> {
391 public org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject> requestCommit(
392 DataModification<InstanceIdentifier<? extends DataObject>, DataObject> bindingTransaction) {
395 * Transaction was created as DOM transaction, in that case we do
396 * not need to forward it back.
398 if (bindingOpenedTransactions.containsKey(bindingTransaction.getIdentifier())) {
400 return CommitHandlerTransactions.allwaysSuccessfulTransaction(bindingTransaction);
402 DataModificationTransaction domTransaction = createBindingToDomTransaction(bindingTransaction);
403 BindingToDomTransaction wrapped = new BindingToDomTransaction(domTransaction, bindingTransaction);
404 LOG.info("Forwarding Binding Transaction: {} as DOM Transaction: {} .", bindingTransaction.getIdentifier(),
405 domTransaction.getIdentifier());
410 private class DomToBindingCommitHandler implements //
411 RegistrationListener<DataCommitHandlerRegistration<InstanceIdentifier<?>, DataObject>>, //
412 DataCommitHandler<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> {
415 public void onRegister(DataCommitHandlerRegistration<InstanceIdentifier<?>, DataObject> registration) {
417 org.opendaylight.yangtools.yang.data.api.InstanceIdentifier domPath = mappingService.toDataDom(registration
423 public void onUnregister(DataCommitHandlerRegistration<InstanceIdentifier<?>, DataObject> registration) {
425 // FIXME: do registration based on only active commit handlers.
428 public org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> requestCommit(
429 DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> domTransaction) {
430 Object identifier = domTransaction.getIdentifier();
433 * We checks if the transcation was originated in this mapper. If it
434 * was originated in this mapper we are returing allways success
435 * commit hanlder to prevent creating loop in two-phase commit and
438 if (domOpenedTransactions.containsKey(identifier)) {
439 return CommitHandlerTransactions.allwaysSuccessfulTransaction(domTransaction);
442 org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction baTransaction = createDomToBindingTransaction(domTransaction);
443 DomToBindingTransaction forwardedTransaction = new DomToBindingTransaction(baTransaction, domTransaction);
444 LOG.info("Forwarding DOM Transaction: {} as Binding Transaction: {}.", domTransaction.getIdentifier(),
445 baTransaction.getIdentifier());
446 return forwardedTransaction;
450 private class DomToBindingRpcForwardingManager implements
451 RouteChangeListener<RpcContextIdentifier, InstanceIdentifier<?>> {
453 private final Map<Class<? extends RpcService>, DomToBindingRpcForwarder> forwarders = new WeakHashMap<>();
456 public void onRouteChange(RouteChange<RpcContextIdentifier, InstanceIdentifier<?>> change) {
457 for (Entry<RpcContextIdentifier, Set<InstanceIdentifier<?>>> entry : change.getAnnouncements().entrySet()) {
458 bindingRoutesAdded(entry);
462 private void bindingRoutesAdded(Entry<RpcContextIdentifier, Set<InstanceIdentifier<?>>> entry) {
463 Class<? extends BaseIdentity> context = entry.getKey().getRoutingContext();
464 Class<? extends RpcService> service = entry.getKey().getRpcService();
465 if (context != null) {
466 getRpcForwarder(service, context).registerPaths(context, service, entry.getValue());
470 private DomToBindingRpcForwarder getRpcForwarder(Class<? extends RpcService> service,
471 Class<? extends BaseIdentity> context) {
472 DomToBindingRpcForwarder potential = forwarders.get(service);
473 if (potential != null) {
476 if (context == null) {
477 potential = new DomToBindingRpcForwarder(service);
479 potential = new DomToBindingRpcForwarder(service, context);
481 forwarders.put(service, potential);
487 private class DomToBindingRpcForwarder implements RpcImplementation {
489 private final Set<QName> supportedRpcs;
490 private final WeakReference<Class<? extends RpcService>> rpcServiceType;
491 private Set<org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration> registrations;
493 public DomToBindingRpcForwarder(Class<? extends RpcService> service) {
494 this.rpcServiceType = new WeakReference<Class<? extends RpcService>>(service);
495 this.supportedRpcs = mappingService.getRpcQNamesFor(service);
496 for (QName rpc : supportedRpcs) {
497 biRpcRegistry.addRpcImplementation(rpc, this);
499 registrations = ImmutableSet.of();
502 public DomToBindingRpcForwarder(Class<? extends RpcService> service, Class<? extends BaseIdentity> context) {
503 this.rpcServiceType = new WeakReference<Class<? extends RpcService>>(service);
504 this.supportedRpcs = mappingService.getRpcQNamesFor(service);
505 registrations = new HashSet<>();
506 for (QName rpc : supportedRpcs) {
507 registrations.add(biRpcRegistry.addRoutedRpcImplementation(rpc, this));
509 registrations = ImmutableSet.copyOf(registrations);
512 public void registerPaths(Class<? extends BaseIdentity> context, Class<? extends RpcService> service,
513 Set<InstanceIdentifier<?>> set) {
514 QName ctx = BindingReflections.findQName(context);
515 for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier path : FluentIterable.from(set).transform(
516 toDOMInstanceIdentifier)) {
517 for (org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration reg : registrations) {
518 reg.registerPath(ctx, path);
523 public void removePaths(Class<? extends BaseIdentity> context, Class<? extends RpcService> service,
524 Set<InstanceIdentifier<?>> set) {
525 QName ctx = BindingReflections.findQName(context);
526 for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier path : FluentIterable.from(set).transform(
527 toDOMInstanceIdentifier)) {
528 for (org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration reg : registrations) {
529 reg.unregisterPath(ctx, path);
535 public Set<QName> getSupportedRpcs() {
536 return supportedRpcs;
540 public RpcResult<CompositeNode> invokeRpc(QName rpc, CompositeNode domInput) {
541 checkArgument(rpc != null);
542 checkArgument(domInput != null);
544 Class<? extends RpcService> rpcType = rpcServiceType.get();
545 checkState(rpcType != null);
546 RpcService rpcService = baRpcRegistry.getRpcService(rpcType);
547 checkState(rpcService != null);
548 CompositeNode domUnwrappedInput = domInput.getFirstCompositeByName(QName.create(rpc, "input"));
550 return resolveInvocationStrategy(rpc, rpcType).invokeOn(rpcService, domUnwrappedInput);
551 } catch (Exception e) {
552 throw new IllegalStateException(e);
556 private RpcInvocationStrategy resolveInvocationStrategy(final QName rpc,
557 final Class<? extends RpcService> rpcType) throws Exception {
558 return ClassLoaderUtils.withClassLoader(rpcType.getClassLoader(), new Callable<RpcInvocationStrategy>() {
560 public RpcInvocationStrategy call() throws Exception {
561 String methodName = BindingMapping.getMethodName(rpc);
562 Method targetMethod = null;
563 for (Method possibleMethod : rpcType.getMethods()) {
564 if (possibleMethod.getName().equals(methodName)
565 && BindingReflections.isRpcMethod(possibleMethod)) {
566 targetMethod = possibleMethod;
570 checkState(targetMethod != null, "Rpc method not found");
571 Optional<Class<?>> outputClass = BindingReflections.resolveRpcOutputClass(targetMethod);
572 Optional<Class<? extends DataContainer>> inputClass = BindingReflections
573 .resolveRpcInputClass(targetMethod);
575 RpcInvocationStrategy strategy = null;
576 if (outputClass.isPresent()) {
577 if (inputClass.isPresent()) {
578 strategy = new DefaultInvocationStrategy(targetMethod, outputClass.get(), inputClass.get());
580 strategy = new NoInputNoOutputInvocationStrategy(targetMethod);
592 private abstract class RpcInvocationStrategy {
594 protected final Method targetMethod;
596 public RpcInvocationStrategy(Method targetMethod) {
597 this.targetMethod = targetMethod;
600 public abstract RpcResult<CompositeNode> uncheckedInvoke(RpcService rpcService, CompositeNode domInput)
603 public RpcResult<CompositeNode> invokeOn(RpcService rpcService, CompositeNode domInput) throws Exception {
604 return uncheckedInvoke(rpcService, domInput);
608 private class DefaultInvocationStrategy extends RpcInvocationStrategy {
610 @SuppressWarnings("rawtypes")
611 private WeakReference<Class> inputClass;
613 @SuppressWarnings("rawtypes")
614 private WeakReference<Class> outputClass;
616 @SuppressWarnings({ "rawtypes", "unchecked" })
617 public DefaultInvocationStrategy(Method targetMethod, Class<?> outputClass,
618 Class<? extends DataContainer> inputClass) {
620 this.outputClass = new WeakReference(outputClass);
621 this.inputClass = new WeakReference(inputClass);
625 public RpcResult<CompositeNode> uncheckedInvoke(RpcService rpcService, CompositeNode domInput) throws Exception {
626 DataContainer bindingInput = mappingService.dataObjectFromDataDom(inputClass.get(), domInput);
627 Future<RpcResult<?>> result = (Future<RpcResult<?>>) targetMethod.invoke(rpcService, bindingInput);
628 if (result == null) {
629 return Rpcs.getRpcResult(false);
631 RpcResult<?> bindingResult = result.get();
632 return Rpcs.getRpcResult(true);
637 private class NoInputNoOutputInvocationStrategy extends RpcInvocationStrategy {
639 public NoInputNoOutputInvocationStrategy(Method targetMethod) {
643 public RpcResult<CompositeNode> uncheckedInvoke(RpcService rpcService, CompositeNode domInput) throws Exception {
644 @SuppressWarnings("unchecked")
645 Future<RpcResult<Void>> result = (Future<RpcResult<Void>>) targetMethod.invoke(rpcService);
646 RpcResult<Void> bindingResult = result.get();
647 return Rpcs.getRpcResult(bindingResult.isSuccessful(), bindingResult.getErrors());
651 public boolean isRpcForwarding() {
652 return rpcForwarding;
655 public boolean isDataForwarding() {
656 return dataForwarding;
659 public boolean isNotificationForwarding() {
660 // TODO Auto-generated method stub
661 return notificationForwarding;
664 public BindingIndependentMappingService getMappingService() {
665 return mappingService;