code: /*
   * Copyright (c) 2021 the Eclipse Milo Authors
   *
   * This program and the accompanying materials are made
   * available under the terms of the Eclipse Public License 2.0
   * which is available at https://www.eclipse.org/legal/epl-2.0/
   *
   * SPDX-License-Identifier: EPL-2.0
   */
  
  package org.eclipse.milo.opcua.sdk.client.api.subscriptions;
  
  import java.util.concurrent.CompletableFuture;
  import java.util.function.BiFunction;
  import java.util.function.Function;
  
  import com.google.common.collect.ImmutableList;
  import org.eclipse.milo.opcua.sdk.client.api.UaSession;
  import org.eclipse.milo.opcua.stack.core.UaException;
  import org.eclipse.milo.opcua.stack.core.types.builtin.DateTime;
  import org.eclipse.milo.opcua.stack.core.types.builtin.StatusCode;
  import org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.UByte;
  import org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.UInteger;
  
  public interface UaSubscriptionManager {
  
      /**
       * Create a {@link UaSubscription} using default parameters.
       * <p>
       * The requested max keep-alive count and lifetime count will be derived from the requested publishing interval.
       *
       * @param requestedPublishingInterval the requested publishing interval of the subscription.
       * @return a {@link CompletableFuture} containing the {@link UaSubscription}.
       */
      CompletableFuture<UaSubscription> createSubscription(double requestedPublishingInterval);
  
      /**
       * Create a {@link UaSubscription}.
       *
       * @param requestedPublishingInterval the requested publishing interval.
       * @param requestedLifetimeCount      the requested lifetime count.
       * @param requestedMaxKeepAliveCount  the requested max keep-alive count.
       * @param maxNotificationsPerPublish  the maximum number of notifications allowed in a publish response.
       * @param publishingEnabled           {@code true} if publishing is enabled for the subscription.
       * @param priority                    the relative priority to assign to the subscription.
       * @return a {@link CompletableFuture} containing the {@link UaSubscription}.
       */
      CompletableFuture<UaSubscription> createSubscription(double requestedPublishingInterval,
                                                           UInteger requestedLifetimeCount,
                                                           UInteger requestedMaxKeepAliveCount,
                                                           UInteger maxNotificationsPerPublish,
                                                           boolean publishingEnabled,
                                                           UByte priority);
  
      /**
       * Create a {@link UaSubscription}.
       * <p>
       * This overload uses provided functions to calculate keep-alive and lifetime counts. They may be called more than
       * once, with revised values, in order to modify the subscription if the server revises the requested publishing
       * interval.
       *
       * @param requestedPublishingInterval the requested publishing interval.
       * @param getLifetimeCount            function returning lifetime count given publishing interval and
       *                                    keep-alive count.
       * @param getMaxKeepAliveCount        function returning max keep-alive count given publishing interval.
       * @param maxNotificationsPerPublish  the maximum number of notifications allowed in a publish response.
       * @param publishingEnabled           {@code true} if publishing is enabled for the subscription.
       * @param priority                    the relative priority to assign to the subscription.
       * @return a {@link CompletableFuture} containing the {@link UaSubscription}.
       */
      CompletableFuture<UaSubscription> createSubscription(double requestedPublishingInterval,
                                                           BiFunction<Double, UInteger, UInteger> getLifetimeCount,
                                                           Function<Double, UInteger> getMaxKeepAliveCount,
                                                           UInteger maxNotificationsPerPublish,
                                                           boolean publishingEnabled,
                                                           UByte priority);
  
      /**
       * Request a new publishing interval for a {@link UaSubscription}.
       * <p>
       * The requested max keep-alive count and lifetime count will be derived from the requested publishing interval.
       *
       * @param subscriptionId              the server-assigned id of the {@link UaSubscription} to modify.
       * @param requestedPublishingInterval the requested publishing interval.
       * @return a {@link CompletableFuture} containing the {@link UaSubscription}.
       */
      CompletableFuture<UaSubscription> modifySubscription(UInteger subscriptionId,
                                                           double requestedPublishingInterval);
  
      /**
       * Modify a {@link UaSubscription}.
       *
       * @param subscriptionId              the server-assigned id of the {@link UaSubscription} to modify.
       * @param requestedPublishingInterval the requested publishing interval.
       * @param requestedLifetimeCount      the requested lifetime count.
       * @param requestedMaxKeepAliveCount  the requested max keep-alive count.
       * @param maxNotificationsPerPublish  the maximum number of notifications allowed in a publish response.
       * @param priority                    the relative priority to assign to the subscription.
       * @return a {@link CompletableFuture} containing the {@link UaSubscription}.
       */
      CompletableFuture<UaSubscription> modifySubscription(UInteger subscriptionId,
                                                           double requestedPublishingInterval,
                                                           UInteger requestedLifetimeCount,
                                                           UInteger requestedMaxKeepAliveCount,
                                                           UInteger maxNotificationsPerPublish,
                                                           UByte priority);
  
      /**
       * Modify a {@link UaSubscription}.
       * <p>
       * This overload uses provided functions to calculate keep-alive and lifetime counts. They may be called more than
       * once, with revised values, in order to modify the subscription if the server revises the requested publishing
       * interval.
       *
       * @param subscriptionId              the server-assigned id of the {@link UaSubscription} to modify.
       * @param requestedPublishingInterval the requested publishing interval.
       * @param getLifetimeCount            function returning lifetime count given publishing interval and
       *                                    keep-alive count.
       * @param getMaxKeepAliveCount        function returning max keep-alive count given publishing interval.
       * @param maxNotificationsPerPublish  the maximum number of notifications allowed in a publish response.
       * @param priority                    the relative priority to assign to the subscription.
       * @return a {@link CompletableFuture} containing the {@link UaSubscription}.
       */
      CompletableFuture<UaSubscription> modifySubscription(UInteger subscriptionId,
                                                           double requestedPublishingInterval,
                                                           BiFunction<Double, UInteger, UInteger> getLifetimeCount,
                                                           Function<Double, UInteger> getMaxKeepAliveCount,
                                                           UInteger maxNotificationsPerPublish,
                                                           UByte priority);
  
      /**
       * Delete a {@link UaSubscription}.
       *
       * @param subscriptionId the server-assigned id of the {@link UaSubscription} to delete.
       * @return a {@link CompletableFuture} containing the deleted {@link UaSubscription}.
       */
      CompletableFuture<UaSubscription> deleteSubscription(UInteger subscriptionId);
  
      /**
       * @return an {@link ImmutableList} of {@link UaSubscription}s managed by this {@link UaSubscriptionManager}.
       */
      ImmutableList<UaSubscription> getSubscriptions();
  
      /**
       * Add a {@link SubscriptionListener}.
       *
       * @param listener the {@link SubscriptionListener} to add.
       */
      void addSubscriptionListener(SubscriptionListener listener);
  
      /**
       * Remove a {@link SubscriptionListener}.
       *
       * @param listener the {@link SubscriptionListener} to remove.
       */
      void removeSubscriptionListener(SubscriptionListener listener);
  
      interface SubscriptionListener {
  
          /**
           * A keep-alive message was received.
           *
           * @param subscription the {@link UaSubscription} that received the keep-alive.
           * @param publishTime  the time the server published the keep-alive.
           */
          default void onKeepAlive(UaSubscription subscription, DateTime publishTime) {}
  
          /**
           * A status change notification was received.
           *
           * @param subscription the {@link UaSubscription} that received the status change.
           * @param status       the new subscription status.
           */
          default void onStatusChanged(UaSubscription subscription, StatusCode status) {}
  
          /**
           * A publish failure has occurred.
           * <p>
           * No additional action is required.
           *
           * @param exception the cause of the failure.
           */
          default void onPublishFailure(UaException exception) {}
  
          /**
           * Attempts to recover missed notification data have failed.
           * <p>
           * When a notification is missed a series of Republish requests are initiated to recover the missing data. If
           * republishing fails, or any of the notifications are no longer available, this callback will be invoked.
           *
           * @param subscription the subscription that missed notification data.
           */
          default void onNotificationDataLost(UaSubscription subscription) {}
  
          /**
           * A new {@link UaSession} was established, and upon attempting to transfer an existing subscription to this
           * new session, a failure occurred.
           * <p>
           * This subscription will be removed from {@link UaSubscriptionManager}'s bookkeeping. It must be re-created.
           *
           * @param subscription the {@link UaSubscription} that could not be transferred.
           * @param statusCode   the {@link StatusCode} for the transfer failure.
           */
          default void onSubscriptionTransferFailed(UaSubscription subscription, StatusCode statusCode) {}
  
          /**
           * The subscription watchdog timer has elapsed. The receiver of this callback should
           * consider deleting and re-creating this subscription or taking other appropriate action.
           * <p>
           * The timer elapses when 125% of the expected keep-alive interval has passed since receipt
           * of the last PublishResponse. The watchdog timer will not be restarted unless a new
           * PublishResponse for this subscription is received.
           * <p>
           * The expected keep-alive interval is {@code publishingInterval * keepAliveCount}
           * milliseconds.
           *
           * @param subscription the {@link UaSubscription} that has not received a response.
           */
          default void onSubscriptionWatchdogTimerElapsed(UaSubscription subscription) {}
  
      }
  
  }
  