diff --git a/.codegen.json b/.codegen.json index c1132aff1..a75d41fbe 100644 --- a/.codegen.json +++ b/.codegen.json @@ -1 +1 @@ -{ "engineHash": "91b0f90", "specHash": "ec8720b", "version": "0.1.0" } +{ "engineHash": "fa469c0", "specHash": "60778fb", "version": "0.1.0" } diff --git a/README.md b/README.md index af8e807a2..3541ca3df 100644 --- a/README.md +++ b/README.md @@ -90,7 +90,7 @@ Browse the [docs](docs/README.md) or see [API Reference](https://developer.box.c # Upgrades -The SDK is updated regularly to include new features, enhancements, and bug fixes. If you are upgrading from manual SDK to this new generated SDK checkout the [migration guide](MIGRATION_GUIDE.md) and [changelog](CHANGELOG.md) for more information. +The SDK is updated regularly to include new features, enhancements, and bug fixes. If you are upgrading from manual SDK to this new generated SDK checkout the [migration guide](migration-guides/from-v4-to-v10.md) and [changelog](CHANGELOG.md) for more information. # Integration Tests diff --git a/docs/EventStream.md b/docs/EventStream.md new file mode 100644 index 000000000..a91eef21f --- /dev/null +++ b/docs/EventStream.md @@ -0,0 +1,29 @@ +# Event Stream + +The Event Stream class utilizes long-polling to receive real-time events from Box. The SDK provides an easy way to set up and manage the event stream which returns an iterable object and yields events as they are received. + + + + +- [Event Stream](#event-stream) + - [Listening to the Event Stream](#listening-to-the-event-stream) + - [Deduplication](#deduplication) + + + +## Listening to the Event Stream + +When the `EventStream` is started, it will begin long-polling asynchronously. Events received from the API are then yielded to the caller. + +```java +EventStream stream = client.getEvents().getEventStream(); +for (Event event : stream) { + System.out.printf( + "Received event: ID=%s, Type=%s, CreatedAt=%s%n\n",event.getEventId(),event.getEventType(),event.getCreatedAt()); +} + +``` + +## Deduplication + +The `EventStream` class automatically deduplicates events based on their `eventId`. This means that if the same event is received multiple times, it will only be emitted once to the listeners. diff --git a/docs/events.md b/docs/events.md index 2290e88eb..94013cc64 100644 --- a/docs/events.md +++ b/docs/events.md @@ -3,6 +3,7 @@ - [Get events long poll endpoint](#get-events-long-poll-endpoint) - [List user and enterprise events](#list-user-and-enterprise-events) +- [Get event stream](#get-event-stream) ## Get events long poll endpoint @@ -107,3 +108,30 @@ chunk, as well as the next `stream_position` that can be queried. +## Get event stream + +Get an event stream for the Box API + +This operation is performed by calling function `getEventStream`. + + + +``` +client.getEvents().getEventStream() +``` + +### Arguments + +- queryParams `GetEventStreamQueryParams` + - Query parameters of getEvents method +- headers `GetEventStreamHeaders` + - Headers of getEvents method + + +### Returns + +This function returns a value of type `EventStream`. + + + + diff --git a/docs/hubcollaborations.md b/docs/hubcollaborations.md index e36f79e12..609b5e572 100644 --- a/docs/hubcollaborations.md +++ b/docs/hubcollaborations.md @@ -1,15 +1,15 @@ # HubCollaborationsManager -- [Get hub collaborations](#get-hub-collaborations) -- [Create hub collaboration](#create-hub-collaboration) -- [Get hub collaboration by collaboration ID](#get-hub-collaboration-by-collaboration-id) -- [Update hub collaboration](#update-hub-collaboration) -- [Remove hub collaboration](#remove-hub-collaboration) +- [Get Box Hub collaborations](#get-box-hub-collaborations) +- [Create Box Hub collaboration](#create-box-hub-collaboration) +- [Get Box Hub collaboration by collaboration ID](#get-box-hub-collaboration-by-collaboration-id) +- [Update Box Hub collaboration](#update-box-hub-collaboration) +- [Remove Box Hub collaboration](#remove-box-hub-collaboration) -## Get hub collaborations +## Get Box Hub collaborations -Retrieves all collaborations for a hub. +Retrieves all collaborations for a Box Hub. This operation is performed by calling function `getHubCollaborationsV2025R0`. @@ -33,12 +33,12 @@ client.getHubCollaborations().getHubCollaborationsV2025R0(new GetHubCollaboratio This function returns a value of type `HubCollaborationsV2025R0`. -Retrieves the collaborations associated with the specified hub. +Retrieves the collaborations associated with the specified Box Hub. -## Create hub collaboration +## Create Box Hub collaboration -Adds a collaboration for a single user or a single group to a hub. +Adds a collaboration for a single user or a single group to a Box Hub. Collaborations can be created using email address, user IDs, or group IDs. @@ -64,12 +64,12 @@ client.getHubCollaborations().createHubCollaborationV2025R0(new HubCollaboration This function returns a value of type `HubCollaborationV2025R0`. -Returns a new hub collaboration object. +Returns a new Box Hub collaboration object. -## Get hub collaboration by collaboration ID +## Get Box Hub collaboration by collaboration ID -Retrieves details for a hub collaboration by collaboration ID. +Retrieves details for a Box Hub collaboration by collaboration ID. This operation is performed by calling function `getHubCollaborationByIdV2025R0`. @@ -93,13 +93,13 @@ client.getHubCollaborations().getHubCollaborationByIdV2025R0(createdCollaboratio This function returns a value of type `HubCollaborationV2025R0`. -Returns a hub collaboration object. +Returns a Box Hub collaboration object. -## Update hub collaboration +## Update Box Hub collaboration -Updates a hub collaboration. -Can be used to change the hub role. +Updates a Box Hub collaboration. +Can be used to change the Box Hub role. This operation is performed by calling function `updateHubCollaborationByIdV2025R0`. @@ -125,12 +125,12 @@ client.getHubCollaborations().updateHubCollaborationByIdV2025R0(createdCollabora This function returns a value of type `HubCollaborationV2025R0`. -Returns an updated hub collaboration object. +Returns an updated Box Hub collaboration object. -## Remove hub collaboration +## Remove Box Hub collaboration -Deletes a single hub collaboration. +Deletes a single Box Hub collaboration. This operation is performed by calling function `deleteHubCollaborationByIdV2025R0`. @@ -154,7 +154,7 @@ client.getHubCollaborations().deleteHubCollaborationByIdV2025R0(createdCollabora This function returns a value of type `void`. -A blank response is returned if the hub collaboration was +A blank response is returned if the Box Hub collaboration was successfully deleted. diff --git a/docs/hubitems.md b/docs/hubitems.md index 11a77727d..b826422e4 100644 --- a/docs/hubitems.md +++ b/docs/hubitems.md @@ -1,12 +1,12 @@ # HubItemsManager -- [Get hub items](#get-hub-items) -- [Manage hub items](#manage-hub-items) +- [Get Box Hub items](#get-box-hub-items) +- [Manage Box Hub items](#manage-box-hub-items) -## Get hub items +## Get Box Hub items -Retrieves all items associated with a Hub. +Retrieves all items associated with a Box Hub. This operation is performed by calling function `getHubItemsV2025R0`. @@ -30,12 +30,12 @@ client.getHubItems().getHubItemsV2025R0(new GetHubItemsV2025R0QueryParams(create This function returns a value of type `HubItemsV2025R0`. -Retrieves the items associated with the specified Hub. +Retrieves the items associated with the specified Box Hub. -## Manage hub items +## Manage Box Hub items -Adds and/or removes Hub items from a Hub. +Adds and/or removes Box Hub items from a Box Hub. This operation is performed by calling function `manageHubItemsV2025R0`. diff --git a/docs/hubs.md b/docs/hubs.md index ae08762db..45f7182e6 100644 --- a/docs/hubs.md +++ b/docs/hubs.md @@ -1,17 +1,17 @@ # HubsManager -- [List all hubs](#list-all-hubs) -- [Create hub](#create-hub) -- [List all hubs for requesting enterprise](#list-all-hubs-for-requesting-enterprise) -- [Get hub information by ID](#get-hub-information-by-id) -- [Update hub information by ID](#update-hub-information-by-id) -- [Delete hub](#delete-hub) -- [Copy hub](#copy-hub) +- [List all Box Hubs](#list-all-box-hubs) +- [Create Box Hub](#create-box-hub) +- [List all Box Hubs for requesting enterprise](#list-all-box-hubs-for-requesting-enterprise) +- [Get Box Hub information by ID](#get-box-hub-information-by-id) +- [Update Box Hub information by ID](#update-box-hub-information-by-id) +- [Delete Box Hub](#delete-box-hub) +- [Copy Box Hub](#copy-box-hub) -## List all hubs +## List all Box Hubs -Retrieves all hubs for requesting user. +Retrieves all Box Hubs for requesting user. This operation is performed by calling function `getHubsV2025R0`. @@ -35,12 +35,12 @@ client.getHubs().getHubsV2025R0(new GetHubsV2025R0QueryParams.Builder().scope("a This function returns a value of type `HubsV2025R0`. -Returns all hubs for the given user or enterprise. +Returns all Box Hubs for the given user or enterprise. -## Create hub +## Create Box Hub -Creates a new Hub. +Creates a new Box Hub. This operation is performed by calling function `createHubV2025R0`. @@ -67,9 +67,9 @@ This function returns a value of type `HubV2025R0`. Returns a new Hub object. -## List all hubs for requesting enterprise +## List all Box Hubs for requesting enterprise -Retrieves all hubs for a given enterprise. +Retrieves all Box Hubs for a given enterprise. Admins or Hub Co-admins of an enterprise with GCM scope can make this call. @@ -96,12 +96,12 @@ client.getHubs().getEnterpriseHubsV2025R0(new GetEnterpriseHubsV2025R0QueryParam This function returns a value of type `HubsV2025R0`. -Returns all hubs for the given user or enterprise. +Returns all Box Hubs for the given user or enterprise. -## Get hub information by ID +## Get Box Hub information by ID -Retrieves details for a hub by its ID. +Retrieves details for a Box Hub by its ID. This operation is performed by calling function `getHubByIdV2025R0`. @@ -128,9 +128,9 @@ This function returns a value of type `HubV2025R0`. Returns a hub object. -## Update hub information by ID +## Update Box Hub information by ID -Updates a Hub. Can be used to change title, description, or Hub settings. +Updates a Box Hub. Can be used to change title, description, or Box Hub settings. This operation is performed by calling function `updateHubByIdV2025R0`. @@ -159,9 +159,9 @@ This function returns a value of type `HubV2025R0`. Returns a Hub object. -## Delete hub +## Delete Box Hub -Deletes a single hub. +Deletes a single Box Hub. This operation is performed by calling function `deleteHubByIdV2025R0`. @@ -189,11 +189,11 @@ A blank response is returned if the hub was successfully deleted. -## Copy hub +## Copy Box Hub -Creates a copy of a Hub. +Creates a copy of a Box Hub. -The original Hub will not be modified. +The original Box Hub will not be modified. This operation is performed by calling function `copyHubV2025R0`. diff --git a/migration-guides/from-box-java-sdk-gen-v0-to-box-java-sdk-v10.md b/migration-guides/from-box-java-sdk-gen-v0-to-box-java-sdk-v10.md new file mode 100644 index 000000000..be55c1b75 --- /dev/null +++ b/migration-guides/from-box-java-sdk-gen-v0-to-box-java-sdk-v10.md @@ -0,0 +1,149 @@ +# Migration guide from beta release (v0.X.Y) of the `box-java-sdk-gen` to the v10 version of the `box-java-sdk` + + + + +- [Installation](#installation) + - [How to migrate](#how-to-migrate) + - [Maven](#maven) + - [Gradle](#gradle) +- [Union classes name changes](#union-classes-name-changes) + - [How to migrate](#how-to-migrate-1) +- [Removed unused models from schemas namespace](#removed-unused-models-from-schemas-namespace) + - [How to migrate](#how-to-migrate-2) + + + +## Installation + +In order to start using v10 version of the Box Java SDK, you need to change the dependency in your project. +The artifact name has changed from `com.box:box-java-sdk-gen` to `com.box:box-java-sdk`. +You also need to set the version to `10.0.0` or higher. You can find the latest version on [Maven Central](https://search.maven.org/artifact/com.box/box-java-sdk). + +### How to migrate + +#### Maven + +To start using v10 version of Box Java SDK in your Maven project replace the dependency in your `pom.xml` file. + +**Old (`box-java-sdk-gen-v0`)** + +```xml + + com.box + box-java-sdk-gen + 0.8.0 + +``` + +**New (`box-java-sdk-v10`)** + +```xml + + com.box + box-java-sdk + 10.0.0 + +``` + +#### Gradle + +To start using v10 version of Box Java SDK in your Gradle project replace the dependency in your `build.gradle` file. + +**Old (`box-java-sdk-gen-v0`)** + +```groovy +implementation 'com.box:box-java-sdk-gen:0.8.0' +``` + +**New (`box-java-sdk-v10`)** + +```groovy +implementation 'com.box:box-java-sdk:10.0.0' +``` + +## Union classes name changes + +In the beta version of the `box-java-sdk-gen` our `OneOf` class names (representing unions from the OpenAPI specification) +were fully auto-generated based on the included variants. This often resulted in overly long names that were difficult +to work with in tools like Git. For example: `MetadataFieldFilterDateRangeOrMetadataFieldFilterFloatRangeOrArrayOfStringOrNumberOrString`. +Additionally, every time the new variant was added to the `OneOf`, the class name itself changed. +Starting in v10, the names of `OneOf` classes are defined directly in the specification. This ensures that they are meaningful, short, and stable over time. + +### How to migrate + +If your code references any of the renamed classes, replace the old name with the new one. +If you were not explicitly using the type names, no changes are needed, since only the class names changed and their behavior remains the same. + +List of changed `OneOf` classes and types associated with them: + +| Old name | New name | +| ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------ | +| AiAgentAskOrAiAgentExtractOrAiAgentExtractStructuredOrAiAgentTextGen | AiAgent | +| AiAgentAskOrAiAgentReference | AiAskAgent | +| AiAgentExtractOrAiAgentReference | AiExtractAgent | +| AiAgentExtractStructuredOrAiAgentReference | AiExtractStructuredAgent | +| AiAgentReferenceOrAiAgentTextGen | AiTextGenAgent | +| AppItemEventSourceOrEventSourceOrFileOrFolderOrGenericSourceOrUser | EventSourceResource | +| FileBaseOrFolderBaseOrWebLinkBase | AppItemAssociatedItem | +| FileFullOrFolderFull | MetadataQueryResultItem | +| FileFullOrFolderFullOrWebLink | SearchResultWithSharedLinkItem/RecentItemResource/SearchResultItem | +| FileFullOrFolderMiniOrWebLink | Item | +| FileMiniOrFolderMini | Resource | +| FileOrFolderOrWebLink | LegalHoldPolicyAssignedItem/CollaborationItem | +| FileOrFolderScope | ResourceScope | +| FileOrFolderScopeScopeField | ResourceScopeScopeField | +| FileReferenceOrFolderReferenceOrWeblinkReferenceV2025R0 | HubItemReferenceV2025R0 | +| GroupMiniOrUserCollaborations | CollaborationAccessGrantee | +| IntegrationMappingPartnerItemSlackUnion | IntegrationMappingPartnerItemSlack | +| IntegrationMappingPartnerItemTeamsUnion | IntegrationMappingPartnerItemTeams | +| KeywordSkillCardOrStatusSkillCardOrTimelineSkillCardOrTranscriptSkillCard | SkillCard | +| MetadataFieldFilterDateRangeOrMetadataFieldFilterFloatRangeOrArrayOfStringOrNumberOrString | MetadataFilterValue | +| SearchResultsOrSearchResultsWithSharedLinks | SearchResultsResponse | + +Some classes were split into multiple ones depending on context. + +Manager functions affected by these changes: + +| Function | Old return type | New return type | +| -------------------------------------- | -------------------------------------------------------------------- | --------------------- | +| AiManager.getAiAgentDefaultConfig(...) | AiAgentAskOrAiAgentExtractOrAiAgentExtractStructuredOrAiAgentTextGen | AiAgent | +| SearchManager.searchForContent(...) | SearchResultsOrSearchResultsWithSharedLinks | SearchResultsResponse | + +## Removed unused models from schemas namespace + +Several unused types (classes and enums) have been removed from the schemas because they were not used by any SDK functions or by the Box API. + +### How to migrate + +Here is the full list of removed types: + +| Removed classes/enums | +| ------------------------------------------ | +| FileOrFolder | +| HubActionV2025R0 | +| MetadataQueryIndex | +| MetadataQueryIndexFieldsField | +| MetadataQueryIndexFieldsSortDirectionField | +| MetadataQueryIndexStatusField | +| RetentionPolicyAssignmentBase | +| RetentionPolicyAssignmentBaseTypeField | +| SkillInvocation | +| SkillInvocationEnterpriseField | +| SkillInvocationEnterpriseTypeField | +| SkillInvocationSkillField | +| SkillInvocationSkillTypeField | +| SkillInvocationStatusField | +| SkillInvocationStatusStateField | +| SkillInvocationTokenField | +| SkillInvocationTokenReadField | +| SkillInvocationTokenReadTokenTypeField | +| SkillInvocationTokenWriteField | +| SkillInvocationTokenWriteTokenTypeField | +| SkillInvocationTypeField | +| WebhookInvocation | +| WebhookInvocationTriggerField | +| WebhookInvocationTypeField | +| WorkflowFull | + +If your code references any of these types, remove those references. diff --git a/migration-guide.md b/migration-guides/from-v4-to-v10.md similarity index 100% rename from migration-guide.md rename to migration-guides/from-v4-to-v10.md diff --git a/src/main/java/com/box/sdkgen/box/eventstream/EventStream.java b/src/main/java/com/box/sdkgen/box/eventstream/EventStream.java new file mode 100644 index 000000000..a9b8b6e02 --- /dev/null +++ b/src/main/java/com/box/sdkgen/box/eventstream/EventStream.java @@ -0,0 +1,47 @@ +package com.box.sdkgen.box.eventstream; + +import com.box.sdkgen.managers.events.EventsManager; +import com.box.sdkgen.managers.events.GetEventStreamHeaders; +import com.box.sdkgen.managers.events.GetEventStreamQueryParams; +import com.box.sdkgen.schemas.event.Event; +import java.util.Iterator; + +public class EventStream implements Iterable { + + EventStreamIterator iterator; + + private EventStream(Builder builder) { + this.iterator = + new EventStreamIterator(builder.eventsManager, builder.queryParams, builder.headersInput); + } + + @Override + public Iterator iterator() { + return this.iterator; + } + + public void stop() { + this.iterator.stop(); + } + + public static class Builder { + final EventsManager eventsManager; + final GetEventStreamQueryParams queryParams; + GetEventStreamHeaders headersInput; + + public Builder(EventsManager eventsManager, GetEventStreamQueryParams queryParams) { + this.eventsManager = eventsManager; + this.queryParams = queryParams; + this.headersInput = new GetEventStreamHeaders(); + } + + public Builder headersInput(GetEventStreamHeaders headersInput) { + this.headersInput = headersInput != null ? headersInput : new GetEventStreamHeaders(); + return this; + } + + public EventStream build() { + return new EventStream(this); + } + } +} diff --git a/src/main/java/com/box/sdkgen/box/eventstream/EventStreamIterator.java b/src/main/java/com/box/sdkgen/box/eventstream/EventStreamIterator.java new file mode 100644 index 000000000..49eb59ad7 --- /dev/null +++ b/src/main/java/com/box/sdkgen/box/eventstream/EventStreamIterator.java @@ -0,0 +1,345 @@ +package com.box.sdkgen.box.eventstream; + +import com.box.sdkgen.box.errors.BoxSDKError; +import com.box.sdkgen.managers.events.EventsManager; +import com.box.sdkgen.managers.events.GetEventStreamHeaders; +import com.box.sdkgen.managers.events.GetEventStreamQueryParams; +import com.box.sdkgen.managers.events.GetEventsHeaders; +import com.box.sdkgen.managers.events.GetEventsQueryParams; +import com.box.sdkgen.managers.events.GetEventsQueryParamsEventTypeField; +import com.box.sdkgen.managers.events.GetEventsQueryParamsStreamTypeField; +import com.box.sdkgen.networking.fetchoptions.FetchOptions; +import com.box.sdkgen.networking.fetchoptions.ResponseFormat; +import com.box.sdkgen.networking.fetchresponse.FetchResponse; +import com.box.sdkgen.schemas.event.Event; +import com.box.sdkgen.schemas.events.Events; +import com.box.sdkgen.schemas.realtimeserver.RealtimeServer; +import com.box.sdkgen.schemas.realtimeservers.RealtimeServers; +import com.box.sdkgen.serialization.json.Valuable; +import com.fasterxml.jackson.databind.JsonNode; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.concurrent.CountDownLatch; +import java.util.stream.Collectors; + +enum RealtimeServerEvent { + NEW_CHANGE("new_change"), + RECONNECT("reconnect"); + + private final String value; + + RealtimeServerEvent(String value) { + this.value = value; + } + + public String getValue() { + return value; + } +} + +enum EventStreamAction { + FETCH_EVENTS, + RECONNECT, + RETRY, + STOP +} + +class EventStreamIterator implements Iterator { + private static final int DEDUPLICATION_SIZE = 1000; + private final EventsManager eventsManager; + private final GetEventStreamQueryParams queryParams; + private final GetEventStreamHeaders headersInput; + private String streamPosition; + private RealtimeServer longPollInfo; + private volatile boolean stopped; + private final CountDownLatch stopLatch; + private final Map dedupHash; + private final List eventQueue; + private boolean started; + private int longPollingRetries; + private static final int DEFAULT_MAX_RETRIES = 10; + + EventStreamIterator( + EventsManager eventsManager, + GetEventStreamQueryParams queryParams, + GetEventStreamHeaders headersInput) { + this.eventsManager = eventsManager; + this.queryParams = queryParams; + this.headersInput = headersInput; + this.streamPosition = + queryParams.getStreamPosition() != null ? queryParams.getStreamPosition() : "now"; + this.longPollInfo = null; + this.started = false; + this.stopped = false; + this.stopLatch = new CountDownLatch(1); + this.dedupHash = new HashMap<>(); + this.eventQueue = new ArrayList<>(); + this.longPollingRetries = 0; + } + + @Override + public boolean hasNext() { + return !eventQueue.isEmpty() || (!stopped && stopLatch.getCount() > 0); + } + + @Override + public Event next() { + if (!hasNext()) { + stop(); + throw new NoSuchElementException("No more events available or stream stopped"); + } + if (!eventQueue.isEmpty()) { + return eventQueue.remove(0); + } + if (!started) { + started = true; + fetchEvents(); + if (!eventQueue.isEmpty()) { + return eventQueue.remove(0); + } + } + + getLongPollInfo(); + while (!stopped && stopLatch.getCount() > 0) { + try { + EventStreamAction action = doLongPoll(); + switch (action) { + case FETCH_EVENTS: + fetchEvents(); + if (!eventQueue.isEmpty()) { + return eventQueue.remove(0); + } + break; + case RETRY: + try { + Thread.sleep(5000); + } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); + } + continue; + case RECONNECT: + getLongPollInfo(); + continue; + case STOP: + stop(); + break; + } + } catch (Exception e) { + boolean isBoxError = e instanceof BoxSDKError; + if (!isBoxError) { + throw e; + } + } + } + throw new NoSuchElementException("Stream stopped"); + } + + public void stop() { + if (!stopped) { + this.stopped = true; + this.stopLatch.countDown(); + } + } + + private void getLongPollInfo() throws BoxSDKError { + if (stopped || stopLatch.getCount() == 0) { + return; + } + + try { + RealtimeServers info = eventsManager.getEventsWithLongPolling(); + RealtimeServer server = null; + if (info.getEntries() != null) { + for (RealtimeServer entry : info.getEntries()) { + if (entry.getType().equals("realtime_server")) { + server = entry; + break; + } + } + } + + if (server == null) { + throw new BoxSDKError("No realtime server found in the response."); + } + + this.longPollInfo = server; + this.longPollingRetries = 0; + + } catch (Exception e) { + if (!stopped && stopLatch.getCount() > 0) { + throw new BoxSDKError( + "Failed to fetch long polling info: " + (e.getMessage() != null ? e.getMessage() : ""), + e); + } + } + } + + private EventStreamAction doLongPoll() throws BoxSDKError { + if (stopped || stopLatch.getCount() == 0) { + return EventStreamAction.STOP; + } + + try { + int maxRetries = + (longPollInfo != null && longPollInfo.getMaxRetries() != null) + ? Integer.parseInt(longPollInfo.getMaxRetries()) + : DEFAULT_MAX_RETRIES; + + if (longPollInfo == null || longPollingRetries > maxRetries) { + getLongPollInfo(); + } + + longPollingRetries++; + + String longPollUrl = longPollInfo.getUrl(); + String separator = longPollUrl.contains("?") ? "&" : "?"; + String longPollWithStreamPosition = + longPollUrl + separator + "stream_position=" + streamPosition; + Map headers = new HashMap<>(); + headers.put("Content-Type", "application/json"); + + FetchResponse response = + eventsManager + .getNetworkSession() + .getNetworkClient() + .fetch( + new FetchOptions.Builder(longPollWithStreamPosition, "GET") + .responseFormat(ResponseFormat.JSON) + .auth(eventsManager.getAuth()) + .networkSession(eventsManager.getNetworkSession()) + .headers(headers) + .build()); + + if (stopped || stopLatch.getCount() == 0) { + return EventStreamAction.STOP; + } + + if (response.getStatus() == 200 && response.getData() != null) { + JsonNode message = response.getData(); + String messageText = message.has("message") ? message.get("message").asText() : null; + + if (RealtimeServerEvent.NEW_CHANGE.getValue().equals(messageText)) { + return EventStreamAction.FETCH_EVENTS; + } else if (RealtimeServerEvent.RECONNECT.getValue().equals(messageText)) { + return EventStreamAction.RECONNECT; + } + } + return EventStreamAction.RETRY; + } catch (Exception e) { + if (!stopped && stopLatch.getCount() > 0) { + return EventStreamAction.RETRY; + } + return EventStreamAction.STOP; + } + } + + private void fetchEvents() throws BoxSDKError { + if (stopped || stopLatch.getCount() == 0) { + return; + } + + try { + GetEventsQueryParams.Builder fetchParamsBuilder = + new GetEventsQueryParams.Builder().streamPosition(streamPosition); + + if (queryParams.getLimit() != null) { + fetchParamsBuilder.limit(queryParams.getLimit()); + } + if (queryParams.getCreatedAfter() != null) { + fetchParamsBuilder.createdAfter(queryParams.getCreatedAfter()); + } + if (queryParams.getCreatedBefore() != null) { + fetchParamsBuilder.createdBefore(queryParams.getCreatedBefore()); + } + + if (queryParams.getStreamType() != null) { + String streamTypeValue = queryParams.getStreamType().getValue(); + GetEventsQueryParamsStreamTypeField streamType = convertStreamType(streamTypeValue); + fetchParamsBuilder.streamType(streamType); + } + + List eventTypes = + queryParams.getEventType() != null + ? queryParams.getEventType().stream() + .map(enumWrapper -> convertEventType(enumWrapper.getValue())) + .collect(Collectors.toList()) + : null; + if (eventTypes != null) { + fetchParamsBuilder.eventType(eventTypes); + } + + GetEventsQueryParams fetchParams = fetchParamsBuilder.build(); + GetEventsHeaders fetchHeaders = + new GetEventsHeaders.Builder() + .extraHeaders( + headersInput.getExtraHeaders() != null + ? headersInput.getExtraHeaders() + : new HashMap<>()) + .build(); + + Events events = eventsManager.getEvents(fetchParams, fetchHeaders); + if (events.getEntries() != null && !events.getEntries().isEmpty()) { + for (Event event : events.getEntries()) { + String eventId = event.getEventId(); + if (eventId != null && !dedupHash.containsKey(eventId)) { + dedupHash.put(eventId, true); + if (stopped || stopLatch.getCount() == 0) { + return; + } + eventQueue.add(event); + } + } + } + + streamPosition = + events.getNextStreamPosition() != null + ? (events.getNextStreamPosition().isString() + ? events.getNextStreamPosition().getString() + : String.valueOf(events.getNextStreamPosition().getLongNumber())) + : "now"; + + if (dedupHash.size() >= DEDUPLICATION_SIZE) { + dedupHash.clear(); + for (Event event : events.getEntries()) { + String eventId = event.getEventId(); + if (eventId != null) { + dedupHash.put(eventId, true); + } + } + } + } catch (Exception e) { + if (!stopped && stopLatch.getCount() > 0) { + if (e instanceof BoxSDKError) { + throw (BoxSDKError) e; + } else { + throw new BoxSDKError( + "Failed to fetch events: " + (e.getMessage() != null ? e.getMessage() : ""), e); + } + } + } + } + + private GetEventsQueryParamsStreamTypeField convertStreamType(String streamTypeValue) { + if (streamTypeValue == null) return null; + try { + return GetEventsQueryParamsStreamTypeField.valueOf( + streamTypeValue.toUpperCase().replace(" ", "_")); + } catch (IllegalArgumentException e) { + throw new BoxSDKError("Invalid stream type: " + streamTypeValue); + } + } + + private Valuable convertEventType(String eventTypeValue) { + if (eventTypeValue == null) return null; + try { + return GetEventsQueryParamsEventTypeField.valueOf( + eventTypeValue.toUpperCase().replace(" ", "_")); + } catch (IllegalArgumentException e) { + throw new BoxSDKError("Invalid event type: " + eventTypeValue); + } + } +} diff --git a/src/main/java/com/box/sdkgen/managers/events/EventsManager.java b/src/main/java/com/box/sdkgen/managers/events/EventsManager.java index 6c608b7c8..fe891c60c 100644 --- a/src/main/java/com/box/sdkgen/managers/events/EventsManager.java +++ b/src/main/java/com/box/sdkgen/managers/events/EventsManager.java @@ -6,6 +6,7 @@ import static com.box.sdkgen.internal.utils.UtilsManager.mergeMaps; import static com.box.sdkgen.internal.utils.UtilsManager.prepareParams; +import com.box.sdkgen.box.eventstream.EventStream; import com.box.sdkgen.networking.auth.Authentication; import com.box.sdkgen.networking.fetchoptions.FetchOptions; import com.box.sdkgen.networking.fetchoptions.ResponseFormat; @@ -93,6 +94,23 @@ public Events getEvents(GetEventsQueryParams queryParams, GetEventsHeaders heade return JsonManager.deserialize(response.getData(), Events.class); } + public EventStream getEventStream() { + return getEventStream(new GetEventStreamQueryParams(), new GetEventStreamHeaders()); + } + + public EventStream getEventStream(GetEventStreamQueryParams queryParams) { + return getEventStream(queryParams, new GetEventStreamHeaders()); + } + + public EventStream getEventStream(GetEventStreamHeaders headers) { + return getEventStream(new GetEventStreamQueryParams(), headers); + } + + public EventStream getEventStream( + GetEventStreamQueryParams queryParams, GetEventStreamHeaders headers) { + return new EventStream.Builder(this, queryParams).headersInput(headers).build(); + } + public Authentication getAuth() { return auth; } diff --git a/src/main/java/com/box/sdkgen/managers/events/GetEventStreamHeaders.java b/src/main/java/com/box/sdkgen/managers/events/GetEventStreamHeaders.java new file mode 100644 index 000000000..527cbfced --- /dev/null +++ b/src/main/java/com/box/sdkgen/managers/events/GetEventStreamHeaders.java @@ -0,0 +1,40 @@ +package com.box.sdkgen.managers.events; + +import static com.box.sdkgen.internal.utils.UtilsManager.mapOf; + +import java.util.Map; + +public class GetEventStreamHeaders { + + public Map extraHeaders; + + public GetEventStreamHeaders() { + this.extraHeaders = mapOf(); + } + + protected GetEventStreamHeaders(Builder builder) { + this.extraHeaders = builder.extraHeaders; + } + + public Map getExtraHeaders() { + return extraHeaders; + } + + public static class Builder { + + protected Map extraHeaders; + + public Builder() { + this.extraHeaders = mapOf(); + } + + public Builder extraHeaders(Map extraHeaders) { + this.extraHeaders = extraHeaders; + return this; + } + + public GetEventStreamHeaders build() { + return new GetEventStreamHeaders(this); + } + } +} diff --git a/src/main/java/com/box/sdkgen/managers/events/GetEventStreamQueryParams.java b/src/main/java/com/box/sdkgen/managers/events/GetEventStreamQueryParams.java new file mode 100644 index 000000000..afb1b1821 --- /dev/null +++ b/src/main/java/com/box/sdkgen/managers/events/GetEventStreamQueryParams.java @@ -0,0 +1,175 @@ +package com.box.sdkgen.managers.events; + +import com.box.sdkgen.serialization.json.EnumWrapper; +import com.box.sdkgen.serialization.json.Valuable; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +public class GetEventStreamQueryParams { + + public EnumWrapper streamType; + + public String streamPosition; + + public Long limit; + + public List> eventType; + + public Date createdAfter; + + public Date createdBefore; + + public GetEventStreamQueryParams() {} + + protected GetEventStreamQueryParams(Builder builder) { + this.streamType = builder.streamType; + this.streamPosition = builder.streamPosition; + this.limit = builder.limit; + this.eventType = builder.eventType; + this.createdAfter = builder.createdAfter; + this.createdBefore = builder.createdBefore; + } + + public EnumWrapper getStreamType() { + return streamType; + } + + public String getStreamPosition() { + return streamPosition; + } + + public Long getLimit() { + return limit; + } + + public List> getEventType() { + return eventType; + } + + public Date getCreatedAfter() { + return createdAfter; + } + + public Date getCreatedBefore() { + return createdBefore; + } + + public static class Builder { + + protected EnumWrapper streamType; + + protected String streamPosition; + + protected Long limit; + + protected List> eventType; + + protected Date createdAfter; + + protected Date createdBefore; + + public Builder streamType(GetEventStreamQueryParamsStreamTypeField streamType) { + this.streamType = new EnumWrapper(streamType); + return this; + } + + public Builder streamType(EnumWrapper streamType) { + this.streamType = streamType; + return this; + } + + public Builder streamPosition(String streamPosition) { + this.streamPosition = streamPosition; + return this; + } + + public Builder limit(Long limit) { + this.limit = limit; + return this; + } + + public Builder eventType(List eventType) { + this.eventType = + EnumWrapper.wrapValuableEnumList( + eventType, GetEventStreamQueryParamsEventTypeField.class); + return this; + } + + public Builder createdAfter(Date createdAfter) { + this.createdAfter = createdAfter; + return this; + } + + public Builder createdBefore(Date createdBefore) { + this.createdBefore = createdBefore; + return this; + } + + public GetEventStreamQueryParams build() { + return new GetEventStreamQueryParams(this); + } + } + + public static class EventTypeDeserializer + extends JsonDeserializer>> { + + public final JsonDeserializer> + elementDeserializer; + + public EventTypeDeserializer() { + super(); + this.elementDeserializer = + new GetEventStreamQueryParamsEventTypeField + .GetEventStreamQueryParamsEventTypeFieldDeserializer(); + } + + @Override + public List> deserialize( + JsonParser p, DeserializationContext ctxt) throws IOException { + JsonNode node = p.getCodec().readTree(p); + List> elements = new ArrayList<>(); + for (JsonNode item : node) { + JsonParser pa = item.traverse(p.getCodec()); + pa.nextToken(); + elements.add(elementDeserializer.deserialize(pa, ctxt)); + } + return elements; + } + } + + public static class EventTypeSerializer + extends JsonSerializer>> { + + public final JsonSerializer> + elementSerializer; + + public EventTypeSerializer() { + super(); + this.elementSerializer = + new GetEventStreamQueryParamsEventTypeField + .GetEventStreamQueryParamsEventTypeFieldSerializer(); + } + + @Override + public void serialize( + List> value, + JsonGenerator gen, + SerializerProvider serializers) + throws IOException { + gen.writeStartArray(); + for (EnumWrapper item : value) { + elementSerializer.serialize(item, gen, serializers); + } + gen.writeEndArray(); + } + } +} diff --git a/src/main/java/com/box/sdkgen/managers/events/GetEventStreamQueryParamsEventTypeField.java b/src/main/java/com/box/sdkgen/managers/events/GetEventStreamQueryParamsEventTypeField.java new file mode 100644 index 000000000..9658150d4 --- /dev/null +++ b/src/main/java/com/box/sdkgen/managers/events/GetEventStreamQueryParamsEventTypeField.java @@ -0,0 +1,176 @@ +package com.box.sdkgen.managers.events; + +import com.box.sdkgen.serialization.json.EnumWrapper; +import com.box.sdkgen.serialization.json.Valuable; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; +import java.io.IOException; +import java.util.Arrays; + +public enum GetEventStreamQueryParamsEventTypeField implements Valuable { + ACCESS_GRANTED("ACCESS_GRANTED"), + ACCESS_REVOKED("ACCESS_REVOKED"), + ADD_DEVICE_ASSOCIATION("ADD_DEVICE_ASSOCIATION"), + ADD_LOGIN_ACTIVITY_DEVICE("ADD_LOGIN_ACTIVITY_DEVICE"), + ADMIN_LOGIN("ADMIN_LOGIN"), + APPLICATION_CREATED("APPLICATION_CREATED"), + APPLICATION_PUBLIC_KEY_ADDED("APPLICATION_PUBLIC_KEY_ADDED"), + APPLICATION_PUBLIC_KEY_DELETED("APPLICATION_PUBLIC_KEY_DELETED"), + CHANGE_ADMIN_ROLE("CHANGE_ADMIN_ROLE"), + CHANGE_FOLDER_PERMISSION("CHANGE_FOLDER_PERMISSION"), + COLLABORATION_ACCEPT("COLLABORATION_ACCEPT"), + COLLABORATION_EXPIRATION("COLLABORATION_EXPIRATION"), + COLLABORATION_INVITE("COLLABORATION_INVITE"), + COLLABORATION_REMOVE("COLLABORATION_REMOVE"), + COLLABORATION_ROLE_CHANGE("COLLABORATION_ROLE_CHANGE"), + COMMENT_CREATE("COMMENT_CREATE"), + COMMENT_DELETE("COMMENT_DELETE"), + CONTENT_WORKFLOW_ABNORMAL_DOWNLOAD_ACTIVITY("CONTENT_WORKFLOW_ABNORMAL_DOWNLOAD_ACTIVITY"), + CONTENT_WORKFLOW_AUTOMATION_ADD("CONTENT_WORKFLOW_AUTOMATION_ADD"), + CONTENT_WORKFLOW_AUTOMATION_DELETE("CONTENT_WORKFLOW_AUTOMATION_DELETE"), + CONTENT_WORKFLOW_POLICY_ADD("CONTENT_WORKFLOW_POLICY_ADD"), + CONTENT_WORKFLOW_SHARING_POLICY_VIOLATION("CONTENT_WORKFLOW_SHARING_POLICY_VIOLATION"), + CONTENT_WORKFLOW_UPLOAD_POLICY_VIOLATION("CONTENT_WORKFLOW_UPLOAD_POLICY_VIOLATION"), + COPY("COPY"), + DATA_RETENTION_CREATE_RETENTION("DATA_RETENTION_CREATE_RETENTION"), + DATA_RETENTION_REMOVE_RETENTION("DATA_RETENTION_REMOVE_RETENTION"), + DELETE("DELETE"), + DELETE_USER("DELETE_USER"), + DEVICE_TRUST_CHECK_FAILED("DEVICE_TRUST_CHECK_FAILED"), + DOWNLOAD("DOWNLOAD"), + EDIT("EDIT"), + EDIT_USER("EDIT_USER"), + EMAIL_ALIAS_CONFIRM("EMAIL_ALIAS_CONFIRM"), + EMAIL_ALIAS_REMOVE("EMAIL_ALIAS_REMOVE"), + ENTERPRISE_APP_AUTHORIZATION_UPDATE("ENTERPRISE_APP_AUTHORIZATION_UPDATE"), + EXTERNAL_COLLAB_SECURITY_SETTINGS("EXTERNAL_COLLAB_SECURITY_SETTINGS"), + FAILED_LOGIN("FAILED_LOGIN"), + FILE_MARKED_MALICIOUS("FILE_MARKED_MALICIOUS"), + FILE_WATERMARKED_DOWNLOAD("FILE_WATERMARKED_DOWNLOAD"), + GROUP_ADD_ITEM("GROUP_ADD_ITEM"), + GROUP_ADD_USER("GROUP_ADD_USER"), + GROUP_CREATION("GROUP_CREATION"), + GROUP_DELETION("GROUP_DELETION"), + GROUP_EDITED("GROUP_EDITED"), + GROUP_REMOVE_ITEM("GROUP_REMOVE_ITEM"), + GROUP_REMOVE_USER("GROUP_REMOVE_USER"), + ITEM_EMAIL_SEND("ITEM_EMAIL_SEND"), + ITEM_MODIFY("ITEM_MODIFY"), + ITEM_OPEN("ITEM_OPEN"), + ITEM_SHARED_UPDATE("ITEM_SHARED_UPDATE"), + ITEM_SYNC("ITEM_SYNC"), + ITEM_UNSYNC("ITEM_UNSYNC"), + LEGAL_HOLD_ASSIGNMENT_CREATE("LEGAL_HOLD_ASSIGNMENT_CREATE"), + LEGAL_HOLD_ASSIGNMENT_DELETE("LEGAL_HOLD_ASSIGNMENT_DELETE"), + LEGAL_HOLD_POLICY_CREATE("LEGAL_HOLD_POLICY_CREATE"), + LEGAL_HOLD_POLICY_DELETE("LEGAL_HOLD_POLICY_DELETE"), + LEGAL_HOLD_POLICY_UPDATE("LEGAL_HOLD_POLICY_UPDATE"), + LOCK("LOCK"), + LOGIN("LOGIN"), + METADATA_INSTANCE_CREATE("METADATA_INSTANCE_CREATE"), + METADATA_INSTANCE_DELETE("METADATA_INSTANCE_DELETE"), + METADATA_INSTANCE_UPDATE("METADATA_INSTANCE_UPDATE"), + METADATA_TEMPLATE_CREATE("METADATA_TEMPLATE_CREATE"), + METADATA_TEMPLATE_DELETE("METADATA_TEMPLATE_DELETE"), + METADATA_TEMPLATE_UPDATE("METADATA_TEMPLATE_UPDATE"), + MOVE("MOVE"), + NEW_USER("NEW_USER"), + OAUTH2_ACCESS_TOKEN_REVOKE("OAUTH2_ACCESS_TOKEN_REVOKE"), + PREVIEW("PREVIEW"), + REMOVE_DEVICE_ASSOCIATION("REMOVE_DEVICE_ASSOCIATION"), + REMOVE_LOGIN_ACTIVITY_DEVICE("REMOVE_LOGIN_ACTIVITY_DEVICE"), + RENAME("RENAME"), + RETENTION_POLICY_ASSIGNMENT_ADD("RETENTION_POLICY_ASSIGNMENT_ADD"), + SHARE("SHARE"), + SHARED_LINK_SEND("SHARED_LINK_SEND"), + SHARE_EXPIRATION("SHARE_EXPIRATION"), + SHIELD_ALERT("SHIELD_ALERT"), + SHIELD_EXTERNAL_COLLAB_ACCESS_BLOCKED("SHIELD_EXTERNAL_COLLAB_ACCESS_BLOCKED"), + SHIELD_EXTERNAL_COLLAB_ACCESS_BLOCKED_MISSING_JUSTIFICATION( + "SHIELD_EXTERNAL_COLLAB_ACCESS_BLOCKED_MISSING_JUSTIFICATION"), + SHIELD_EXTERNAL_COLLAB_INVITE_BLOCKED("SHIELD_EXTERNAL_COLLAB_INVITE_BLOCKED"), + SHIELD_EXTERNAL_COLLAB_INVITE_BLOCKED_MISSING_JUSTIFICATION( + "SHIELD_EXTERNAL_COLLAB_INVITE_BLOCKED_MISSING_JUSTIFICATION"), + SHIELD_JUSTIFICATION_APPROVAL("SHIELD_JUSTIFICATION_APPROVAL"), + SHIELD_SHARED_LINK_ACCESS_BLOCKED("SHIELD_SHARED_LINK_ACCESS_BLOCKED"), + SHIELD_SHARED_LINK_STATUS_RESTRICTED_ON_CREATE("SHIELD_SHARED_LINK_STATUS_RESTRICTED_ON_CREATE"), + SHIELD_SHARED_LINK_STATUS_RESTRICTED_ON_UPDATE("SHIELD_SHARED_LINK_STATUS_RESTRICTED_ON_UPDATE"), + SIGN_DOCUMENT_ASSIGNED("SIGN_DOCUMENT_ASSIGNED"), + SIGN_DOCUMENT_CANCELLED("SIGN_DOCUMENT_CANCELLED"), + SIGN_DOCUMENT_COMPLETED("SIGN_DOCUMENT_COMPLETED"), + SIGN_DOCUMENT_CONVERTED("SIGN_DOCUMENT_CONVERTED"), + SIGN_DOCUMENT_CREATED("SIGN_DOCUMENT_CREATED"), + SIGN_DOCUMENT_DECLINED("SIGN_DOCUMENT_DECLINED"), + SIGN_DOCUMENT_EXPIRED("SIGN_DOCUMENT_EXPIRED"), + SIGN_DOCUMENT_SIGNED("SIGN_DOCUMENT_SIGNED"), + SIGN_DOCUMENT_VIEWED_BY_SIGNED("SIGN_DOCUMENT_VIEWED_BY_SIGNED"), + SIGNER_DOWNLOADED("SIGNER_DOWNLOADED"), + SIGNER_FORWARDED("SIGNER_FORWARDED"), + STORAGE_EXPIRATION("STORAGE_EXPIRATION"), + TASK_ASSIGNMENT_CREATE("TASK_ASSIGNMENT_CREATE"), + TASK_ASSIGNMENT_DELETE("TASK_ASSIGNMENT_DELETE"), + TASK_ASSIGNMENT_UPDATE("TASK_ASSIGNMENT_UPDATE"), + TASK_CREATE("TASK_CREATE"), + TASK_UPDATE("TASK_UPDATE"), + TERMS_OF_SERVICE_ACCEPT("TERMS_OF_SERVICE_ACCEPT"), + TERMS_OF_SERVICE_REJECT("TERMS_OF_SERVICE_REJECT"), + UNDELETE("UNDELETE"), + UNLOCK("UNLOCK"), + UNSHARE("UNSHARE"), + UPDATE_COLLABORATION_EXPIRATION("UPDATE_COLLABORATION_EXPIRATION"), + UPDATE_SHARE_EXPIRATION("UPDATE_SHARE_EXPIRATION"), + UPLOAD("UPLOAD"), + USER_AUTHENTICATE_OAUTH2_ACCESS_TOKEN_CREATE("USER_AUTHENTICATE_OAUTH2_ACCESS_TOKEN_CREATE"), + WATERMARK_LABEL_CREATE("WATERMARK_LABEL_CREATE"), + WATERMARK_LABEL_DELETE("WATERMARK_LABEL_DELETE"); + + private final String value; + + GetEventStreamQueryParamsEventTypeField(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + + public static class GetEventStreamQueryParamsEventTypeFieldDeserializer + extends JsonDeserializer> { + + public GetEventStreamQueryParamsEventTypeFieldDeserializer() { + super(); + } + + @Override + public EnumWrapper deserialize( + JsonParser p, DeserializationContext ctxt) throws IOException { + String value = p.getValueAsString(); + return Arrays.stream(GetEventStreamQueryParamsEventTypeField.values()) + .filter((v) -> v.getValue().equalsIgnoreCase(value)) + .findFirst() + .map(EnumWrapper::new) + .orElse(new EnumWrapper(value)); + } + } + + public static class GetEventStreamQueryParamsEventTypeFieldSerializer + extends JsonSerializer> { + + public GetEventStreamQueryParamsEventTypeFieldSerializer() { + super(); + } + + @Override + public void serialize( + EnumWrapper value, + JsonGenerator gen, + SerializerProvider serializers) + throws IOException { + gen.writeString(value.getStringValue()); + } + } +} diff --git a/src/main/java/com/box/sdkgen/managers/events/GetEventStreamQueryParamsStreamTypeField.java b/src/main/java/com/box/sdkgen/managers/events/GetEventStreamQueryParamsStreamTypeField.java new file mode 100644 index 000000000..6521cd10e --- /dev/null +++ b/src/main/java/com/box/sdkgen/managers/events/GetEventStreamQueryParamsStreamTypeField.java @@ -0,0 +1,66 @@ +package com.box.sdkgen.managers.events; + +import com.box.sdkgen.serialization.json.EnumWrapper; +import com.box.sdkgen.serialization.json.Valuable; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; +import java.io.IOException; +import java.util.Arrays; + +public enum GetEventStreamQueryParamsStreamTypeField implements Valuable { + ALL("all"), + CHANGES("changes"), + SYNC("sync"), + ADMIN_LOGS("admin_logs"), + ADMIN_LOGS_STREAMING("admin_logs_streaming"); + + private final String value; + + GetEventStreamQueryParamsStreamTypeField(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + + public static class GetEventStreamQueryParamsStreamTypeFieldDeserializer + extends JsonDeserializer> { + + public GetEventStreamQueryParamsStreamTypeFieldDeserializer() { + super(); + } + + @Override + public EnumWrapper deserialize( + JsonParser p, DeserializationContext ctxt) throws IOException { + String value = p.getValueAsString(); + return Arrays.stream(GetEventStreamQueryParamsStreamTypeField.values()) + .filter((v) -> v.getValue().equalsIgnoreCase(value)) + .findFirst() + .map(EnumWrapper::new) + .orElse(new EnumWrapper(value)); + } + } + + public static class GetEventStreamQueryParamsStreamTypeFieldSerializer + extends JsonSerializer> { + + public GetEventStreamQueryParamsStreamTypeFieldSerializer() { + super(); + } + + @Override + public void serialize( + EnumWrapper value, + JsonGenerator gen, + SerializerProvider serializers) + throws IOException { + gen.writeString(value.getStringValue()); + } + } +} diff --git a/src/test/java/com/box/sdkgen/test/events/EventsITest.java b/src/test/java/com/box/sdkgen/test/events/EventsITest.java index 6d1044b0f..2dcb534fa 100644 --- a/src/test/java/com/box/sdkgen/test/events/EventsITest.java +++ b/src/test/java/com/box/sdkgen/test/events/EventsITest.java @@ -5,6 +5,7 @@ import static com.box.sdkgen.internal.utils.UtilsManager.getEpochTimeInSeconds; import static com.box.sdkgen.test.commons.CommonsManager.getDefaultClient; +import com.box.sdkgen.box.eventstream.EventStream; import com.box.sdkgen.client.BoxClient; import com.box.sdkgen.managers.events.GetEventsQueryParams; import com.box.sdkgen.managers.events.GetEventsQueryParamsEventTypeField; @@ -109,4 +110,10 @@ public void testGetEventsWithDateFilters() { .build()); assert servers.getEntries().size() == 1; } + + @Test + public void testGetEventStream() { + EventStream eventStream = client.getEvents().getEventStream(); + assert !(eventStream == null); + } }