Migrated Hydrogen Notification Broker to not use Javassist.
[controller.git] / opendaylight / md-sal / sal-binding-broker / src / main / java / org / opendaylight / controller / md / sal / binding / compat / NotificationInvoker.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.compat;
9
10 import com.google.common.collect.ImmutableMap;
11 import java.lang.reflect.Method;
12 import java.util.HashMap;
13 import java.util.HashSet;
14 import java.util.Map;
15 import java.util.Set;
16 import org.opendaylight.yangtools.yang.binding.Notification;
17 import org.opendaylight.yangtools.yang.binding.NotificationListener;
18 import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
19 import org.opendaylight.yangtools.yang.binding.util.NotificationListenerInvoker;
20 import org.opendaylight.yangtools.yang.common.QName;
21
22 final class NotificationInvoker implements org.opendaylight.controller.sal.binding.api.NotificationListener<Notification> {
23
24     private final NotificationListener delegate;
25     private final Map<Class<? extends Notification>,InvokerContext> invokers;
26
27
28     private NotificationInvoker(final NotificationListener listener) {
29         delegate = listener;
30         final Map<Class<? extends Notification>, InvokerContext> builder = new HashMap<>();
31         for(final Class<?> iface : listener.getClass().getInterfaces()) {
32             if(NotificationListener.class.isAssignableFrom(iface) && BindingReflections.isBindingClass(iface)) {
33                 @SuppressWarnings("unchecked")
34                 final Class<? extends NotificationListener> listenerType = (Class<? extends NotificationListener>) iface;
35                 final NotificationListenerInvoker invoker = NotificationListenerInvoker.from(listenerType);
36                 for(final Class<? extends Notification> type : getNotificationTypes(listenerType)) {
37                     builder.put(type, new InvokerContext(BindingReflections.findQName(type) , invoker));
38                 }
39             }
40         }
41         invokers = ImmutableMap.copyOf(builder);
42     }
43
44     public static NotificationInvoker invokerFor(final NotificationListener listener) {
45         return new NotificationInvoker(listener);
46     }
47
48     public Set<Class<? extends Notification>> getSupportedNotifications() {
49         return invokers.keySet();
50     }
51
52     @Override
53     public void onNotification(final Notification notification) {
54         getContext(notification.getImplementedInterface()).invoke(notification);
55     };
56
57     private InvokerContext getContext(final Class<?> type) {
58         return invokers.get(type);
59     }
60
61     @SuppressWarnings("unchecked")
62     private static Set<Class<? extends Notification>> getNotificationTypes(final Class<? extends org.opendaylight.yangtools.yang.binding.NotificationListener> type) {
63         // TODO: Investigate possibility and performance impact if we cache this or expose
64         // it from NotificationListenerInvoker
65         final Set<Class<? extends Notification>> ret = new HashSet<>();
66         for(final Method method : type.getMethods()) {
67             if(BindingReflections.isNotificationCallback(method)) {
68                 final Class<? extends Notification> notification = (Class<? extends Notification>) method.getParameterTypes()[0];
69                 ret.add(notification);
70             }
71         }
72         return ret;
73     }
74
75     private class InvokerContext {
76
77         private final QName name;
78         private final NotificationListenerInvoker invoker;
79
80         private InvokerContext(final QName name, final NotificationListenerInvoker invoker) {
81             this.name = name;
82             this.invoker = invoker;
83         }
84
85         public void invoke(final Notification notification) {
86             invoker.invokeNotification(delegate, name, notification);
87         }
88
89     }
90
91 }