# Java

Source: https://docs.interop.io/desktop/capabilities/notifications/java/index.html

## Overview

Available since io.Connect Java 1.8.0

The Notifications API is accessible via the `io.notifications()` object.

> ⚠️ *Note that the following sections describe the Notifications API available since io.Connect Java 1.8.0. The [legacy Notifications API](#legacy_notifications_api) has been deprecated and it's highly recommended to use the new API for raising notifications.*

## Configuration

To specify global notification settings dynamically, use the `configure()` method. It accepts a `NotificationConfiguration` object as an argument with the following properties:

| Property | Type | Description |
|----------|------|-------------|
| `closeNotificationOnClick` | `boolean` | If `true`, when the user clicks on the body of a notification in the Notification Panel, the notification will be removed from the list. |
| `disabled` | `boolean` | If `true`, will disable all notifications - notification toasts and notifications in the Notification Panel. |
| `placement` | `PlacementSettings` | Placement settings for the Notification Panel and the notification toasts. |
| `showNotificationBadge` | `boolean` | If `true`, a notification badge will be shown. |
| `snooze` | `SnoozeSettings` | Snooze settings for notifications. |
| `sourceFilter` | `NotificationFilter` | Filter with names of apps that are allowed or not allowed to raise notifications. |
| `toastExpiry` | `Duration` | Interval after which the notification toasts will be hidden. Defaults to 15 seconds. |
| `toasts` | `ToastSettings` | Settings for the notification toasts. |
| `toastsDisabled` | `boolean` | If `true`, will disable notification toasts. |

To create a `NotificationConfiguration` object, use the provided builder.

To disable all notifications:

```java
NotificationConfiguration config = NotificationConfiguration.builder()
        .disabled(true)
        .build();

io.notifications().configure(config);
```

To disable only toast notifications:

```java
NotificationConfiguration config = NotificationConfiguration.builder()
        .toastsDisabled(true)
        .build();

io.notifications().configure(config);
```

To set the position of the Notification Panel and the notification toasts on the screen:

```java
NotificationConfiguration config = NotificationConfiguration.builder()
        .placement(new NotificationConfiguration.PlacementSettings("left", "top-left"))
        .build();

io.notifications().configure(config);
```

To retrieve the current global notification settings, use the `getConfiguration()` method:

```java
NotificationConfiguration config = io.notifications().getConfiguration().toCompletableFuture().join();
```

## Raising Notifications

To raise a notification from your app, use the `raise()` method of the API. The method accepts a `NotificationOptions` object as an argument with settings for the notification you want to raise. To create a `NotificationOptions` object, use the provided builder. The only required property is `title`, which can be set via the `builder()` method:

```java
NotificationOptions options = NotificationOptions.builder("New Trade")
        .body("VOD.L: 23 shares sold @ $212.03")
        .action(NotificationAction.builder("HandleNotificationClick")
                .action("openClientPortfolio").title("Open Portfolio").build())
        .build();

// Raising a notification.
RaisedNotification notification = io.notifications().raise(options).toCompletableFuture().join();
```

![Raising Notifications](https://docs.interop.io/desktop/images/notifications/notification.png)

### Notification Options

The following table lists some of the more important properties of the `NotificationOptions` object:

| Property | Type | Description |
|----------|------|-------------|
| `body` | `String` | The body text of the notification. |
| `clickInterop` | `NotificationAction.InteropActionSettings` | Specifies an [Interop method](https://docs.interop.io/desktop/capabilities/data-sharing/interop/java/index.md) to invoke when the user clicks on the notification. |
| `data` | `Object` | Arbitrary data associated with the notification. |
| `icon` | `String` | URL of an icon to be displayed in the notification. |
| `image` | `String` | URL of an image to be displayed in the notification. |
| `panelExpiry` | `Duration` | Interval after which the notification will be removed from the Notification Panel. |
| `severity` | `NotificationSeverity` | Defines the urgency of the notification: `LOW`, `MEDIUM`, `HIGH`, `CRITICAL`, or `NONE`. |
| `source` | `String` | Overrides the source of the notification. Provide the name of the io.Connect app to display as the source. |
| `state` | `NotificationState` | Notification state: `ACTIVE`, `ACKNOWLEDGED`, `SEEN`, `CLOSED`, `STALE`, `SNOOZED`, or `PROCESSING`. Defaults to `ACTIVE`. |
| `title` | `String` | **Required.** The title of the notification. |
| `toastExpiry` | `Duration` | Interval after which the notification toast will be hidden. |
| `type` | `NotificationType` | `NOTIFICATION` or `ALERT`. This property is meant to distinguish between notification types for different visual representations. |

## Notification Click

You can use the `clickInterop` property of the `NotificationOptions` object to specify an [Interop method](https://docs.interop.io/desktop/capabilities/data-sharing/interop/java/index.md) that will be invoked when the user clicks on the notification.

> ℹ️ *For details on how to use standard handlers for notification clicks, see the `onClick()` method of the `RaisedNotification` object in the [Raised Notification](#raised_notification) section.*

For instance, another app has registered an Interop method:

```java
io.interop().register("HandleNotificationClick", (arg, caller) -> {
    System.out.println("Notification clicked: " + arg);
    return Collections.emptyMap();
});
```

To invoke this Interop method for handling the notification click, define a `NotificationAction.InteropActionSettings` object and assign it as a value to the `clickInterop` property of the `NotificationOptions` object:

```java
Map<String, Object> args = new HashMap<>();
args.put("name", "Vernon Mullen");
args.put("id", "1");

NotificationAction.InteropActionSettings interopSettings = NotificationAction.InteropActionSettings.any(
        "HandleNotificationClick", args);

NotificationOptions options = NotificationOptions.builder("New Trade")
        .body("VOD.L: 23 shares sold @ $212.03")
        .clickInterop(interopSettings)
        .build();

io.notifications().raise(options);
```

## Notification Actions

You can create action buttons for the notification. When the user clicks on an action button, the specified [Interop method](https://docs.interop.io/desktop/capabilities/data-sharing/interop/java/index.md) will be invoked.

> ℹ️ *For details on how to use standard handlers for action button clicks, see the `onAction()` method of the `RaisedNotification` object in the [Raised Notification](#raised_notification) section.*

![Actions](https://docs.interop.io/desktop/images/notifications/actions.png)

To define action buttons, use the `action()` method of the `NotificationOptions` builder when creating a notification:

```java
// Registering Interop methods to be used as callbacks for notification actions.
io.interop().register("CallClient", (arg, caller) -> Collections.emptyMap());
io.interop().register("OpenPortfolio", (arg, caller) -> Collections.emptyMap());

NotificationOptions options = NotificationOptions.builder("New Trade")
        .body("VOD.L: 23 shares sold @ $212.03")
        // Provide the Interop method name, a title for the action button,
        // and an optional map with parameters to pass to the Interop method.
        .action("CallClient", "Call Client", Collections.singletonMap("id", 42))
        .action("OpenPortfolio", "Open Portfolio", Collections.singletonMap("id", 42))
        .build();

io.notifications().raise(options);
```

For more control over actions, you can use `NotificationAction.builder()` directly:

```java
NotificationAction action = NotificationAction.builder("CallClient")
        .title("Call Client")
        .label("Call Client")
        .parameters(Collections.singletonMap("customerId", "11"))
        .interop(NotificationAction.InteropActionSettings.any("CallClient", Collections.singletonMap("customerId", "11")))
        .build();

NotificationOptions options = NotificationOptions.builder("New Trade")
        .action(action)
        .build();

io.notifications().raise(options);
```

## Raised Notification

The `raise()` method returns a `CompletionStage<RaisedNotification>`. The `RaisedNotification` object provides access to the notification data and per-notification event callbacks:

```java
RaisedNotification notification = io.notifications().raise(options).toCompletableFuture().join();

// Access the notification data.
NotificationData data = notification.getData();
System.out.println("Notification ID: " + data.getId());

// Provide a callback to be invoked when a notification action button is clicked.
notification.onAction(action -> System.out.println("Action clicked: " + action));

// Provide a callback to be invoked when the notification body is clicked.
notification.onClick(() -> System.out.println("Notification was clicked."));

// Provide a callback to be invoked when the notification is shown.
notification.onShow(() -> System.out.println("Notification was shown."));

// Provide a callback to be invoked when a notification error occurs.
notification.onError(error -> System.out.println("Notification error: " + error));

// Provide a callback to be invoked when the notification is closed.
notification.onClose(() -> System.out.println("Notification was closed."));
```

## Listing Notifications

To retrieve a list of all available notifications, use the `list()` method:

```java
List<NotificationData> allNotifications = io.notifications().list().toCompletableFuture().join();
```

## Clearing Notifications

To clear all notifications, use the `clearAll()` method:

```java
io.notifications().clearAll();
```

To clear a specific notification, use the `clear()` method and pass as a required argument the ID of the notification to clear:

```java
io.notifications().clear(notification.getData().getId());
```

To clear all notifications seen by the user, use the `clearOld()` method:

```java
io.notifications().clearOld();
```

To clear multiple notifications at a time, use the `clearMany()` method and pass as a required argument a list of IDs of the notifications to clear:

```java
List<String> ids = allNotifications.stream()
        .map(NotificationData::getId)
        .collect(Collectors.toList());

io.notifications().clearMany(ids);
```

## Clicking Notifications

To click a notification or a notification action programmatically, use the `click()` method and pass either only the notification ID, or the notification ID and the name of the action to click:

```java
String id = notification.getData().getId();

// Clicking a notification.
io.notifications().click(id, null, null);

// Clicking a notification action.
io.notifications().click(id, "openClientPortfolio", null);

// Clicking a notification and closing it.
io.notifications().click(id, null, Notifications.ClickOptions.shouldClose(true));
```

## Snoozing Notifications

To snooze a notification programmatically, use the `snooze()` method and pass as required arguments the ID of the notification to snooze and the duration in milliseconds for which to snooze it:

```java
io.notifications().snooze(notification.getData().getId(), 600000);
```

To snooze multiple notifications at a time, use the `snoozeMany()` method and pass as required arguments a list of IDs of the notifications to snooze and the duration in milliseconds for which to snooze them:

```java
List<String> ids = allNotifications.stream()
        .map(NotificationData::getId)
        .collect(Collectors.toList());

io.notifications().snoozeMany(ids, 600000);
```

## Updating Notification Data

To update the arbitrary data associated with the notification, use the `updateData()` method and provide the ID of the notification and the new data:

```java
String id = notification.getData().getId();
Map<String, Object> newData = Collections.singletonMap("io", 42);

io.notifications().updateData(id, newData);
```

## Importing Notifications

Importing notifications can be useful if you want to persist the notification history between user sessions. Even if the user shuts down the platform, you can dynamically import the previously saved batch of existing notifications when the user logs in again. All imported notifications will be visible in the Notification Panel and will be available in the notification list that can be accessed programmatically, but only notifications with state set to `ACTIVE` will be displayed as notification toasts to the user. An event for a raised notification will be triggered for all imported notifications.

To import notifications, use the `importNotifications()` method and provide a list of `NotificationOptions` objects as a required argument:

```java
List<NotificationOptions> notifications = Arrays.asList(
        NotificationOptions.builder("New Trade")
                .body("VOD.L: 23 shares sold @ $212.03")
                .state(NotificationState.ACTIVE)
                .build(),
        NotificationOptions.builder("New Trade")
                .body("VOD.L: 42 shares bought @ $211.73")
                .state(NotificationState.SEEN)
                .build()
);

List<NotificationData> imported = io.notifications().importNotifications(notifications)
        .toCompletableFuture().join();
```

## Notification State

Notifications can have the following states describing their lifetime:

| State | Description |
|-------|-------------|
| `ACKNOWLEDGED` | A notification can be marked as acknowledged when the user has interacted with it by clicking on the notification or on an action in it. |
| `ACTIVE` | A notification can be marked as active when it's raised, but the user hasn't seen it, or interacted in any way with it yet. |
| `CLOSED` | A notification can be marked as closed when the user has closed the notification in the Notification Panel. |
| `PROCESSING` | A notification can be marked as processing when its state is in the process of changing (e.g., the user interacts with a notification from the UI, you make a request to a remote service to update the notification state, and you are still waiting for a response). |
| `SEEN` | A notification can be marked as seen when the user has seen it (e.g., by opening the Notification Panel). |
| `SNOOZED` | A notification can be marked as snoozed when the user snoozes it from the UI. |
| `STALE` | A notification can be marked as stale after a predefined period of time. |

To set the state of a notification, use the `setState()` method and pass as required arguments the ID of the notification whose state to set and the `NotificationState` value to which to set it:

```java
String id = notification.getData().getId();

io.notifications().setState(id, NotificationState.ACKNOWLEDGED);
```

To set the states of multiple notifications at a time, use the `setStates()` method and pass as required arguments a list of IDs of the notifications whose states to set and the `NotificationState` value to which to set them:

```java
List<String> ids = allNotifications.stream()
        .map(NotificationData::getId)
        .collect(Collectors.toList());

io.notifications().setStates(ids, NotificationState.SEEN);
```

## Notification Filters

Notifications can be filtered programmatically based on lists of allowed and blocked apps.

To set a notification filter, use the `setFilter()` method and pass a `NotificationFilter` object as an argument. To create a `NotificationFilter` object, use the provided builder:

```java
NotificationFilter filter = NotificationFilter.builder()
        .allowed(Collections.singletonList("*"))
        .blocked(Arrays.asList("app-one", "app-two"))
        .build();

io.notifications().setFilter(filter);
```

To get the current notification filter, use the `getFilter()` method:

```java
NotificationFilter filter = io.notifications().getFilter().toCompletableFuture().join();
```

## Events

The Notifications API provides methods for subscribing for notification events. All methods return an `AsynchronousCloseable`, which you can use to unsubscribe from the respective event.

To get notified when a notification is raised, use the `onRaised()` method:

```java
AsynchronousCloseable subscription = io.notifications()
        .onRaised(n -> System.out.println("Notification raised: " + n.getId()));
```

To get notified when a notification is closed, use the `onClosed()` method:

```java
io.notifications().onClosed(notification -> System.out.println("Notification closed: " + notification.getId()));
```

To get notified when the state of a notification is changed, use the `onStateChanged()` method:

```java
io.notifications().onStateChanged((notification, state) ->
        System.out.println("Notification " + notification.getId() + " changed to " + state));
```

To get notified when the number of active notifications changes, use the `onCounterChanged()` method:

```java
io.notifications().onCounterChanged(count ->
        System.out.println("Active notifications: " + count));
```

To get notified when the global notification settings change, use the `onConfigurationChanged()` method:

```java
io.notifications().onConfigurationChanged(config ->
        System.out.println("Notification settings updated."));
```

To get notified when the `data` property of a notification is updated, use the `onDataChanged()` method:

```java
io.notifications().onDataChanged((notification, data) ->
        System.out.println("Data changed for notification " + notification.getId() + ": " + data));
```

## Notification Panel

The Notification Panel can be controlled programmatically - show, hide or toggle its visibility. The Notification Panel API is accessible via the `io.notifications().panel()` object.

### Operations

To check whether the Notification Panel is visible, use the `isVisible()` method:

```java
boolean isVisible = io.notifications().panel().isVisible().toCompletableFuture().join();
```

To show the Notification Panel, use the `show()` method:

```java
io.notifications().panel().show();
```

To hide the Notification Panel, use the `hide()` method:

```java
io.notifications().panel().hide();
```

To toggle the visibility of the Notification Panel, use the `toggle()` method:

```java
io.notifications().panel().toggle();
```

### Events

To get notified when the visibility of the Notification Panel changes, use the `onVisibilityChanged()` method:

```java
io.notifications().panel().onVisibilityChanged(isVisible ->
        System.out.println("Notification Panel is " + (isVisible ? "visible" : "hidden")));
```

## Legacy Notifications API

> ⚠️ *Note that the legacy Notifications API has been deprecated. It's highly recommended to use the new Notifications API for [raising notifications](#raising_notifications) instead.*

To raise a notification with the legacy Notifications API, use the `create()` method to build a `Notification` instance. Then, use the `raise()` method of the `Notification` instance and pass a `NotificationSeverity` value as an argument to raise the notification:

```java
// Creating a notification instance.
Notification notification = io.notifications()
        .create("Notification", notification -> notification
                .title("New Trade")
                .description("VOD.L: 23 shares sold @ $212.03"));

// Raising the notification.
notification.raise(NotificationSeverity.LOW);
```

To specify what happens when the user clicks on the notification, use the `details()` method and pass the name of an [Interop method](https://docs.interop.io/desktop/capabilities/data-sharing/interop/java/index.md) to invoke when the notification is clicked:

```java
io.notifications()
        .create("Notification", notification -> notification
                .title("New Trade")
                .details("DetailsHandler"));
```

To add action buttons, use the `action()` method and pass as arguments the name of an Interop method to invoke when the action is clicked, the title of the action button, and an optional map with parameters to pass to the Interop method:

```java
io.interop().register("CallClient", (arg, caller) -> Collections.emptyMap());
io.interop().register("OpenPortfolio", (arg, caller) -> Collections.emptyMap());

Notification notification = io.notifications()
        .create("Notification", notification -> notification
                .title("New Trade")
                .action("CallClient", "Call Client", Collections.singletonMap("id", 42))
                .action("OpenPortfolio", "Open Portfolio", Collections.singletonMap("id", 42)));

notification.raise(NotificationSeverity.LOW);
```
