2 * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
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
9 package org.opendaylight.controller.config.facade.xml.osgi;
11 import com.google.common.base.Function;
12 import com.google.common.collect.Collections2;
13 import com.google.common.collect.ImmutableSet;
14 import com.google.common.collect.Sets;
15 import com.google.common.util.concurrent.ThreadFactoryBuilder;
16 import java.util.Collections;
17 import java.util.HashSet;
20 import java.util.concurrent.ExecutorService;
21 import java.util.concurrent.Executors;
22 import javax.annotation.concurrent.GuardedBy;
23 import org.opendaylight.controller.config.util.capability.Capability;
24 import org.opendaylight.controller.config.util.capability.ModuleListener;
25 import org.opendaylight.controller.config.util.capability.YangModuleCapability;
26 import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry;
27 import org.opendaylight.yangtools.sal.binding.generator.util.BindingRuntimeContext;
28 import org.opendaylight.yangtools.yang.common.QName;
29 import org.opendaylight.yangtools.yang.model.api.Module;
30 import org.opendaylight.yangtools.yang.model.api.ModuleIdentifier;
31 import org.opendaylight.yangtools.yang.model.api.SchemaContextProvider;
32 import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
33 import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceProvider;
35 public class YangStoreService implements YangStoreContext {
37 private final SchemaSourceProvider<YangTextSchemaSource> sourceProvider;
38 private final ExecutorService notificationExecutor = Executors.newSingleThreadExecutor(
39 new ThreadFactoryBuilder().setDaemon(true).setNameFormat("yangstore-capability-notifications").build());
42 * Guarded by explicit lock to allow for properly synchronizing the initial notification and modification
43 * of the listener set.
45 @GuardedBy("listeners")
46 private final Set<ModuleListener> listeners = new HashSet<ModuleListener>();
49 * This is the latest snapshot. Some of its state is always initialized, but the MXBean maps potentially cause
50 * recomputation. Accessing those two specific methods needs to re-check whether the snapshot has changed
51 * asynchronously and retry if it didi.
53 private volatile YangStoreSnapshot snap;
55 public YangStoreService(final SchemaContextProvider schemaContextProvider,
56 final SchemaSourceProvider<YangTextSchemaSource> sourceProvider) {
57 this.sourceProvider = sourceProvider;
60 public YangStoreContext getCurrentSnapshot() {
66 public Map<String, Map<String, ModuleMXBeanEntry>> getModuleMXBeanEntryMap() {
67 Map<String, Map<String, ModuleMXBeanEntry>> ret;
68 YangStoreSnapshot snapshot;
72 ret = snapshot.getModuleMXBeanEntryMap();
73 } while (!snapshot.equals(snap));
79 public Map<QName, Map<String, ModuleMXBeanEntry>> getQNamesToIdentitiesToModuleMXBeanEntries() {
80 Map<QName, Map<String, ModuleMXBeanEntry>> ret;
81 YangStoreSnapshot snapshot;
85 ret = snapshot.getQNamesToIdentitiesToModuleMXBeanEntries();
86 } while (!snapshot.equals(snap));
92 public Set<Module> getModules() {
93 return snap.getModules();
97 public String getModuleSource(final ModuleIdentifier moduleIdentifier) {
98 return snap.getModuleSource(moduleIdentifier);
102 public EnumResolver getEnumResolver() {
103 return snap.getEnumResolver();
106 public void refresh(final BindingRuntimeContext runtimeContext) {
107 final YangStoreSnapshot next = new YangStoreSnapshot(runtimeContext, sourceProvider);
108 final YangStoreSnapshot previous = snap;
110 notificationExecutor.submit(new Runnable() {
113 notifyListeners(previous, next);
118 public AutoCloseable registerModuleListener(final ModuleListener listener) {
119 final YangStoreContext context = snap;
121 synchronized (listeners) {
122 if (context != null) {
123 listener.onCapabilitiesChanged(toCapabilities(context.getModules(), context), Collections.<Capability>emptySet());
125 this.listeners.add(listener);
128 return new AutoCloseable() {
130 public void close() {
131 synchronized (listeners) {
132 listeners.remove(listener);
138 void notifyListeners(final YangStoreSnapshot previous, final YangStoreSnapshot current) {
139 final Set<Module> prevModules = previous.getModules();
140 final Set<Module> currModules = current.getModules();
141 final Set<Module> removed = Sets.difference(prevModules, currModules);
142 final Set<Module> added = Sets.difference(currModules, prevModules);
144 final Set<Capability> addedCaps = toCapabilities(added, current);
145 final Set<Capability> removedCaps = toCapabilities(removed, current);
147 synchronized (listeners) {
148 for (final ModuleListener listener : listeners) {
149 listener.onCapabilitiesChanged(addedCaps, removedCaps);
154 private static Set<Capability> toCapabilities(final Set<Module> modules, final YangStoreContext current) {
155 return ImmutableSet.copyOf(Collections2.transform(modules, new Function<Module, Capability>() {
157 public Capability apply(final Module input) {
158 return new YangModuleCapability(input, current.getModuleSource(input));