Bump upstreams to SNAPSHOTs
[netconf.git] / netconf / netconf-impl / src / main / java / org / opendaylight / netconf / impl / osgi / AggregatedNetconfOperationServiceFactory.java
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.netconf.impl.osgi;
9
10 import com.google.common.collect.HashMultimap;
11 import com.google.common.collect.ImmutableSet;
12 import com.google.common.collect.ImmutableSet.Builder;
13 import com.google.common.collect.Multimap;
14 import com.google.common.collect.Multimaps;
15 import java.util.HashMap;
16 import java.util.HashSet;
17 import java.util.List;
18 import java.util.Map;
19 import java.util.Set;
20 import java.util.concurrent.ConcurrentHashMap;
21 import org.opendaylight.netconf.api.capability.Capability;
22 import org.opendaylight.netconf.api.monitoring.CapabilityListener;
23 import org.opendaylight.netconf.mapping.api.NetconfOperation;
24 import org.opendaylight.netconf.mapping.api.NetconfOperationService;
25 import org.opendaylight.netconf.mapping.api.NetconfOperationServiceFactory;
26 import org.opendaylight.netconf.mapping.api.NetconfOperationServiceFactoryListener;
27 import org.opendaylight.netconf.util.CloseableUtil;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
30
31 /**
32  * NetconfOperationService aggregator. Makes a collection of operation services accessible as one.
33  */
34 public final class AggregatedNetconfOperationServiceFactory
35         implements NetconfOperationServiceFactory, NetconfOperationServiceFactoryListener, AutoCloseable {
36
37     private static final Logger LOG = LoggerFactory.getLogger(AggregatedNetconfOperationServiceFactory.class);
38
39     private final Set<NetconfOperationServiceFactory> factories = ConcurrentHashMap.newKeySet();
40     private final Multimap<NetconfOperationServiceFactory, AutoCloseable> registrations =
41             Multimaps.synchronizedMultimap(HashMultimap.create());
42     private final Set<CapabilityListener> listeners = ConcurrentHashMap.newKeySet();
43
44     public AggregatedNetconfOperationServiceFactory() {
45     }
46
47     public AggregatedNetconfOperationServiceFactory(final List<NetconfOperationServiceFactory> mappers) {
48         mappers.forEach(this::onAddNetconfOperationServiceFactory);
49     }
50
51     @Override
52     public synchronized void onAddNetconfOperationServiceFactory(final NetconfOperationServiceFactory service) {
53         factories.add(service);
54
55         for (final CapabilityListener listener : listeners) {
56             AutoCloseable reg = service.registerCapabilityListener(listener);
57             registrations.put(service, reg);
58         }
59     }
60
61     @SuppressWarnings("checkstyle:IllegalCatch")
62     @Override
63     public synchronized void onRemoveNetconfOperationServiceFactory(final NetconfOperationServiceFactory service) {
64         factories.remove(service);
65
66         for (final AutoCloseable autoCloseable : registrations.get(service)) {
67             try {
68                 autoCloseable.close();
69             } catch (Exception e) {
70                 LOG.warn("Unable to close listener registration", e);
71             }
72         }
73
74         registrations.removeAll(service);
75     }
76
77     @Override
78     public Set<Capability> getCapabilities() {
79         final Set<Capability> capabilities = new HashSet<>();
80         for (final NetconfOperationServiceFactory factory : factories) {
81             capabilities.addAll(factory.getCapabilities());
82         }
83         return capabilities;
84     }
85
86     @Override
87     public synchronized AutoCloseable registerCapabilityListener(final CapabilityListener listener) {
88         final Map<NetconfOperationServiceFactory, AutoCloseable> regs = new HashMap<>();
89
90         for (final NetconfOperationServiceFactory factory : factories) {
91             final AutoCloseable reg = factory.registerCapabilityListener(listener);
92             regs.put(factory, reg);
93         }
94         listeners.add(listener);
95
96         return () -> {
97             synchronized (AggregatedNetconfOperationServiceFactory.this) {
98                 listeners.remove(listener);
99                 CloseableUtil.closeAll(regs.values());
100                 for (final Map.Entry<NetconfOperationServiceFactory, AutoCloseable> reg : regs.entrySet()) {
101                     registrations.remove(reg.getKey(), reg.getValue());
102                 }
103             }
104         };
105     }
106
107     @Override
108     public synchronized NetconfOperationService createService(final String netconfSessionIdForReporting) {
109         return new AggregatedNetconfOperation(factories, netconfSessionIdForReporting);
110     }
111
112     @Override
113     public synchronized void close() throws Exception {
114         factories.clear();
115         for (AutoCloseable reg : registrations.values()) {
116             reg.close();
117         }
118         registrations.clear();
119         listeners.clear();
120     }
121
122     private static final class AggregatedNetconfOperation implements NetconfOperationService {
123
124         private final Set<NetconfOperationService> services;
125
126         AggregatedNetconfOperation(final Set<NetconfOperationServiceFactory> factories,
127                                    final String netconfSessionIdForReporting) {
128             final Builder<NetconfOperationService> b = ImmutableSet.builder();
129             for (final NetconfOperationServiceFactory factory : factories) {
130                 b.add(factory.createService(netconfSessionIdForReporting));
131             }
132             services = b.build();
133         }
134
135         @Override
136         public Set<NetconfOperation> getNetconfOperations() {
137             final Set<NetconfOperation> operations = new HashSet<>();
138             for (final NetconfOperationService service : services) {
139                 operations.addAll(service.getNetconfOperations());
140             }
141             return operations;
142         }
143
144         @SuppressWarnings("checkstyle:IllegalCatch")
145         @Override
146         public void close() {
147             try {
148                 CloseableUtil.closeAll(services);
149             } catch (final Exception e) {
150                 throw new IllegalStateException("Unable to properly close all aggregated services", e);
151             }
152         }
153     }
154 }