org.opendaylight.controller.config.facade.xml.osgi.YangStoreService.java Source code

Java tutorial

Introduction

Here is the source code for org.opendaylight.controller.config.facade.xml.osgi.YangStoreService.java

Source

/*
 * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
 * and is available at http://www.eclipse.org/legal/epl-v10.html
 */

package org.opendaylight.controller.config.facade.xml.osgi;

import com.google.common.base.Function;
import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.annotation.concurrent.GuardedBy;
import org.opendaylight.controller.config.util.capability.Capability;
import org.opendaylight.controller.config.util.capability.ModuleListener;
import org.opendaylight.controller.config.util.capability.YangModuleCapability;
import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry;
import org.opendaylight.yangtools.sal.binding.generator.util.BindingRuntimeContext;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.model.api.Module;
import org.opendaylight.yangtools.yang.model.api.ModuleIdentifier;
import org.opendaylight.yangtools.yang.model.api.SchemaContextProvider;
import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceProvider;

public class YangStoreService implements YangStoreContext {

    private final SchemaSourceProvider<YangTextSchemaSource> sourceProvider;
    private final ExecutorService notificationExecutor = Executors.newSingleThreadExecutor(
            new ThreadFactoryBuilder().setDaemon(true).setNameFormat("yangstore-capability-notifications").build());

    /**
     * Guarded by explicit lock to allow for properly synchronizing the initial notification and modification
     * of the listener set.
     */
    @GuardedBy("listeners")
    private final Set<ModuleListener> listeners = new HashSet<ModuleListener>();

    /**
     * This is the latest snapshot. Some of its state is always initialized, but the MXBean maps potentially cause
     * recomputation. Accessing those two specific methods needs to re-check whether the snapshot has changed
     * asynchronously and retry if it didi.
     */
    private volatile YangStoreSnapshot snap;

    public YangStoreService(final SchemaContextProvider schemaContextProvider,
            final SchemaSourceProvider<YangTextSchemaSource> sourceProvider) {
        this.sourceProvider = sourceProvider;
    }

    public YangStoreContext getCurrentSnapshot() {
        return snap;
    }

    @Deprecated
    @Override
    public Map<String, Map<String, ModuleMXBeanEntry>> getModuleMXBeanEntryMap() {
        Map<String, Map<String, ModuleMXBeanEntry>> ret;
        YangStoreSnapshot snapshot;

        do {
            snapshot = snap;
            ret = snapshot.getModuleMXBeanEntryMap();
        } while (!snapshot.equals(snap));

        return ret;
    }

    @Override
    public Map<QName, Map<String, ModuleMXBeanEntry>> getQNamesToIdentitiesToModuleMXBeanEntries() {
        Map<QName, Map<String, ModuleMXBeanEntry>> ret;
        YangStoreSnapshot snapshot;

        do {
            snapshot = snap;
            ret = snapshot.getQNamesToIdentitiesToModuleMXBeanEntries();
        } while (!snapshot.equals(snap));

        return ret;
    }

    @Override
    public Set<Module> getModules() {
        return snap.getModules();
    }

    @Override
    public String getModuleSource(final ModuleIdentifier moduleIdentifier) {
        return snap.getModuleSource(moduleIdentifier);
    }

    @Override
    public EnumResolver getEnumResolver() {
        return snap.getEnumResolver();
    }

    public void refresh(final BindingRuntimeContext runtimeContext) {
        final YangStoreSnapshot next = new YangStoreSnapshot(runtimeContext, sourceProvider);
        final YangStoreSnapshot previous = snap;
        snap = next;
        notificationExecutor.submit(new Runnable() {
            @Override
            public void run() {
                notifyListeners(previous, next);
            }
        });
    }

    public AutoCloseable registerModuleListener(final ModuleListener listener) {
        final YangStoreContext context = snap;

        synchronized (listeners) {
            if (context != null) {
                listener.onCapabilitiesChanged(toCapabilities(context.getModules(), context),
                        Collections.<Capability>emptySet());
            }
            this.listeners.add(listener);
        }

        return new AutoCloseable() {
            @Override
            public void close() {
                synchronized (listeners) {
                    listeners.remove(listener);
                }
            }
        };
    }

    void notifyListeners(final YangStoreSnapshot previous, final YangStoreSnapshot current) {
        final Set<Module> prevModules = previous.getModules();
        final Set<Module> currModules = current.getModules();
        final Set<Module> removed = Sets.difference(prevModules, currModules);
        final Set<Module> added = Sets.difference(currModules, prevModules);

        final Set<Capability> addedCaps = toCapabilities(added, current);
        final Set<Capability> removedCaps = toCapabilities(removed, current);

        synchronized (listeners) {
            for (final ModuleListener listener : listeners) {
                listener.onCapabilitiesChanged(addedCaps, removedCaps);
            }
        }
    }

    private static Set<Capability> toCapabilities(final Set<Module> modules, final YangStoreContext current) {
        return ImmutableSet.copyOf(Collections2.transform(modules, new Function<Module, Capability>() {
            @Override
            public Capability apply(final Module input) {
                return new YangModuleCapability(input, current.getModuleSource(input));
            }
        }));
    }
}