Integrate netconf-mapping-api into netconf-server
[netconf.git] / protocol / netconf-server / src / main / java / org / opendaylight / netconf / server / 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.server.osgi;
9
10 import com.google.common.collect.HashMultimap;
11 import com.google.common.collect.ImmutableSet;
12 import com.google.common.collect.Multimap;
13 import com.google.common.collect.Multimaps;
14 import java.util.HashMap;
15 import java.util.HashSet;
16 import java.util.List;
17 import java.util.Map;
18 import java.util.Set;
19 import java.util.concurrent.ConcurrentHashMap;
20 import org.opendaylight.netconf.api.capability.Capability;
21 import org.opendaylight.netconf.api.monitoring.CapabilityListener;
22 import org.opendaylight.netconf.server.api.operations.NetconfOperation;
23 import org.opendaylight.netconf.server.api.operations.NetconfOperationService;
24 import org.opendaylight.netconf.server.api.operations.NetconfOperationServiceFactory;
25 import org.opendaylight.netconf.server.api.operations.NetconfOperationServiceFactoryListener;
26 import org.opendaylight.yangtools.concepts.AbstractRegistration;
27 import org.opendaylight.yangtools.concepts.Registration;
28
29 /**
30  * NetconfOperationService aggregator. Makes a collection of operation services accessible as one.
31  */
32 // Non-final for OSGi DS
33 // FIXME: split into abstract class for the multiple uses we have, which really is about which construct is being
34 //        invoked
35 public class AggregatedNetconfOperationServiceFactory
36         implements NetconfOperationServiceFactory, NetconfOperationServiceFactoryListener, AutoCloseable {
37     private final Set<NetconfOperationServiceFactory> factories = ConcurrentHashMap.newKeySet();
38     private final Multimap<NetconfOperationServiceFactory, Registration> registrations =
39             Multimaps.synchronizedMultimap(HashMultimap.create());
40     private final Set<CapabilityListener> listeners = ConcurrentHashMap.newKeySet();
41
42     public AggregatedNetconfOperationServiceFactory() {
43     }
44
45     public AggregatedNetconfOperationServiceFactory(final List<NetconfOperationServiceFactory> mappers) {
46         mappers.forEach(this::onAddNetconfOperationServiceFactory);
47     }
48
49     @Override
50     public final synchronized void onAddNetconfOperationServiceFactory(final NetconfOperationServiceFactory service) {
51         factories.add(service);
52
53         for (final CapabilityListener listener : listeners) {
54             registrations.put(service, service.registerCapabilityListener(listener));
55         }
56     }
57
58     @Override
59     public final synchronized void onRemoveNetconfOperationServiceFactory(
60             final NetconfOperationServiceFactory service) {
61         factories.remove(service);
62         registrations.removeAll(service).forEach(Registration::close);
63     }
64
65     @Override
66     public final Set<Capability> getCapabilities() {
67         final Set<Capability> capabilities = new HashSet<>();
68         for (final NetconfOperationServiceFactory factory : factories) {
69             capabilities.addAll(factory.getCapabilities());
70         }
71         return capabilities;
72     }
73
74     @Override
75     public final synchronized Registration registerCapabilityListener(final CapabilityListener listener) {
76         final Map<NetconfOperationServiceFactory, Registration> regs = new HashMap<>();
77
78         for (final NetconfOperationServiceFactory factory : factories) {
79             regs.put(factory, factory.registerCapabilityListener(listener));
80         }
81         listeners.add(listener);
82
83         return new AbstractRegistration() {
84
85             @Override
86             protected void removeRegistration() {
87                 synchronized (AggregatedNetconfOperationServiceFactory.this) {
88                     listeners.remove(listener);
89                     regs.values().forEach(Registration::close);
90                     for (var reg : regs.entrySet()) {
91                         registrations.remove(reg.getKey(), reg.getValue());
92                     }
93                 }
94             }
95         };
96     }
97
98     @Override
99     public final synchronized NetconfOperationService createService(final String netconfSessionIdForReporting) {
100         return new AggregatedNetconfOperation(factories, netconfSessionIdForReporting);
101     }
102
103     @Override
104     public synchronized void close() {
105         factories.clear();
106         registrations.values().forEach(Registration::close);
107         registrations.clear();
108         listeners.clear();
109     }
110
111     private static final class AggregatedNetconfOperation implements NetconfOperationService {
112         private final ImmutableSet<NetconfOperationService> services;
113
114         AggregatedNetconfOperation(final Set<NetconfOperationServiceFactory> factories,
115                                    final String netconfSessionIdForReporting) {
116             services = factories.stream()
117                 .map(factory -> factory.createService(netconfSessionIdForReporting))
118                 .collect(ImmutableSet.toImmutableSet());
119         }
120
121         @Override
122         public Set<NetconfOperation> getNetconfOperations() {
123             return services.stream()
124                 .flatMap(service -> service.getNetconfOperations().stream())
125                 .collect(ImmutableSet.toImmutableSet());
126         }
127
128         @Override
129         public void close() {
130             services.forEach(NetconfOperationService::close);
131         }
132     }
133 }