8fba700bdd2a1be4bf6a22f33377d8a6f9c6b0c4
[hc2vpp.git] /
1 /*
2  * Copyright (c) 2016 Cisco and/or its affiliates.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package io.fd.honeycomb.v3po.notification.impl;
17
18 import static com.google.common.base.Preconditions.checkArgument;
19
20 import com.google.common.collect.HashMultimap;
21 import com.google.common.collect.Maps;
22 import com.google.common.collect.Multimap;
23 import io.fd.honeycomb.v3po.notification.ManagedNotificationProducer;
24 import io.fd.honeycomb.v3po.notification.NotificationProducer;
25 import java.util.Collection;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.Set;
29 import java.util.stream.Collectors;
30 import javax.annotation.concurrent.ThreadSafe;
31 import org.opendaylight.yangtools.yang.binding.Notification;
32 import org.opendaylight.yangtools.yang.common.QName;
33
34 /**
35  * Holds the collection of registered notification producers.
36  * Provides additional information about the types of notifications produced per producer and overall.
37  */
38 @ThreadSafe
39 public final class NotificationProducerRegistry {
40
41     private final Set<Class<? extends Notification>> notificationTypes;
42     private final Map<QName, ManagedNotificationProducer> notificationQNameToProducer;
43     private final Multimap<ManagedNotificationProducer, QName> notificationProducerQNames;
44
45     public NotificationProducerRegistry(final List<ManagedNotificationProducer> notificationProducersDependency) {
46         this.notificationTypes = toTypes(notificationProducersDependency);
47         this.notificationQNameToProducer = toQNameMap(notificationProducersDependency);
48         this.notificationProducerQNames = toQNameMapReversed(notificationProducersDependency);
49     }
50
51     private static Multimap<ManagedNotificationProducer, QName> toQNameMapReversed(final List<ManagedNotificationProducer> notificationProducers) {
52         final Multimap<ManagedNotificationProducer, QName> multimap = HashMultimap.create();
53
54         for (ManagedNotificationProducer producer : notificationProducers) {
55             for (Class<? extends Notification> aClass : producer.getNotificationTypes()) {
56                 multimap.put(producer, getQName(aClass));
57             }
58         }
59         return multimap;
60     }
61
62     private static Set<Class<? extends Notification>> toTypes(final List<ManagedNotificationProducer> notificationProducersDependency) {
63         // Get all notification types registered from HC notification producers
64         return notificationProducersDependency
65             .stream()
66             .flatMap(producer -> producer.getNotificationTypes().stream())
67             .collect(Collectors.toSet());
68     }
69
70
71     private static Map<QName, ManagedNotificationProducer> toQNameMap(final List<ManagedNotificationProducer> producerDependencies) {
72         // Only a single notification producer per notification type is allowed
73         final Map<QName, ManagedNotificationProducer> qNamesToProducers = Maps.newHashMap();
74         for (ManagedNotificationProducer notificationProducer : producerDependencies) {
75             for (QName qName : typesToQNames(notificationProducer.getNotificationTypes())) {
76                 final NotificationProducer previousProducer = qNamesToProducers.put(qName, notificationProducer);
77                 checkArgument(previousProducer == null, "2 producers of the same notification type: %s. " +
78                     "Producer 1: {} Producer 2: {}" , qName, previousProducer, notificationProducer);
79             }
80         }
81         return qNamesToProducers;
82     }
83
84
85     private static Set<QName> typesToQNames(final Collection<Class<? extends Notification>> notificationTypes) {
86         return notificationTypes
87             .stream()
88             .map(NotificationProducerRegistry::getQName)
89             .collect(Collectors.toSet());
90     }
91
92
93     public static QName getQName(final Class<? extends Notification> aClass) {
94         try {
95             return (QName) aClass.getField("QNAME").get(null);
96         } catch (NoSuchFieldException | IllegalAccessException e) {
97             throw new IllegalArgumentException("Unable to retrieve QName for notification of type: " + aClass, e);
98         }
99     }
100
101     Set<Class<? extends Notification>> getNotificationTypes() {
102         return notificationTypes;
103     }
104
105     Map<QName, ManagedNotificationProducer> getNotificationQNameToProducer() {
106         return notificationQNameToProducer;
107     }
108
109     Multimap<ManagedNotificationProducer, QName> getNotificationProducerQNames() {
110         return notificationProducerQNames;
111     }
112 }