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