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

com.pushtechnology.diffusion.client.features.control.topics.TopicNotifications Maven / Gradle / Ivy

There is a newer version: 6.11.2
Show newest version
/*******************************************************************************
 * Copyright (c) 2023 DiffusionData Ltd., All Rights Reserved.
 *
 * Use is subject to license terms.
 *
 * NOTICE: All information contained herein is, and remains the
 * property of Push Technology. The intellectual and technical
 * concepts contained herein are proprietary to Push Technology and
 * may be covered by U.S. and Foreign Patents, patents in process, and
 * are protected by trade secret or copyright law.
 *******************************************************************************/
package com.pushtechnology.diffusion.client.features.control.topics;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.pushtechnology.diffusion.client.callbacks.Registration;
import com.pushtechnology.diffusion.client.callbacks.Stream;
import com.pushtechnology.diffusion.client.session.Feature;
import com.pushtechnology.diffusion.client.session.PermissionsException;
import com.pushtechnology.diffusion.client.session.SessionClosedException;
import com.pushtechnology.diffusion.client.topics.TopicSelector;
import com.pushtechnology.diffusion.client.topics.TopicSelectors;
import com.pushtechnology.diffusion.client.topics.details.TopicSpecification;
import com.pushtechnology.diffusion.client.types.PathPermission;

/**
 * This feature allows a client session to receive notifications about changes
 * to selected topics.
 *
 * 

Notifications

Sessions receive notifications via * {@link TopicNotifications.TopicNotificationListener * TopicNotificationListener}s. The listener will be provided with the * {@link TopicSpecification specifications} for all topics bound to paths that * match registered selectors, and any subsequent notifications for the selected * topics on those paths, via * {@link TopicNotifications.TopicNotificationListener#onTopicNotification * onTopicNotificaion}. Notifications will only be emitted for paths where a * topic is bound. *

* For example, with a registered selector {@code "?a//"}, if a topic is added * at path {@code a/b/c/d} with no topics bound to paths higher in the hierarchy * {@link TopicNotifications.TopicNotificationListener#onTopicNotification * onTopicNotification} will be called once with a topic path of * {@code "a/b/c/d"}, a notification type of * {@link TopicNotifications.TopicNotificationListener.NotificationType#ADDED * ADDED}, and the topic's associated {@link TopicSpecification}. *

* The nature of the notification is provided by the * {@link TopicNotifications.TopicNotificationListener.NotificationType * NotificationType} enum. * {@link TopicNotifications.TopicNotificationListener.NotificationType#ADDED * ADDED} and * {@link TopicNotifications.TopicNotificationListener.NotificationType#REMOVED * REMOVED} represent structural changes to the topic tree; * {@link TopicNotifications.TopicNotificationListener.NotificationType#SELECTED * SELECTED} indicates that a pre-existing topic has been selected by a new * registered selector, and similarly * {@link TopicNotifications.TopicNotificationListener.NotificationType#DESELECTED * DESELECTED} indicates that a topic is no longer selected because of changes * to the set of registered selectors for the listener. *

Selection and deselection

Registered * {@link TopicNotifications.TopicNotificationListener * TopicNotificationListeners} will receive notifications for all topics * matching registered selections. Selection of topics using * {@link TopicSelector} expressions is provided via the * {@link NotificationRegistration} associated for a specific listener. *

* A session can request selections at any time, even if the topics do not exist * at the server. Selections are stored on the server and any subsequently added * topics that match registered selectors will generate notifications. *

Immediate descendant notifications

Listeners will be informed about * the presence or absence of unselected immediate descendants via * {@link TopicNotifications.TopicNotificationListener#onDescendantNotification * onDescendantNotification}. This allows listeners to determine whether to * select deeper topic paths in order to walk the topic tree. An immediate * descendant is defined as the first bound topic on any branch below a given * topic path. *

* For example, for topics at {@code "a/b", "a/c", "a/c/d", "a/e/f/g"}, the * immediate descendants of {@code "a"} would be {@code "a/b", "a/c", "a/e/f/g"} * . *

* Immediate descendant notifications provide a * {@link TopicNotifications.TopicNotificationListener.NotificationType * NotificationType} to indicate the reason for the notification in the same * manner as * {@link TopicNotifications.TopicNotificationListener#onTopicNotification * onTopicNotification}. *

* For example, with a registered selector {@code ">a"}, if a topic is added at * path {@code a/b} then * {@link TopicNotifications.TopicNotificationListener#onDescendantNotification * onDescendantNotification} will be called with a topic path of {@code "a/b"} * and a notification type of * {@link TopicNotifications.TopicNotificationListener.NotificationType#ADDED * ADDED}. If a topic was subsequently added at path {@code a/b/c}, no further * notifications will be received until {@link NotificationRegistration#select} * was used to select the deeper topic path {@code ">a/b"}. * *

Access control

A listener will only be notified about topics for * which the session has {@link PathPermission#SELECT_TOPIC SELECT_TOPIC} and * {@link PathPermission#READ_TOPIC READ_TOPIC} permissions. * {@link PathPermission#SELECT_TOPIC SELECT_TOPIC} determines which selectors * a listener may register; {@link PathPermission#READ_TOPIC READ_TOPIC} * determines which selected topics the client may receive notifications for. * * @author DiffusionData Limited * @since 6.0 */ public interface TopicNotifications extends Feature { /** * Register a listener to receive topic notifications. * * @param listener the listener to receive topic specification notifications * * @return A completable future providing the registration state *

* If the registration completes successfully, the CompletableFuture * result will be a {@link NotificationRegistration}, which may be * used to later close the listener and remove it from the server. *

* Otherwise, the CompletableFuture will complete exceptionally with * a {@link CompletionException}. Common reasons for failure, listed * by the exception reported as the * {@link CompletionException#getCause() cause}, include: * *

    *
  • {@link SessionClosedException} – if the session is * closed. *
*/ CompletableFuture addListener(TopicNotificationListener listener); /** * The NotificationRegistration represents the registration state of the * associated listener on the server. *

* The NotificationRegistration also provides operations to control which * topic paths the listener will receive notifications for. */ interface NotificationRegistration extends Registration { /** * Request to receive notifications for all topics matched by the * provided topic selector. * * @param selector the selector to register * @return a CompletableFuture that completes when a response is * received from the server. *

* If the selection completes successfully, the * CompletableFuture result will be null. The result type is * any rather than Void to provide forward compatibility with * future iterations of this API that may provide a non-null * result with a more specific result type. * *

* Otherwise, the CompletableFuture will complete exceptionally * with a {@link CompletionException}. Common reasons for * failure, listed by the exception reported as the * {@link CompletionException#getCause() cause}, include: * *

    *
  • {@link PermissionsException} – if the calling * session does not have {@code SELECT_TOPIC} permission for the * path prefix of the selector expression; * *
  • {@link SessionClosedException} – if the session is * closed. *
*/ CompletableFuture select(TopicSelector selector); /** * Request to receive notifications for all topics matched by the * provided selector. *

* This is equivalent to calling {@link #select(TopicSelector)} with a * selector parsed using {@link TopicSelectors#parse(String)}. * * @param selector the selector to register * @return a CompletableFuture that completes when a response is * received from the server. *

* If the selection completes successfully, the * CompletableFuture result will be null. The result type is * any rather than Void to provide forward compatibility with * future iterations of this API that may provide a non-null * result with a more specific result type. * *

* Otherwise, the CompletableFuture will complete exceptionally * with a {@link CompletionException}. Common reasons for * failure, listed by the exception reported as the * {@link CompletionException#getCause() cause}, include: * *

    *
  • {@link PermissionsException} – if the calling * session does not have {@code SELECT_TOPIC} permission for the * path prefix of the selector expression; * *
  • {@link SessionClosedException} – if the session is * closed. *
*/ CompletableFuture select(String selector); /** * Request to stop receiving notifications for all topics matched by the * given selector. * * @param selector the selector to register * @return a CompletableFuture that completes when a response is * received from the server. *

* If the deselection completes successfully, the * CompletableFuture result will be null. The result type is * any rather than Void to provide forward compatibility with * future iterations of this API that may provide a non-null * result with a more specific result type. * *

* Otherwise, the CompletableFuture will complete exceptionally * with a {@link CompletionException}. Common reasons for * failure, listed by the exception reported as the * {@link CompletionException#getCause() cause}, include: * *

    *
  • {@link PermissionsException} – if the calling * session does not have {@code SELECT_TOPIC} permission for the * path prefix of the selector expression; * *
  • {@link SessionClosedException} – if the session is * closed. *
*/ CompletableFuture deselect(TopicSelector selector); /** * Request to stop receiving notifications for all topics matched by the * given selector. *

* This is equivalent to calling {@link #deselect(TopicSelector)} with a * selector parsed using {@link TopicSelectors#parse(String)}. * * @param selector the selector to register * @return a CompletableFuture that completes when a response is * received from the server. *

* If the deselection completes successfully, the * CompletableFuture result will be null. The result type is * any rather than Void to provide forward compatibility with * future iterations of this API that may provide a non-null * result with a more specific result type. * *

* Otherwise, the CompletableFuture will complete exceptionally * with a {@link CompletionException}. Common reasons for * failure, listed by the exception reported as the * {@link CompletionException#getCause() cause}, include: * *

    *
  • {@link PermissionsException} – if the calling * session does not have {@code SELECT_TOPIC} permission for the * path prefix of the selector expression; * *
  • {@link SessionClosedException} – if the session is * closed. *
*/ CompletableFuture deselect(String selector); } /** * Listener for topic notifications. */ interface TopicNotificationListener extends Stream { /** * Notification for an immediate descendant of a selected topic path. * This notifies the presence or absence of a descendant topic that may * subsequently be explicitly selected. * * @param topicPath the path of the immediate descendant that is not selected * @param type the type of notification */ void onDescendantNotification(String topicPath, NotificationType type); /** * A notification for a selected topic. * * @param topicPath the path of the topic that this notification is for * @param specification the specification of the topic that this * notification is for * @param type the type of notification */ void onTopicNotification( String topicPath, TopicSpecification specification, NotificationType type); /** * The type of notification that has been received. */ enum NotificationType { /** * The topic has been added. */ ADDED, /** * The topic existed at the time of the selector registration. */ SELECTED, /** * The topic has been removed. */ REMOVED, /** * The topic is no longer selected due to the removal of a selector. */ DESELECTED } /** * Default listener. *

* This simply logs {@link TopicNotificationListener} method calls at * {@code debug} level. This class may be extended to provide more * specific processing. */ class Default extends Stream.Default implements TopicNotificationListener { private static final Logger LOG = LoggerFactory.getLogger( TopicNotificationListener.Default.class); @Override public void onTopicNotification( String topicPath, TopicSpecification specification, NotificationType type) { LOG.debug( "Topic notification: path={}, specification={}, type={}", topicPath, specification, type); } @Override public void onDescendantNotification( String topicPath, NotificationType type) { LOG.debug("Descendant notification: path={}, type={}", topicPath, type); } } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy