Bug 629: Make BindingDataBroker to be visible.
[controller.git] / opendaylight / md-sal / sal-binding-broker / src / main / java / org / opendaylight / controller / sal / binding / codegen / impl / RuntimeCodeGenerator.xtend
1 /*
2  * Copyright (c) 2013 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.sal.binding.codegen.impl
9
10 import java.util.Map
11 import javassist.ClassPool
12 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
13 import org.opendaylight.yangtools.yang.binding.Notification
14 import org.opendaylight.yangtools.yang.binding.RpcImplementation
15 import org.opendaylight.yangtools.yang.binding.util.BindingReflections
16 import org.opendaylight.yangtools.yang.binding.util.ClassLoaderUtils
17
18 import static extension org.opendaylight.controller.sal.binding.codegen.RuntimeCodeSpecification.*
19 import org.opendaylight.yangtools.yang.binding.RpcService
20
21 class RuntimeCodeGenerator extends AbstractRuntimeCodeGenerator {
22
23     new(ClassPool pool) {
24         super(pool)
25     }
26
27     override directProxySupplier(Class iface) {
28         return [|
29             val proxyName = iface.directProxyName;
30             val potentialClass = ClassLoaderUtils.tryToLoadClassWithTCCL(proxyName)
31             if(potentialClass != null) {
32                 return potentialClass.newInstance as RpcService;
33             }
34             val supertype = iface.asCtClass
35             val createdCls = createClass(iface.directProxyName, supertype) [
36                 field(DELEGATE_FIELD, iface);
37                 implementsType(RpcImplementation.asCtClass)
38                 implementMethodsFrom(supertype) [
39                     body = '''
40                     {
41                         if(«DELEGATE_FIELD» == null) {
42                             throw new java.lang.IllegalStateException("No default provider is available");
43                         }
44                         return ($r) «DELEGATE_FIELD».«it.name»($$);
45                     }
46                     '''
47                 ]
48                 implementMethodsFrom(RpcImplementation.asCtClass) [
49                     body = '''
50                     {
51                         throw new java.lang.IllegalStateException("No provider is processing supplied message");
52                         return ($r) null;
53                     }
54                     '''
55                 ]
56             ]
57             return createdCls.toClass(iface.classLoader).newInstance as RpcService
58         ]
59     }
60
61     override routerSupplier(Class iface, RpcServiceMetadata metadata) {
62         return [ |
63             val supertype = iface.asCtClass
64             val routerName = iface.routerName;
65             val potentialClass = ClassLoaderUtils.tryToLoadClassWithTCCL(routerName)
66             if(potentialClass != null) {
67                 return potentialClass.newInstance as RpcService;
68             }
69
70             val targetCls = createClass(iface.routerName, supertype) [
71
72
73                 field(DELEGATE_FIELD, iface)
74                 //field(REMOTE_INVOKER_FIELD,iface);
75                 implementsType(RpcImplementation.asCtClass)
76
77                 for (ctx : metadata.contexts) {
78                     field(ctx.routingTableField, Map)
79                 }
80                 implementMethodsFrom(supertype) [
81                     if (parameterTypes.size === 1) {
82                         val rpcMeta = metadata.getRpcMethod(name);
83                         val bodyTmp = '''
84                         {
85                             final «InstanceIdentifier.name» identifier = $1.«rpcMeta.inputRouteGetter.name»()«IF rpcMeta.
86                             routeEncapsulated».getValue()«ENDIF»;
87                             «supertype.name» instance = («supertype.name») «rpcMeta.context.routingTableField».get(identifier);
88                             if(instance == null) {
89                                instance = «DELEGATE_FIELD»;
90                             }
91                             if(instance == null) {
92                                 throw new java.lang.IllegalStateException("No routable provider is processing routed message for " + String.valueOf(identifier));
93                             }
94                             return ($r) instance.«it.name»($$);
95                         }'''
96                         body = bodyTmp
97                     } else if (parameterTypes.size === 0) {
98                         body = '''return ($r) «DELEGATE_FIELD».«it.name»($$);'''
99                     }
100                 ]
101                 implementMethodsFrom(RpcImplementation.asCtClass) [
102                     body = '''
103                     {
104                         throw new java.lang.IllegalStateException("No provider is processing supplied message");
105                         return ($r) null;
106                     }
107                     '''
108                 ]
109             ]
110             return  targetCls.toClass(iface.classLoader,iface.protectionDomain).newInstance as RpcService
111         ];
112     }
113
114     override generateListenerInvoker(Class iface) {
115         val callbacks = iface.methods.filter[BindingReflections.isNotificationCallback(it)]
116
117         val supportedNotification = callbacks.map[parameterTypes.get(0) as Class<? extends Notification>].toSet;
118
119         val targetCls = createClass(iface.invokerName, brokerNotificationListener) [
120             field(DELEGATE_FIELD, iface)
121             implementMethodsFrom(brokerNotificationListener) [
122                 body = '''
123                     {
124                         «FOR callback : callbacks SEPARATOR " else "»
125                             «val cls = callback.parameterTypes.get(0).name»
126                                 if($1 instanceof «cls») {
127                                     «DELEGATE_FIELD».«callback.name»((«cls») $1);
128                                     return null;
129                                 }
130                         «ENDFOR»
131                         return null;
132                     }
133                 '''
134             ]
135         ]
136         val finalClass = targetCls.toClass(iface.classLoader, iface.protectionDomain)
137         return new RuntimeGeneratedInvokerPrototype(supportedNotification,
138             finalClass as Class<? extends org.opendaylight.controller.sal.binding.api.NotificationListener<?>>);
139     }
140 }