Bug 2364: Migrated Binding MD-SAL to not use composites nodes
[controller.git] / opendaylight / md-sal / sal-binding-broker / src / main / java / org / opendaylight / controller / md / sal / binding / impl / RpcServiceAdapter.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.controller.md.sal.binding.impl;
9
10 import com.google.common.collect.ImmutableMap;
11 import com.google.common.util.concurrent.ListenableFuture;
12 import java.lang.reflect.InvocationHandler;
13 import java.lang.reflect.Method;
14 import java.lang.reflect.Proxy;
15 import org.opendaylight.yangtools.yang.binding.DataObject;
16 import org.opendaylight.yangtools.yang.binding.RpcService;
17 import org.opendaylight.yangtools.yang.common.RpcResult;
18 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
19
20 class RpcServiceAdapter implements InvocationHandler {
21
22     interface InvocationDelegate {
23
24         ListenableFuture<RpcResult<?>> invoke(SchemaPath rpc, DataObject dataObject);
25
26     }
27
28     private final RpcService proxy;
29     private final ImmutableMap<Method,SchemaPath> rpcNames;
30     private final Class<? extends RpcService> type;
31     private final InvocationDelegate delegate;
32
33     RpcServiceAdapter(Class<? extends RpcService> type, ImmutableMap<Method, SchemaPath> rpcNames, InvocationDelegate delegate) {
34         this.rpcNames = rpcNames;
35         this.type = type;
36         this.delegate = delegate;
37         this.proxy = (RpcService) Proxy.newProxyInstance(type.getClassLoader(), new Class[]{type}, this);
38     }
39
40     RpcService getProxy() {
41         return proxy;
42     }
43
44     @Override
45     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
46
47         SchemaPath rpc = rpcNames.get(method);
48         if(rpc != null) {
49             if(method.getParameterTypes().length == 0) {
50                 return delegate.invoke(rpc, null);
51             }
52             if(args.length != 1) {
53                 throw new IllegalArgumentException("Input must be provided.");
54             }
55             return delegate.invoke(rpc,(DataObject) args[0]);
56         }
57
58         if(isObjectMethod(method)) {
59             return callObjectMethod(proxy, method, args);
60         }
61         throw new UnsupportedOperationException("Method " + method.toString() + "is unsupported.");
62     }
63
64     private static boolean isObjectMethod(Method m) {
65         switch (m.getName()) {
66         case "toString":
67             return (m.getReturnType() == String.class && m.getParameterTypes().length == 0);
68         case "hashCode":
69             return (m.getReturnType() == int.class && m.getParameterTypes().length == 0);
70         case "equals":
71             return (m.getReturnType() == boolean.class && m.getParameterTypes().length == 1 && m.getParameterTypes()[0] == Object.class);
72         }
73         return false;
74     }
75
76     private Object callObjectMethod(Object self, Method m, Object[] args) {
77         switch (m.getName()) {
78         case "toString":
79             return type.getName() + "$Adapter{delegate=" + delegate.toString()+"}";
80         case "hashCode":
81             return System.identityHashCode(self);
82         case "equals":
83             return (self == args[0]);
84         }
85         return null;
86     }
87 }