All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.opendaylight.jsonrpc.impl.JsonRPCNotificationService Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2017 Brocade Communications Systems, Inc. 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.jsonrpc.impl;

import static org.opendaylight.jsonrpc.provider.common.Util.findNode;

import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Multimap;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.Collection;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.opendaylight.jsonrpc.bus.jsonrpc.JsonRpcNotificationMessage;
import org.opendaylight.jsonrpc.bus.messagelib.NotificationMessageHandler;
import org.opendaylight.jsonrpc.bus.messagelib.SubscriberSession;
import org.opendaylight.jsonrpc.bus.messagelib.TransportFactory;
import org.opendaylight.jsonrpc.dom.codec.JsonRpcCodecFactory;
import org.opendaylight.jsonrpc.hmap.DataType;
import org.opendaylight.jsonrpc.hmap.HierarchicalEnumMap;
import org.opendaylight.jsonrpc.model.RemoteGovernance;
import org.opendaylight.mdsal.dom.api.DOMNotification;
import org.opendaylight.mdsal.dom.api.DOMNotificationListener;
import org.opendaylight.mdsal.dom.api.DOMNotificationService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.jsonrpc.rev161201.Peer;
import org.opendaylight.yangtools.concepts.AbstractRegistration;
import org.opendaylight.yangtools.concepts.Registration;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.common.QNameModule;
import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
import org.opendaylight.yangtools.yang.model.api.Module;
import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public final class JsonRPCNotificationService extends AbstractJsonRPCComponent
        implements DOMNotificationService, NotificationMessageHandler, AutoCloseable {
    private static final Logger LOG = LoggerFactory.getLogger(JsonRPCNotificationService.class);
    private final Multimap listeners = HashMultimap.create();
    private final Map mapped;

    public JsonRPCNotificationService(final @NonNull Peer peer, final @NonNull EffectiveModelContext schemaContext,
            final @NonNull HierarchicalEnumMap pathMap,
            final @NonNull JsonRpcCodecFactory codecFactory, final @NonNull TransportFactory transportFactory,
            final @Nullable RemoteGovernance governance) throws URISyntaxException {
        super(schemaContext, transportFactory, pathMap, codecFactory, peer);

        final ImmutableMap.Builder builder = ImmutableMap.builder();

        for (final NotificationDefinition def : schemaContext.getNotifications()) {
            final QNameModule qm = def.getQName().getModule();
            final String localName = def.getQName().getLocalName();
            final Optional possibleModule = schemaContext.findModule(qm);
            final JsonObject path = createRootPath(possibleModule.orElseThrow(), def.getQName());
            final String endpoint = getEndpoint(DataType.NOTIFICATION, governance, path);
            if (endpoint != null) {
                LOG.debug("Notification '{}' mapped to {}", localName, endpoint);
                builder.put(def.getQName(), transportFactory.endpointBuilder().subscriber().create(endpoint, this));
            } else {
                LOG.debug("Notification '{}' cannot be mapped, no known endpoint", localName);
            }
        }
        mapped = builder.build();
    }

    @Override
    public void close() {
        // Close all notification listeners
        mapped.values().forEach(SubscriberSession::close);
        listeners.clear();
    }

    /*
     * Notification listener is running in a separate thread so invoking them from here is not an issue (this is the
     * major difference between this code and netconf - it was nearly verbatim lifted out of there
     */
    private synchronized void publishNotification(final DOMNotification notification) {
        listeners.get(notification.getType()).forEach(l -> {
            LOG.debug("Invoking listener {} with notification {}", l, notification);
            l.onNotification(notification);
        });
    }

    @Override
    public synchronized Registration registerNotificationListener(final DOMNotificationListener listener,
            final Collection types) {
        for (final Absolute type : types) {
            listeners.put(type, listener);
        }
        return new AbstractRegistration() {
            @Override
            protected void removeRegistration() {
                for (final Absolute type : types) {
                    listeners.remove(type, listener);
                }
            }
        };
    }

    @Override
    public Registration registerNotificationListeners(final Map typeToListener) {
        for (final Entry entry : typeToListener.entrySet()) {
            listeners.put(entry.getKey(), entry.getValue());
        }
        return new AbstractRegistration() {
            @Override
            protected void removeRegistration() {
                for (final Entry entry : typeToListener.entrySet()) {
                    listeners.remove(entry.getKey(), entry.getValue());
                }
            }
        };
    }

    @Override
    public void handleNotification(final JsonRpcNotificationMessage notification) {
        try {
            final NotificationDefinition def = findNode(schemaContext, notification.getMethod(),
                    Module::getNotifications)
                            .orElseThrow(() -> new IllegalStateException(
                                    String.format("Notification with name '%s' not found", notification.getMethod())));
            publishNotification(codecFactory.notificationCodec(def).deserialize(notification.getParams()));
        } catch (IOException e) {
            throw new IllegalStateException(e);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy