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

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

/*******************************************************************************
 * 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 static com.pushtechnology.diffusion.client.Diffusion.sessionIdFromString;
import static com.pushtechnology.diffusion.client.session.Session.SESSION_ID;

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

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

import com.pushtechnology.diffusion.client.Diffusion;
import com.pushtechnology.diffusion.client.callbacks.Registration;
import com.pushtechnology.diffusion.client.callbacks.Stream;
import com.pushtechnology.diffusion.client.features.Callback;
import com.pushtechnology.diffusion.client.features.ClusterRoutingException;
import com.pushtechnology.diffusion.client.features.ContextCallback;
import com.pushtechnology.diffusion.client.features.HandlerConflictException;
import com.pushtechnology.diffusion.client.features.RegisteredHandler;
import com.pushtechnology.diffusion.client.features.TopicTreeHandler;
import com.pushtechnology.diffusion.client.session.Feature;
import com.pushtechnology.diffusion.client.session.PermissionsException;
import com.pushtechnology.diffusion.client.session.Session;
import com.pushtechnology.diffusion.client.session.SessionClosedException;
import com.pushtechnology.diffusion.client.session.SessionException;
import com.pushtechnology.diffusion.client.session.SessionId;
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.topics.details.TopicType;
import com.pushtechnology.diffusion.client.types.GlobalPermission;
import com.pushtechnology.diffusion.client.types.PathPermission;

/**
 * This feature allows a session to manage topics. It provides the following
 * capabilities:
 * 

* 1) Adding and removing topics.
* 2) Missing topic notifications — listening for requests to subscribe to * topics that do not exist thus allowing dynamic topic creation on demand.
* 3) Topic event listeners — listening for topic events, such as the number of * subscribers to a topic changing from zero to greater than zero or from * greater than zero to zero. * *

Topics

*

* The Diffusion server stores data in topics. Each topic is bound to a topic * path in the topic tree, and may have a current value. Sessions can subscribe * to topics. Updates to topic values are broadcast to subscribing sessions. * There are several types of topic. The {@link TopicType topic type} determines * the type of the data values a topic publishes to subscribers. * *

Adding topics

* *

Creating topics

*

* The simplest way to create a topic is to call * {@link #addTopic(String, TopicType)}, supplying a topic type. For example, to * create a {@link TopicType#JSON JSON} topic bound to the topic path * {@code foo}: * *

 * CompletableFuture<AddTopicResult%gt; result =
 *     topicControl.addTopic("foo", TopicType.JSON);
 * 
* *

* Success or failure is reported asynchronously through the CompletableFuture * result. * *

* The nature of a topic depends primarily on its topic type, but can be * customized using topic properties. Some types of topic cannot be created * without supplying mandatory topic properties. Topic properties can be * supplied in a {@link TopicSpecification topic specification} using * {@link #addTopic(String, TopicSpecification, AddCallback)}. Topic * specifications can be created using {@link #newSpecification(TopicType)} and * further customized with builder methods. For example, to create a * {@link TopicType#JSON JSON} topic bound to the topic path {@code foo} with * the {@link TopicSpecification#VALIDATE_VALUES VALIDATE_VALUES} property set * to {@code true}: * *

 * CompletableFuture<AddTopicResult> result =
 *     topicControl.addTopic(
 *         "foo",
 *         topicControl.newSpecification(TopicType.JSON)
 *             .withProperty(TopicSpecification.VALIDATE_VALUES, "true"));
 * 
* *

* See {@link TopicSpecification} for details of the available topic properties * and their effects on the different types of topic. * *

* Topic creation is idempotent. If {@link #addTopic(String, TopicSpecification) * addTopic(path, specification)} is called and there is already a topic bound * to {@code path} with a topic specification equal to {@code specification}, * the call will complete normally with an {@link AddTopicResult#EXISTS} result. * However, if there is a topic bound to {@code path} with a different topic * specification, the call will complete exceptionally with an * {@link ExistingTopicException}. * *

Removing topics

* *

* Topics can be removed using {@link #removeTopics(TopicSelector)}. Only those * selected topics that the caller has {@link PathPermission#MODIFY_TOPIC * MODIFY_TOPIC} permission to will be removed, any others will remain. * *

* Topics can also be automatically removed according to a removal criteria * specified using the {@link TopicSpecification#REMOVAL REMOVAL} topic * property. * *

Managing topic tree hierarchies

* *

* A topic can be bound to any path in the topic tree namespace. The only * restriction is that two topics can not have the same path. *

* In the following example a topic can be created with the path {@code A/B/foo} * even though there are no topics with path {@code A} or {@code A/B}: * *

 * topicControl.addTopic("A/B/foo", TopicType.JSON);
 * 
* *

* Topics bound to the paths {@code A} or {@code A/B} can be created later. *

* Topics can be removed without affecting the topics subordinate to them in the * topic tree using {@link #remove} providing a path topic selector. By using * the {@code //} topic selector qualifier it is possible to remove a topic and * all of its descendant topics, that is to remove whole topic tree branches. * *

Access control

*

* To add or remove a topic, a session needs {@link PathPermission#MODIFY_TOPIC * MODIFY_TOPIC} permission for the topic path. When removing topics with a * topic selector that matches more than one topic, only topics with paths for * which the session has {@code MODIFY_TOPIC} permission will be removed. *

* To register a * {@link #addMissingTopicHandler(String, MissingTopicNotificationStream) * missing topic handler} the session needs * {@link GlobalPermission#REGISTER_HANDLER REGISTER_HANDLER} permission. * *

Accessing the feature

*

* This feature may be obtained from a {@link Session session} as follows: * *

 * TopicControl topicControl = session.feature(TopicControl.class);
 * 
* * @author DiffusionData Limited * @since 5.0 */ public interface TopicControl extends Feature { /** * Create a new {@link TopicSpecification} for a given topic type. * * @param topicType the topic type * * @return a new immutable specification with no properties set. New * specifications with different properties can be produced using * the {@link TopicSpecification#withProperty(String, String) * withProperty} or * {@link TopicSpecification#withProperties(java.util.Map) * withProperties} methods of the provided specification. * * @since 5.7 * * @deprecated since 6.7 *

* Use * {@link com.pushtechnology.diffusion.client.Diffusion#newTopicSpecification * Diffusion.newTopicSpecification} which can be imported with a * static import, instead. */ @Deprecated TopicSpecification newSpecification(TopicType topicType); /** * Request creation of a topic. *

* This is a convenience method that is equivalent to: * *

     * topicControl.addTopic(
     *     topicPath,
     *     topicControl.newSpecification(topicType));
     * 
* * @param topicPath the topic path to which the topic will be bound * @param topicType the type of topic to be created * * @return a CompletableFuture that completes when a response is received * from the server. * *

* If the task completes successfully, the CompletableFuture result * will be indicate whether a new topic was created, or whether a * topic with an identical topic specification is already bound to * at {@code topicPath}. * *

* 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 ExistingTopicException} – a topic is bound to * {@code topicPath} with a different topic specification; *
  • {@link IncompatibleExistingTopicException} – an * incompatible topic already exists at {@code topicPath}; *
  • {@link IncompatibleParentTopicException} – a topic * could not be added because a topic at a parent path is * incompatible; *
  • {@link InvalidTopicPathException} – {@code topicPath} * is not a valid topic path; *
  • {@link InvalidTopicSpecificationException} – the * specification is invalid, possibly because mandatory properties * not supplied; *
  • {@link TopicLicenseLimitException} – the topic could * not be added as it would breach a licensing limit; *
  • {@link ClusterRoutingException} – if the operation failed * due to a transient cluster error; *
  • {@link AddTopicException} – the topic could not be * created for some reason other than those specified above; *
  • {@link PermissionsException} – the calling session * does not have {@code MODIFY_TOPIC} permission for * {@code topicPath}; *
  • {@link SessionClosedException} – the session is closed. *
* * @since 6.0 */ CompletableFuture addTopic( String topicPath, TopicType topicType); /** * Request creation of a topic. * * @param topicPath the topic path to which the topic will be bound * @param specification defines the topic to be created. A specification can * be created using {@link #newSpecification(TopicType)}. * * @return a CompletableFuture that completes when a response is received * from the server. * *

* If the task completes successfully, the CompletableFuture result * will be indicate whether a new topic was created, or whether a * topic with an identical topic specification is already bound to * at {@code topicPath}. * *

* 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 ExistingTopicException} – a topic is bound to * {@code topicPath} with a different topic specification; *
  • {@link IncompatibleExistingTopicException} – an * incompatible topic already exists at {@code topicPath}; *
  • {@link IncompatibleParentTopicException} – a topic * could not be added because a topic at a parent path is * incompatible; *
  • {@link InvalidTopicPathException} – {@code topicPath} * is not a valid topic path; *
  • {@link InvalidTopicSpecificationException} – the * specification is invalid; *
  • {@link TopicLicenseLimitException} – the topic could * not be added as it would breach a licensing limit; *
  • {@link ClusterRoutingException} – if the operation failed * due to a transient cluster error; *
  • {@link AddTopicException} – the topic could not be * created for some reason other than those specified above; *
  • {@link PermissionsException} – the calling session * does not have {@code MODIFY_TOPIC} permission for * {@code topicPath}; *
  • {@link SessionClosedException} – the session is closed. *
* * @since 6.0 */ CompletableFuture addTopic( String topicPath, TopicSpecification specification); /** * Version of {@link #addTopic(String, TopicSpecification, AddCallback)} * that allows a user defined context to be provided. * * @param topicPath the topic path to which the topic will be bound * * @param specification defines the topic to be created. A specification can * be created using {@link #newSpecification(TopicType)}. * * @param context an object passed to the callback with the reply to allow * requests and replies to be correlated. The caller may use any * convenient object reference, including {@code null} * * @param callback called with the result * * @param the context object type * * @since 5.7 * * @deprecated since 6.7 *

* Methods that use callbacks are deprecated and will be removed * in a future release. Use CompletableFuture variant instead. */ @Deprecated void addTopic( String topicPath, TopicSpecification specification, C context, AddContextCallback callback); /** * Send a request to the server to add a topic. * * @param topicPath the topic path to which the topic will be bound * * @param specification defines the topic to be created. A specification can * be created using {@link #newSpecification(TopicType)}. * * @param callback called with the result * * @since 5.7 * * @deprecated since 6.7 *

* Methods that use callbacks are deprecated and will be removed * in a future release. Use CompletableFuture variant instead. */ @Deprecated void addTopic( String topicPath, TopicSpecification specification, AddCallback callback); /** * Send a request to remove one or more topics. *

* All topics that match the provided {@code topicSelector} that the caller * has permission to remove will be removed. *

* The selector's {@link TopicSelectors descendant pattern qualifier} (a * trailing {@code /} or {@code //}), can be used to remove descendant * topics. If a single {@code /} qualifier is specified, all descendants of * the matched topic paths will be removed. If {@code //} is specified, the * matched paths and all descendants of the matched paths (complete * branches) will be removed. * * @param topicSelector specifies the topics to remove * * @return a CompletableFuture that completes when a response is received * from the server. * *

* If the task completes successfully, the CompletableFuture result * will bear a {@link TopicRemovalResult}. This provides the number * of topics removed by calling * {@link TopicRemovalResult#getRemovedCount()}. * *

* 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} – the session is closed. *
* * @since 6.0 */ CompletableFuture removeTopics(TopicSelector topicSelector); /** * Send a request to remove one or more topics. *

* This is equivalent to calling {@link #removeTopics(TopicSelector)} with a * selector parsed using {@link TopicSelectors#parse(String)}. * * @param topicSelector a {@link TopicSelectors topic selector expression} * specifying the topics to remove. * * @return a CompletableFuture that completes when a response is received * from the server. * *

* If the task completes successfully, the CompletableFuture result * will bear a {@link TopicRemovalResult}. This provides the number * of topics removed by calling * {@link TopicRemovalResult#getRemovedCount()}. * *

* 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} – the session is closed. *
* * @throws IllegalArgumentException if {@code topicSelector} is an invalid * topic selector expression * @since 6.0 */ CompletableFuture removeTopics(String topicSelector) throws IllegalArgumentException; /** * Send a request to remove one or more topics. *

* All topics that match the provided {@code topicSelector} that the caller * has permission to remove will be removed. *

* The selector's {@link TopicSelectors descendant pattern qualifier} (a * trailing {@code /} or {@code //}), can be used to remove descendant * topics. If a single {@code /} qualifier is specified, all descendants of * the matched topic paths will be removed. If {@code //} is specified, the * matched paths and all descendants of the matched paths (complete * branches) will be removed. * * @param topicSelector a {@link TopicSelectors topic selector expression} * specifying the topics to remove * * @param callback called to notify request completed * * @throws IllegalArgumentException if {@code topicSelector} is an invalid * topic selector expression * * @since 5.9 * * @deprecated since 6.7 *

* Methods that use callbacks are deprecated and will be removed * in a future release. Use CompletableFuture variant instead. */ @Deprecated void remove(String topicSelector, RemovalCallback callback) throws IllegalArgumentException; /** * Version of {@link #remove(String, RemovalCallback)} that allows a user * defined context to be provided. * * @param topicSelector a {@link TopicSelectors topic selector expression} * specifying the topics to remove * * @param context an object passed to the callback with the reply to allow * requests and replies to be correlated. The caller may use any * convenient object reference, including {@code null} * * @param callback called to notify request completed * * @param the context object type * * @throws IllegalArgumentException if {@code topicSelector} is an invalid * topic selector expression * * @since 5.9 * * @deprecated since 6.7 *

* Methods that use callbacks are deprecated and will be removed * in a future release. Use CompletableFuture variant instead. */ @Deprecated void remove( String topicSelector, C context, RemovalContextCallback callback) throws IllegalArgumentException; /** * Register a {@link MissingTopicNotificationStream} to handle requests for * a branch of the topic tree. * *

* The provided handler is called when a session subscribes using a topic * selector that matches no existing topics. This allows a control client * session to be notified when another session requests a topic that does * not exist. * *

* A session can register multiple handlers, but may only register a single * handler for a given topic path. If there is already a handler registered * for the topic path the operation will fail with a * {@link HandlerConflictException}. A handler will only be called for topic * selectors with a {@link TopicSelector#getPathPrefix() path prefix} that * starts with or is equal to {@code topicPath}. If the path prefix matches * multiple handlers, the one registered for the most specific (longest) * topic path will be called. * *

* Prefer this method to the callback-based alternative * {@link #addMissingTopicHandler(String, MissingTopicHandler)} since it * provides better error reporting. * * @param topicPath identifies a branch of the topic tree * * @param handler the handler to use for notifying topics at or below the * {@code topicPath} (unless there is a handler registered for a more * specific topic path) * * @return a CompletableFuture that completes when the handler is registered * with the server. * *

* If registration was successful, the CompletableFuture will * complete successfully with a {@link Registration} which can be * used to unregister the handler. * *

* 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 HandlerConflictException} – if the session has * already registered a missing topic handler for {@code topicPath}; * *
  • {@link PermissionsException} – if the session does * not have {@code REGISTER_HANDLER} permission; * *
  • {@link SessionClosedException} – if the session is * closed. *
* * @since 6.0 */ CompletableFuture addMissingTopicHandler( String topicPath, MissingTopicNotificationStream handler); /** * Register a {@link MissingTopicHandler} to handle requests for a branch of * the topic tree. *

* The provided handler is called when a session subscribes using a topic * selector that matches no existing topics. * *

* A session can register multiple handlers, but may only register a single * handler for a given topic path. See * {@link MissingTopicHandler#onActive(String, RegisteredHandler) onActive}. * A handler will only be called for topic selectors with a * {@link TopicSelector#getPathPrefix() path prefix} that starts with or is * equal to {@code topicPath}. If the path prefix matches multiple handlers, * the one registered for the most specific (longest) topic path will be * called. * * @param topicPath identifies a branch of the topic tree * * @param handler the handler to use for notifying topics at or below the * {@code topicPath} (unless there is a handler registered for a more * specific topic path) * * @deprecated since 6.7 *

* Prefer the CompletableFuture-based alternative * {@link #addMissingTopicHandler(String, MissingTopicNotificationStream)} * since it provides better error reporting. */ @Deprecated void addMissingTopicHandler(String topicPath, MissingTopicHandler handler); /** * Callback interface for adding topics when no context is provided. * * @deprecated since 6.7 *

* Methods that use callbacks are deprecated and will be removed * in a future release. Use CompletableFuture variant instead. */ @Deprecated interface AddCallback extends Callback { /** * This will be called when the topic has been successfully added. * * @param topicPath the topic path of the topic that was added */ void onTopicAdded(String topicPath); /** * This will be called if an attempt to add a topic has failed. * * @param topicPath the topic path as supplied to the add request * * @param reason the reason for failure */ void onTopicAddFailed(String topicPath, TopicAddFailReason reason); /** * A default implementation of {@link AddCallback}. *

* Simply logs onTopicAdded callback at 'debug' level and * onTopicAddFailed callback at 'warn' level. These methods can be * overridden to perform actions as required. */ class Default extends Callback.Default implements AddCallback { private static final Logger LOG = LoggerFactory.getLogger(AddCallback.Default.class); @Override public void onTopicAdded(String topicPath) { LOG.debug("{} - Topic {} added", this, topicPath); } @Override public void onTopicAddFailed( String topicPath, TopicAddFailReason reason) { LOG.warn( "{} - Failed to add topic {} : {}", this, topicPath, reason); } } } /** * Contextual callback interface for adding topics. *

* Use this alternative to {@link AddCallback} to associate some arbitrary * context object with each call. * * @param context object type * * @deprecated since 6.7 *

* Methods that use callbacks are deprecated and will be removed * in a future release. Use CompletableFuture variant instead. */ @Deprecated interface AddContextCallback extends ContextCallback { /** * This will be called when the topic has been successfully added. * * @param context the context object the application supplied when * making the call; may be {@code null} * * @param topicPath the topic path of the topic that was added */ void onTopicAdded(C context, String topicPath); /** * This will be called if an attempt to add a topic has failed. * * @param context the context object the application supplied when * making the call; may be {@code null} * * @param topicPath the topic path as supplied to the add request * * @param reason the reason for failure */ void onTopicAddFailed( C context, String topicPath, TopicAddFailReason reason); /** * A default implementation of {@link AddContextCallback}. *

* Simply logs onTopicAdded callback at 'debug' level and * onTopicAddFailed callback at 'warn' level. These methods can be * overridden to perform actions as required. * * @param context object type */ class Default extends ContextCallback.Default implements AddContextCallback { private static final Logger LOG = LoggerFactory.getLogger(AddContextCallback.Default.class); @Override public void onTopicAdded(C context, String topicPath) { LOG.debug( "{} - Topic {} added, context={}", this, topicPath, context); } @Override public void onTopicAddFailed( C context, String topicPath, TopicAddFailReason reason) { LOG.warn( "{} - Failed to add topic {} : {}, context={}", this, topicPath, reason, context); } } } /** * Callback interface for * {@link TopicControl#remove(String, RemovalCallback) remove} requests when * no context is used. * * @deprecated since 6.7 *

* Methods that use callbacks are deprecated and will be removed * in a future release. Use CompletableFuture variant instead. */ @Deprecated interface RemovalCallback extends com.pushtechnology.diffusion.client.callbacks.Callback { /** * Called to indicate that the requested remove operation has been * actioned at the server. This does not mean that all intended topics * have actually been removed. For example, if the caller did not have * sufficient permissions to remove the topic(s). */ void onTopicsRemoved(); /** * A default implementation of {@link RemovalCallback}. *

* This simply logs onTopicsRemoved calls at 'debug' level. This can be * overridden to perform some more specific action. */ class Default extends com.pushtechnology.diffusion.client.callbacks.Callback.Default implements RemovalCallback { private static final Logger LOG = LoggerFactory.getLogger(RemovalCallback.Default.class); @Override public void onTopicsRemoved() { LOG.debug("{} - Removed topic(s)", this); } } } /** * Contextual callback interface for * {@link TopicControl#remove(String, Object, RemovalContextCallback) * remove} requests. *

* Use this alternative to {@link RemovalCallback} to associate some * arbitrary context object with each call. * * @param context object type * * @deprecated since 6.7 *

* Methods that use callbacks are deprecated and will be removed * in a future release. Use CompletableFuture variant instead. */ @Deprecated interface RemovalContextCallback extends com.pushtechnology.diffusion.client.callbacks.ContextCallback { /** * Called to indicate that the requested remove operation has been * actioned at the server. This does not mean that all intended topics * have actually been removed. For example, if the caller did not have * sufficient permissions to remove the topic(s). * * @param context the context object the application supplied when * making the call; may be {@code null} */ void onTopicsRemoved(C context); /** * A default implementation of {@link RemovalContextCallback}. *

* This simply logs onTopicsRemoved calls at 'debug' level. * * @param context object type */ class Default extends com.pushtechnology.diffusion.client.callbacks.ContextCallback.Default implements RemovalContextCallback { private static final Logger LOG = LoggerFactory.getLogger(RemovalContextCallback.Default.class); @Override public void onTopicsRemoved(C context) { LOG.debug("{} - Removed topic(s), context={}", this, context); } } } /** * Stream called when a session subscribes using a topic selector that * matches no topics. *

* Instances can be registered using * {@link TopicControl#addMissingTopicHandler(String, MissingTopicNotificationStream) * addMissingTopicHandler}. * * @since 6.0 */ interface MissingTopicNotificationStream extends Stream { /** * Called when a session requests a topic that does not exist, and the * topic path belongs to part of the topic tree for which this handler * was registered. * * @param notification the missing topic notification */ void onMissingTopic(MissingTopicNotification notification); /** * Abstract {@link MissingTopicNotificationStream}. *

* This can be extended to provide the * {@link MissingTopicNotificationStream#onMissingTopic(TopicControl.MissingTopicNotification) * onMissingTopic} method. */ abstract class Default extends Stream.Default implements MissingTopicNotificationStream { } } /** * Handler called when a session subscribes using a topic selector that * matches no topics. *

* Handler instances can be registered using * {@link TopicControl#addMissingTopicHandler(String, MissingTopicHandler) * addMissingTopicHandler}. * * @deprecated since 6.7 *

* Use {@link MissingTopicNotificationStream} instead. */ @Deprecated interface MissingTopicHandler extends TopicTreeHandler { /** * Called when a session subscribes using a topic selector that matches * no existing topics. * * @param notification the missing topic notification */ void onMissingTopic(MissingTopicNotification notification); /** * Abstract {@link MissingTopicHandler}. *

* This can be extended to provide the * {@link MissingTopicHandler#onMissingTopic(TopicControl.MissingTopicNotification) * onMissingTopic} method. */ abstract class Default extends TopicTreeHandler.Default implements MissingTopicHandler { } } /** * Notification that a session has made a subscription request using a * selector that does not match any topics. */ interface MissingTopicNotification { /** * Returns the session properties of the session that made the request. * * @return the session properties * * @since 6.7 */ Map getSessionProperties(); /** * Returns the identity of the session that made the request. *

* This method is equivalent to calling * {@link Diffusion#sessionIdFromString * sessionIdFromString(getSessionProperties().get(Session.SESSION_ID)}. * * @return the session identifier */ default SessionId getSessionId() { return sessionIdFromString(getSessionProperties().get(SESSION_ID)); } /** * Returns the topic path derived from the requested topic selector. * This method is equivalent to calling * {@link TopicSelector#getPathPrefix() * getTopicSelector().getPathPrefix()}. * * @return the topic path */ default String getTopicPath() { return getTopicSelector().getPathPrefix(); } /** * Returns the {@link TopicSelector} that triggered this notification. * * @return the topic selector * @since 5.1 */ TopicSelector getTopicSelector(); /** * Returns a list of the names of the servers through which the * notification has been routed. *

* The first name in the list will be the name of the server to which * the originating session was connected. If the notification was routed * through remote server connections before reaching the recipient then * those servers will also be listed in the order that the notification * passed through them. * * @return list of server names, the first being the one which the * originating session was connected to * * @since 6.7 */ List getServerNames(); /** * This method has no effect. * * @deprecated since 6.6 *

* This method is a no-op. In previous releases this would * cause the selector to be added to the session's * selections and the selection to be re-evaluated. Since * 6.6 the selector is always added to the session's * selections before this notification is issued. */ @Deprecated void proceed(); /** * This method has no effect. * * @since 5.1 * * @deprecated since 6.6 *

* This method is a no-op. In previous releases this would * prevent the selector from being added to the session's * selections. Since 6.6 the selector is always added to the * session's selections before this notification is issued * regardless. */ @Deprecated void cancel(); } /** * Used to report the result of adding a topic. * * @since 6.0 */ enum AddTopicResult { /** * A new topic was created. */ CREATED, /** * A topic with the same specification already exists. */ EXISTS, } /** * Reports the number of topics removed by a call to {@link #removeTopics}. * * @since 6.6 */ interface TopicRemovalResult { /** * The integer returned represents the number of topics removed by the * operation. This does not include any derived topics created by a * topic view which were removed as a side effect of this action. * * @return the count of topics removed */ int getRemovedCount(); } /** * Exception thrown to report a failure to add a topic. * * @since 6.0 */ class AddTopicException extends SessionException { private static final long serialVersionUID = -7842778740912571614L; /** * @param message the exception message */ public AddTopicException(String message) { super(message); } } /** * Exception thrown to report a topic could not be added because the * specification is invalid. * * @since 6.0 */ final class InvalidTopicSpecificationException extends AddTopicException { private static final long serialVersionUID = -4737003936657468838L; /** * @param message the exception message */ public InvalidTopicSpecificationException(String message) { super(message); } } /** * Exception thrown to report a topic could not be added because an existing * topic with a different specification is bound to the topic path. * * @since 6.0 */ final class ExistingTopicException extends AddTopicException { private static final long serialVersionUID = 177584683079519534L; /** * @param message the exception message */ public ExistingTopicException(String message) { super(message); } } /** * Exception thrown to report a topic could not be added because the topic * path supplied is invalid. * *

* Invalid topic paths include the empty string, and strings adjacent path * separators such as {@code //}. * * @since 6.0 */ final class InvalidTopicPathException extends AddTopicException { private static final long serialVersionUID = -132560805100117118L; /** * @param message the exception message */ public InvalidTopicPathException(String message) { super(message); } } /** * Exception thrown to report a topic could not be added because a license * limit has been exceeded. * * @since 6.0 */ final class TopicLicenseLimitException extends AddTopicException { private static final long serialVersionUID = 3459583462376598320L; /** * @param message the exception message */ public TopicLicenseLimitException(String message) { super(message); } } /** * Exception thrown to report a topic could not be added because there is an * existing topic that is incompatible with the request. * * @since 6.0 */ abstract class IncompatibleTopicException extends AddTopicException { private static final long serialVersionUID = 8083381286283811102L; /** * @param message the exception message */ public IncompatibleTopicException(String message) { super(message); } } /** * Exception thrown to report that a topic exists at the same path that is * managed by a component that has exclusive control over the topic. *

* For example, a topic may already exist at the same path that is under the * control of fan-out distribution. * * @since 6.0 */ final class IncompatibleExistingTopicException extends IncompatibleTopicException { private static final long serialVersionUID = 5075815951750161358L; /** * @param message the exception message */ public IncompatibleExistingTopicException(String message) { super(message); } } /** * Exception thrown to report that a topic could not be added because a * topic at a parent path is incompatible. * * @since 6.0 * @deprecated since 6.5 *

* Since 6.5, this exception is no longer used. This exception * will be removed in a future release. */ @Deprecated final class IncompatibleParentTopicException extends IncompatibleTopicException { private static final long serialVersionUID = 1988899455119482084L; /** * @param message the exception message */ public IncompatibleParentTopicException(String message) { super(message); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy