BUG-614: introduce AbstractRuntimeCodeGenerator 43/7743/5
authorRobert Varga <rovarga@cisco.com>
Thu, 5 Jun 2014 12:15:44 +0000 (14:15 +0200)
committerRobert Varga <rovarga@cisco.com>
Tue, 10 Jun 2014 08:46:31 +0000 (08:46 +0000)
Introduce AbstractRuntimeCodeGenerator, which is the base service class
for interactions with the rest of the world. It implements the public
contracts and as much of the logic as possible in pure Java and defines
a clear interface subclasses need to provide. RuntimeCodeGenerator.xtend
then adds an implementation of it.

Change-Id: Ic04f3e840825ae1f59583c0a9a2f6fbfc7bb66f6
Signed-off-by: Robert Varga <rovarga@cisco.com>
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/AbstractRuntimeCodeGenerator.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RpcRouterCodegenInstance.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RpcServiceMetadata.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RuntimeCodeGenerator.xtend

diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/AbstractRuntimeCodeGenerator.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/AbstractRuntimeCodeGenerator.java
new file mode 100644 (file)
index 0000000..9605a4d
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.sal.binding.codegen.impl;
+
+import java.util.Map;
+import java.util.WeakHashMap;
+
+import javassist.ClassPool;
+import javassist.CtClass;
+import javassist.CtMethod;
+import javassist.NotFoundException;
+
+import javax.annotation.concurrent.GuardedBy;
+
+import org.eclipse.xtext.xbase.lib.Extension;
+import org.opendaylight.controller.sal.binding.api.rpc.RpcRouter;
+import org.opendaylight.controller.sal.binding.spi.NotificationInvokerFactory;
+import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.NotificationListener;
+import org.opendaylight.yangtools.yang.binding.RpcService;
+import org.opendaylight.yangtools.yang.binding.annotations.RoutingContext;
+import org.opendaylight.yangtools.yang.binding.util.ClassLoaderUtils;
+
+import com.google.common.base.Supplier;
+
+abstract class AbstractRuntimeCodeGenerator implements org.opendaylight.controller.sal.binding.codegen.RuntimeCodeGenerator, NotificationInvokerFactory {
+    @GuardedBy("this")
+    private final Map<Class<? extends NotificationListener>, RuntimeGeneratedInvokerPrototype> invokerClasses = new WeakHashMap<>();
+    private final CtClass brokerNotificationListener;
+
+    @Extension
+    protected final JavassistUtils utils;
+
+    protected AbstractRuntimeCodeGenerator(final ClassPool pool) {
+        utils = JavassistUtils.forClassPool(pool);
+
+        /*
+         * Make sure Javassist ClassPool sees the classloader of RpcService
+         */
+        utils.ensureClassLoader(RpcService.class);
+
+        brokerNotificationListener = utils.asCtClass(org.opendaylight.controller.sal.binding.api.NotificationListener.class);
+    }
+
+    protected final CtClass getBrokerNotificationListener() {
+        return brokerNotificationListener;
+    }
+
+    protected abstract RuntimeGeneratedInvokerPrototype generateListenerInvoker(Class<? extends NotificationListener> cls);
+    protected abstract <T extends RpcService> Supplier<T> directProxySupplier(final Class<T> serviceType);
+    protected abstract <T extends RpcService> Supplier<T> routerSupplier(final Class<T> serviceType, RpcServiceMetadata metadata);
+
+    private RpcServiceMetadata getRpcMetadata(final CtClass iface) throws ClassNotFoundException, NotFoundException {
+        final RpcServiceMetadata metadata = new RpcServiceMetadata();
+
+        for (CtMethod method : iface.getMethods()) {
+            if (iface.equals(method.getDeclaringClass()) && method.getParameterTypes().length == 1) {
+                final RpcMetadata routingPair = getRpcMetadata(method);
+                if (routingPair != null) {
+                    metadata.addContext(routingPair.getContext());
+                    metadata.addRpcMethod(method.getName(), routingPair);
+
+                    /*
+                     * Force-load the RPC class representing the "input" of this RPC.
+                     *
+                     * FIXME: this is pre-existing side-effect of the original code, which
+                     *        kept a reference to the loaded class, but it did not use it.
+                     *
+                     *        There was no explanation as to why forcing this load was
+                     *        necessary. As far as I can tell now is that it forces the
+                     *        resolution of method arguments, which would (according to
+                     *        my reading of JLS) occur only when the method is invoked via
+                     *        binding-aware class action, not when coming from
+                     *        binding-independent world. Whether that makes sense or not,
+                     *        remains to be investigated.
+                     */
+                    Thread.currentThread().getContextClassLoader().loadClass(routingPair.getInputType().getName());
+                }
+            }
+        }
+
+        return metadata;
+    }
+
+    private RpcMetadata getRpcMetadata(final CtMethod method) throws NotFoundException {
+        final CtClass inputClass = method.getParameterTypes()[0];
+        return rpcMethodMetadata(inputClass, inputClass, method.getName());
+    }
+
+    private RpcMetadata rpcMethodMetadata(final CtClass dataClass, final CtClass inputClass, final String rpcMethod) throws NotFoundException {
+        for (CtMethod method : dataClass.getMethods()) {
+            if (method.getName().startsWith("get") && method.getParameterTypes().length == 0) {
+                for (Object annotation : method.getAvailableAnnotations()) {
+                    if (annotation instanceof RoutingContext) {
+                        boolean encapsulated = !method.getReturnType().equals(utils.asCtClass(InstanceIdentifier.class));
+                        return new RpcMetadata(rpcMethod, ((RoutingContext)annotation).value(), method, encapsulated, inputClass);
+                    }
+                }
+            }
+        }
+
+        for (CtClass iface : dataClass.getInterfaces()) {
+            final RpcMetadata ret = rpcMethodMetadata(iface, inputClass, rpcMethod);
+            if(ret != null) {
+                return ret;
+            }
+        }
+        return null;
+    }
+
+    private synchronized RuntimeGeneratedInvokerPrototype resolveInvokerClass(final Class<? extends NotificationListener> cls) {
+        RuntimeGeneratedInvokerPrototype invoker = invokerClasses.get(cls);
+        if (invoker != null) {
+            return invoker;
+        }
+
+        utils.getLock().lock();
+        try {
+            invoker = ClassLoaderUtils.withClassLoader(cls.getClassLoader(), new Supplier<RuntimeGeneratedInvokerPrototype>() {
+                @Override
+                public RuntimeGeneratedInvokerPrototype get() {
+                    return generateListenerInvoker(cls);
+                }
+            });
+
+            invokerClasses.put(cls, invoker);
+            return invoker;
+        } finally {
+            utils.getLock().unlock();
+        }
+    }
+
+    @Override
+    public final NotificationInvokerFactory getInvokerFactory() {
+        return this;
+    }
+
+    @Override
+    public final <T extends RpcService> T getDirectProxyFor(final Class<T> serviceType) {
+        utils.getLock().lock();
+        try {
+            return ClassLoaderUtils.withClassLoader(serviceType.getClassLoader(), directProxySupplier(serviceType));
+        } finally {
+            utils.getLock().unlock();
+        }
+    }
+
+    @Override
+    public final <T extends RpcService> RpcRouter<T> getRouterFor(final Class<T> serviceType, final String name) {
+        final RpcServiceMetadata metadata = ClassLoaderUtils.withClassLoader(serviceType.getClassLoader(), new Supplier<RpcServiceMetadata>() {
+            @Override
+            public RpcServiceMetadata get() {
+                try {
+                    return getRpcMetadata(utils.asCtClass(serviceType));
+                } catch (ClassNotFoundException | NotFoundException e) {
+                    throw new IllegalStateException(String.format("Failed to load metadata for class {}", serviceType), e);
+                }
+            }
+        });
+
+        utils.getLock().lock();
+        try {
+            final T instance = ClassLoaderUtils.withClassLoader(serviceType.getClassLoader(), routerSupplier(serviceType, metadata));
+            return new RpcRouterCodegenInstance<T>(name, serviceType, instance, metadata.getContexts());
+        } finally {
+            utils.getLock().unlock();
+        }
+    }
+
+    @Override
+    public NotificationInvoker invokerFor(final NotificationListener instance) {
+        final Class<? extends NotificationListener> cls = instance.getClass();
+        final RuntimeGeneratedInvokerPrototype prototype = resolveInvokerClass(cls);
+
+        try {
+            return RuntimeGeneratedInvoker.create(instance, prototype);
+        } catch (InstantiationException | IllegalAccessException e) {
+            throw new IllegalStateException(String.format("Failed to create invoker for %s", instance), e);
+        }
+    }
+}
index 5578f75ae21d6800cf2c73661afa15a071bd6ef8..052fd2169a523b955a427f036e2a0ab6b7a03bc4 100644 (file)
@@ -24,7 +24,6 @@ import org.opendaylight.yangtools.concepts.AbstractObjectRegistration;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
 import org.opendaylight.yangtools.yang.binding.BaseIdentity;
-import org.opendaylight.yangtools.yang.binding.DataContainer;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.RpcService;
 import org.slf4j.Logger;
@@ -34,7 +33,7 @@ import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 
 public class RpcRouterCodegenInstance<T extends RpcService> implements //
-        RpcRouter<T>, RouteChangeListener<Class<? extends BaseIdentity>, InstanceIdentifier<?>> {
+RpcRouter<T>, RouteChangeListener<Class<? extends BaseIdentity>, InstanceIdentifier<?>> {
 
     private static final Logger LOG = LoggerFactory.getLogger(RpcRouterCodegenInstance.class);
 
@@ -53,8 +52,7 @@ public class RpcRouterCodegenInstance<T extends RpcService> implements //
     private final String name;
 
     @SuppressWarnings("unchecked")
-    public RpcRouterCodegenInstance(String name,Class<T> type, T routerImpl, Set<Class<? extends BaseIdentity>> contexts,
-            Set<Class<? extends DataContainer>> inputs) {
+    public RpcRouterCodegenInstance(final String name,final Class<T> type, final T routerImpl, final Iterable<Class<? extends BaseIdentity>> contexts) {
         this.name = name;
         this.listeners = ListenerRegistry.create();
         this.serviceType = type;
@@ -86,7 +84,7 @@ public class RpcRouterCodegenInstance<T extends RpcService> implements //
 
     @Override
     @SuppressWarnings("unchecked")
-    public <C extends BaseIdentity> RpcRoutingTable<C, T> getRoutingTable(Class<C> routeContext) {
+    public <C extends BaseIdentity> RpcRoutingTable<C, T> getRoutingTable(final Class<C> routeContext) {
         return (RpcRoutingTable<C, T>) routingTables.get(routeContext);
     }
 
@@ -102,12 +100,12 @@ public class RpcRouterCodegenInstance<T extends RpcService> implements //
 
     @Override
     public <L extends RouteChangeListener<Class<? extends BaseIdentity>, InstanceIdentifier<?>>> ListenerRegistration<L> registerRouteChangeListener(
-            L listener) {
+            final L listener) {
         return listeners.registerWithType(listener);
     }
 
     @Override
-    public void onRouteChange(RouteChange<Class<? extends BaseIdentity>, InstanceIdentifier<?>> change) {
+    public void onRouteChange(final RouteChange<Class<? extends BaseIdentity>, InstanceIdentifier<?>> change) {
         for (ListenerRegistration<RouteChangeListener<Class<? extends BaseIdentity>, InstanceIdentifier<?>>> listener : listeners) {
             try {
                 listener.getInstance().onRouteChange(change);
@@ -118,17 +116,17 @@ public class RpcRouterCodegenInstance<T extends RpcService> implements //
     }
 
     @Override
-    public T getService(Class<? extends BaseIdentity> context, InstanceIdentifier<?> path) {
+    public T getService(final Class<? extends BaseIdentity> context, final InstanceIdentifier<?> path) {
         return routingTables.get(context).getRoute(path);
     }
 
     @Override
-    public RoutedRpcRegistration<T> addRoutedRpcImplementation(T service) {
+    public RoutedRpcRegistration<T> addRoutedRpcImplementation(final T service) {
         return new RoutedRpcRegistrationImpl(service);
     }
 
     @Override
-    public RpcRegistration<T> registerDefaultService(T service) {
+    public RpcRegistration<T> registerDefaultService(final T service) {
         // TODO Auto-generated method stub
         RuntimeCodeHelper.setDelegate(invocationProxy, service);
         return null;
@@ -136,7 +134,7 @@ public class RpcRouterCodegenInstance<T extends RpcService> implements //
 
     private class RoutedRpcRegistrationImpl extends AbstractObjectRegistration<T> implements RoutedRpcRegistration<T> {
 
-        public RoutedRpcRegistrationImpl(T instance) {
+        public RoutedRpcRegistrationImpl(final T instance) {
             super(instance);
         }
 
@@ -146,22 +144,22 @@ public class RpcRouterCodegenInstance<T extends RpcService> implements //
         }
 
         @Override
-        public void registerPath(Class<? extends BaseIdentity> context, InstanceIdentifier<?> path) {
+        public void registerPath(final Class<? extends BaseIdentity> context, final InstanceIdentifier<?> path) {
             routingTables.get(context).updateRoute(path, getInstance());
         }
 
         @Override
-        public void unregisterPath(Class<? extends BaseIdentity> context, InstanceIdentifier<?> path) {
+        public void unregisterPath(final Class<? extends BaseIdentity> context, final InstanceIdentifier<?> path) {
             routingTables.get(context).removeRoute(path, getInstance());
         }
 
         @Override
-        public void registerInstance(Class<? extends BaseIdentity> context, InstanceIdentifier<?> instance) {
+        public void registerInstance(final Class<? extends BaseIdentity> context, final InstanceIdentifier<?> instance) {
             registerPath(context, instance);
         }
 
         @Override
-        public void unregisterInstance(Class<? extends BaseIdentity> context, InstanceIdentifier<?> instance) {
+        public void unregisterInstance(final Class<? extends BaseIdentity> context, final InstanceIdentifier<?> instance) {
             unregisterPath(context, instance);
         }
 
index 399afe74e8704f3832f9fc161e21fa7f68b890f1..430b7a7e319a04e8216da93e9e9ba594e1885361 100644 (file)
@@ -9,29 +9,31 @@ package org.opendaylight.controller.sal.binding.codegen.impl;
 
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
 
 import org.opendaylight.yangtools.yang.binding.BaseIdentity;
-import org.opendaylight.yangtools.yang.binding.DataContainer;
+
+import com.google.common.collect.Iterables;
 
 final class RpcServiceMetadata {
-    private final HashMap<Class<? extends DataContainer>, RpcMetadata> rpcInputs = new HashMap<>();
-    private final HashSet<Class<? extends DataContainer>> supportedInputs = new HashSet<>();
-    private final HashSet<Class<? extends BaseIdentity>> contexts = new HashSet<>();
-    private final HashMap<String, RpcMetadata> rpcMethods = new HashMap<>();
+    private final Set<Class<? extends BaseIdentity>> contexts = new HashSet<>();
+    private final Map<String, RpcMetadata> rpcMethods = new HashMap<>();
+    private final Iterable<Class<? extends BaseIdentity>> roContexts = Iterables.unmodifiableIterable(contexts);
 
-    public HashSet<Class<? extends BaseIdentity>> getContexts() {
-        return this.contexts;
+    public Iterable<Class<? extends BaseIdentity>> getContexts() {
+        return roContexts;
     }
 
-    public HashMap<String, RpcMetadata> getRpcMethods() {
-        return this.rpcMethods;
+    public RpcMetadata getRpcMethod(final String name) {
+        return rpcMethods.get(name);
     }
 
-    public HashMap<Class<? extends DataContainer>, RpcMetadata> getRpcInputs() {
-        return this.rpcInputs;
+    public void addContext(final Class<? extends BaseIdentity> context) {
+        contexts.add(context);
     }
 
-    public HashSet<Class<? extends DataContainer>> getSupportedInputs() {
-        return this.supportedInputs;
+    public void addRpcMethod(final String name, final RpcMetadata routingPair) {
+        rpcMethods.put(name, routingPair);
     }
 }
index ac782051a85b708ad5d2d7ac1444b408753acef0..1be6e2dfb112f5b5f56194d24e865b24cb802e23 100644 (file)
@@ -8,45 +8,27 @@
 package org.opendaylight.controller.sal.binding.codegen.impl
 
 import java.util.Map
-import java.util.WeakHashMap
 import javassist.ClassPool
-import javassist.CtClass
-import javassist.CtMethod
-import javassist.LoaderClassPath
-import org.opendaylight.controller.sal.binding.spi.NotificationInvokerFactory
-import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils
-import org.opendaylight.yangtools.yang.binding.DataContainer
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
 import org.opendaylight.yangtools.yang.binding.Notification
-import org.opendaylight.yangtools.yang.binding.NotificationListener
 import org.opendaylight.yangtools.yang.binding.RpcImplementation
-import org.opendaylight.yangtools.yang.binding.RpcService
-import org.opendaylight.yangtools.yang.binding.annotations.RoutingContext
+import org.opendaylight.controller.sal.binding.codegen.YangtoolsMappingHelper
 import org.opendaylight.yangtools.yang.binding.util.ClassLoaderUtils
 
 import static extension org.opendaylight.controller.sal.binding.codegen.RuntimeCodeSpecification.*
-import static extension org.opendaylight.controller.sal.binding.codegen.YangtoolsMappingHelper.*
-
-class RuntimeCodeGenerator implements org.opendaylight.controller.sal.binding.codegen.RuntimeCodeGenerator, NotificationInvokerFactory {
-
-    val CtClass BROKER_NOTIFICATION_LISTENER;
-    val extension JavassistUtils utils;
-    val Map<Class<? extends NotificationListener>, RuntimeGeneratedInvokerPrototype> invokerClasses;
 
+class RuntimeCodeGenerator extends AbstractRuntimeCodeGenerator {
 
     new(ClassPool pool) {
-        utils = new JavassistUtils(pool);
-        invokerClasses = new WeakHashMap();
-        BROKER_NOTIFICATION_LISTENER = org.opendaylight.controller.sal.binding.api.NotificationListener.asCtClass;
-        pool.appendClassPath(new LoaderClassPath(RpcService.classLoader));
+        super(pool)
     }
 
-    override <T extends RpcService> getDirectProxyFor(Class<T> iface) {
-        val T instance = ClassLoaderUtils.withClassLoaderAndLock(iface.classLoader,lock) [|
+    override directProxySupplier(Class iface) {
+        return [|
             val proxyName = iface.directProxyName;
             val potentialClass = ClassLoaderUtils.tryToLoadClassWithTCCL(proxyName)
             if(potentialClass != null) {
-                return potentialClass.newInstance as T;
+                return potentialClass.newInstance;
             }
             val supertype = iface.asCtClass
             val createdCls = createClass(iface.directProxyName, supertype) [
@@ -71,23 +53,17 @@ class RuntimeCodeGenerator implements org.opendaylight.controller.sal.binding.co
                     '''
                 ]
             ]
-            return createdCls.toClass(iface.classLoader).newInstance as T
+            return createdCls.toClass(iface.classLoader).newInstance
         ]
-        return instance;
     }
 
-    override <T extends RpcService> getRouterFor(Class<T> iface,String routerInstanceName) {
-        val metadata = ClassLoaderUtils.withClassLoader(iface.classLoader) [|
-            val supertype = iface.asCtClass
-            return supertype.rpcMetadata;
-        ]
-
-        val instance = ClassLoaderUtils.<T>withClassLoaderAndLock(iface.classLoader,lock) [ |
+    override routerSupplier(Class iface, RpcServiceMetadata metadata) {
+        return [ |
             val supertype = iface.asCtClass
             val routerName = iface.routerName;
             val potentialClass = ClassLoaderUtils.tryToLoadClassWithTCCL(routerName)
             if(potentialClass != null) {
-                return potentialClass.newInstance as T;
+                return potentialClass.newInstance;
             }
 
             val targetCls = createClass(iface.routerName, supertype) [
@@ -102,7 +78,7 @@ class RuntimeCodeGenerator implements org.opendaylight.controller.sal.binding.co
                 }
                 implementMethodsFrom(supertype) [
                     if (parameterTypes.size === 1) {
-                        val rpcMeta = metadata.rpcMethods.get(name);
+                        val rpcMeta = metadata.getRpcMethod(name);
                         val bodyTmp = '''
                         {
                             final «InstanceIdentifier.name» identifier = $1.«rpcMeta.inputRouteGetter.name»()«IF rpcMeta.
@@ -130,74 +106,18 @@ class RuntimeCodeGenerator implements org.opendaylight.controller.sal.binding.co
                     '''
                 ]
             ]
-            return targetCls.toClass(iface.classLoader,iface.protectionDomain).newInstance as T
-
+            return targetCls.toClass(iface.classLoader,iface.protectionDomain).newInstance
         ];
-        return new RpcRouterCodegenInstance(routerInstanceName,iface, instance, metadata.contexts,metadata.supportedInputs);
     }
 
-    private def RpcServiceMetadata getRpcMetadata(CtClass iface) {
-        val metadata = new RpcServiceMetadata;
-
-        iface.methods.filter[declaringClass == iface && parameterTypes.size === 1].forEach [ method |
-            val routingPair = method.rpcMetadata;
-            if (routingPair !== null) {
-                metadata.contexts.add(routingPair.context)
-                metadata.rpcMethods.put(method.name,routingPair)
-                val input = routingPair.inputType.javaClass as Class<? extends DataContainer>;
-                metadata.supportedInputs.add(input);
-                metadata.rpcInputs.put(input,routingPair);
-            }
-        ]
-        return metadata;
-    }
-
-    private def getRpcMetadata(CtMethod method) {
-        val inputClass = method.parameterTypes.get(0);
-        return inputClass.rpcMethodMetadata(inputClass,method.name);
-    }
-
-    private def RpcMetadata rpcMethodMetadata(CtClass dataClass, CtClass inputClass, String rpcMethod) {
-        for (method : dataClass.methods) {
-            if (method.name.startsWith("get") && method.parameterTypes.size === 0) {
-                for (annotation : method.availableAnnotations) {
-                    if (annotation instanceof RoutingContext) {
-                        val encapsulated = !method.returnType.equals(InstanceIdentifier.asCtClass);
-                        return new RpcMetadata(rpcMethod,(annotation as RoutingContext).value, method, encapsulated,inputClass);
-                    }
-                }
-            }
-        }
-        for (iface : dataClass.interfaces) {
-            val ret = rpcMethodMetadata(iface,inputClass,rpcMethod);
-            if(ret != null) return ret;
-        }
-        return null;
-    }
-
-    private def getJavaClass(CtClass cls) {
-        Thread.currentThread.contextClassLoader.loadClass(cls.name)
-    }
-
-    override getInvokerFactory() {
-        return this;
-    }
-
-    override invokerFor(NotificationListener instance) {
-        val cls = instance.class
-        val prototype = resolveInvokerClass(cls);
-
-        return RuntimeGeneratedInvoker.create(instance, prototype)
-    }
-
-    protected def generateListenerInvoker(Class<? extends NotificationListener> iface) {
-        val callbacks = iface.methods.filter[notificationCallback]
+    override generateListenerInvoker(Class iface) {
+        val callbacks = iface.methods.filter[YangtoolsMappingHelper.isNotificationCallback(it)]
 
         val supportedNotification = callbacks.map[parameterTypes.get(0) as Class<? extends Notification>].toSet;
 
-        val targetCls = createClass(iface.invokerName, BROKER_NOTIFICATION_LISTENER) [
+        val targetCls = createClass(iface.invokerName, brokerNotificationListener) [
             field(DELEGATE_FIELD, iface)
-            implementMethodsFrom(BROKER_NOTIFICATION_LISTENER) [
+            implementMethodsFrom(brokerNotificationListener) [
                 body = '''
                     {
                         «FOR callback : callbacks SEPARATOR " else "»
@@ -216,16 +136,4 @@ class RuntimeCodeGenerator implements org.opendaylight.controller.sal.binding.co
         return new RuntimeGeneratedInvokerPrototype(supportedNotification,
             finalClass as Class<? extends org.opendaylight.controller.sal.binding.api.NotificationListener<?>>);
     }
-
-    protected def resolveInvokerClass(Class<? extends NotificationListener> class1) {
-        return ClassLoaderUtils.<RuntimeGeneratedInvokerPrototype>withClassLoaderAndLock(class1.classLoader,lock) [|
-            val invoker = invokerClasses.get(class1);
-            if (invoker !== null) {
-                return invoker;
-            }
-            val newInvoker = generateListenerInvoker(class1);
-            invokerClasses.put(class1, newInvoker);
-            return newInvoker
-        ]
-    }
 }