+
+ private Notification deserialize(final DOMNotification notification) {
+ if (notification instanceof LazySerializedDOMNotification) {
+ return ((LazySerializedDOMNotification) notification).getBindingData();
+ }
+ return codec.fromNormalizedNodeNotification(notification.getType(), notification.getBody());
+ }
+
+ private NotificationListenerInvoker getInvoker(final SchemaPath type) {
+ return invokers.get(type);
+ }
+
+ protected Set<SchemaPath> getSupportedNotifications() {
+ return invokers.keySet();
+ }
+
+ public static Map<SchemaPath, NotificationListenerInvoker> createInvokerMapFor(
+ final Class<? extends NotificationListener> implClz) {
+ final Map<SchemaPath, NotificationListenerInvoker> builder = new HashMap<>();
+ for (final TypeToken<?> ifaceToken : TypeToken.of(implClz).getTypes().interfaces()) {
+ Class<?> iface = ifaceToken.getRawType();
+ if (NotificationListener.class.isAssignableFrom(iface) && BindingReflections.isBindingClass(iface)) {
+ @SuppressWarnings("unchecked")
+ final Class<? extends NotificationListener> listenerType =
+ (Class<? extends NotificationListener>) iface;
+ final NotificationListenerInvoker invoker = NotificationListenerInvoker.from(listenerType);
+ for (final SchemaPath path : getNotificationTypes(listenerType)) {
+ builder.put(path, invoker);
+ }
+ }
+ }
+ return ImmutableMap.copyOf(builder);
+ }
+
+ private static Set<SchemaPath> getNotificationTypes(final Class<? extends NotificationListener> type) {
+ // TODO: Investigate possibility and performance impact if we cache this or expose
+ // it from NotificationListenerInvoker
+ final Set<SchemaPath> ret = new HashSet<>();
+ for (final Method method : type.getMethods()) {
+ if (BindingReflections.isNotificationCallback(method)) {
+ final Class<?> notification = method.getParameterTypes()[0];
+ final QName name = BindingReflections.findQName(notification);
+ ret.add(SchemaPath.create(true, name));
+ }
+ }
+ return ret;
+ }
+}