diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index df9fe6b14..d8b2918be 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,2 +1,2 @@ # https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners -* @asein-sinch @JPPortier @matsk-sinch @rpredescu-sinch @edu-sinch @Hurus111 +* @asein-sinch @JPPortier @matsk-sinch @edu-sinch @Hurus111 @marcos-sinch diff --git a/.github/workflows/generate-upload-documentation.yml b/.github/workflows/generate-upload-documentation.yml new file mode 100644 index 000000000..b2a5fd038 --- /dev/null +++ b/.github/workflows/generate-upload-documentation.yml @@ -0,0 +1,78 @@ +name: Generate and upload documentation + +on: + release: + types: [published] + workflow_dispatch: + inputs: + version: + description: 'Version to use for the documentation package in semver format (e.g. 1.2.3)' + required: true + +jobs: + upload-documentation: + runs-on: ubuntu-latest + env: + SDK_NAME: sinch-sdk-java + + steps: + - name: Checkout Code + uses: actions/checkout@v4 + + - name: Resolve Version + id: version + run: | + if [ "${{ github.event_name }}" = "release" ]; then + VERSION="${{ github.event.release.tag_name }}" + else + VERSION="${{ inputs.version }}" + fi + # Strip leading 'v' if present (e.g. v1.2.3 → 1.2.3) + VERSION="${VERSION#v}" + echo "value=${VERSION}" >> "$GITHUB_OUTPUT" + + - name: Validate Version Format + run: | + VERSION="${{ steps.version.outputs.value }}" + SEMVER_REGEX='^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(-((alpha|beta|preview)(\.[0-9]+)?))?$' + if [[ ! "$VERSION" =~ $SEMVER_REGEX ]]; then + echo "::error::Invalid version format: '$VERSION'. Expected semver (e.g. 1.2.3, 1.2.3-alpha, 1.2.3-beta.1, 1.2.3-preview)" + exit 1 + fi + echo "Version '$VERSION' is valid" + + - name: Setup Java SDK + uses: actions/setup-java@v4 + with: + java-version: '21' + distribution: 'temurin' + cache: maven + + - name: Generate Documentation + run: mvn -B javadoc:javadoc --file pom.xml + + - name: Package Documentation + run: | + cd target/site/apidocs + zip -r "../../../${{ env.SDK_NAME }}-${{ steps.version.outputs.value }}.zip" . + + - name: Upload to GitLab Registry + run: | + echo "Uploading documentation package to GitLab Registry..." + VERSION="${{ steps.version.outputs.value }}" + curl --fail --show-error --location --header "PRIVATE-TOKEN: ${{ secrets.GITLAB_REGISTRY_UPLOAD_DOC_TOKEN }}" \ + --upload-file "./${{ env.SDK_NAME }}-${VERSION}.zip" \ + "https://gitlab.com/api/v4/projects/63164411/packages/generic/${{ env.SDK_NAME }}/${VERSION}/${{ env.SDK_NAME }}-${VERSION}.zip" + echo "Documentation package for version ${VERSION} uploaded to GitLab Registry" + + - name: Trigger Downstream GitLab Pipeline + run: | + echo "Triggering downstream GitLab pipeline to notify about new documentation package version..." + VERSION="${{ steps.version.outputs.value }}" + curl --fail --show-error --location --request POST \ + --form "token=${{ secrets.GITLAB_NOTIFY_REGISTRY_UPLOADED_DOC_TOKEN }}" \ + --form "ref=main" \ + --form "variables[UPSTREAM_PACKAGE_NAME]=${{ env.SDK_NAME }}" \ + --form "variables[UPSTREAM_PACKAGE_VERSION]=${VERSION}" \ + "https://gitlab.com/api/v4/projects/63164411/trigger/pipeline" + echo "Documentation repo notified about new package version ${VERSION}" diff --git a/CHANGELOG.md b/CHANGELOG.md index 7683628b2..4bd0d8b31 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,36 @@ All notable changes to the **Sinch Java SDK** are documented in this file. --- +## v2.1 – 2026-07-02 + +### Numbers +- Extend `NumberSinchEvents` class. + - **[fix]** `EventTypeEnum`: `DEPROVISIONING_TO_VOICE_PLATFORM` is deprecated and has to be replaced by `DEPROVISIONING_FROM_VOICE_PLATFORM`. + - **[feature]** Support new `internalFailureCode` field. + - **[feature]** Support new `StatusEnum` values: `IN_REVIEW`, `BLOCKED`, `COMPLETED`, `REJECTED`, `EXPIRED`. + - **[feature]** Support new `EventTypeEnum` value: `NUMBER_ORDER_PROCESSING`. + +### Conversation +- **[feature]** Support `Consents` API: `listIdentities` and `listAuditRecords` endpoints + +### Number Lookup +- **[feature]** Support `Number Lookup` API V2 + +### SDK +- **[feature]** HTTP proxy support: configure an unauthenticated or authenticated (Basic) proxy via `HttpProxyConfiguration` +- **[feature]** `SinchClient` exposes a `close()` method to shut down the underlying HTTP connection pool and release all associated resources deterministically +- **[fix]** `HttpClientApache`: declare now `headersToBeAdded` as `volatile` to guarantee visibility across threads in concurrent usage +- **[fix]** `HttpClientApache`: wrap response-body `Scanner` in a try-with-resources block to prevent resource leaks; gracefully handle empty (`null`) response entities +- **[fix]** `SinchClient`: guard against a `NullPointerException` when `java.vendor` system property is absent while building the `User-Agent` auxiliary flag +- **[fix]** `Configuration`: correct copy-paste error in `toString()` and Javadoc — `conversationContext` label was incorrectly attributed to the Voice domain +- **[doc]** Improve README structure and content. + + +### Examples / Snippets +- **[doc]** Fix typos in `conversation/conversations/Create` and `voice/applications/GetEventDestinations` snippets + +--- + ## v2.0 – 2026-03-31 ### Major breaking changes with major release diff --git a/README.md b/README.md index f4a4e141b..c65232c8c 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,7 @@ For more information on the SDK, refer to the dedicated [Java SDK documentation - [Getting started](#getting-started) - [Logging](#logging) - [Handling Exceptions](#handling-exceptions) +- [Proxy configuration](#proxy-configuration) - [Third-party dependencies](#third-party-dependencies) - [Examples](#examples) - [Changelog and Migration](#changelog--migration) @@ -61,6 +62,7 @@ Note: The `${sdk.version}` needs to be set according to the released version to | Voice and Video | [Voice API](https://developers.sinch.com/docs/voice/) | | Numbers | [Numbers API](https://developers.sinch.com/docs/numbers/) | | Verification | [Verification API](https://developers.sinch.com/docs/verification/) | +| | [Number Lookup API](https://developers.sinch.com/docs/number-lookup/) | > **Note:** The SMS API is end-of-sale. New integrations should use the [Conversation API](https://developers.sinch.com/docs/conversation/) instead, which supports SMS and many other channels. @@ -226,6 +228,10 @@ NumberSinchEvent event = sinchEvents.parseEvent(body); You can find a complete example in [examples/sinch-events](examples/sinch-events). +### Number Lookup API + +The Number Lookup API needs no extra parameters, use the [common client](#client-initialization) shown above. + ### Verification API The Verification API uses application credentials. Set `applicationKey` and `applicationSecret`, both available on the [Apps dashboard](https://dashboard.sinch.com/verification/apps): @@ -392,6 +398,54 @@ try { - `ApiAuthException`: authentication/authorization failures. - `ApiMappingException`: the response payload could not be deserialized into the expected type. +## Proxy configuration + +If your network environment routes outbound traffic through an HTTP proxy, provide proxy +configuration via [HttpProxyConfiguration](client/src/main/com/sinch/sdk/models/HttpProxyConfiguration.java) on the [Configuration](client/src/main/com/sinch/sdk/models/Configuration.java) builder. + +When used, all connections will go through the proxy (including OAuth). + +**Unauthenticated proxy:** + +```java +import com.sinch.sdk.SinchClient; +import com.sinch.sdk.models.Configuration; +import com.sinch.sdk.models.HttpProxyConfiguration; + +... +Configuration configuration = Configuration.builder() + .setKeyId(PARAM_KEY_ID) + .setKeySecret(PARAM_KEY_SECRET) + .setProjectId(PARAM_PROJECT_ID) + .setHttpProxyConfiguration( + HttpProxyConfiguration.builder() + .setHostname(PARAM_PROXY_HOSTNAME) + .setPort(PARAM_PROXY_PORT) + .build()) + .build(); +SinchClient client = new SinchClient(configuration); +``` + +**Authenticated proxy:** + + +```java +Configuration configuration = Configuration.builder() + .setKeyId(PARAM_KEY_ID) + .setKeySecret(PARAM_KEY_SECRET) + .setProjectId(PARAM_PROJECT_ID) + .setHttpProxyConfiguration( + HttpProxyConfiguration.builder() + .setHostname(PARAM_PROXY_HOSTNAME) + .setPort(PARAM_PROXY_PORT) + .setUsername(PARAM_PROXY_USERNAME) + // prefer char[] over String to reduce password exposure in heap memory + .setPassword(PARAM_PROXY_PASSWORD_AS_CHAR_ARRAY) + .build()) + .build(); +SinchClient client = new SinchClient(configuration); +``` + ## Third-party dependencies The SDK relies on the following third-party dependencies: @@ -435,11 +489,11 @@ Note: Replace `VERSION-YOU-WANT-TO-BE-USED` with a Jackson version of at least ` ## Examples You can find: - - self-contained code snippets covering every API operation in the [examples/snippets](./examples/snippets) folder. - - getting started guides for specific use cases in the [examples/getting-started](./examples/getting-started) folder. - - a Spring Boot server template to process received Sinch Events in the [examples/sinch-events](./examples/sinch-events) folder. - - an SDK client template application in the [examples/client](./examples/client) folder. - - step-by-step tutorials combining multiple SDK features in the [examples/tutorials](./examples/tutorials) folder. +- self-contained code snippets covering every API operation in the [examples/snippets](./examples/snippets) folder. +- getting started guides for specific use cases in the [examples/getting-started](./examples/getting-started) folder. +- a Spring Boot server template to process received Sinch Events in the [examples/sinch-events](./examples/sinch-events) folder. +- an SDK client template application in the [examples/client](./examples/client) folder. +- step-by-step tutorials combining multiple SDK features in the [examples/tutorials](./examples/tutorials) folder. ## Changelog & Migration @@ -452,4 +506,4 @@ This project is licensed under the Apache License. See the [LICENSE](LICENSE) fi ## Contact -Developer Experience engineering team: [team-developer-experience@sinch.com](mailto:team-developer-experience@sinch.com) +Developer Experience engineering team: [team-developer-experience@sinch.com](mailto:team-developer-experience@sinch.com) \ No newline at end of file diff --git a/client/resources/config-default.properties b/client/resources/config-default.properties index 0009c6269..102be6245 100644 --- a/client/resources/config-default.properties +++ b/client/resources/config-default.properties @@ -21,3 +21,5 @@ voice-server-south-east-asia2=https://calling-apse2.api.sinch.com conversation-region= conversation-server=https://%s.conversation.api.sinch.com template-management-conversation-server=https://%s.template.api.sinch.com + +number-lookup-server=https://lookup.api.sinch.com diff --git a/client/src/main/com/sinch/sdk/SDK.java b/client/src/main/com/sinch/sdk/SDK.java index 98d6ab17c..d01900177 100644 --- a/client/src/main/com/sinch/sdk/SDK.java +++ b/client/src/main/com/sinch/sdk/SDK.java @@ -3,6 +3,6 @@ public class SDK { public static final String NAME = "Sinch Java SDK"; - public static final String VERSION = "2.1.0-dev"; + public static final String VERSION = "2.2.0-dev"; public static final String AUXILIARY_FLAG = ""; } diff --git a/client/src/main/com/sinch/sdk/SinchClient.java b/client/src/main/com/sinch/sdk/SinchClient.java index 9e7897162..36a6d6b1b 100644 --- a/client/src/main/com/sinch/sdk/SinchClient.java +++ b/client/src/main/com/sinch/sdk/SinchClient.java @@ -2,6 +2,7 @@ import com.sinch.sdk.core.utils.StringUtil; import com.sinch.sdk.domains.conversation.ConversationService; +import com.sinch.sdk.domains.numberlookup.NumberLookupService; import com.sinch.sdk.domains.numbers.NumbersService; import com.sinch.sdk.domains.sms.SMSService; import com.sinch.sdk.domains.verification.VerificationService; @@ -10,6 +11,7 @@ import com.sinch.sdk.models.Configuration; import com.sinch.sdk.models.ConversationContext; import com.sinch.sdk.models.ConversationRegion; +import com.sinch.sdk.models.NumberLookupContext; import com.sinch.sdk.models.NumbersContext; import com.sinch.sdk.models.SMSRegion; import com.sinch.sdk.models.SmsContext; @@ -19,10 +21,11 @@ import com.sinch.sdk.models.adapters.DualToneMultiFrequencyMapper; import java.io.IOException; import java.io.InputStream; +import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.Objects; import java.util.Properties; +import java.util.logging.Level; import java.util.logging.Logger; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -49,6 +52,8 @@ public class SinchClient { private static final String CONVERSATION_TEMPLATE_SERVER_KEY = "template-management-conversation-server"; + private static final String NUMBER_LOOKUP_SERVER_KEY = "number-lookup-server"; + // sinch-sdk/{sdk_version} ({language}/{language_version}; {implementation_type}; // {auxiliary_flag}) private static final String SDK_USER_AGENT_HEADER = "User-Agent"; @@ -62,6 +67,7 @@ public class SinchClient { private volatile VerificationService verification; private volatile VoiceService voice; private volatile ConversationService conversation; + private volatile NumberLookupService lookup; private volatile HttpClientApache httpClient; /** @@ -87,6 +93,7 @@ public SinchClient(Configuration configuration) { handleDefaultVerificationSettings(configurationGuard, props, builder); handleDefaultVoiceSettings(configurationGuard, props, builder); handleDefaultConversationSettings(configurationGuard, props, builder); + handleDefaultNumberLookupSettings(configurationGuard, props, builder); Configuration newConfiguration = builder.build(); checkConfiguration(newConfiguration); @@ -227,6 +234,23 @@ private void handleDefaultConversationSettings( builder.setConversationContext(contextBuilder.build()); } + private void handleDefaultNumberLookupSettings( + Configuration configuration, Properties props, Configuration.Builder builder) { + + String url = + configuration + .getNumberLookupContext() + .map(NumberLookupContext::getNumberLookupUrl) + .orElse(null); + + if (null == url && props.containsKey(NUMBER_LOOKUP_SERVER_KEY)) { + builder.setNumberLookupContext( + NumberLookupContext.builder() + .setNumberLookupUrl(props.getProperty(NUMBER_LOOKUP_SERVER_KEY)) + .build()); + } + } + /** * Get current configuration * @@ -332,6 +356,23 @@ public ConversationService conversation() { return conversation; } + /** + * Get Number Lookup domain service + * + * @return Return instance onto Number Lookup API service + * @since 2.1 + */ + public NumberLookupService lookup() { + if (null == lookup) { + synchronized (this) { + if (null == lookup) { + lookup = lookupInit(); + } + } + } + return lookup; + } + private void checkConfiguration(Configuration configuration) throws NullPointerException { Objects.requireNonNull(configuration.getOAuthUrl(), "'oauthUrl' cannot be null"); } @@ -383,6 +424,14 @@ private ConversationService conversationInit() { this::getHttpClient); } + private NumberLookupService lookupInit() { + return new com.sinch.sdk.domains.numberlookup.adapters.NumberLookupService( + getConfiguration().getUnifiedCredentials().orElse(null), + getConfiguration().getNumberLookupContext().orElse(null), + getConfiguration().getOAuthServer(), + this::getHttpClient); + } + private Properties handlePropertiesFile(String fileName) { Properties prop = new Properties(); @@ -400,9 +449,7 @@ private HttpClientApache getHttpClient() { synchronized (this) { local = httpClient; if (null == local || local.isClosed()) { - // TODO: by adding a setter, we could imagine having another HTTP client provided - // programmatically or use configuration file referencing another class by name - local = new HttpClientApache(); + local = new HttpClientApache(configuration.getHttpProxyConfiguration().orElse(null)); // set SDK User-Agent String userAgent = formatSdkUserAgentHeader(); @@ -430,15 +477,54 @@ private String formatSdkUserAgentHeader() { } private String formatAuxiliaryFlag() { + return formatAuxiliaryFlag(SDK.AUXILIARY_FLAG); + } - Collection values = Collections.singletonList(System.getProperty("java.vendor")); - - if (!StringUtil.isEmpty(SDK.AUXILIARY_FLAG)) { - values.add(SDK.AUXILIARY_FLAG); + // Package-private to allow unit-testing with an arbitrary flag value + String formatAuxiliaryFlag(String auxiliaryFlag) { + Collection values = new ArrayList<>(); + String vendor = System.getProperty("java.vendor"); + values.add(StringUtil.isEmpty(vendor) ? "" : vendor); + if (!StringUtil.isEmpty(auxiliaryFlag)) { + values.add(auxiliaryFlag); } return String.join(",", values); } + /** + * Releases the underlying HTTP client and its connection pool, and resets all lazily-initialized + * domain services. + * + *

After this call, in-flight requests may be affected by shutdown of the underlying HTTP + * client and are not guaranteed to complete normally. The next API call on any domain service + * will transparently re-initialize both the service and the HTTP client. Idempotent: safe to call + * more than once. + * + *

Any exception thrown by the underlying HTTP client during close is caught and logged at + * WARNING level. + * + * @since 2.1 + */ + public void close() { + synchronized (this) { + HttpClientApache local = httpClient; + httpClient = null; + numbers = null; + sms = null; + verification = null; + voice = null; + conversation = null; + lookup = null; + if (local != null) { + try { + local.close(); + } catch (Exception e) { + LOGGER.log(Level.WARNING, "Exception while closing HTTP client", e); + } + } + } + } + static { LocalLazyInit.init(); } diff --git a/client/src/main/com/sinch/sdk/domains/conversation/api/v1/ConversationService.java b/client/src/main/com/sinch/sdk/domains/conversation/api/v1/ConversationService.java index dd36aec6c..d26ac5d4e 100644 --- a/client/src/main/com/sinch/sdk/domains/conversation/api/v1/ConversationService.java +++ b/client/src/main/com/sinch/sdk/domains/conversation/api/v1/ConversationService.java @@ -98,4 +98,12 @@ public interface ConversationService { * @since 2.0 */ TemplatesService templates(); + + /** + * Consents Service instance + * + * @return service instance for project + * @since 2.1 + */ + ConsentsService consents(); } diff --git a/client/src/main/com/sinch/sdk/domains/conversation/api/v1/adapters/ConversationService.java b/client/src/main/com/sinch/sdk/domains/conversation/api/v1/adapters/ConversationService.java index ce9c0160d..aa6ad3230 100644 --- a/client/src/main/com/sinch/sdk/domains/conversation/api/v1/adapters/ConversationService.java +++ b/client/src/main/com/sinch/sdk/domains/conversation/api/v1/adapters/ConversationService.java @@ -9,6 +9,7 @@ import com.sinch.sdk.core.utils.StringUtil; import com.sinch.sdk.domains.conversation.api.v1.AppsService; import com.sinch.sdk.domains.conversation.api.v1.CapabilityService; +import com.sinch.sdk.domains.conversation.api.v1.ConsentsService; import com.sinch.sdk.domains.conversation.api.v1.ContactsService; import com.sinch.sdk.domains.conversation.api.v1.ConversationsService; import com.sinch.sdk.domains.conversation.api.v1.EventDestinationsService; @@ -66,6 +67,7 @@ public class ConversationService private volatile Map authManagers; private volatile AppsService apps; + private volatile ConsentsService consents; private volatile ContactsService contacts; private volatile MessagesService messages; private volatile ConversationsService conversations; @@ -112,6 +114,24 @@ public AppsService apps() { return this.apps; } + public ConsentsService consents() { + if (null == this.consents) { + synchronized (this) { + if (null == this.consents) { + instanceLazyInit(); + this.consents = + new ConsentsServiceImpl( + httpClientSupplier.get(), + context.getServer(), + authManagers, + HttpMapper.getInstance(), + uriUUID); + } + } + } + return this.consents; + } + public ContactsService contacts() { if (null == this.contacts) { synchronized (this) { diff --git a/client/src/main/com/sinch/sdk/domains/numberlookup/NumberLookupService.java b/client/src/main/com/sinch/sdk/domains/numberlookup/NumberLookupService.java new file mode 100644 index 000000000..0fbda1df4 --- /dev/null +++ b/client/src/main/com/sinch/sdk/domains/numberlookup/NumberLookupService.java @@ -0,0 +1,19 @@ +package com.sinch.sdk.domains.numberlookup; + +/** + * Number Lookup Service + * + * @see https://developers.sinch.com/docs/number-lookup-api-v2 + * @since 2.1 + */ +public interface NumberLookupService { + + /** + * Number Lookup Service V2 + * + * @return V2 service instance for project + * @since 2.1 + */ + com.sinch.sdk.domains.numberlookup.api.v2.NumberLookupService v2(); +} diff --git a/client/src/main/com/sinch/sdk/domains/numberlookup/adapters/NumberLookupService.java b/client/src/main/com/sinch/sdk/domains/numberlookup/adapters/NumberLookupService.java new file mode 100644 index 000000000..4e21d9ac8 --- /dev/null +++ b/client/src/main/com/sinch/sdk/domains/numberlookup/adapters/NumberLookupService.java @@ -0,0 +1,42 @@ +package com.sinch.sdk.domains.numberlookup.adapters; + +import com.sinch.sdk.core.http.HttpClient; +import com.sinch.sdk.core.models.ServerConfiguration; +import com.sinch.sdk.models.NumberLookupContext; +import com.sinch.sdk.models.UnifiedCredentials; +import java.util.function.Supplier; + +public class NumberLookupService implements com.sinch.sdk.domains.numberlookup.NumberLookupService { + + private final UnifiedCredentials credentials; + private final NumberLookupContext context; + private final ServerConfiguration oAuthServer; + private final Supplier httpClientSupplier; + + private volatile com.sinch.sdk.domains.numberlookup.api.v2.NumberLookupService v2; + + public NumberLookupService( + UnifiedCredentials credentials, + NumberLookupContext context, + ServerConfiguration oAuthServer, + Supplier httpClientSupplier) { + this.credentials = credentials; + this.context = context; + this.oAuthServer = oAuthServer; + this.httpClientSupplier = httpClientSupplier; + } + + @Override + public com.sinch.sdk.domains.numberlookup.api.v2.NumberLookupService v2() { + if (null == this.v2) { + synchronized (this) { + if (null == this.v2) { + this.v2 = + new com.sinch.sdk.domains.numberlookup.api.v2.adapters.NumberLookupService( + credentials, context, oAuthServer, httpClientSupplier); + } + } + } + return this.v2; + } +} diff --git a/client/src/main/com/sinch/sdk/domains/numberlookup/api/v2/NumberLookupService.java b/client/src/main/com/sinch/sdk/domains/numberlookup/api/v2/NumberLookupService.java new file mode 100644 index 000000000..52e3df737 --- /dev/null +++ b/client/src/main/com/sinch/sdk/domains/numberlookup/api/v2/NumberLookupService.java @@ -0,0 +1,10 @@ +package com.sinch.sdk.domains.numberlookup.api.v2; + +/** + * Number Lookup Service V2 + * + * @see https://developers.sinch.com/docs/number-lookup-api-v2 + * @since 2.1 + */ +public interface NumberLookupService extends NumberLookupV2Service {} diff --git a/client/src/main/com/sinch/sdk/domains/numberlookup/api/v2/adapters/NumberLookupService.java b/client/src/main/com/sinch/sdk/domains/numberlookup/api/v2/adapters/NumberLookupService.java new file mode 100644 index 000000000..5fdb4dcf8 --- /dev/null +++ b/client/src/main/com/sinch/sdk/domains/numberlookup/api/v2/adapters/NumberLookupService.java @@ -0,0 +1,104 @@ +package com.sinch.sdk.domains.numberlookup.api.v2.adapters; + +import com.sinch.sdk.auth.adapters.OAuthManager; +import com.sinch.sdk.core.exceptions.ApiException; +import com.sinch.sdk.core.http.AuthManager; +import com.sinch.sdk.core.http.HttpClient; +import com.sinch.sdk.core.http.HttpMapper; +import com.sinch.sdk.core.models.ServerConfiguration; +import com.sinch.sdk.core.utils.StringUtil; +import com.sinch.sdk.domains.numberlookup.models.v2.request.NumberLookupRequest; +import com.sinch.sdk.domains.numberlookup.models.v2.response.NumberLookupResponse; +import com.sinch.sdk.models.NumberLookupContext; +import com.sinch.sdk.models.UnifiedCredentials; +import java.util.AbstractMap; +import java.util.Map; +import java.util.Objects; +import java.util.function.Supplier; +import java.util.logging.Logger; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class NumberLookupService + implements com.sinch.sdk.domains.numberlookup.api.v2.NumberLookupService { + + private static final Logger LOGGER = Logger.getLogger(NumberLookupService.class.getName()); + private static final String SECURITY_SCHEME_KEYWORD_NUMBER_LOOKUP = "OAuth2"; + + private final UnifiedCredentials credentials; + private final NumberLookupContext context; + private final ServerConfiguration oAuthServer; + private final Supplier httpClientSupplier; + + private volatile String uriUUID; + private volatile Map authManagers; + + private volatile NumberLookupServiceFacade lookup; + + public NumberLookupService( + UnifiedCredentials credentials, + NumberLookupContext context, + ServerConfiguration oAuthServer, + Supplier httpClientSupplier) { + this.credentials = credentials; + this.context = context; + this.oAuthServer = oAuthServer; + this.httpClientSupplier = httpClientSupplier; + } + + NumberLookupServiceFacade getLookupFacade() { + if (null == this.lookup) { + synchronized (this) { + if (null == this.lookup) { + instanceLazyInit(); + this.lookup = + new NumberLookupServiceFacade(uriUUID, context, httpClientSupplier, authManagers); + } + } + } + return this.lookup; + } + + @Override + public NumberLookupResponse lookup(NumberLookupRequest numberLookupRequest) throws ApiException { + return getLookupFacade().lookup(numberLookupRequest); + } + + private void instanceLazyInit() { + if (null != this.authManagers) { + return; + } + synchronized (this) { + if (null == this.authManagers) { + Objects.requireNonNull( + credentials, "Number Lookup service requires unified credentials to be defined"); + Objects.requireNonNull(context, "Number Lookup service requires context to be defined"); + StringUtil.requireNonEmpty( + credentials.getKeyId(), "Number Lookup service requires 'keyId' to be defined"); + StringUtil.requireNonEmpty( + credentials.getKeySecret(), "Number Lookup service requires 'keySecret' to be defined"); + StringUtil.requireNonEmpty( + credentials.getProjectId(), "Number Lookup service requires 'projectId' to be defined"); + StringUtil.requireNonEmpty( + context.getNumberLookupUrl(), + "Number Lookup service requires 'numberLookupUrl' to be defined"); + + LOGGER.fine( + "Activate Number Lookup API with server='" + + context.getNumberLookupServer().getUrl() + + "'"); + + AuthManager authManager = + new OAuthManager( + credentials, oAuthServer, HttpMapper.getInstance(), httpClientSupplier); + + uriUUID = credentials.getProjectId(); + authManagers = + Stream.of( + new AbstractMap.SimpleEntry<>( + SECURITY_SCHEME_KEYWORD_NUMBER_LOOKUP, authManager)) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + } + } + } +} diff --git a/client/src/main/com/sinch/sdk/domains/numberlookup/api/v2/adapters/NumberLookupServiceFacade.java b/client/src/main/com/sinch/sdk/domains/numberlookup/api/v2/adapters/NumberLookupServiceFacade.java new file mode 100644 index 000000000..14b3aedf1 --- /dev/null +++ b/client/src/main/com/sinch/sdk/domains/numberlookup/api/v2/adapters/NumberLookupServiceFacade.java @@ -0,0 +1,37 @@ +package com.sinch.sdk.domains.numberlookup.api.v2.adapters; + +import com.sinch.sdk.core.exceptions.ApiException; +import com.sinch.sdk.core.http.AuthManager; +import com.sinch.sdk.core.http.HttpClient; +import com.sinch.sdk.core.http.HttpMapper; +import com.sinch.sdk.domains.numberlookup.api.v2.NumberLookupV2Service; +import com.sinch.sdk.domains.numberlookup.models.v2.request.NumberLookupRequest; +import com.sinch.sdk.domains.numberlookup.models.v2.response.NumberLookupResponse; +import com.sinch.sdk.models.NumberLookupContext; +import java.util.Map; +import java.util.function.Supplier; + +final class NumberLookupServiceFacade + implements com.sinch.sdk.domains.numberlookup.api.v2.NumberLookupService { + + private final NumberLookupV2Service lookup; + + NumberLookupServiceFacade( + String uriUUID, + NumberLookupContext context, + Supplier httpClientSupplier, + Map authManagers) { + this.lookup = + new NumberLookupV2ServiceImpl( + httpClientSupplier.get(), + context.getNumberLookupServer(), + authManagers, + HttpMapper.getInstance(), + uriUUID); + } + + @Override + public NumberLookupResponse lookup(NumberLookupRequest numberLookupRequest) throws ApiException { + return lookup.lookup(numberLookupRequest); + } +} diff --git a/client/src/main/com/sinch/sdk/domains/voice/models/v1/svaml/action/ManagedCallSvamlAction.java b/client/src/main/com/sinch/sdk/domains/voice/models/v1/svaml/action/ManagedCallSvamlAction.java new file mode 100644 index 000000000..dbc22d00a --- /dev/null +++ b/client/src/main/com/sinch/sdk/domains/voice/models/v1/svaml/action/ManagedCallSvamlAction.java @@ -0,0 +1,12 @@ +package com.sinch.sdk.domains.voice.models.v1.svaml.action; + +/** + * Base class related to SVAML actions available for managing ongoing, connected calls (updateCall + * and manageCallWithCallLeg). + * + * @see SvamlActionHangup + * @see SvamlActionContinue + * @see SvamlActionPark + * @since 2.1 + */ +public interface ManagedCallSvamlAction {} diff --git a/client/src/main/com/sinch/sdk/http/HttpClientApache.java b/client/src/main/com/sinch/sdk/http/HttpClientApache.java index ed4918628..bf3f1dad2 100644 --- a/client/src/main/com/sinch/sdk/http/HttpClientApache.java +++ b/client/src/main/com/sinch/sdk/http/HttpClientApache.java @@ -16,6 +16,7 @@ import com.sinch.sdk.core.http.URLParameter; import com.sinch.sdk.core.models.ServerConfiguration; import com.sinch.sdk.core.utils.Pair; +import com.sinch.sdk.models.HttpProxyConfiguration; import java.io.File; import java.io.IOException; import java.nio.charset.Charset; @@ -31,14 +32,22 @@ import java.util.Scanner; import java.util.logging.Logger; import java.util.stream.Collectors; +import org.apache.hc.client5.http.ClientProtocolException; +import org.apache.hc.client5.http.HttpResponseException; +import org.apache.hc.client5.http.auth.AuthScope; +import org.apache.hc.client5.http.auth.CredentialsProvider; import org.apache.hc.client5.http.entity.mime.MultipartEntityBuilder; +import org.apache.hc.client5.http.impl.auth.CredentialsProviderBuilder; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.apache.hc.client5.http.impl.classic.HttpClientBuilder; import org.apache.hc.client5.http.impl.classic.HttpClients; +import org.apache.hc.client5.http.impl.routing.DefaultProxyRoutePlanner; import org.apache.hc.core5.http.ClassicHttpRequest; import org.apache.hc.core5.http.ClassicHttpResponse; import org.apache.hc.core5.http.ContentType; import org.apache.hc.core5.http.Header; import org.apache.hc.core5.http.HttpEntity; +import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.io.entity.StringEntity; import org.apache.hc.core5.http.io.support.ClassicRequestBuilder; import org.apache.hc.core5.http.support.AbstractMessageBuilder; @@ -47,12 +56,48 @@ public class HttpClientApache implements com.sinch.sdk.core.http.HttpClient { private static final Logger LOGGER = Logger.getLogger(HttpClientApache.class.getName()); - private Map headersToBeAdded; + /** + * HTTP 407 Proxy Authentication Required. Kept as a local constant to make the guard in {@link + * #invokeAPI} self-documenting and independent of any external enum. + */ + private static final int HTTP_PROXY_AUTHENTICATION_REQUIRED = 407; + + private volatile Map headersToBeAdded; private volatile CloseableHttpClient client; public HttpClientApache() { - this.client = HttpClients.createDefault(); + this(null); + } + + public HttpClientApache(HttpProxyConfiguration proxyConfiguration) { + this.client = buildHttpClient(proxyConfiguration); + } + + private static CloseableHttpClient buildHttpClient(HttpProxyConfiguration proxyConfiguration) { + if (proxyConfiguration == null) { + return HttpClients.createDefault(); + } + + HttpHost proxyHost = + new HttpHost(proxyConfiguration.getHostname(), proxyConfiguration.getPort()); + HttpClientBuilder builder = + HttpClients.custom().setRoutePlanner(new DefaultProxyRoutePlanner(proxyHost)); + + if (proxyConfiguration.getUsername().isPresent()) { + // getPassword() returns a defensive copy of the internal array; HC5 receives that copy and + // owns it for the lifetime of the client. The caller does not need to keep the original + // alive. + CredentialsProvider credentialsProvider = + CredentialsProviderBuilder.create() + .add( + new AuthScope(proxyHost), + proxyConfiguration.getUsername().orElse(""), + proxyConfiguration.getPassword().orElse(new char[0])) + .build(); + builder.setDefaultCredentialsProvider(credentialsProvider); + } + return builder.build(); } public void setRequestHeaders(Map headers) { @@ -71,10 +116,15 @@ private static HttpResponse processResponse(ClassicHttpResponse response) throws } HttpEntity entity = response.getEntity(); - Scanner s = new Scanner(entity.getContent()).useDelimiter("\\A"); - String content = (s.hasNext() ? s.next() : ""); - - return new HttpResponse(statusCode, message, headers, content.getBytes(StandardCharsets.UTF_8)); + if (null == entity) { + return new HttpResponse(statusCode, message, headers, null); + } + try (Scanner s = + new Scanner(entity.getContent(), StandardCharsets.UTF_8.name()).useDelimiter("\\A")) { + String content = (s.hasNext() ? s.next() : ""); + return new HttpResponse( + statusCode, message, headers, content.getBytes(StandardCharsets.UTF_8)); + } } private static Map> transformResponseHeaders(Header[] headers) { @@ -99,6 +149,11 @@ public HttpResponse invokeAPI( HttpRequest httpRequest) throws ApiException { + CloseableHttpClient activeClient = this.client; + if (activeClient == null) { + throw new ApiException("HTTP client has been closed"); + } + try { String path = httpRequest @@ -143,9 +198,23 @@ public HttpResponse invokeAPI( ClassicHttpRequest request = requestBuilder.build(); - HttpResponse response = processRequest(client, request); + HttpResponse response = processRequest(activeClient, request); LOGGER.finest("connection response: " + response); + // HTTP 407 (Proxy Authentication Required) is normally handled transparently by Apache + // HttpClient via DefaultProxyRoutePlanner + CredentialsProvider (the 407→retry cycle + // happens inside processRequest and is invisible to this method). + // If 407 surfaces here it means proxy credentials are absent, wrong, or the proxy uses an + // unsupported auth scheme. Guard explicitly so that the OAuth-refresh block below does NOT + // misfire: some enterprise proxies include a `www-authenticate: Bearer error="expired"` + // header on 407 responses, which would incorrectly trigger an OAuth token reset. + if (response.getCode() == HTTP_PROXY_AUTHENTICATION_REQUIRED) { + LOGGER.warning( + "Proxy authentication required (HTTP 407). " + + "Verify HttpProxyConfiguration hostname, port and credentials."); + return response; + } + // UNAUTHORIZED (HTTP 401) error code could imply refreshing the OAuth token if (response.getCode() == HttpStatus.UNAUTHORIZED) { boolean couldRetryRequest = @@ -154,11 +223,20 @@ public HttpResponse invokeAPI( // refresh authorization addAuth(requestBuilder, authManagersByOasSecuritySchemes, authNames, body); request = requestBuilder.build(); - response = processRequest(client, request); + response = processRequest(activeClient, request); LOGGER.finest("connection response on retry: " + response); } } return response; + } catch (ClientProtocolException cpe) { + int code = extractHttpStatusCode(cpe); + if (code > 0) { + LOGGER.severe("HTTP protocol error with status code " + code + ": " + cpe.getMessage()); + throw new ApiException( + "HTTP protocol error (status code " + code + "): " + cpe.getMessage(), cpe, code); + } + LOGGER.severe("HTTP protocol error: " + cpe.getMessage()); + throw new ApiException("HTTP protocol error: " + cpe.getMessage(), cpe); } catch (Exception e) { LOGGER.severe("Error:" + e); throw new ApiException(e); @@ -170,6 +248,9 @@ private boolean processUnauthorizedResponse( HttpResponse response, Map authManagersByOasSecuritySchemes) { + if (null == authManagersByOasSecuritySchemes) { + return false; + } Map authManagersByAuthSchemes = authManagersByOasSecuritySchemes.values().stream() .map(authManager -> new AbstractMap.SimpleEntry<>(authManager.getSchema(), authManager)) @@ -338,6 +419,42 @@ HttpResponse processRequest(CloseableHttpClient client, ClassicHttpRequest reque return client.execute(request, HttpClientApache::processResponse); } + /** + * Extracts the HTTP status code from a {@link ClientProtocolException}. + * + *

Handles two cases: + * + *

+ * + * @return the HTTP status code, or {@code -1} if it cannot be determined + */ + private static int extractHttpStatusCode(ClientProtocolException e) { + if (e instanceof HttpResponseException) { + return ((HttpResponseException) e).getStatusCode(); + } + String message = e.getMessage(); + if (message == null) { + return -1; + } + int idx = message.indexOf("HTTP/"); + if (idx < 0) { + return -1; + } + String[] parts = message.substring(idx).split(" ", 3); + if (parts.length < 2) { + return -1; + } + try { + return Integer.parseInt(parts[1]); + } catch (NumberFormatException ignored) { + return -1; + } + } + private Optional extractCharset(AbstractMessageBuilder messageBuilder) { Header[] headers = messageBuilder.getHeaders(CONTENT_TYPE_HEADER); @@ -359,10 +476,12 @@ public boolean isClosed() { @Override public void close() throws Exception { if (!isClosed()) { - try { - client.close(); - } finally { + synchronized (this) { + CloseableHttpClient local = client; client = null; + if (local != null) { + local.close(); + } } } } diff --git a/client/src/main/com/sinch/sdk/models/Configuration.java b/client/src/main/com/sinch/sdk/models/Configuration.java index 913a52713..05d26aef1 100644 --- a/client/src/main/com/sinch/sdk/models/Configuration.java +++ b/client/src/main/com/sinch/sdk/models/Configuration.java @@ -15,17 +15,21 @@ public class Configuration { private final VerificationContext verificationContext; private final VoiceContext voiceContext; private final ConversationContext conversationContext; + private final HttpProxyConfiguration httpProxyConfiguration; + private final NumberLookupContext numberLookupContext; private Configuration( UnifiedCredentials unifiedCredentials, ApplicationCredentials applicationCredentials, SmsServicePlanCredentials smsServicePlanCredentials, String oauthUrl, + HttpProxyConfiguration httpProxyConfiguration, NumbersContext numbersContext, SmsContext smsContext, VerificationContext verificationContext, VoiceContext voiceContext, - ConversationContext conversationContext) { + ConversationContext conversationContext, + NumberLookupContext numberLookupContext) { this.unifiedCredentials = unifiedCredentials; this.applicationCredentials = applicationCredentials; this.smsServicePlanCredentials = smsServicePlanCredentials; @@ -35,6 +39,8 @@ private Configuration( this.voiceContext = voiceContext; this.verificationContext = verificationContext; this.conversationContext = conversationContext; + this.numberLookupContext = numberLookupContext; + this.httpProxyConfiguration = httpProxyConfiguration; } @Override @@ -51,10 +57,12 @@ public String toString() { + verificationContext + ", voiceContext=" + voiceContext - + ", conversationRegion=" - + conversationContext + ", conversationContext=" + conversationContext + + ", numberLookupContext=" + + numberLookupContext + + ", httpProxyConfiguration=" + + httpProxyConfiguration + "}"; } @@ -153,15 +161,35 @@ public Optional getApplicationCredentials() { } /** - * Get Voice domain related execution context + * Get Conversation domain related execution context * - * @return Current Voice context + * @return Current Conversation context * @since 1.0 */ public Optional getConversationContext() { return Optional.ofNullable(conversationContext); } + /** + * Get Number Lookup domain related execution context + * + * @return Current Number Lookup context + * @since 2.1 + */ + public Optional getNumberLookupContext() { + return Optional.ofNullable(numberLookupContext); + } + + /** + * Get HTTP proxy configuration + * + * @return HTTP proxy configuration + * @since 2.1 + */ + public Optional getHttpProxyConfiguration() { + return Optional.ofNullable(httpProxyConfiguration); + } + /** * Getting Builder * @@ -199,6 +227,8 @@ public static class Builder { VerificationContext.Builder verificationContext; VoiceContext.Builder voiceContext; ConversationContext.Builder conversationContext; + NumberLookupContext.Builder numberLookupContext; + HttpProxyConfiguration httpProxyConfiguration; protected Builder() {} @@ -230,6 +260,9 @@ protected Builder(Configuration configuration) { this.voiceContext = configuration.getVoiceContext().map(VoiceContext::builder).orElse(null); this.conversationContext = configuration.getConversationContext().map(ConversationContext::builder).orElse(null); + this.numberLookupContext = + configuration.getNumberLookupContext().map(NumberLookupContext::builder).orElse(null); + this.httpProxyConfiguration = configuration.getHttpProxyConfiguration().orElse(null); } /** @@ -488,6 +521,46 @@ public Builder setConversationContext(ConversationContext context) { return this; } + /** + * Set Number Lookup API URL + * + * @param numberLookupUrl Number Lookup API URL + * @return Current builder + * @since 2.1 + */ + public Builder setNumberLookupUrl(String numberLookupUrl) { + if (null == this.numberLookupContext) { + this.numberLookupContext = NumberLookupContext.builder(); + } + this.numberLookupContext.setNumberLookupUrl(numberLookupUrl); + return this; + } + + /** + * Set Number Lookup related context + * + * @param context {@link #getNumberLookupContext() getter} + * @return Current builder + * @since 2.1 + */ + public Builder setNumberLookupContext(NumberLookupContext context) { + this.numberLookupContext = null != context ? NumberLookupContext.builder(context) : null; + return this; + } + + /** + * Set HTTP proxy configuration + * + * @param httpProxyConfiguration proxy configuration, or {@code null} to disable proxy + * @return Current builder + * @see Configuration#getHttpProxyConfiguration() getter + * @since 2.1 + */ + public Builder setHttpProxyConfiguration(HttpProxyConfiguration httpProxyConfiguration) { + this.httpProxyConfiguration = httpProxyConfiguration; + return this; + } + /** * Build a Configuration instance from builder current state * @@ -501,11 +574,13 @@ public Configuration build() { null != applicationCredentials ? applicationCredentials.build() : null, null != smsServicePlanCredentials ? smsServicePlanCredentials.build() : null, oauthUrl, + httpProxyConfiguration, null != numbersContext ? numbersContext.build() : null, null != smsContext ? smsContext.build() : null, null != verificationContext ? verificationContext.build() : null, null != voiceContext ? voiceContext.build() : null, - null != conversationContext ? conversationContext.build() : null); + null != conversationContext ? conversationContext.build() : null, + null != numberLookupContext ? numberLookupContext.build() : null); } } } diff --git a/client/src/main/com/sinch/sdk/models/HttpProxyConfiguration.java b/client/src/main/com/sinch/sdk/models/HttpProxyConfiguration.java new file mode 100644 index 000000000..519767e9c --- /dev/null +++ b/client/src/main/com/sinch/sdk/models/HttpProxyConfiguration.java @@ -0,0 +1,255 @@ +package com.sinch.sdk.models; + +import com.sinch.sdk.core.utils.StringUtil; +import java.util.Arrays; +import java.util.Optional; + +/** + * HTTP proxy configuration for the Sinch SDK HTTP client. + * + *

Provides a transport-agnostic proxy abstraction. Use {@link Builder} to construct an instance, + * optionally providing credentials for authenticated proxies. + * + *

Scheme: Only plain HTTP proxies are supported. HTTPS-terminating (SSL + * intercepting) proxies are not. All outbound connections — including OAuth token exchange — are + * routed through the configured proxy. + * + *

{@code
+ * // Unauthenticated proxy
+ * HttpProxyConfiguration proxy = HttpProxyConfiguration.builder()
+ *     .setHostname("proxy.corp.example.com")
+ *     .setPort(3128)
+ *     .build();
+ *
+ * // Authenticated proxy
+ * HttpProxyConfiguration proxy = HttpProxyConfiguration.builder()
+ *     .setHostname("proxy.corp.example.com")
+ *     .setPort(3128)
+ *     .setUsername("user")
+ *     .setPassword("secret")
+ *     .build();
+ * }
+ * + * @since 2.1 + */ +public class HttpProxyConfiguration { + private final String hostname; + private final int port; + private final String username; + private final char[] password; + + private HttpProxyConfiguration(String hostname, int port, String username, char[] password) { + this.hostname = hostname; + this.port = port; + this.username = username; + this.password = password; + } + + /** + * Proxy host name or IP address. + * + * @return hostname + * @since 2.1 + */ + public String getHostname() { + return hostname; + } + + /** + * Proxy port number. + * + * @return port + * @since 2.1 + */ + public int getPort() { + return port; + } + + /** + * Proxy username, present only when the proxy requires authentication. + * + * @return username, or empty if not configured + * @since 2.1 + */ + public Optional getUsername() { + return Optional.ofNullable(username); + } + + /** + * Proxy password, present only when the proxy requires authentication. + * + *

Returns a defensive copy of the internal array. Callers are encouraged to zero the array + * with {@code Arrays.fill(pwd, '\0')} once they have finished using it. + * + * @return password as a char array, or empty if not configured + * @since 2.1 + */ + public Optional getPassword() { + return password == null + ? Optional.empty() + : Optional.of(Arrays.copyOf(password, password.length)); + } + + @Override + public String toString() { + return "HttpProxyConfiguration{" + + "hostname='" + + hostname + + '\'' + + ", port=" + + port + + ", username=" + + (username != null ? "'***'" : "null") + + ", password=" + + (password != null ? "'***'" : "null") + + '}'; + } + + /** + * Getting Builder + * + * @return New Builder instance + * @since 2.1 + */ + public static Builder builder() { + return new Builder(); + } + + /** + * Getting Builder pre-populated from an existing instance + * + * @param configuration source configuration + * @return New Builder instance + * @since 2.1 + */ + public static Builder builder(HttpProxyConfiguration configuration) { + return new Builder(configuration); + } + + /** + * Dedicated Builder + * + * @since 2.1 + */ + public static class Builder { + + private String hostname; + private int port; + private String username; + private char[] password; + + protected Builder() {} + + protected Builder(HttpProxyConfiguration configuration) { + if (null == configuration) { + return; + } + this.hostname = configuration.hostname; + this.port = configuration.port; + this.username = configuration.username; + this.password = + configuration.password == null + ? null + : Arrays.copyOf(configuration.password, configuration.password.length); + } + + /** + * Set proxy hostname or IP address + * + * @param hostname proxy host + * @return Current builder + * @since 2.1 + */ + public Builder setHostname(String hostname) { + this.hostname = hostname; + return this; + } + + /** + * Set proxy port + * + * @param port proxy port + * @return Current builder + * @since 2.1 + */ + public Builder setPort(int port) { + this.port = port; + return this; + } + + /** + * Set proxy username (for authenticated proxies) + * + * @param username proxy username + * @return Current builder + * @since 2.1 + */ + public Builder setUsername(String username) { + this.username = username; + return this; + } + + /** + * Set proxy password (for authenticated proxies). + * + *

The {@code String} argument is converted to a {@code char[]} immediately and the reference + * is not retained. Prefer {@link #setPassword(char[])} when the password is already available + * as a {@code char[]} (e.g. from {@code Console.readPassword()}) to avoid creating an + * intermediate {@code String} on the heap. + * + * @param password proxy password + * @return Current builder + * @since 2.1 + */ + public Builder setPassword(String password) { + this.password = password == null ? null : password.toCharArray(); + return this; + } + + /** + * Set proxy password as a char array (for authenticated proxies). + * + *

A defensive copy of the provided array is stored. The caller may zero the original array + * with {@code Arrays.fill(password, '\0')} immediately after this call. + * + * @param password proxy password as a char array + * @return Current builder + * @since 2.1 + */ + public Builder setPassword(char[] password) { + this.password = password == null ? null : Arrays.copyOf(password, password.length); + return this; + } + + /** + * Build an {@link HttpProxyConfiguration} instance + * + * @return HttpProxyConfiguration instance + * @since 2.1 + */ + public HttpProxyConfiguration build() { + String trimmedHostname = hostname == null ? null : hostname.trim(); + if (StringUtil.isEmpty(trimmedHostname)) { + throw new IllegalArgumentException( + "HttpProxyConfiguration: hostname must not be null or empty"); + } + if (port <= 0 || port > 65535) { + throw new IllegalArgumentException( + "HttpProxyConfiguration: port must be in range 1–65535, got: " + port); + } + if (password != null && username == null) { + throw new IllegalArgumentException( + "HttpProxyConfiguration: a password was provided without a username"); + } + if (username != null && password == null) { + throw new IllegalArgumentException( + "HttpProxyConfiguration: a username was provided without a password"); + } + return new HttpProxyConfiguration( + trimmedHostname, + port, + username, + password == null ? null : Arrays.copyOf(password, password.length)); + } + } +} diff --git a/client/src/main/com/sinch/sdk/models/NumberLookupContext.java b/client/src/main/com/sinch/sdk/models/NumberLookupContext.java new file mode 100644 index 000000000..8813767b1 --- /dev/null +++ b/client/src/main/com/sinch/sdk/models/NumberLookupContext.java @@ -0,0 +1,93 @@ +package com.sinch.sdk.models; + +import com.sinch.sdk.core.models.ServerConfiguration; + +/** Execution context related to Number Lookup domain */ +public class NumberLookupContext { + + private final String numberLookupUrl; + + private NumberLookupContext(String numberLookupUrl) { + this.numberLookupUrl = numberLookupUrl; + } + + /** + * Number Lookup Server Configuration + * + * @return Number Lookup Server configuration to be used + * @since 2.1 + */ + public ServerConfiguration getNumberLookupServer() { + return new ServerConfiguration(getNumberLookupUrl()); + } + + /** + * Number Lookup URL + * + * @return Number Lookup Server URL + * @since 2.1 + */ + public String getNumberLookupUrl() { + return numberLookupUrl; + } + + /** + * Getting Builder + * + * @return New Builder instance + * @since 2.1 + */ + public static Builder builder() { + return new Builder(); + } + + /** + * Getting Builder + * + * @param context Source context to fill initial builder state + * @return New Builder instance + * @since 2.1 + */ + public static Builder builder(NumberLookupContext context) { + return new Builder(context); + } + + /** + * Dedicated Builder + * + * @since 2.1 + */ + public static class Builder { + + String numberLookupUrl; + + protected Builder() {} + + protected Builder(NumberLookupContext context) { + this.numberLookupUrl = null != context ? context.getNumberLookupUrl() : null; + } + + /** + * Set Number Lookup API URL + * + * @param numberLookupUrl Number Lookup API URL + * @return Current builder + * @since 2.1 + */ + public Builder setNumberLookupUrl(String numberLookupUrl) { + this.numberLookupUrl = numberLookupUrl; + return this; + } + + /** + * Create instance + * + * @return The instance build with current builder values + * @since 2.1 + */ + public NumberLookupContext build() { + + return new NumberLookupContext(numberLookupUrl); + } + } +} diff --git a/client/src/test/java/com/sinch/sdk/SinchClientTest.java b/client/src/test/java/com/sinch/sdk/SinchClientTest.java index 7a9610b4c..8baee2d6a 100644 --- a/client/src/test/java/com/sinch/sdk/SinchClientTest.java +++ b/client/src/test/java/com/sinch/sdk/SinchClientTest.java @@ -3,11 +3,15 @@ import static org.junit.jupiter.api.Assertions.*; import com.sinch.sdk.core.utils.StringUtil; +import com.sinch.sdk.http.HttpClientApache; import com.sinch.sdk.models.Configuration; import com.sinch.sdk.models.ConversationRegion; +import com.sinch.sdk.models.HttpProxyConfiguration; import com.sinch.sdk.models.SMSRegion; import com.sinch.sdk.models.VoiceContext; import com.sinch.sdk.models.VoiceRegion; +import java.lang.reflect.Field; +import java.lang.reflect.Method; import org.junit.jupiter.api.Test; class SinchClientTest { @@ -142,6 +146,14 @@ void defaultVerificationUrlAvailable() { assertNotNull(client.getConfiguration().getVerificationContext().get().getVerificationUrl()); } + @Test + void defaultNumberLookupUrlAvailable() { + Configuration configuration = + Configuration.builder().setKeyId("foo").setKeySecret("foo").setProjectId("foo").build(); + SinchClient client = new SinchClient(configuration); + assertNotNull(client.getConfiguration().getNumberLookupContext().get().getNumberLookupUrl()); + } + @Test void defaultVoiceRegion() { Configuration configuration = Configuration.builder().build(); @@ -218,4 +230,111 @@ void voiceApplicationManagementUrlFromUrl() { client.getConfiguration().getVoiceContext().get().getVoiceApplicationManagementUrl(), "my foo url"); } + + @Test + void formatAuxiliaryFlagReturnsVendorWhenFlagIsEmpty() { + SinchClient client = new SinchClient(); + // AUXILIARY_FLAG is "" in SDK — only vendor should be present, no comma separator + String result = client.formatAuxiliaryFlag(""); + assertNotNull(result); + assertEquals( + System.getProperty("java.vendor"), + result, + "When auxiliaryFlag is empty, the result should match java.vendor exactly"); + } + + @Test + void formatAuxiliaryFlagHandlesNullJavaVendor() { + String original = System.getProperty("java.vendor"); + try { + System.clearProperty("java.vendor"); + SinchClient client = new SinchClient(); + String result = client.formatAuxiliaryFlag(""); + assertNotNull(result); + assertFalse(result.contains("null"), "Null java.vendor must not render as 'null' string"); + } finally { + if (null != original) { + System.setProperty("java.vendor", original); + } + } + } + + @Test + void formatAuxiliaryFlagAppendsNonEmptyFlag() { + SinchClient client = new SinchClient(); + String result = client.formatAuxiliaryFlag("my-wrapper/1.0"); + assertNotNull(result); + assertTrue(result.contains(","), "A comma must separate vendor from the auxiliary flag"); + assertTrue( + result.endsWith(",my-wrapper/1.0"), + "Auxiliary flag must be the last element after the comma"); + } + + @Test + void closeBeforeAnyCall() { + SinchClient client = new SinchClient(); + assertDoesNotThrow(client::close); + } + + @Test + void doubleCloseBeforeAnyCall() { + SinchClient client = new SinchClient(); + client.close(); + assertDoesNotThrow(client::close); + } + + /** + * Verifies that a proxy configuration set on {@link Configuration} is preserved in the {@link + * SinchClient}'s internal configuration after construction. + */ + @Test + void proxyConfigurationPreservedInConfiguration() { + HttpProxyConfiguration proxy = + HttpProxyConfiguration.builder() + .setHostname("proxy.corp.example.com") + .setPort(3128) + .build(); + Configuration configuration = Configuration.builder().setHttpProxyConfiguration(proxy).build(); + SinchClient client = new SinchClient(configuration); + assertTrue( + client.getConfiguration().getHttpProxyConfiguration().isPresent(), + "Proxy configuration must be present in the SinchClient's stored configuration"); + assertEquals( + "proxy.corp.example.com", + client.getConfiguration().getHttpProxyConfiguration().get().getHostname(), + "Proxy hostname must survive SinchClient construction"); + assertEquals( + 3128, + client.getConfiguration().getHttpProxyConfiguration().get().getPort(), + "Proxy port must survive SinchClient construction"); + } + + @Test + void proxyConfigurationWiredIntoHttpClient() throws Exception { + HttpProxyConfiguration proxy = + HttpProxyConfiguration.builder() + .setHostname("proxy.corp.example.com") + .setPort(3128) + .build(); + Configuration configuration = Configuration.builder().setHttpProxyConfiguration(proxy).build(); + SinchClient sinchClient = new SinchClient(configuration); + + Method getHttpClient = SinchClient.class.getDeclaredMethod("getHttpClient"); + getHttpClient.setAccessible(true); + Object httpClientApache = getHttpClient.invoke(sinchClient); + assertInstanceOf(HttpClientApache.class, httpClientApache); + + Field clientField = HttpClientApache.class.getDeclaredField("client"); + clientField.setAccessible(true); + Object apacheClient = clientField.get(httpClientApache); + + Field routePlannerField = apacheClient.getClass().getDeclaredField("routePlanner"); + routePlannerField.setAccessible(true); + Object routePlanner = routePlannerField.get(apacheClient); + + assertInstanceOf( + org.apache.hc.client5.http.impl.routing.DefaultProxyRoutePlanner.class, + routePlanner, + "HttpClient must use a DefaultProxyRoutePlanner when proxy is configured"); + } } diff --git a/client/src/test/java/com/sinch/sdk/SinchClientTestIT.java b/client/src/test/java/com/sinch/sdk/SinchClientTestIT.java index c95624e5e..1a5bdf7e2 100644 --- a/client/src/test/java/com/sinch/sdk/SinchClientTestIT.java +++ b/client/src/test/java/com/sinch/sdk/SinchClientTestIT.java @@ -52,6 +52,7 @@ void sdkUserAgent() throws InterruptedException { // noop } RecordedRequest recordedRequest = mockBackEnd.takeRequest(); + assertThat(recordedRequest).isNotNull(); String header = recordedRequest.getHeader("User-Agent"); assertThat(header).matches("^sinch-sdk/.* \\(Java/.*; Apache; .*\\)$"); } diff --git a/client/src/test/java/com/sinch/sdk/domains/conversation/api/templates/adapters/v2/TemplatesV2ServiceTest.java b/client/src/test/java/com/sinch/sdk/domains/conversation/api/templates/adapters/v2/TemplatesV2ServiceTest.java index 47e1d1f6c..945897100 100644 --- a/client/src/test/java/com/sinch/sdk/domains/conversation/api/templates/adapters/v2/TemplatesV2ServiceTest.java +++ b/client/src/test/java/com/sinch/sdk/domains/conversation/api/templates/adapters/v2/TemplatesV2ServiceTest.java @@ -57,7 +57,7 @@ public class TemplatesV2ServiceTest extends TemplatesBaseTest { @GivenTextResource("/domains/conversation/templates/v2/request/TemplateV2RequestDto.json") String jsonTemplateV2RequestDto; - @GivenTextResource("/domains/conversation/templates/v2/TemplateV2Dto.json") + @GivenTextResource("/domains/conversation/templates/v2/response/TemplateV2ResponseDto.json") String jsonTemplateV2Dto; @GivenTextResource("/domains/conversation/templates/v2/response/TemplatesV2ListResponseDto.json") @@ -96,9 +96,9 @@ void create() throws ApiException { argThat(new HttpRequestMatcher(httpRequest)))) .thenReturn(httpResponse); - TemplateV2 response = service.create(TemplateV2DtoTest.expectedDto); + TemplateV2 response = service.create(TemplateV2DtoTest.expectedRequestDto); - TestHelpers.recursiveEquals(response, TemplateV2DtoTest.expectedDto); + TestHelpers.recursiveEquals(response, TemplateV2DtoTest.expectedResponseDto); } @Test @@ -109,7 +109,7 @@ void get() throws ApiException { String.format( "/v2/projects/%s/templates/%s", URLPathUtils.encodePathSegment(uriPartID), - URLPathUtils.encodePathSegment(TemplateV2DtoTest.expectedDto.getId())), + URLPathUtils.encodePathSegment(TemplateV2DtoTest.expectedRequestDto.getId())), HttpMethod.GET, Collections.emptyList(), (String) null, @@ -126,9 +126,9 @@ void get() throws ApiException { argThat(new HttpRequestMatcher(httpRequest)))) .thenReturn(httpResponse); - TemplateV2 response = service.get(TemplateV2DtoTest.expectedDto.getId()); + TemplateV2 response = service.get(TemplateV2DtoTest.expectedRequestDto.getId()); - TestHelpers.recursiveEquals(response, TemplateV2DtoTest.expectedDto); + TestHelpers.recursiveEquals(response, TemplateV2DtoTest.expectedResponseDto); } @Test @@ -178,7 +178,7 @@ void listTranslations() throws ApiException { String.format( "/v2/projects/%s/templates/%s/translations", URLPathUtils.encodePathSegment(uriPartID), - URLPathUtils.encodePathSegment(TemplateV2DtoTest.expectedDto.getId())), + URLPathUtils.encodePathSegment(TemplateV2DtoTest.expectedRequestDto.getId())), HttpMethod.GET, Collections.emptyList(), (String) null, @@ -197,7 +197,7 @@ void listTranslations() throws ApiException { .thenReturn(httpResponse); TranslationsV2ListResponse response = - service.listTranslations(TemplateV2DtoTest.expectedDto.getId()); + service.listTranslations(TemplateV2DtoTest.expectedRequestDto.getId()); Iterator iterator = response.iterator(); TranslationsV2ListResponse expectedListResponse = @@ -221,7 +221,7 @@ void listTranslationsWithParameters() throws ApiException { String.format( "/v2/projects/%s/templates/%s/translations", URLPathUtils.encodePathSegment(uriPartID), - URLPathUtils.encodePathSegment(TemplateV2DtoTest.expectedDto.getId())), + URLPathUtils.encodePathSegment(TemplateV2DtoTest.expectedRequestDto.getId())), HttpMethod.GET, Arrays.asList( new URLParameter("language_code", "language code", STYLE.FORM, true), @@ -243,7 +243,7 @@ void listTranslationsWithParameters() throws ApiException { TranslationsV2ListResponse response = service.listTranslations( - TemplateV2DtoTest.expectedDto.getId(), + TemplateV2DtoTest.expectedRequestDto.getId(), ListTranslationsQueryParameters.builder() .setLanguageCode("language code") .setTranslationVersion("translation version") @@ -271,7 +271,7 @@ void update() throws ApiException { String.format( "/v2/projects/%s/templates/%s", URLPathUtils.encodePathSegment(uriPartID), - URLPathUtils.encodePathSegment(TemplateV2DtoTest.expectedDto.getId())), + URLPathUtils.encodePathSegment(TemplateV2DtoTest.expectedRequestDto.getId())), HttpMethod.PUT, Collections.emptyList(), jsonTemplateV2RequestDto, @@ -289,9 +289,10 @@ void update() throws ApiException { .thenReturn(httpResponse); TemplateV2 response = - service.update(TemplateV2DtoTest.expectedDto.getId(), TemplateV2DtoTest.expectedDto); + service.update( + TemplateV2DtoTest.expectedRequestDto.getId(), TemplateV2DtoTest.expectedRequestDto); - TestHelpers.recursiveEquals(response, TemplateV2DtoTest.expectedDto); + TestHelpers.recursiveEquals(response, TemplateV2DtoTest.expectedResponseDto); } @Test @@ -302,7 +303,7 @@ void delete() throws ApiException { String.format( "/v2/projects/%s/templates/%s", URLPathUtils.encodePathSegment(uriPartID), - URLPathUtils.encodePathSegment(TemplateV2DtoTest.expectedDto.getId())), + URLPathUtils.encodePathSegment(TemplateV2DtoTest.expectedRequestDto.getId())), HttpMethod.DELETE, Collections.emptyList(), (String) null, @@ -318,6 +319,6 @@ void delete() throws ApiException { argThat(new HttpRequestMatcher(httpRequest)))) .thenReturn(httpResponse); - service.delete(TemplateV2DtoTest.expectedDto.getId()); + service.delete(TemplateV2DtoTest.expectedResponseDto.getId()); } } diff --git a/client/src/test/java/com/sinch/sdk/domains/conversation/api/v1/adapters/ConsentsServiceTest.java b/client/src/test/java/com/sinch/sdk/domains/conversation/api/v1/adapters/ConsentsServiceTest.java new file mode 100644 index 000000000..9d5c47eb2 --- /dev/null +++ b/client/src/test/java/com/sinch/sdk/domains/conversation/api/v1/adapters/ConsentsServiceTest.java @@ -0,0 +1,205 @@ +package com.sinch.sdk.domains.conversation.api.v1.adapters; + +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.when; + +import com.adelean.inject.resources.junit.jupiter.GivenTextResource; +import com.adelean.inject.resources.junit.jupiter.TestWithResources; +import com.sinch.sdk.BaseTest; +import com.sinch.sdk.core.TestHelpers; +import com.sinch.sdk.core.exceptions.ApiException; +import com.sinch.sdk.core.http.AuthManager; +import com.sinch.sdk.core.http.HttpClient; +import com.sinch.sdk.core.http.HttpContentType; +import com.sinch.sdk.core.http.HttpMapper; +import com.sinch.sdk.core.http.HttpMethod; +import com.sinch.sdk.core.http.HttpRequest; +import com.sinch.sdk.core.http.HttpRequestTest.HttpRequestMatcher; +import com.sinch.sdk.core.http.HttpResponse; +import com.sinch.sdk.core.http.URLParameter; +import com.sinch.sdk.core.http.URLParameter.STYLE; +import com.sinch.sdk.core.http.URLPathUtils; +import com.sinch.sdk.core.models.ServerConfiguration; +import com.sinch.sdk.domains.conversation.api.v1.ConsentsService; +import com.sinch.sdk.domains.conversation.models.v1.consents.ConsentsDtoTest; +import com.sinch.sdk.domains.conversation.models.v1.consents.ConsentsListType; +import com.sinch.sdk.domains.conversation.models.v1.consents.Identity; +import com.sinch.sdk.domains.conversation.models.v1.consents.request.ConsentsListQueryParameters; +import com.sinch.sdk.domains.conversation.models.v1.consents.response.AuditRecordsResponse; +import com.sinch.sdk.domains.conversation.models.v1.consents.response.ConsentsListResponse; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.Map; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; + +@TestWithResources +class ConsentsServiceTest extends BaseTest { + + @Mock HttpClient httpClient; + @Mock ServerConfiguration serverConfiguration; + @Mock Map authManagers; + + static final String uriUUID = "foo"; + static final String APP_ID = "an app id"; + static final String IDENTITY = "an identity value"; + static final Collection AUTH_NAMES = Arrays.asList("Basic", "oAuth2"); + + ConsentsService service; + + @GivenTextResource("/domains/conversation/v1/consents/ConsentsListResponseDtoPage0.json") + String jsonConsentsListResponseDtoPage0; + + @GivenTextResource("/domains/conversation/v1/consents/ConsentsListResponseDtoPage1.json") + String jsonConsentsListResponseDtoPage1; + + @GivenTextResource("/domains/conversation/v1/consents/AuditRecordsResponseDto.json") + String jsonAuditRecordsResponseDto; + + @BeforeEach + public void initMocks() { + service = + new ConsentsServiceImpl( + httpClient, serverConfiguration, authManagers, HttpMapper.getInstance(), uriUUID); + } + + @Test + void listIdentities() throws ApiException { + + HttpRequest httpRequest1 = + new HttpRequest( + String.format( + "/v1/projects/%s/apps/%s/consents/%s", + URLPathUtils.encodePathSegment(uriUUID), + URLPathUtils.encodePathSegment(APP_ID), + URLPathUtils.encodePathSegment(ConsentsListType.OPT_OUT_ALL.toString())), + HttpMethod.GET, + Collections.emptyList(), + (String) null, + Collections.emptyMap(), + Collections.singletonList(HttpContentType.APPLICATION_JSON), + Collections.emptyList(), + AUTH_NAMES); + HttpRequest httpRequest2 = + new HttpRequest( + String.format( + "/v1/projects/%s/apps/%s/consents/%s", + URLPathUtils.encodePathSegment(uriUUID), + URLPathUtils.encodePathSegment(APP_ID), + URLPathUtils.encodePathSegment(ConsentsListType.OPT_OUT_ALL.toString())), + HttpMethod.GET, + Collections.singletonList( + new URLParameter("page_token", "the next page token value", STYLE.FORM, true)), + (String) null, + Collections.emptyMap(), + Collections.singletonList(HttpContentType.APPLICATION_JSON), + Collections.emptyList(), + AUTH_NAMES); + HttpResponse httpResponse1 = + new HttpResponse( + 200, null, Collections.emptyMap(), jsonConsentsListResponseDtoPage0.getBytes()); + HttpResponse httpResponse2 = + new HttpResponse( + 200, null, Collections.emptyMap(), jsonConsentsListResponseDtoPage1.getBytes()); + + when(httpClient.invokeAPI( + eq(serverConfiguration), + eq(authManagers), + argThat(new HttpRequestMatcher(httpRequest1)))) + .thenReturn(httpResponse1); + when(httpClient.invokeAPI( + eq(serverConfiguration), + eq(authManagers), + argThat(new HttpRequestMatcher(httpRequest2)))) + .thenReturn(httpResponse2); + + ConsentsListResponse response = service.listIdentities(APP_ID, ConsentsListType.OPT_OUT_ALL); + + Iterator iterator = response.iterator(); + + Assertions.assertThat(iterator.hasNext()).isEqualTo(true); + Identity item = iterator.next(); + TestHelpers.recursiveEquals(item, ConsentsDtoTest.expectedIdentityDto); + + item = iterator.next(); + TestHelpers.recursiveEquals( + item, Identity.builder().setIdentity("a 2nd identity value").build()); + Assertions.assertThat(iterator.hasNext()).isEqualTo(true); + + item = iterator.next(); + TestHelpers.recursiveEquals( + item, Identity.builder().setIdentity("a 3rd identity value").build()); + Assertions.assertThat(iterator.hasNext()).isEqualTo(false); + } + + @Test + void listIdentitiesWithQueryParameters() throws ApiException { + + HttpRequest httpRequest = + new HttpRequest( + String.format( + "/v1/projects/%s/apps/%s/consents/%s", + URLPathUtils.encodePathSegment(uriUUID), + URLPathUtils.encodePathSegment(APP_ID), + URLPathUtils.encodePathSegment(ConsentsListType.OPT_OUT_MARKETING.toString())), + HttpMethod.GET, + Collections.singletonList(new URLParameter("page_size", 5, STYLE.FORM, true)), + (String) null, + Collections.emptyMap(), + Collections.singletonList(HttpContentType.APPLICATION_JSON), + Collections.emptyList(), + AUTH_NAMES); + HttpResponse httpResponse = + new HttpResponse( + 200, null, Collections.emptyMap(), jsonConsentsListResponseDtoPage1.getBytes()); + + when(httpClient.invokeAPI( + eq(serverConfiguration), + eq(authManagers), + argThat(new HttpRequestMatcher(httpRequest)))) + .thenReturn(httpResponse); + + ConsentsListQueryParameters queryParams = + ConsentsListQueryParameters.builder().setPageSize(5).build(); + ConsentsListResponse response = + service.listIdentities(APP_ID, ConsentsListType.OPT_OUT_MARKETING, queryParams); + + Assertions.assertThat(response.getContent()).isNotEmpty(); + } + + @Test + void listAuditRecords() throws ApiException { + + HttpRequest httpRequest = + new HttpRequest( + String.format( + "/v1/projects/%s/apps/%s/consents/identities/%s", + URLPathUtils.encodePathSegment(uriUUID), + URLPathUtils.encodePathSegment(APP_ID), + URLPathUtils.encodePathSegment(IDENTITY)), + HttpMethod.GET, + Collections.emptyList(), + (String) null, + Collections.emptyMap(), + Collections.singletonList(HttpContentType.APPLICATION_JSON), + Collections.emptyList(), + AUTH_NAMES); + HttpResponse httpResponse = + new HttpResponse(200, null, Collections.emptyMap(), jsonAuditRecordsResponseDto.getBytes()); + + when(httpClient.invokeAPI( + eq(serverConfiguration), + eq(authManagers), + argThat(new HttpRequestMatcher(httpRequest)))) + .thenReturn(httpResponse); + + AuditRecordsResponse response = service.listAuditRecords(APP_ID, IDENTITY); + + TestHelpers.recursiveEquals(response, ConsentsDtoTest.expectedAuditRecordsResponseDto); + } +} diff --git a/client/src/test/java/com/sinch/sdk/domains/numberlookup/api/v2/adapters/CredentialsValidationHelper.java b/client/src/test/java/com/sinch/sdk/domains/numberlookup/api/v2/adapters/CredentialsValidationHelper.java new file mode 100644 index 000000000..4df84f691 --- /dev/null +++ b/client/src/test/java/com/sinch/sdk/domains/numberlookup/api/v2/adapters/CredentialsValidationHelper.java @@ -0,0 +1,153 @@ +package com.sinch.sdk.domains.numberlookup.api.v2.adapters; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import com.sinch.sdk.core.http.HttpClient; +import com.sinch.sdk.core.models.ServerConfiguration; +import com.sinch.sdk.models.NumberLookupContext; +import com.sinch.sdk.models.UnifiedCredentials; +import java.util.function.Consumer; +import java.util.function.Supplier; + +class CredentialsValidationHelper { + + static ServerConfiguration oAuthServer = new ServerConfiguration("https://oauth.foo.url"); + + static void checkCredentials( + Supplier httpClientSupplier, Consumer service) { + doNotAcceptNullCredentials(httpClientSupplier, service); + doNotAcceptNullKey(httpClientSupplier, service); + doNotAcceptNullKeySecret(httpClientSupplier, service); + doNotAcceptNullProject(httpClientSupplier, service); + doNotAcceptNullContext(httpClientSupplier, service); + doNotAcceptNullNumberLookupUrl(httpClientSupplier, service); + initPassed(httpClientSupplier, service); + } + + static void doNotAcceptNullCredentials( + Supplier httpClientSupplier, Consumer service) { + NumberLookupContext context = + NumberLookupContext.builder().setNumberLookupUrl("foo url").build(); + + Exception exception = + assertThrows( + NullPointerException.class, + () -> + service.accept( + new NumberLookupService(null, context, oAuthServer, httpClientSupplier))); + assertTrue( + exception + .getMessage() + .contains("Number Lookup service requires unified credentials to be defined")); + } + + static void doNotAcceptNullKey( + Supplier httpClientSupplier, Consumer service) { + UnifiedCredentials credentials = + UnifiedCredentials.builder().setKeyId(null).setKeySecret("foo").setProjectId("foo").build(); + NumberLookupContext context = + NumberLookupContext.builder().setNumberLookupUrl("foo url").build(); + + Exception exception = + assertThrows( + IllegalArgumentException.class, + () -> + service.accept( + new NumberLookupService( + credentials, context, oAuthServer, httpClientSupplier))); + assertTrue(exception.getMessage().contains("keyId")); + } + + static void doNotAcceptNullKeySecret( + Supplier httpClientSupplier, Consumer service) { + UnifiedCredentials credentials = + UnifiedCredentials.builder().setKeyId("foo").setKeySecret(null).setProjectId("foo").build(); + NumberLookupContext context = + NumberLookupContext.builder().setNumberLookupUrl("foo url").build(); + + Exception exception = + assertThrows( + IllegalArgumentException.class, + () -> + service.accept( + new NumberLookupService( + credentials, context, oAuthServer, httpClientSupplier))); + assertTrue(exception.getMessage().contains("keySecret")); + } + + static void doNotAcceptNullProject( + Supplier httpClientSupplier, Consumer service) { + UnifiedCredentials credentials = + UnifiedCredentials.builder().setKeyId("foo").setKeySecret("foo").setProjectId(null).build(); + NumberLookupContext context = + NumberLookupContext.builder().setNumberLookupUrl("foo url").build(); + + Exception exception = + assertThrows( + IllegalArgumentException.class, + () -> + service.accept( + new NumberLookupService( + credentials, context, oAuthServer, httpClientSupplier))); + assertTrue(exception.getMessage().contains("projectId")); + } + + static void doNotAcceptNullContext( + Supplier httpClientSupplier, Consumer service) { + UnifiedCredentials credentials = + UnifiedCredentials.builder() + .setKeyId("foo") + .setKeySecret("foo") + .setProjectId("foo") + .build(); + + Exception exception = + assertThrows( + NullPointerException.class, + () -> + service.accept( + new NumberLookupService(credentials, null, oAuthServer, httpClientSupplier))); + assertTrue( + exception.getMessage().contains("Number Lookup service requires context to be defined")); + } + + static void doNotAcceptNullNumberLookupUrl( + Supplier httpClientSupplier, Consumer service) { + UnifiedCredentials credentials = + UnifiedCredentials.builder() + .setKeyId("foo") + .setKeySecret("foo") + .setProjectId("foo") + .build(); + NumberLookupContext context = NumberLookupContext.builder().build(); + + Exception exception = + assertThrows( + IllegalArgumentException.class, + () -> + service.accept( + new NumberLookupService( + credentials, context, oAuthServer, httpClientSupplier))); + assertTrue(exception.getMessage().contains("numberLookupUrl")); + } + + static void initPassed( + Supplier httpClientSupplier, Consumer service) { + UnifiedCredentials credentials = + UnifiedCredentials.builder() + .setKeyId("foo") + .setKeySecret("foo") + .setProjectId("foo") + .build(); + NumberLookupContext context = + NumberLookupContext.builder().setNumberLookupUrl("foo url").build(); + + assertDoesNotThrow( + () -> + service.accept( + new NumberLookupService(credentials, context, oAuthServer, httpClientSupplier)), + "Init passed"); + } +} diff --git a/client/src/test/java/com/sinch/sdk/domains/numberlookup/api/v2/adapters/NumberLookupServiceTest.java b/client/src/test/java/com/sinch/sdk/domains/numberlookup/api/v2/adapters/NumberLookupServiceTest.java new file mode 100644 index 000000000..85cfe07a6 --- /dev/null +++ b/client/src/test/java/com/sinch/sdk/domains/numberlookup/api/v2/adapters/NumberLookupServiceTest.java @@ -0,0 +1,16 @@ +package com.sinch.sdk.domains.numberlookup.api.v2.adapters; + +import com.sinch.sdk.core.http.HttpClient; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; + +class NumberLookupServiceTest { + + @Mock HttpClient httpClient; + + @Test + void checkCredentialsNumberLookup() { + CredentialsValidationHelper.checkCredentials( + () -> httpClient, NumberLookupService::getLookupFacade); + } +} diff --git a/client/src/test/java/com/sinch/sdk/domains/numberlookup/api/v2/adapters/NumberLookupV2ServiceTest.java b/client/src/test/java/com/sinch/sdk/domains/numberlookup/api/v2/adapters/NumberLookupV2ServiceTest.java new file mode 100644 index 000000000..9aeaa5312 --- /dev/null +++ b/client/src/test/java/com/sinch/sdk/domains/numberlookup/api/v2/adapters/NumberLookupV2ServiceTest.java @@ -0,0 +1,173 @@ +package com.sinch.sdk.domains.numberlookup.api.v2.adapters; + +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.when; + +import com.adelean.inject.resources.junit.jupiter.GivenTextResource; +import com.adelean.inject.resources.junit.jupiter.TestWithResources; +import com.sinch.sdk.BaseTest; +import com.sinch.sdk.core.TestHelpers; +import com.sinch.sdk.core.exceptions.ApiException; +import com.sinch.sdk.core.http.AuthManager; +import com.sinch.sdk.core.http.HttpClient; +import com.sinch.sdk.core.http.HttpContentType; +import com.sinch.sdk.core.http.HttpMapper; +import com.sinch.sdk.core.http.HttpMethod; +import com.sinch.sdk.core.http.HttpRequest; +import com.sinch.sdk.core.http.HttpRequestTest.HttpRequestMatcher; +import com.sinch.sdk.core.http.HttpResponse; +import com.sinch.sdk.core.http.URLPathUtils; +import com.sinch.sdk.core.models.ServerConfiguration; +import com.sinch.sdk.domains.numberlookup.api.v2.NumberLookupV2Service; +import com.sinch.sdk.domains.numberlookup.models.v2.request.NumberLookupRequestDtoTest; +import com.sinch.sdk.domains.numberlookup.models.v2.response.NumberLookupResponse; +import com.sinch.sdk.domains.numberlookup.models.v2.response.NumberLookupResponseDtoTest; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; + +@TestWithResources +public class NumberLookupV2ServiceTest extends BaseTest { + + @Mock HttpClient httpClient; + @Mock ServerConfiguration serverConfiguration; + @Mock Map authManagers; + + static final String PROJECT_ID = "test_project_id"; + static final Collection AUTH_NAMES = Arrays.asList("Basic", "OAuth2"); + + NumberLookupV2Service service; + + @GivenTextResource("/domains/numberlookup/v2/request/NumberLookupRequestMinimalDto.json") + String jsonNumberLookupRequestMinimalDto; + + @GivenTextResource("/domains/numberlookup/v2/request/NumberLookupRequestWithFeaturesDto.json") + String jsonNumberLookupRequestWithFeaturesDto; + + @GivenTextResource("/domains/numberlookup/v2/request/NumberLookupRequestWithRndOptionsDto.json") + String jsonNumberLookupRequestWithRndOptionsDto; + + @GivenTextResource("/domains/numberlookup/v2/response/NumberLookupResponseMinimalDto.json") + String jsonNumberLookupResponseMinimalDto; + + @GivenTextResource("/domains/numberlookup/v2/response/NumberLookupResponseFullDto.json") + String jsonNumberLookupResponseFullDto; + + @BeforeEach + public void initMocks() { + service = + new NumberLookupV2ServiceImpl( + httpClient, serverConfiguration, authManagers, HttpMapper.getInstance(), PROJECT_ID); + } + + @Test + void lookupWithRequiredParameters() throws ApiException { + + HttpRequest httpRequest = + new HttpRequest( + "/v2/projects/" + URLPathUtils.encodePathSegment(PROJECT_ID) + "/lookups", + HttpMethod.POST, + Collections.emptyList(), + jsonNumberLookupRequestMinimalDto, + Collections.emptyMap(), + Collections.singletonList(HttpContentType.APPLICATION_JSON), + Collections.singletonList(HttpContentType.APPLICATION_JSON), + AUTH_NAMES); + HttpResponse httpResponse = + new HttpResponse( + 200, null, Collections.emptyMap(), jsonNumberLookupResponseMinimalDto.getBytes()); + + when(httpClient.invokeAPI( + eq(serverConfiguration), + eq(authManagers), + argThat(new HttpRequestMatcher(httpRequest)))) + .thenReturn(httpResponse); + + NumberLookupResponse response = + service.lookup(NumberLookupRequestDtoTest.numberLookupRequestMinimalDto); + + TestHelpers.recursiveEquals( + response, NumberLookupResponseDtoTest.numberLookupResponseMinimalDto); + } + + @Test + void lookupWithFeatures() throws ApiException { + + HttpRequest httpRequest = + new HttpRequest( + "/v2/projects/" + URLPathUtils.encodePathSegment(PROJECT_ID) + "/lookups", + HttpMethod.POST, + Collections.emptyList(), + jsonNumberLookupRequestWithFeaturesDto, + Collections.emptyMap(), + Collections.singletonList(HttpContentType.APPLICATION_JSON), + Collections.singletonList(HttpContentType.APPLICATION_JSON), + AUTH_NAMES); + HttpResponse httpResponse = + new HttpResponse( + 200, null, Collections.emptyMap(), jsonNumberLookupResponseFullDto.getBytes()); + + when(httpClient.invokeAPI( + eq(serverConfiguration), + eq(authManagers), + argThat(new HttpRequestMatcher(httpRequest)))) + .thenReturn(httpResponse); + + NumberLookupResponse response = + service.lookup(NumberLookupRequestDtoTest.numberLookupRequestWithFeaturesDto); + + TestHelpers.recursiveEquals(response, NumberLookupResponseDtoTest.numberLookupResponseFullDto); + } + + @Test + void lookupWithRndOptions() throws ApiException { + + HttpRequest httpRequest = + new HttpRequest( + "/v2/projects/" + URLPathUtils.encodePathSegment(PROJECT_ID) + "/lookups", + HttpMethod.POST, + Collections.emptyList(), + jsonNumberLookupRequestWithRndOptionsDto, + Collections.emptyMap(), + Collections.singletonList(HttpContentType.APPLICATION_JSON), + Collections.singletonList(HttpContentType.APPLICATION_JSON), + AUTH_NAMES); + HttpResponse httpResponse = + new HttpResponse( + 200, null, Collections.emptyMap(), jsonNumberLookupResponseFullDto.getBytes()); + + when(httpClient.invokeAPI( + eq(serverConfiguration), + eq(authManagers), + argThat(new HttpRequestMatcher(httpRequest)))) + .thenReturn(httpResponse); + + NumberLookupResponse response = + service.lookup(NumberLookupRequestDtoTest.numberLookupRequestWithRndOptionsDto); + + TestHelpers.recursiveEquals(response, NumberLookupResponseDtoTest.numberLookupResponseFullDto); + } + + @Test + void lookupMissingProjectIdThrows() { + + NumberLookupV2Service serviceWithoutProjectId = + new NumberLookupV2ServiceImpl( + httpClient, serverConfiguration, authManagers, HttpMapper.getInstance(), null); + + ApiException thrown = + Assertions.assertThrows( + ApiException.class, + () -> + serviceWithoutProjectId.lookup( + NumberLookupRequestDtoTest.numberLookupRequestMinimalDto)); + + Assertions.assertEquals(400, thrown.getCode()); + } +} diff --git a/client/src/test/java/com/sinch/sdk/domains/voice/api/v1/adapters/CallsServiceTest.java b/client/src/test/java/com/sinch/sdk/domains/voice/api/v1/adapters/CallsServiceTest.java index 3d158a320..22e11c14d 100644 --- a/client/src/test/java/com/sinch/sdk/domains/voice/api/v1/adapters/CallsServiceTest.java +++ b/client/src/test/java/com/sinch/sdk/domains/voice/api/v1/adapters/CallsServiceTest.java @@ -22,8 +22,8 @@ import com.sinch.sdk.domains.voice.api.v1.CallsService; import com.sinch.sdk.domains.voice.models.v1.calls.CallInformationTest; import com.sinch.sdk.domains.voice.models.v1.calls.request.CallLeg; +import com.sinch.sdk.domains.voice.models.v1.calls.request.CallUpdateRequestTest; import com.sinch.sdk.domains.voice.models.v1.calls.response.CallInformation; -import com.sinch.sdk.domains.voice.models.v1.svaml.SvamlControlTest; import java.util.Arrays; import java.util.Collection; import java.util.Collections; @@ -38,8 +38,8 @@ public class CallsServiceTest extends BaseTest { @GivenTextResource("/domains/voice/v1/calls/GetCallInformationResponseDto.json") String getCallInformationResponseDto; - @GivenTextResource("/domains/voice/v1/svaml/SvamlControlDto.json") - String svamlControlDto; + @GivenTextResource("/domains/voice/v1/calls/request/CallUpdateRequestDto.json") + String callUpdateRequestDto; static final Collection AUTH_NAMES = Arrays.asList("Basic", "Signed"); @@ -95,7 +95,7 @@ void update() throws ApiException { "/calling/v1/calls/id/" + URLPathUtils.encodePathSegment("call/id"), HttpMethod.PATCH, Collections.emptyList(), - svamlControlDto, + callUpdateRequestDto, Collections.emptyMap(), Collections.emptyList(), Collections.singletonList(HttpContentType.APPLICATION_JSON), @@ -108,7 +108,7 @@ void update() throws ApiException { argThat(new HttpRequestMatcher(httpRequest)))) .thenReturn(httpResponse); - service.update("call/id", SvamlControlTest.expectedSvamlControl); + service.update("call/id", CallUpdateRequestTest.expectedCallUpdateRequest); } @Test @@ -119,7 +119,7 @@ void manageWithCallLeg() throws ApiException { "/calling/v1/calls/id/" + URLPathUtils.encodePathSegment("call/id") + "/leg/both", HttpMethod.PATCH, Collections.emptyList(), - svamlControlDto, + callUpdateRequestDto, Collections.emptyMap(), Collections.singletonList(HttpContentType.APPLICATION_JSON), Collections.singletonList(HttpContentType.APPLICATION_JSON), @@ -132,6 +132,7 @@ void manageWithCallLeg() throws ApiException { argThat(new HttpRequestMatcher(httpRequest)))) .thenReturn(httpResponse); - service.manageWithCallLeg("call/id", CallLeg.BOTH, SvamlControlTest.expectedSvamlControl); + service.manageWithCallLeg( + "call/id", CallLeg.BOTH, CallUpdateRequestTest.expectedCallUpdateRequest); } } diff --git a/client/src/test/java/com/sinch/sdk/e2e/Config.java b/client/src/test/java/com/sinch/sdk/e2e/Config.java index 830149340..ec636f6d4 100644 --- a/client/src/test/java/com/sinch/sdk/e2e/Config.java +++ b/client/src/test/java/com/sinch/sdk/e2e/Config.java @@ -4,6 +4,8 @@ import com.sinch.sdk.models.Configuration; import com.sinch.sdk.models.ConversationContext; import com.sinch.sdk.models.ConversationRegion; +import com.sinch.sdk.models.HttpProxyConfiguration; +import com.sinch.sdk.models.NumberLookupContext; import com.sinch.sdk.models.NumbersContext; import com.sinch.sdk.models.SMSRegion; import com.sinch.sdk.models.SmsContext; @@ -34,8 +36,22 @@ public class Config { public static final String VERIFICATION_HOST_NAME = "http://localhost:3018"; + public static final String NUMBER_LOOKUP_HOST_NAME = "http://localhost:3022"; + + public static final int PROXY_UNAUTHENTICATED_PORT = 3128; + public static final int PROXY_AUTHENTICATED_PORT = 3129; + public static final String PROXY_HOST = "localhost"; + public static final String PROXY_USERNAME = "user"; + public static final String PROXY_PASSWORD = "password"; + + public static final String PROXY_VISIBLE_AUTH_URL = + "http://authentication-server:1080/oauth2/token"; + public static final String PROXY_VISIBLE_NUMBER_LOOKUP_URL = "http://proxy-reachable-server:1080"; + private final SinchClient client; private final SinchClient clientServicePlanId; + private final SinchClient clientProxyUnauthenticated; + private final SinchClient clientProxyAuthenticated; private Config() { @@ -63,6 +79,8 @@ private Config() { SmsContext.builder().setSmsUrl(SMS_HOST_NAME).setSmsRegion(SMSRegion.EU).build()) .setVerificationContext( VerificationContext.builder().setVerificationUrl(VERIFICATION_HOST_NAME).build()) + .setNumberLookupContext( + NumberLookupContext.builder().setNumberLookupUrl(NUMBER_LOOKUP_HOST_NAME).build()) .build(); client = new SinchClient(configuration); @@ -76,6 +94,24 @@ private Config() { .build(); clientServicePlanId = new SinchClient(configurationServicePlanId); + + clientProxyUnauthenticated = + new SinchClient( + createConfigurationWithProxyUsage( + HttpProxyConfiguration.builder() + .setHostname(PROXY_HOST) + .setPort(Config.PROXY_UNAUTHENTICATED_PORT) + .build())); + + clientProxyAuthenticated = + new SinchClient( + createConfigurationWithProxyUsage( + HttpProxyConfiguration.builder() + .setHostname(PROXY_HOST) + .setPort(Config.PROXY_AUTHENTICATED_PORT) + .setUsername(PROXY_USERNAME) + .setPassword(PROXY_PASSWORD) + .build())); } private static class LazyHolder { @@ -89,4 +125,26 @@ public static SinchClient getSinchClient() { public static SinchClient getSinchClientServicePlanId() { return LazyHolder.INSTANCE.clientServicePlanId; } + + public static SinchClient getSinchClientProxyUnauthenticated() { + return LazyHolder.INSTANCE.clientProxyUnauthenticated; + } + + public static SinchClient getSinchClientProxyAuthenticated() { + return LazyHolder.INSTANCE.clientProxyAuthenticated; + } + + private static Configuration createConfigurationWithProxyUsage(HttpProxyConfiguration proxy) { + return Configuration.builder() + .setOAuthUrl(PROXY_VISIBLE_AUTH_URL) + .setProjectId(Config.PROJECT_ID) + .setKeyId(Config.KEY_ID) + .setKeySecret(Config.KEY_SECRET) + .setNumberLookupContext( + NumberLookupContext.builder() + .setNumberLookupUrl(PROXY_VISIBLE_NUMBER_LOOKUP_URL) + .build()) + .setHttpProxyConfiguration(proxy) + .build(); + } } diff --git a/client/src/test/java/com/sinch/sdk/e2e/domains/conversation/ConsentsSteps.java b/client/src/test/java/com/sinch/sdk/e2e/domains/conversation/ConsentsSteps.java index 8c04b3c41..8597f86aa 100644 --- a/client/src/test/java/com/sinch/sdk/e2e/domains/conversation/ConsentsSteps.java +++ b/client/src/test/java/com/sinch/sdk/e2e/domains/conversation/ConsentsSteps.java @@ -1,57 +1,101 @@ package com.sinch.sdk.e2e.domains.conversation; +import com.sinch.sdk.core.TestHelpers; +import com.sinch.sdk.domains.conversation.api.v1.ConsentsService; +import com.sinch.sdk.domains.conversation.models.v1.consents.ConsentsListType; +import com.sinch.sdk.domains.conversation.models.v1.consents.request.ConsentsListQueryParameters; +import com.sinch.sdk.domains.conversation.models.v1.consents.response.AuditRecord; +import com.sinch.sdk.domains.conversation.models.v1.consents.response.AuditRecordsResponse; +import com.sinch.sdk.domains.conversation.models.v1.consents.response.ConsentsListResponse; +import com.sinch.sdk.e2e.Config; import io.cucumber.java.en.Given; import io.cucumber.java.en.Then; import io.cucumber.java.en.When; +import java.time.Instant; +import java.util.Iterator; +import org.junit.jupiter.api.Assertions; public class ConsentsSteps { + static final String APP_ID = AppsSteps.APP_ID; + static final String IDENTITY = "33612345678"; + + ConsentsService service; + ConsentsListResponse listPageResponse; + AuditRecordsResponse listAuditRecordsResponse; + @Given("^the Conversation service \"Consents\" is available$") public void serviceAvailable() { - // TODO implement conversation consents steps + service = Config.getSinchClient().conversation().v1().consents(); } @When("^I send a request to list the existing Consent Identities$") public void listPage() { - - // TODO implement conversation consents steps + ConsentsListQueryParameters queryParams = + ConsentsListQueryParameters.builder().setPageSize(10).build(); + listPageResponse = service.listIdentities(APP_ID, ConsentsListType.OPT_OUT_ALL, queryParams); } @When("^I send a request to list all the Consent Identities$") public void listAll() { - - // TODO implement conversation consents steps + ConsentsListQueryParameters queryParams = + ConsentsListQueryParameters.builder().setPageSize(10).build(); + listPageResponse = service.listIdentities(APP_ID, ConsentsListType.OPT_OUT_ALL, queryParams); } @When("^I iterate manually over the Consent Identities pages$") public void listIterateManually() { - - // TODO implement conversation consents steps + ConsentsListQueryParameters queryParams = + ConsentsListQueryParameters.builder().setPageSize(10).build(); + listPageResponse = service.listIdentities(APP_ID, ConsentsListType.OPT_OUT_ALL, queryParams); } @When("^I send a request to list the Audit Records associated with an identity$") public void listAuditRecords() { - - // TODO implement conversation consents steps + listAuditRecordsResponse = service.listAuditRecords(APP_ID, IDENTITY); } @Then("the response contains \"{int}\" Consent Identities") public void listPageResult(int count) { - // TODO implement conversation consents steps + Assertions.assertEquals(count, listPageResponse.getContent().size()); } @Then("the Consent Identities list contains \"{int}\" Consent Identities") public void listAllResult(int count) { - // TODO implement conversation consents steps + Iterator iterator = listPageResponse.iterator(); + TestHelpers.checkIteratorItems(iterator, count); } @Then("the Consent Identities iteration result contains the data from \"{int}\" pages") public void listPageIterateResult(int count) { - // TODO implement conversation consents steps + int pageCount = 0; + ConsentsListResponse currentPage = listPageResponse; + do { + pageCount++; + if (!currentPage.hasNextPage()) { + break; + } + currentPage = currentPage.nextPage(); + } while (true); + + Assertions.assertEquals(pageCount, count); } @Then("the response contains list of the Audit Records associated with an identity") public void listAuditRecordsResult() { - // TODO implement conversation consents steps + Assertions.assertNotNull(listAuditRecordsResponse); + Assertions.assertNotNull(listAuditRecordsResponse.getIdentity()); + Assertions.assertEquals("33612345678", listAuditRecordsResponse.getIdentity().getIdentity()); + + Assertions.assertNotNull(listAuditRecordsResponse.getAuditRecords()); + Assertions.assertEquals(1, listAuditRecordsResponse.getAuditRecords().size()); + + AuditRecord record = listAuditRecordsResponse.getAuditRecords().get(0); + Assertions.assertEquals(AuditRecord.OriginEnum.ORIGIN_MO, record.getOrigin()); + Assertions.assertEquals(AuditRecord.OperationEnum.OPERATION_INSERT, record.getOperation()); + Assertions.assertEquals(ConsentsListType.OPT_OUT_ALL, record.getListType()); + Assertions.assertEquals("123coffee-dada-beef-cafe-baadc0de5678", record.getProjectId()); + Assertions.assertEquals(APP_ID, record.getAppId()); + Assertions.assertEquals(Instant.parse("2025-06-06T14:42:56.031323Z"), record.getDatetime()); } } diff --git a/client/src/test/java/com/sinch/sdk/e2e/domains/conversation/ContactsSteps.java b/client/src/test/java/com/sinch/sdk/e2e/domains/conversation/ContactsSteps.java index 6827278d8..8bb48a5a2 100644 --- a/client/src/test/java/com/sinch/sdk/e2e/domains/conversation/ContactsSteps.java +++ b/client/src/test/java/com/sinch/sdk/e2e/domains/conversation/ContactsSteps.java @@ -30,16 +30,12 @@ public class ContactsSteps { ContactsService service; Contact createResponse; ContactsListResponse listPageResponse; - ContactsListResponse listAllResponse; - ContactsListResponse listPageIterateResponse; Contact getResponse; Contact updateResponse; Contact mergeResponse; boolean deletePassed; GetChannelProfileResponse channelProfileByContactIdResponse; IdentityConflictsListResponse listIdentityConflictsResponse; - IdentityConflictsListResponse listAllIdentityConflictsResponse; - IdentityConflictsListResponse listPageIterateIdentityConflictsResponse; @Given("^the Conversation service \"Contacts\" is available$") public void serviceAvailable() { @@ -78,7 +74,7 @@ public void listAll() { ContactsListQueryParameters request = ContactsListQueryParameters.builder().setPageSize(2).build(); - listAllResponse = service.list(request); + listPageResponse = service.list(request); } @When("^I iterate manually over the contacts pages$") @@ -86,7 +82,7 @@ public void listPageIterate() { ContactsListQueryParameters request = ContactsListQueryParameters.builder().setPageSize(2).build(); - listPageIterateResponse = service.list(request); + listPageResponse = service.list(request); } @When("^I send a request to retrieve a contact$") @@ -156,7 +152,7 @@ public void listIdentityConflictsAll() { IdentityConflictsListQueryParameters request = IdentityConflictsListQueryParameters.builder().setPageSize(2).build(); - listAllIdentityConflictsResponse = service.listIdentityConflicts(request); + listIdentityConflictsResponse = service.listIdentityConflicts(request); } @When("^I iterate manually over the identity conflicts pages$") @@ -164,7 +160,7 @@ public void listIdentityConflictsPageIterate() { IdentityConflictsListQueryParameters request = IdentityConflictsListQueryParameters.builder().setPageSize(2).build(); - listPageIterateIdentityConflictsResponse = service.listIdentityConflicts(request); + listIdentityConflictsResponse = service.listIdentityConflicts(request); } @Then("the contact is created") @@ -181,15 +177,7 @@ public void listExistingResult(int size) { @Then("the contacts list contains \"{int}\" contacts") public void listAllResult(int size) { - // FIXME: to be thread-safe compliant we need to check which variables are set - Iterator iterator = null; - if (null != listAllResponse) { - iterator = listAllResponse.iterator(); - } - - if (null != listPageIterateResponse) { - iterator = listPageIterateResponse.iterator(); - } + Iterator iterator = listPageResponse.iterator(); TestHelpers.checkIteratorItems(iterator, size); } @@ -197,15 +185,13 @@ public void listAllResult(int size) { public void listPageIterateResult(int size) { int pageCount = 0; - - ContactsListResponse listPageIterateResponseThreadSafety = listPageIterateResponse; + ContactsListResponse currentPage = listPageResponse; do { pageCount++; - if (!listPageIterateResponseThreadSafety.hasNextPage()) { + if (!currentPage.hasNextPage()) { break; } - listPageIterateResponseThreadSafety = listPageIterateResponseThreadSafety.nextPage(); - + currentPage = currentPage.nextPage(); } while (true); Assertions.assertEquals(pageCount, size); @@ -281,15 +267,8 @@ public void listIdentityConflictsResults(int count) { @Then("the identity conflicts list contains \"{int}\" identity conflicts") public void listIdentityConflictsAllResults(int count) { - // FIXME: to be thread-safe compliant we need to check which variables are set - Iterator iterator = null; - if (null != listAllIdentityConflictsResponse) { - iterator = listAllIdentityConflictsResponse.iterator(); - } - - if (null != listPageIterateIdentityConflictsResponse) { - iterator = listPageIterateIdentityConflictsResponse.iterator(); - } + + Iterator iterator = listIdentityConflictsResponse.iterator(); TestHelpers.checkIteratorItems(iterator, count); } @@ -297,15 +276,13 @@ public void listIdentityConflictsAllResults(int count) { public void listAllIdentityConflictsPageIterateResults(int count) { int pageCount = 0; - IdentityConflictsListResponse listPageIterateResponseThreadSafety = - listPageIterateIdentityConflictsResponse; + IdentityConflictsListResponse currentPage = listIdentityConflictsResponse; do { pageCount++; - if (!listPageIterateResponseThreadSafety.hasNextPage()) { + if (!currentPage.hasNextPage()) { break; } - listPageIterateResponseThreadSafety = listPageIterateResponseThreadSafety.nextPage(); - + currentPage = currentPage.nextPage(); } while (true); Assertions.assertEquals(pageCount, count); diff --git a/client/src/test/java/com/sinch/sdk/e2e/domains/conversation/ConversationIT.java b/client/src/test/java/com/sinch/sdk/e2e/domains/conversation/ConversationIT.java index f865e2159..e5e633e6c 100644 --- a/client/src/test/java/com/sinch/sdk/e2e/domains/conversation/ConversationIT.java +++ b/client/src/test/java/com/sinch/sdk/e2e/domains/conversation/ConversationIT.java @@ -1,6 +1,7 @@ package com.sinch.sdk.e2e.domains.conversation; import static io.cucumber.junit.platform.engine.Constants.GLUE_PROPERTY_NAME; +import static io.cucumber.junit.platform.engine.Constants.PARALLEL_EXECUTION_ENABLED_PROPERTY_NAME; import org.junit.platform.suite.api.ConfigurationParameter; import org.junit.platform.suite.api.IncludeEngines; @@ -13,4 +14,5 @@ @IncludeEngines("cucumber") @SelectClasspathResource("features/conversation") @ConfigurationParameter(key = GLUE_PROPERTY_NAME, value = "com.sinch.sdk.e2e.domains.conversation") +@ConfigurationParameter(key = PARALLEL_EXECUTION_ENABLED_PROPERTY_NAME, value = "true") public class ConversationIT {} diff --git a/client/src/test/java/com/sinch/sdk/e2e/domains/conversation/ConversationsSteps.java b/client/src/test/java/com/sinch/sdk/e2e/domains/conversation/ConversationsSteps.java index 6c0db3b92..971a8864d 100644 --- a/client/src/test/java/com/sinch/sdk/e2e/domains/conversation/ConversationsSteps.java +++ b/client/src/test/java/com/sinch/sdk/e2e/domains/conversation/ConversationsSteps.java @@ -38,11 +38,7 @@ public class ConversationsSteps { ConversationsService service; Conversation createResponse; ConversationsListResponse listPageResponse; - ConversationsListResponse listAllResponse; - ConversationsListResponse listPageIterateResponse; RecentConversationsListResponse listRecentPageResponse; - RecentConversationsListResponse listRecentAllResponse; - RecentConversationsListResponse listRecentPageIterateResponse; Conversation getResponse; Conversation updateResponse; boolean deletePassed; @@ -87,7 +83,7 @@ public void listAll() { ConversationsListQueryParameters request = ConversationsListQueryParameters.builder().setAppId(AppsSteps.APP_ID).build(); - listAllResponse = service.list(request); + listPageResponse = service.list(request); } @When("^I iterate manually over the conversations pages$") @@ -95,7 +91,7 @@ public void listPageIterate() { ConversationsListQueryParameters request = ConversationsListQueryParameters.builder().setAppId(AppsSteps.APP_ID).build(); - listPageIterateResponse = service.list(request); + listPageResponse = service.list(request); } @When("^I send a request to list the recent conversations$") @@ -111,7 +107,7 @@ public void listRecentAll() { RecentConversationsListQueryParameters request = RecentConversationsListQueryParameters.builder().setAppId(AppsSteps.APP_ID).build(); - listRecentAllResponse = service.listRecent(request); + listRecentPageResponse = service.listRecent(request); } @When("^I iterate manually over the recent conversations pages$") @@ -119,7 +115,7 @@ public void listRecentPageIterate() { RecentConversationsListQueryParameters request = RecentConversationsListQueryParameters.builder().setAppId(AppsSteps.APP_ID).build(); - listRecentPageIterateResponse = service.listRecent(request); + listRecentPageResponse = service.listRecent(request); } @When("^I send a request to retrieve a conversation$") @@ -205,15 +201,7 @@ public void listPageResult(int size) { @Then("the conversations list contains \"{int}\" conversations") public void listAllResult(int size) { - // FIXME: to be thread-safe compliant we need to check which variables are set - Iterator iterator = null; - if (null != listAllResponse) { - iterator = listAllResponse.iterator(); - } - - if (null != listPageIterateResponse) { - iterator = listPageIterateResponse.iterator(); - } + Iterator iterator = listPageResponse.iterator(); TestHelpers.checkIteratorItems(iterator, size); } @@ -221,15 +209,13 @@ public void listAllResult(int size) { public void listPageIterateResult(int size) { int pageCount = 0; - - ConversationsListResponse listPageIterateResponseThreadSafety = listPageIterateResponse; + ConversationsListResponse currentPage = listPageResponse; do { pageCount++; - if (!listPageIterateResponseThreadSafety.hasNextPage()) { + if (!currentPage.hasNextPage()) { break; } - listPageIterateResponseThreadSafety = listPageIterateResponseThreadSafety.nextPage(); - + currentPage = currentPage.nextPage(); } while (true); Assertions.assertEquals(pageCount, size); @@ -244,14 +230,7 @@ public void listRecentPageResult(int size) { @Then("the recent conversations list contains \"{int}\" recent conversations") public void listRecentAllResult(int size) { - Iterator iterator = null; - if (null != listRecentAllResponse) { - iterator = listRecentAllResponse.iterator(); - } - - if (null != listRecentPageIterateResponse) { - iterator = listRecentPageIterateResponse.iterator(); - } + Iterator iterator = listRecentPageResponse.iterator(); TestHelpers.checkIteratorItems(iterator, size); } @@ -259,16 +238,13 @@ public void listRecentAllResult(int size) { public void listRecentPageIterateResult(int size) { int pageCount = 0; - - RecentConversationsListResponse listPageIterateResponseThreadSafety = - listRecentPageIterateResponse; + RecentConversationsListResponse currentPage = listRecentPageResponse; do { pageCount++; - if (!listPageIterateResponseThreadSafety.hasNextPage()) { + if (!currentPage.hasNextPage()) { break; } - listPageIterateResponseThreadSafety = listPageIterateResponseThreadSafety.nextPage(); - + currentPage = currentPage.nextPage(); } while (true); Assertions.assertEquals(pageCount, size); diff --git a/client/src/test/java/com/sinch/sdk/e2e/domains/conversation/EventsSteps.java b/client/src/test/java/com/sinch/sdk/e2e/domains/conversation/EventsSteps.java index 482ae8c09..9cc12aa0e 100644 --- a/client/src/test/java/com/sinch/sdk/e2e/domains/conversation/EventsSteps.java +++ b/client/src/test/java/com/sinch/sdk/e2e/domains/conversation/EventsSteps.java @@ -23,8 +23,6 @@ public class EventsSteps { EventsService service; SendEventResponse sendResponse; EventsListResponse listPageResponse; - EventsListResponse listAllResponse; - EventsListResponse listPageIterateResponse; ConversationEvent getResponse; boolean deletePassed; @@ -57,14 +55,14 @@ public void listPage() { public void listAll() { EventsListQueryParameters request = EventsListQueryParameters.builder().setPageSize(2).build(); - listAllResponse = service.list(request); + listPageResponse = service.list(request); } @When("^I iterate manually over the conversation events pages$") public void listPageIterate() { EventsListQueryParameters request = EventsListQueryParameters.builder().setPageSize(2).build(); - listPageIterateResponse = service.list(request); + listPageResponse = service.list(request); } @When("^I send a request to retrieve a conversation event$") @@ -94,15 +92,7 @@ public void listPageResult(int size) { @Then("the conversation events list contains \"{int}\" conversation events") public void listAllResult(int size) { - // FIXME: to be thread-safe compliant we need to check which variables are set - Iterator iterator = null; - if (null != listAllResponse) { - iterator = listAllResponse.iterator(); - } - - if (null != listPageIterateResponse) { - iterator = listPageIterateResponse.iterator(); - } + Iterator iterator = listPageResponse.iterator(); TestHelpers.checkIteratorItems(iterator, size); } @@ -110,15 +100,13 @@ public void listAllResult(int size) { public void listPageIterateResult(int size) { int pageCount = 0; - - EventsListResponse listPageIterateResponseThreadSafety = listPageIterateResponse; + EventsListResponse currentPage = listPageResponse; do { pageCount++; - if (!listPageIterateResponseThreadSafety.hasNextPage()) { + if (!currentPage.hasNextPage()) { break; } - listPageIterateResponseThreadSafety = listPageIterateResponseThreadSafety.nextPage(); - + currentPage = currentPage.nextPage(); } while (true); Assertions.assertEquals(pageCount, size); diff --git a/client/src/test/java/com/sinch/sdk/e2e/domains/conversation/MessagesSteps.java b/client/src/test/java/com/sinch/sdk/e2e/domains/conversation/MessagesSteps.java index d5b0bea6e..2fede9688 100644 --- a/client/src/test/java/com/sinch/sdk/e2e/domains/conversation/MessagesSteps.java +++ b/client/src/test/java/com/sinch/sdk/e2e/domains/conversation/MessagesSteps.java @@ -29,13 +29,9 @@ public class MessagesSteps { MessagesService service; SendMessageResponse sendResponse; MessagesListResponse listPageResponse; - MessagesListResponse listAllResponse; - MessagesListResponse listPageIterateResponse; ConversationMessage getResponse; ConversationMessage updateResponse; MessagesListResponse listLastMessagesByChannelIdentityResponse; - MessagesListResponse listAllLastMessagesByChannelIdentityResponse; - MessagesListResponse listPageIteratorLastMessagesByChannelIdentityResponse; boolean deletePassed; @@ -73,7 +69,7 @@ public void listAll() { MessagesListQueryParameters request = MessagesListQueryParameters.builder().setPageSize(2).build(); - listAllResponse = service.list(request); + listPageResponse = service.list(request); } @When("^I iterate manually over the messages pages$") @@ -81,7 +77,7 @@ public void listPageIterate() { MessagesListQueryParameters request = MessagesListQueryParameters.builder().setPageSize(2).build(); - listPageIterateResponse = service.list(request); + listPageResponse = service.list(request); } @When("^I send a request to retrieve a message$") @@ -126,8 +122,7 @@ public void listAllLastMessagesByChannelIdentity() { .setMessagesSource(MessageSource.CONVERSATION_SOURCE) .setPageSize(2) .build(); - listAllLastMessagesByChannelIdentityResponse = - service.listLastMessagesByChannelIdentity(request); + listLastMessagesByChannelIdentityResponse = service.listLastMessagesByChannelIdentity(request); } @When("^I iterate manually over the last messages sent to specified channel identities pages$") @@ -139,8 +134,7 @@ public void listLastMessagesByChannelIdentityPageIterator() { .setMessagesSource(MessageSource.CONVERSATION_SOURCE) .setPageSize(2) .build(); - listPageIteratorLastMessagesByChannelIdentityResponse = - service.listLastMessagesByChannelIdentity(request); + listLastMessagesByChannelIdentityResponse = service.listLastMessagesByChannelIdentity(request); } @Then("the response contains the id of the message") @@ -160,15 +154,7 @@ public void listPageResult(int size) { @Then("the messages list contains \"{int}\" messages") public void listAllResult(int size) { - // FIXME: to be thread-safe compliant we need to check which variables are set - Iterator iterator = null; - if (null != listAllResponse) { - iterator = listAllResponse.iterator(); - } - - if (null != listPageIterateResponse) { - iterator = listPageIterateResponse.iterator(); - } + Iterator iterator = listPageResponse.iterator(); TestHelpers.checkIteratorItems(iterator, size); } @@ -176,15 +162,13 @@ public void listAllResult(int size) { public void listPageIterateResult(int size) { int pageCount = 0; - - MessagesListResponse listPageIterateResponseThreadSafety = listPageIterateResponse; + MessagesListResponse currentPage = listPageResponse; do { pageCount++; - if (!listPageIterateResponseThreadSafety.hasNextPage()) { + if (!currentPage.hasNextPage()) { break; } - listPageIterateResponseThreadSafety = listPageIterateResponseThreadSafety.nextPage(); - + currentPage = currentPage.nextPage(); } while (true); Assertions.assertEquals(pageCount, size); @@ -215,16 +199,8 @@ public void listLastMessagesByChannelIdentity(int size) { @Then("the response list contains \"{int}\" last messages sent to specified channel identities") public void listAllLastMessagesByChannelIdentity(int size) { - Iterator iterator = null; - - if (null != listAllLastMessagesByChannelIdentityResponse) { - iterator = listAllLastMessagesByChannelIdentityResponse.iterator(); - } - - if (null != listPageIteratorLastMessagesByChannelIdentityResponse) { - iterator = listPageIteratorLastMessagesByChannelIdentityResponse.iterator(); - } + Iterator iterator = listLastMessagesByChannelIdentityResponse.iterator(); TestHelpers.checkIteratorItems(iterator, size); } @@ -234,16 +210,13 @@ public void listAllLastMessagesByChannelIdentity(int size) { public void listAllLastMessagesByChannelIdentityPageIterator(int size) { int pageCount = 0; - - MessagesListResponse listPageIterateResponseThreadSafety = - listPageIteratorLastMessagesByChannelIdentityResponse; + MessagesListResponse currentPage = listLastMessagesByChannelIdentityResponse; do { pageCount++; - if (!listPageIterateResponseThreadSafety.hasNextPage()) { + if (!currentPage.hasNextPage()) { break; } - listPageIterateResponseThreadSafety = listPageIterateResponseThreadSafety.nextPage(); - + currentPage = currentPage.nextPage(); } while (true); Assertions.assertEquals(pageCount, size); diff --git a/client/src/test/java/com/sinch/sdk/e2e/domains/numberlookup/v2/LookupsSteps.java b/client/src/test/java/com/sinch/sdk/e2e/domains/numberlookup/v2/LookupsSteps.java new file mode 100644 index 000000000..f2b0daf88 --- /dev/null +++ b/client/src/test/java/com/sinch/sdk/e2e/domains/numberlookup/v2/LookupsSteps.java @@ -0,0 +1,124 @@ +package com.sinch.sdk.e2e.domains.numberlookup.v2; + +import com.sinch.sdk.core.TestHelpers; +import com.sinch.sdk.domains.numberlookup.api.v2.NumberLookupV2Service; +import com.sinch.sdk.domains.numberlookup.models.v2.errors.LookupError; +import com.sinch.sdk.domains.numberlookup.models.v2.request.LookupFeatureType; +import com.sinch.sdk.domains.numberlookup.models.v2.request.NumberLookupRequest; +import com.sinch.sdk.domains.numberlookup.models.v2.request.RndFeatureOptions; +import com.sinch.sdk.domains.numberlookup.models.v2.response.Line; +import com.sinch.sdk.domains.numberlookup.models.v2.response.LineType; +import com.sinch.sdk.domains.numberlookup.models.v2.response.NumberLookupResponse; +import com.sinch.sdk.domains.numberlookup.models.v2.response.Rnd; +import com.sinch.sdk.domains.numberlookup.models.v2.response.SimSwap; +import com.sinch.sdk.domains.numberlookup.models.v2.response.VoIPDetection; +import com.sinch.sdk.e2e.Config; +import io.cucumber.java.en.Given; +import io.cucumber.java.en.Then; +import io.cucumber.java.en.When; +import java.time.Instant; +import java.time.LocalDate; +import java.util.Arrays; +import org.junit.jupiter.api.Assertions; + +public class LookupsSteps { + + NumberLookupV2Service service; + NumberLookupResponse lookupNoFeaturesResponse; + NumberLookupResponse lookupAllFeaturesResponse; + + @Given("the Number Lookup service is available") + public void serviceAvailable() { + service = Config.getSinchClient().lookup().v2(); + Assertions.assertNotNull(service, "Number Lookup service is not available"); + } + + @When("I send a request to lookup for a phone number with no additional features") + public void lookupNoFeatures() { + NumberLookupRequest request = NumberLookupRequest.builder().setNumber("+12016666666").build(); + lookupNoFeaturesResponse = service.lookup(request); + } + + @Then("the response contains the details of the phone number lookup with line details only") + public void lookupNoFeaturesResult() { + + NumberLookupResponse expected = + NumberLookupResponse.builder() + .setNumber("+12016666666") + .setCountryCode("US") + .setTraceId("84c1fd4063c38d9f3900d06e56542d48") + .setLine( + Line.builder() + .setCarrier("T-Mobile USA") + .setType(LineType.MOBILE) + .setMobileCountryCode("310") + .setMobileNetworkCode("260") + .build()) + .build(); + + TestHelpers.recursiveEquals(lookupNoFeaturesResponse, expected); + } + + @When("I send a request to lookup for a phone number with all the features") + public void lookupAllFeatures() { + NumberLookupRequest request = + NumberLookupRequest.builder() + .setNumber("+12015555555") + .setFeatures( + Arrays.asList( + LookupFeatureType.LINE_TYPE, + LookupFeatureType.RND, + LookupFeatureType.SIM_SWAP, + LookupFeatureType.VO_IP_DETECTION)) + .setRndFeatureOptions( + RndFeatureOptions.builder().setContactDate(LocalDate.parse("2025-09-09")).build()) + .build(); + lookupAllFeaturesResponse = service.lookup(request); + } + + @Then("the response contains the details of the phone number lookup with all the features") + public void lookupAllFeaturesResult() { + + LookupError simSwapError = + LookupError.builder() + .setStatus(100) + .setTitle("Feature Disabled") + .setDetail("SimSwap feature is currently disabled.") + .build(); + + LookupError voIPDetectionError = + LookupError.builder() + .setStatus(100) + .setTitle("Feature Disabled") + .setDetail("VoIPDetection feature is currently disabled.") + .build(); + + LookupError rndError = + LookupError.builder() + .setStatus(100) + .setTitle("Feature Disabled") + .setDetail("RND feature is currently disabled.") + .build(); + + NumberLookupResponse expected = + NumberLookupResponse.builder() + .setNumber("+12015555555") + .setCountryCode("US") + .setTraceId("5c817a6b7351d80a6b1d8007e5c145b8") + .setLine( + Line.builder() + .setCarrier("AT&T") + .setType(LineType.MOBILE) + .setMobileCountryCode("310") + .setMobileNetworkCode("070") + .setPorted(true) + .setPortingDate(Instant.parse("2010-08-07T23:45:49Z")) + .build()) + .setSimSwap(SimSwap.builder().setError(simSwapError).build()) + .setVoIPDetection(VoIPDetection.builder().setError(voIPDetectionError).build()) + .setRnd(Rnd.builder().setError(rndError).build()) + .build(); + + TestHelpers.recursiveEquals(lookupAllFeaturesResponse, expected); + } +} diff --git a/client/src/test/java/com/sinch/sdk/e2e/domains/numberlookup/v2/NumberLookupIT.java b/client/src/test/java/com/sinch/sdk/e2e/domains/numberlookup/v2/NumberLookupIT.java new file mode 100644 index 000000000..89c7aaae4 --- /dev/null +++ b/client/src/test/java/com/sinch/sdk/e2e/domains/numberlookup/v2/NumberLookupIT.java @@ -0,0 +1,20 @@ +package com.sinch.sdk.e2e.domains.numberlookup.v2; + +import static io.cucumber.junit.platform.engine.Constants.GLUE_PROPERTY_NAME; +import static io.cucumber.junit.platform.engine.Constants.PARALLEL_EXECUTION_ENABLED_PROPERTY_NAME; + +import org.junit.platform.suite.api.ConfigurationParameter; +import org.junit.platform.suite.api.IncludeEngines; +import org.junit.platform.suite.api.SelectClasspathResource; +import org.junit.platform.suite.api.Suite; +import org.junit.platform.suite.api.SuiteDisplayName; + +@Suite +@SuiteDisplayName("Number Lookup V2") +@IncludeEngines("cucumber") +@SelectClasspathResource("features/number-lookup") +@ConfigurationParameter( + key = GLUE_PROPERTY_NAME, + value = "com.sinch.sdk.e2e.domains.numberlookup.v2") +@ConfigurationParameter(key = PARALLEL_EXECUTION_ENABLED_PROPERTY_NAME, value = "true") +public class NumberLookupIT {} diff --git a/client/src/test/java/com/sinch/sdk/e2e/domains/numbers/v1/NumbersIT.java b/client/src/test/java/com/sinch/sdk/e2e/domains/numbers/v1/NumbersIT.java index ea1a27336..3be0f0910 100644 --- a/client/src/test/java/com/sinch/sdk/e2e/domains/numbers/v1/NumbersIT.java +++ b/client/src/test/java/com/sinch/sdk/e2e/domains/numbers/v1/NumbersIT.java @@ -1,6 +1,7 @@ package com.sinch.sdk.e2e.domains.numbers.v1; import static io.cucumber.junit.platform.engine.Constants.GLUE_PROPERTY_NAME; +import static io.cucumber.junit.platform.engine.Constants.PARALLEL_EXECUTION_ENABLED_PROPERTY_NAME; import org.junit.platform.suite.api.ConfigurationParameter; import org.junit.platform.suite.api.IncludeEngines; @@ -13,4 +14,5 @@ @IncludeEngines("cucumber") @SelectClasspathResource("features/numbers") @ConfigurationParameter(key = GLUE_PROPERTY_NAME, value = "com.sinch.sdk.e2e.domains.numbers.v1") +@ConfigurationParameter(key = PARALLEL_EXECUTION_ENABLED_PROPERTY_NAME, value = "true") public class NumbersIT {} diff --git a/client/src/test/java/com/sinch/sdk/e2e/domains/numbers/v1/NumbersSteps.java b/client/src/test/java/com/sinch/sdk/e2e/domains/numbers/v1/NumbersSteps.java index 656f58a09..83f7bf70f 100644 --- a/client/src/test/java/com/sinch/sdk/e2e/domains/numbers/v1/NumbersSteps.java +++ b/client/src/test/java/com/sinch/sdk/e2e/domains/numbers/v1/NumbersSteps.java @@ -46,8 +46,6 @@ public class NumbersSteps { ActiveNumber rentResponse; ActiveNumbersListResponse activeNumberListResponse; - ActiveNumbersListResponse activeNumberListAllResponse; - ActiveNumber updateResponse; ActiveNumber getResponse; ApiException getResponseException; @@ -156,7 +154,7 @@ public void listAll() { .setRegionCode("US") .setType(NumberType.LOCAL) .build(); - activeNumberListAllResponse = service.list(request); + activeNumberListResponse = service.list(request); } @When("I send a request to update the phone number {string}") @@ -336,7 +334,7 @@ public void listResult(int expected) { @Then("the phone numbers list contains \"{int}\" phone numbers") public void listAllResult(int expected) { - Assertions.assertEquals(expected, activeNumberListAllResponse.stream().count()); + Assertions.assertEquals(expected, activeNumberListResponse.stream().count()); } @Then("the response contains a phone number with updated parameters") diff --git a/client/src/test/java/com/sinch/sdk/e2e/domains/numbers/v1/SinchEventsSteps.java b/client/src/test/java/com/sinch/sdk/e2e/domains/numbers/v1/SinchEventsSteps.java index a8b39cae9..8adcd341c 100644 --- a/client/src/test/java/com/sinch/sdk/e2e/domains/numbers/v1/SinchEventsSteps.java +++ b/client/src/test/java/com/sinch/sdk/e2e/domains/numbers/v1/SinchEventsSteps.java @@ -81,6 +81,7 @@ public void validateResult(String status, String trigger) { .setEventType(EventTypeEnum.PROVISIONING_TO_VOICE_PLATFORM) .setStatus(StatusEnum.SUCCEEDED) .setFailureCode(null) + .setInternalFailureCode(null) .build(); NumberSinchEvent expectedFailure = @@ -93,6 +94,7 @@ public void validateResult(String status, String trigger) { .setEventType(EventTypeEnum.PROVISIONING_TO_VOICE_PLATFORM) .setStatus(StatusEnum.FAILED) .setFailureCode(FailureCodeEnum.from("PROVISIONING_TO_VOICE_PLATFORM_FAILED")) + .setInternalFailureCode(null) .build(); NumberSinchEvent expected = diff --git a/client/src/test/java/com/sinch/sdk/e2e/domains/proxy/HttpClientApacheProxyIT.java b/client/src/test/java/com/sinch/sdk/e2e/domains/proxy/HttpClientApacheProxyIT.java new file mode 100644 index 000000000..3064112ed --- /dev/null +++ b/client/src/test/java/com/sinch/sdk/e2e/domains/proxy/HttpClientApacheProxyIT.java @@ -0,0 +1,77 @@ +package com.sinch.sdk.e2e.domains.proxy; + +import static org.junit.jupiter.api.Assertions.*; + +import com.sinch.sdk.core.http.HttpMethod; +import com.sinch.sdk.core.http.HttpRequest; +import com.sinch.sdk.core.http.HttpResponse; +import com.sinch.sdk.core.models.ServerConfiguration; +import com.sinch.sdk.e2e.Config; +import com.sinch.sdk.http.HttpClientApache; +import com.sinch.sdk.models.HttpProxyConfiguration; +import org.junit.jupiter.api.Test; + +class HttpClientApacheProxyIT { + + private static final String PROXY_HOST = "localhost"; + private static final String TARGET_URL = "http://proxy-reachable-server:1080/"; + + private static HttpRequest simpleGetRequest() { + return new HttpRequest("health", HttpMethod.GET, null, (String) null, null, null, null, null); + } + + @Test + void unauthenticatedProxyRoutesTraffic() throws Exception { + HttpProxyConfiguration proxyConfig = + HttpProxyConfiguration.builder() + .setHostname(PROXY_HOST) + .setPort(Config.PROXY_UNAUTHENTICATED_PORT) + .build(); + + try (HttpClientApache client = new HttpClientApache(proxyConfig)) { + HttpResponse response = + client.invokeAPI(new ServerConfiguration(TARGET_URL), null, simpleGetRequest()); + + assertEquals(200, response.getCode(), "Request through unauthenticated proxy must succeed"); + } + } + + @Test + void authenticatedProxyRoutesTraffic() throws Exception { + HttpProxyConfiguration proxyConfig = + HttpProxyConfiguration.builder() + .setHostname(PROXY_HOST) + .setPort(Config.PROXY_AUTHENTICATED_PORT) + .setUsername("user") + .setPassword("password") + .build(); + + try (HttpClientApache client = new HttpClientApache(proxyConfig)) { + HttpResponse response = + client.invokeAPI(new ServerConfiguration(TARGET_URL), null, simpleGetRequest()); + + assertEquals(200, response.getCode(), "Request through authenticated proxy must succeed"); + } + } + + @Test + void authenticatedProxyRejectsWrongCredentials() throws Exception { + HttpProxyConfiguration proxyConfig = + HttpProxyConfiguration.builder() + .setHostname(PROXY_HOST) + .setPort(Config.PROXY_AUTHENTICATED_PORT) + .setUsername("wrong-user") + .setPassword("wrong-pass") + .build(); + + try (HttpClientApache client = new HttpClientApache(proxyConfig)) { + HttpResponse response = + client.invokeAPI(new ServerConfiguration(TARGET_URL), null, simpleGetRequest()); + + assertEquals( + 407, + response.getCode(), + "Wrong credentials must result in 407 Proxy Authentication Required"); + } + } +} diff --git a/client/src/test/java/com/sinch/sdk/e2e/domains/proxy/ProxyIT.java b/client/src/test/java/com/sinch/sdk/e2e/domains/proxy/ProxyIT.java new file mode 100644 index 000000000..80db3d35c --- /dev/null +++ b/client/src/test/java/com/sinch/sdk/e2e/domains/proxy/ProxyIT.java @@ -0,0 +1,18 @@ +package com.sinch.sdk.e2e.domains.proxy; + +import static io.cucumber.junit.platform.engine.Constants.GLUE_PROPERTY_NAME; +import static io.cucumber.junit.platform.engine.Constants.PARALLEL_EXECUTION_ENABLED_PROPERTY_NAME; + +import org.junit.platform.suite.api.ConfigurationParameter; +import org.junit.platform.suite.api.IncludeEngines; +import org.junit.platform.suite.api.SelectClasspathResource; +import org.junit.platform.suite.api.Suite; +import org.junit.platform.suite.api.SuiteDisplayName; + +@Suite +@SuiteDisplayName("Proxy") +@IncludeEngines("cucumber") +@SelectClasspathResource("features/proxy") +@ConfigurationParameter(key = GLUE_PROPERTY_NAME, value = "com.sinch.sdk.e2e.domains.proxy") +@ConfigurationParameter(key = PARALLEL_EXECUTION_ENABLED_PROPERTY_NAME, value = "true") +public class ProxyIT {} diff --git a/client/src/test/java/com/sinch/sdk/e2e/domains/proxy/ProxySteps.java b/client/src/test/java/com/sinch/sdk/e2e/domains/proxy/ProxySteps.java new file mode 100644 index 000000000..d498e65ea --- /dev/null +++ b/client/src/test/java/com/sinch/sdk/e2e/domains/proxy/ProxySteps.java @@ -0,0 +1,69 @@ +package com.sinch.sdk.e2e.domains.proxy; + +import com.sinch.sdk.SinchClient; +import com.sinch.sdk.core.TestHelpers; +import com.sinch.sdk.domains.numberlookup.models.v2.request.NumberLookupRequest; +import com.sinch.sdk.domains.numberlookup.models.v2.response.Line; +import com.sinch.sdk.domains.numberlookup.models.v2.response.LineType; +import com.sinch.sdk.domains.numberlookup.models.v2.response.NumberLookupResponse; +import com.sinch.sdk.e2e.Config; +import io.cucumber.java.en.Given; +import io.cucumber.java.en.Then; +import io.cucumber.java.en.When; +import org.junit.jupiter.api.Assertions; + +public class ProxySteps { + + NumberLookupResponse response; + + @Given("the proxy server is available") + public void proxyServerAvailable() { + Assertions.assertNotNull( + Config.getSinchClientProxyUnauthenticated(), "Unauthenticated proxy client"); + Assertions.assertNotNull( + Config.getSinchClientProxyAuthenticated(), "Authenticated proxy client"); + } + + @When("I send a Number Lookup request through the unauthenticated proxy") + public void lookupThroughUnauthenticatedProxy() { + response = lookup(Config.getSinchClientProxyUnauthenticated()); + } + + @When("I send a Number Lookup request through the authenticated proxy") + public void lookupThroughAuthenticatedProxy() { + response = lookup(Config.getSinchClientProxyAuthenticated()); + } + + @Then("the response is successfully returned through the unauthenticated proxy") + public void responseReturnedThroughUnauthenticatedProxy() { + assertResponse("a11a11a11a11a11a11a11a11a11unauth"); + } + + @Then("the response is successfully returned through the authenticated proxy") + public void responseReturnedThroughAuthenticatedProxy() { + assertResponse("b22b22b22b22b22b22b22b22b22b2auth"); + } + + private void assertResponse(String expectedTraceId) { + NumberLookupResponse expected = + NumberLookupResponse.builder() + .setNumber("+12016666666") + .setCountryCode("US") + .setTraceId(expectedTraceId) + .setLine( + Line.builder() + .setCarrier("T-Mobile USA") + .setType(LineType.MOBILE) + .setMobileCountryCode("310") + .setMobileNetworkCode("260") + .build()) + .build(); + + TestHelpers.recursiveEquals(response, expected); + } + + private static NumberLookupResponse lookup(SinchClient client) { + NumberLookupRequest request = NumberLookupRequest.builder().setNumber("+12016666666").build(); + return client.lookup().v2().lookup(request); + } +} diff --git a/client/src/test/java/com/sinch/sdk/e2e/domains/sms/v1/BatchesSteps.java b/client/src/test/java/com/sinch/sdk/e2e/domains/sms/v1/BatchesSteps.java index c7324263e..f728614c8 100644 --- a/client/src/test/java/com/sinch/sdk/e2e/domains/sms/v1/BatchesSteps.java +++ b/client/src/test/java/com/sinch/sdk/e2e/domains/sms/v1/BatchesSteps.java @@ -36,8 +36,6 @@ public class BatchesSteps { BatchResponse sendTextWithParametersResponse; DryRunResponse dryRunResponse; ListBatchesResponse listOnePageResponse; - ListBatchesResponse listAllResponse; - ListBatchesResponse listAllByPageResponse; BatchResponse getBatchResponse; BatchResponse updateResponse; BatchResponse replaceResponse; @@ -144,7 +142,7 @@ public void listAll() { ListBatchesQueryParameters request = ListBatchesQueryParameters.builder().setPageSize(2).build(); - listAllResponse = service.list(request); + listOnePageResponse = service.list(request); } @When("^I iterate manually over the SMS batches pages$") @@ -152,7 +150,7 @@ public void listAllByPage() { ListBatchesQueryParameters request = ListBatchesQueryParameters.builder().setPageSize(2).build(); - listAllByPageResponse = service.list(request); + listOnePageResponse = service.list(request); } @When("^I send a request to retrieve an SMS batch$") @@ -304,11 +302,8 @@ public void onePageResult(int expected) { @Then("the SMS batches list contains \"{int}\" SMS batches") public void listAllResult(int expected) { - ListBatchesResponse response = - null != listAllResponse ? listAllResponse : listAllByPageResponse; - AtomicInteger count = new AtomicInteger(); - response.iterator().forEachRemaining(_unused -> count.getAndIncrement()); + listOnePageResponse.iterator().forEachRemaining(_unused -> count.getAndIncrement()); Assertions.assertEquals(count.get(), expected); } @@ -316,10 +311,11 @@ public void listAllResult(int expected) { @Then("the SMS batches iteration result contains the data from \"{int}\" pages") public void listAllByPageResult(int expected) { - int count = listAllByPageResponse.getContent().isEmpty() ? 0 : 1; - while (listAllByPageResponse.hasNextPage()) { + int count = listOnePageResponse.getContent().isEmpty() ? 0 : 1; + ListBatchesResponse currentPage = listOnePageResponse; + while (currentPage.hasNextPage()) { count++; - listAllByPageResponse = listAllByPageResponse.nextPage(); + currentPage = currentPage.nextPage(); } Assertions.assertEquals(count, expected); } diff --git a/client/src/test/java/com/sinch/sdk/e2e/domains/sms/v1/DeliveryReportsSteps.java b/client/src/test/java/com/sinch/sdk/e2e/domains/sms/v1/DeliveryReportsSteps.java index 9c53251cf..f9de95f39 100644 --- a/client/src/test/java/com/sinch/sdk/e2e/domains/sms/v1/DeliveryReportsSteps.java +++ b/client/src/test/java/com/sinch/sdk/e2e/domains/sms/v1/DeliveryReportsSteps.java @@ -32,8 +32,6 @@ public class DeliveryReportsSteps { BatchDeliveryReport fullReport; RecipientDeliveryReport recipientReport; ListDeliveryReportsResponse listOnePageResponse; - ListDeliveryReportsResponse listAllResponse; - ListDeliveryReportsResponse listAllByPageResponse; @Given("^the SMS service \"Delivery Reports\" is available") public void serviceAvailable() { @@ -90,7 +88,7 @@ public void listAll() { ListDeliveryReportsQueryParameters request = ListDeliveryReportsQueryParameters.builder().setPageSize(2).build(); - listAllResponse = service.list(request); + listOnePageResponse = service.list(request); } @When("^I iterate manually over the SMS delivery reports pages$") @@ -98,7 +96,7 @@ public void listAllByPage() { ListDeliveryReportsQueryParameters request = ListDeliveryReportsQueryParameters.builder().setPageSize(2).build(); - listAllByPageResponse = service.list(request); + listOnePageResponse = service.list(request); } @Then("the response contains a summary SMS delivery report") @@ -173,11 +171,9 @@ public void onePageResult(int expected) { @Then("the SMS delivery reports list contains \"{int}\" SMS delivery reports") public void listAllResult(int expected) { - ListDeliveryReportsResponse response = - null != listAllResponse ? listAllResponse : listAllByPageResponse; AtomicInteger count = new AtomicInteger(); - response.iterator().forEachRemaining(_unused -> count.getAndIncrement()); + listOnePageResponse.iterator().forEachRemaining(_unused -> count.getAndIncrement()); Assertions.assertEquals(count.get(), expected); } @@ -185,10 +181,11 @@ public void listAllResult(int expected) { @Then("the SMS delivery reports iteration result contains the data from \"{int}\" pages") public void listAllByPageResult(int expected) { - int count = listAllByPageResponse.getContent().isEmpty() ? 0 : 1; - while (listAllByPageResponse.hasNextPage()) { + int count = listOnePageResponse.getContent().isEmpty() ? 0 : 1; + ListDeliveryReportsResponse currentPage = listOnePageResponse; + while (currentPage.hasNextPage()) { count++; - listAllByPageResponse = listAllByPageResponse.nextPage(); + currentPage = currentPage.nextPage(); } Assertions.assertEquals(count, expected); } diff --git a/client/src/test/java/com/sinch/sdk/e2e/domains/sms/v1/GroupsSteps.java b/client/src/test/java/com/sinch/sdk/e2e/domains/sms/v1/GroupsSteps.java index 14bba1bf1..12f0433ee 100644 --- a/client/src/test/java/com/sinch/sdk/e2e/domains/sms/v1/GroupsSteps.java +++ b/client/src/test/java/com/sinch/sdk/e2e/domains/sms/v1/GroupsSteps.java @@ -26,8 +26,6 @@ public class GroupsSteps { Group createResponse; Group getResponse; ListGroupsResponse listOnePageResponse; - ListGroupsResponse listAllResponse; - ListGroupsResponse listAllByPageResponse; Group updateResponse; Group updateRemoveNameResponse; Group replaceResponse; @@ -76,14 +74,14 @@ public void listOnePage() { public void listAll() { ListGroupsQueryParameters request = ListGroupsQueryParameters.builder().setPageSize(2).build(); - listAllResponse = service.list(request); + listOnePageResponse = service.list(request); } @When("^I iterate manually over the SMS groups pages$") public void listAllByPage() { ListGroupsQueryParameters request = ListGroupsQueryParameters.builder().setPageSize(2).build(); - listAllByPageResponse = service.list(request); + listOnePageResponse = service.list(request); } @When("^I send a request to update an SMS group$") @@ -157,10 +155,9 @@ public void onePageResult(int expected) { @Then("the SMS groups list contains \"{int}\" SMS groups") public void listAllResult(int expected) { - ListGroupsResponse response = null != listAllResponse ? listAllResponse : listAllByPageResponse; AtomicInteger count = new AtomicInteger(); - response.iterator().forEachRemaining(_unused -> count.getAndIncrement()); + listOnePageResponse.iterator().forEachRemaining(_unused -> count.getAndIncrement()); Assertions.assertEquals(count.get(), expected); } @@ -168,10 +165,11 @@ public void listAllResult(int expected) { @Then("the SMS groups iteration result contains the data from \"{int}\" pages") public void listAllByPageResult(int expected) { - int count = listAllByPageResponse.getContent().isEmpty() ? 0 : 1; - while (listAllByPageResponse.hasNextPage()) { + int count = listOnePageResponse.getContent().isEmpty() ? 0 : 1; + ListGroupsResponse currentPage = listOnePageResponse; + while (currentPage.hasNextPage()) { count++; - listAllByPageResponse = listAllByPageResponse.nextPage(); + currentPage = currentPage.nextPage(); } Assertions.assertEquals(count, expected); } diff --git a/client/src/test/java/com/sinch/sdk/e2e/domains/sms/v1/InboundsSteps.java b/client/src/test/java/com/sinch/sdk/e2e/domains/sms/v1/InboundsSteps.java index 16f310e86..e36031fa8 100644 --- a/client/src/test/java/com/sinch/sdk/e2e/domains/sms/v1/InboundsSteps.java +++ b/client/src/test/java/com/sinch/sdk/e2e/domains/sms/v1/InboundsSteps.java @@ -20,8 +20,6 @@ public class InboundsSteps { InboundsService service; InboundMessage getResponse; ListInboundsResponse listOnePageResponse; - ListInboundsResponse listAllResponse; - ListInboundsResponse listAllByPageResponse; @Given("^the SMS service \"Inbounds\" is available") public void serviceAvailable() { @@ -62,7 +60,7 @@ public void listAll() { .setPageSize(2) .build(); - listAllResponse = service.list(request); + listOnePageResponse = service.list(request); } @When("^I iterate manually over the inbound messages pages$") @@ -73,7 +71,7 @@ public void listAllByPage() { .setPageSize(2) .build(); - listAllByPageResponse = service.list(request); + listOnePageResponse = service.list(request); } @Then("the response contains the inbound message details") @@ -99,11 +97,9 @@ public void onePageResult(int expected) { @Then("the inbound messages list contains \"{int}\" inbound messages") public void listAllResult(int expected) { - ListInboundsResponse response = - null != listAllResponse ? listAllResponse : listAllByPageResponse; AtomicInteger count = new AtomicInteger(); - response.iterator().forEachRemaining(_unused -> count.getAndIncrement()); + listOnePageResponse.iterator().forEachRemaining(_unused -> count.getAndIncrement()); Assertions.assertEquals(count.get(), expected); } @@ -111,10 +107,11 @@ public void listAllResult(int expected) { @Then("the inbound messages iteration result contains the data from \"{int}\" pages") public void listAllByPageResult(int expected) { - int count = listAllByPageResponse.getContent().isEmpty() ? 0 : 1; - while (listAllByPageResponse.hasNextPage()) { + int count = listOnePageResponse.getContent().isEmpty() ? 0 : 1; + ListInboundsResponse currentPage = listOnePageResponse; + while (currentPage.hasNextPage()) { count++; - listAllByPageResponse = listAllByPageResponse.nextPage(); + currentPage = currentPage.nextPage(); } Assertions.assertEquals(count, expected); } diff --git a/client/src/test/java/com/sinch/sdk/e2e/domains/sms/v1/SmsIT.java b/client/src/test/java/com/sinch/sdk/e2e/domains/sms/v1/SmsIT.java index 42139b9be..3ab37bf7c 100644 --- a/client/src/test/java/com/sinch/sdk/e2e/domains/sms/v1/SmsIT.java +++ b/client/src/test/java/com/sinch/sdk/e2e/domains/sms/v1/SmsIT.java @@ -1,6 +1,7 @@ package com.sinch.sdk.e2e.domains.sms.v1; import static io.cucumber.junit.platform.engine.Constants.GLUE_PROPERTY_NAME; +import static io.cucumber.junit.platform.engine.Constants.PARALLEL_EXECUTION_ENABLED_PROPERTY_NAME; import org.junit.platform.suite.api.ConfigurationParameter; import org.junit.platform.suite.api.IncludeEngines; @@ -13,4 +14,5 @@ @IncludeEngines("cucumber") @SelectClasspathResource("features/sms") @ConfigurationParameter(key = GLUE_PROPERTY_NAME, value = "com.sinch.sdk.e2e.domains.sms.v1") +@ConfigurationParameter(key = PARALLEL_EXECUTION_ENABLED_PROPERTY_NAME, value = "true") public class SmsIT {} diff --git a/client/src/test/java/com/sinch/sdk/e2e/domains/verification/v1/VerificationIT.java b/client/src/test/java/com/sinch/sdk/e2e/domains/verification/v1/VerificationIT.java index 75b21605b..e0e45cb0b 100644 --- a/client/src/test/java/com/sinch/sdk/e2e/domains/verification/v1/VerificationIT.java +++ b/client/src/test/java/com/sinch/sdk/e2e/domains/verification/v1/VerificationIT.java @@ -1,6 +1,7 @@ package com.sinch.sdk.e2e.domains.verification.v1; import static io.cucumber.junit.platform.engine.Constants.GLUE_PROPERTY_NAME; +import static io.cucumber.junit.platform.engine.Constants.PARALLEL_EXECUTION_ENABLED_PROPERTY_NAME; import org.junit.platform.suite.api.ConfigurationParameter; import org.junit.platform.suite.api.IncludeEngines; @@ -15,4 +16,5 @@ @ConfigurationParameter( key = GLUE_PROPERTY_NAME, value = "com.sinch.sdk.e2e.domains.verification.v1") +@ConfigurationParameter(key = PARALLEL_EXECUTION_ENABLED_PROPERTY_NAME, value = "true") public class VerificationIT {} diff --git a/client/src/test/java/com/sinch/sdk/e2e/domains/voice/v1/CallsSteps.java b/client/src/test/java/com/sinch/sdk/e2e/domains/voice/v1/CallsSteps.java index 6e32a5dbf..f371e2c8f 100644 --- a/client/src/test/java/com/sinch/sdk/e2e/domains/voice/v1/CallsSteps.java +++ b/client/src/test/java/com/sinch/sdk/e2e/domains/voice/v1/CallsSteps.java @@ -5,13 +5,13 @@ import com.sinch.sdk.domains.voice.api.v1.CallsService; import com.sinch.sdk.domains.voice.models.v1.Price; import com.sinch.sdk.domains.voice.models.v1.calls.request.CallLeg; +import com.sinch.sdk.domains.voice.models.v1.calls.request.CallUpdateRequest; import com.sinch.sdk.domains.voice.models.v1.calls.response.CallInformation; import com.sinch.sdk.domains.voice.models.v1.calls.response.CallInformation.DomainEnum; import com.sinch.sdk.domains.voice.models.v1.calls.response.CallInformation.ReasonEnum; import com.sinch.sdk.domains.voice.models.v1.calls.response.CallInformation.StatusEnum; import com.sinch.sdk.domains.voice.models.v1.calls.response.CallResult; import com.sinch.sdk.domains.voice.models.v1.destination.DestinationPstn; -import com.sinch.sdk.domains.voice.models.v1.svaml.SvamlControl; import com.sinch.sdk.domains.voice.models.v1.svaml.action.SvamlActionContinue; import com.sinch.sdk.domains.voice.models.v1.svaml.action.SvamlActionHangup; import com.sinch.sdk.domains.voice.models.v1.svaml.instruction.SvamlInstructionPlayFiles; @@ -46,8 +46,8 @@ public void getCall() { @When("^I send a request to update a call$") public void updateCall() { - SvamlControl request = - SvamlControl.builder() + CallUpdateRequest request = + CallUpdateRequest.builder() .setInstructions( Arrays.asList( SvamlInstructionSay.builder() @@ -63,8 +63,8 @@ public void updateCall() { @When("^I send a request to update a call that doesn't exist$") public void updateCallNotExits() { - SvamlControl request = - SvamlControl.builder() + CallUpdateRequest request = + CallUpdateRequest.builder() .setInstructions( Arrays.asList( SvamlInstructionSay.builder() @@ -83,8 +83,8 @@ public void updateCallNotExits() { @When("^I send a request to manage a call with callLeg$") public void manageCallWithCallLeg() { - SvamlControl request = - SvamlControl.builder() + CallUpdateRequest request = + CallUpdateRequest.builder() .setInstructions( Arrays.asList( SvamlInstructionPlayFiles.builder() diff --git a/client/src/test/java/com/sinch/sdk/e2e/domains/voice/v1/VoiceIT.java b/client/src/test/java/com/sinch/sdk/e2e/domains/voice/v1/VoiceIT.java index 421a7a053..3b04db4ef 100644 --- a/client/src/test/java/com/sinch/sdk/e2e/domains/voice/v1/VoiceIT.java +++ b/client/src/test/java/com/sinch/sdk/e2e/domains/voice/v1/VoiceIT.java @@ -1,6 +1,7 @@ package com.sinch.sdk.e2e.domains.voice.v1; import static io.cucumber.junit.platform.engine.Constants.GLUE_PROPERTY_NAME; +import static io.cucumber.junit.platform.engine.Constants.PARALLEL_EXECUTION_ENABLED_PROPERTY_NAME; import org.junit.platform.suite.api.ConfigurationParameter; import org.junit.platform.suite.api.IncludeEngines; @@ -13,4 +14,5 @@ @IncludeEngines("cucumber") @SelectClasspathResource("features/voice") @ConfigurationParameter(key = GLUE_PROPERTY_NAME, value = "com.sinch.sdk.e2e.domains.voice.v1") +@ConfigurationParameter(key = PARALLEL_EXECUTION_ENABLED_PROPERTY_NAME, value = "true") public class VoiceIT {} diff --git a/client/src/test/java/com/sinch/sdk/http/HttpClientApacheLifecycleTest.java b/client/src/test/java/com/sinch/sdk/http/HttpClientApacheLifecycleTest.java new file mode 100644 index 000000000..68f21426b --- /dev/null +++ b/client/src/test/java/com/sinch/sdk/http/HttpClientApacheLifecycleTest.java @@ -0,0 +1,72 @@ +package com.sinch.sdk.http; + +import static org.junit.jupiter.api.Assertions.*; + +import com.sinch.sdk.models.HttpProxyConfiguration; +import org.junit.jupiter.api.Test; + +class HttpClientApacheLifecycleTest { + + @Test + void freshInstanceIsNotClosed() throws Exception { + try (HttpClientApache client = new HttpClientApache()) { + assertFalse(client.isClosed()); + } + } + + @Test + void closeMarksInstanceAsClosed() throws Exception { + HttpClientApache client = new HttpClientApache(); + client.close(); + assertTrue(client.isClosed()); + } + + @Test + void doubleCloseIsIdempotent() throws Exception { + HttpClientApache client = new HttpClientApache(); + client.close(); + assertDoesNotThrow(client::close); + } + + @Test + void closeViaAutoCloseable() { + assertDoesNotThrow( + () -> { + try (HttpClientApache client = new HttpClientApache()) { + assertFalse(client.isClosed()); + } + }); + } + + @Test + void proxyConstructorCreatesOpenInstance() throws Exception { + HttpProxyConfiguration proxy = + HttpProxyConfiguration.builder().setHostname("proxy.example.com").setPort(3128).build(); + try (HttpClientApache client = new HttpClientApache(proxy)) { + assertFalse(client.isClosed(), "HttpClientApache created with proxy config must be open"); + } + } + + @Test + void proxyConstructorWithNullBehavesAsNoArgConstructor() throws Exception { + try (HttpClientApache client = new HttpClientApache(null)) { + assertFalse(client.isClosed(), "HttpClientApache(null) must behave like no-arg constructor"); + } + } + + @Test + void proxyConstructorWithAuthCreatesOpenInstance() throws Exception { + HttpProxyConfiguration proxy = + HttpProxyConfiguration.builder() + .setHostname("proxy.example.com") + .setPort(3128) + .setUsername("user") + .setPassword("pass") + .build(); + try (HttpClientApache client = new HttpClientApache(proxy)) { + assertFalse( + client.isClosed(), + "HttpClientApache created with authenticated proxy config must be open"); + } + } +} diff --git a/client/src/test/java/com/sinch/sdk/http/HttpClientApacheProxyTest.java b/client/src/test/java/com/sinch/sdk/http/HttpClientApacheProxyTest.java new file mode 100644 index 000000000..01e40bcc5 --- /dev/null +++ b/client/src/test/java/com/sinch/sdk/http/HttpClientApacheProxyTest.java @@ -0,0 +1,184 @@ +package com.sinch.sdk.http; + +import static org.junit.jupiter.api.Assertions.*; + +import com.sinch.sdk.core.http.HttpMethod; +import com.sinch.sdk.core.http.HttpRequest; +import com.sinch.sdk.core.models.ServerConfiguration; +import com.sinch.sdk.models.HttpProxyConfiguration; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Base64; +import java.util.concurrent.TimeUnit; +import okhttp3.mockwebserver.MockResponse; +import okhttp3.mockwebserver.MockWebServer; +import okhttp3.mockwebserver.RecordedRequest; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class HttpClientApacheProxyTest { + + MockWebServer mockProxy; + + @BeforeEach + void setUp() throws IOException { + mockProxy = new MockWebServer(); + mockProxy.start(); + } + + @AfterEach + void tearDown() throws IOException { + mockProxy.shutdown(); + } + + @Test + void unauthenticatedProxyRequestRoutedThroughProxy() throws Exception { + HttpProxyConfiguration proxySettings = + HttpProxyConfiguration.builder() + .setHostname("localhost") + .setPort(mockProxy.getPort()) + .build(); + + mockProxy.enqueue( + new MockResponse().setBody("{}").addHeader("Content-Type", "application/json")); + + try (HttpClientApache proxyClient = new HttpClientApache(proxySettings)) { + proxyClient.invokeAPI( + new ServerConfiguration("http://foo.com"), + null, + new HttpRequest( + "/api/path", HttpMethod.GET, null, (String) null, null, null, null, null)); + } + + RecordedRequest request = mockProxy.takeRequest(5, TimeUnit.SECONDS); + assertNotNull(request, "Proxy should have received the request"); + assertTrue( + request.getRequestLine().startsWith("GET http://foo.com/api/path"), + "Initial request should be a full URL as per RFC 7230 when sent to a proxy; actual: " + + request.getRequestLine()); + assertNotNull(request.getRequestUrl(), "Recorded request must have an URL"); + assertEquals( + "localhost", + request.getRequestUrl().host(), + "Proxy request should be sent to the proxy host"); + assertEquals( + mockProxy.getPort(), + request.getRequestUrl().port(), + "Proxy request should be sent to the proxy port"); + assertEquals( + "/", request.getRequestUrl().encodedPath(), "Initial request should have the proxy path"); + + RecordedRequest noMoreRequest = mockProxy.takeRequest(5, TimeUnit.SECONDS); + assertNull(noMoreRequest, "Proxy should not receive more than 1 request for the same call"); + } + + @Test + void authenticatedProxyCredentialsSentAfterChallenge() throws Exception { + HttpProxyConfiguration proxySettings = + HttpProxyConfiguration.builder() + .setHostname("localhost") + .setPort(mockProxy.getPort()) + .setUsername("proxy-user") + .setPassword("proxy-pass") + .build(); + + mockProxy.enqueue( + new MockResponse() + .setResponseCode(407) + .addHeader("Proxy-Authenticate", "Basic realm=\"proxy\"")); + mockProxy.enqueue( + new MockResponse().setBody("{}").addHeader("Content-Type", "application/json")); + + try (HttpClientApache proxyClient = new HttpClientApache(proxySettings)) { + proxyClient.invokeAPI( + new ServerConfiguration("http://foo.com"), + null, + new HttpRequest( + "/api/path", HttpMethod.GET, null, (String) null, null, null, null, null)); + } + + RecordedRequest initial = mockProxy.takeRequest(5, TimeUnit.SECONDS); + assertNotNull(initial, "Proxy should have received the request"); + assertTrue( + initial.getRequestLine().startsWith("GET http://foo.com/api/path"), + "Initial request should be a full URL as per RFC 7230 when sent to a proxy; actual: " + + initial.getRequestLine()); + assertNotNull(initial.getRequestUrl(), "Recorded request must have an URL"); + assertEquals( + "localhost", + initial.getRequestUrl().host(), + "Proxy request should be sent to the proxy host"); + assertEquals( + mockProxy.getPort(), + initial.getRequestUrl().port(), + "Proxy request should be sent to the proxy port"); + assertEquals( + "/", initial.getRequestUrl().encodedPath(), "Initial request should have the proxy path"); + + RecordedRequest retry = mockProxy.takeRequest(5, TimeUnit.SECONDS); + assertNotNull(retry, "Proxy should receive the retry request after 407 challenge"); + + String proxyAuthHeader = retry.getHeader("Proxy-Authorization"); + assertNotNull(proxyAuthHeader, "Proxy-Authorization must be present on the retry"); + assertTrue( + proxyAuthHeader.startsWith("Basic "), + "Proxy-Authorization must use the Basic scheme; actual: " + proxyAuthHeader); + String decoded = + new String( + Base64.getDecoder().decode(proxyAuthHeader.substring("Basic ".length())), + StandardCharsets.UTF_8); + assertEquals( + "proxy-user:proxy-pass", + decoded, + "Proxy-Authorization must encode the exact configured credentials"); + + RecordedRequest noMoreRequest = mockProxy.takeRequest(5, TimeUnit.SECONDS); + assertNull( + noMoreRequest, + "Proxy should not receive more than 2 requests for the same call (initial + retry)"); + } + + @Test + void authenticatedProxyNoChallengeSucceedsDirectly() throws Exception { + HttpProxyConfiguration proxySettings = + HttpProxyConfiguration.builder() + .setHostname("localhost") + .setPort(mockProxy.getPort()) + .setUsername("user") + .setPassword("pass") + .build(); + + mockProxy.enqueue( + new MockResponse().setBody("{}").addHeader("Content-Type", "application/json")); + + try (HttpClientApache proxyClient = new HttpClientApache(proxySettings)) { + proxyClient.invokeAPI( + new ServerConfiguration("http://foo.com"), + null, + new HttpRequest( + "/api/path", HttpMethod.GET, null, (String) null, null, null, null, null)); + } + + RecordedRequest request = mockProxy.takeRequest(5, TimeUnit.SECONDS); + assertNotNull(request, "Proxy should have received the request"); + assertTrue( + request.getRequestLine().startsWith("GET http://foo.com/api/path"), + "Initial request should be a full URL as per RFC 7230 when sent to a proxy; actual: " + + request.getRequestLine()); + assertNotNull(request.getRequestUrl(), "Recorded request must have an URL"); + assertEquals( + "localhost", + request.getRequestUrl().host(), + "Proxy request should be sent to the proxy host"); + assertEquals( + mockProxy.getPort(), + request.getRequestUrl().port(), + "Proxy request should be sent to the proxy port"); + assertEquals( + "/", request.getRequestUrl().encodedPath(), "Initial request should have the proxy path"); + + RecordedRequest noMoreRequest = mockProxy.takeRequest(5, TimeUnit.SECONDS); + assertNull(noMoreRequest, "Proxy should not receive more than 1 request for the same call"); + } +} diff --git a/client/src/test/java/com/sinch/sdk/http/HttpClientApacheTest.java b/client/src/test/java/com/sinch/sdk/http/HttpClientApacheTest.java index 075fc7f3e..f2835cbac 100644 --- a/client/src/test/java/com/sinch/sdk/http/HttpClientApacheTest.java +++ b/client/src/test/java/com/sinch/sdk/http/HttpClientApacheTest.java @@ -9,9 +9,16 @@ import com.sinch.sdk.core.http.HttpRequest; import com.sinch.sdk.core.http.HttpResponse; import com.sinch.sdk.core.models.ServerConfiguration; +import java.io.ByteArrayInputStream; import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.nio.charset.StandardCharsets; import java.util.*; +import java.util.Scanner; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.apache.hc.core5.http.ClassicHttpResponse; +import org.apache.hc.core5.http.Header; +import org.apache.hc.core5.http.HttpEntity; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -46,19 +53,18 @@ void testInvokeApiHandles401WithEmptyHeaders() throws Exception { doReturn(unauthorizedResponse).when(client).processRequest(any(), any()); // Mock ServerConfiguration and HttpRequest - ServerConfiguration serverConfig = mock(ServerConfiguration.class); - when(serverConfig.getUrl()).thenReturn("https://api.example.com"); - - HttpRequest request = mock(HttpRequest.class); - when(request.getFullUrl()).thenReturn(Optional.of("https://api.example.com/v1/test")); - when(request.getMethod()).thenReturn(HttpMethod.GET); - when(request.getQueryParameters()).thenReturn(Collections.emptyList()); - when(request.getBody()).thenReturn(null); - when(request.getFormParams()).thenReturn(Collections.emptyMap()); - when(request.getHeaderParams()).thenReturn(Collections.emptyMap()); - when(request.getAccept()).thenReturn(Collections.emptyList()); - when(request.getContentType()).thenReturn(Collections.emptyList()); - when(request.getAuthNames()).thenReturn(Collections.singletonList("Bearer")); + ServerConfiguration serverConfig = new ServerConfiguration("https://api.example.com"); + + HttpRequest request = + new HttpRequest( + "https://api.example.com/v1/test", + HttpMethod.GET, + Collections.emptyList(), + Collections.emptyMap(), + Collections.emptyMap(), + Collections.emptyList(), + Collections.emptyList(), + Collections.singletonList("Bearer")); // Mock AuthManagers map (bearer) Map authManagers = new HashMap<>(); @@ -75,4 +81,90 @@ void testInvokeApiHandles401WithEmptyHeaders() throws Exception { // AND: resetToken() is not called (no headers to check) verify(mockAuthManager, never()).resetToken(); } + + @Test + void processResponseDecodesBodyAsUtf8() throws Exception { + String nonAscii = "Ünïcödé resülts"; + byte[] utf8Bytes = nonAscii.getBytes(StandardCharsets.UTF_8); + + HttpEntity entity = mock(HttpEntity.class); + when(entity.getContent()).thenReturn(new ByteArrayInputStream(utf8Bytes)); + + ClassicHttpResponse httpResponse = mock(ClassicHttpResponse.class); + when(httpResponse.getCode()).thenReturn(200); + when(httpResponse.getReasonPhrase()).thenReturn("OK"); + when(httpResponse.getHeaders()).thenReturn(new Header[0]); + when(httpResponse.getEntity()).thenReturn(entity); + + Method processResponse = + HttpClientApache.class.getDeclaredMethod("processResponse", ClassicHttpResponse.class); + processResponse.setAccessible(true); + + HttpResponse result = (HttpResponse) processResponse.invoke(null, httpResponse); + + assertNotNull(result.getContent()); + try (Scanner s = + new Scanner(result.getContent(), StandardCharsets.UTF_8.name()).useDelimiter("\\A")) { + String decoded = s.hasNext() ? s.next() : ""; + assertEquals(nonAscii, decoded, "Response body must round-trip through UTF-8 correctly"); + } + } + + /** + * Verifies that a 407 Proxy Authentication Required response returned by {@code processRequest} + * (i.e. Apache's internal 407 handling failed) is returned immediately to the caller without + * triggering the OAuth token-refresh logic. + * + *

Some enterprise proxies include a {@code www-authenticate: Bearer error="expired"} header on + * 407 responses. Without the explicit 407 guard in {@link + * HttpClientApache#invokeAPI(com.sinch.sdk.core.models.ServerConfiguration, Map, + * com.sinch.sdk.core.http.HttpRequest)}, that header would cause the OAuthManager to reset its + * token and retry the request — incorrectly treating a proxy auth failure as an expired API + * token. + */ + @Test + void testInvokeApi407DoesNotTriggerOAuthRefresh() throws Exception { + // GIVEN: a 407 response that also carries www-authenticate: Bearer error="expired" + // (non-standard but seen on some corporate proxies) + Map> proxyHeaders = new HashMap<>(); + proxyHeaders.put( + OAuthManager.BEARER_AUTHENTICATE_RESPONSE_HEADER_KEYWORD, + Collections.singletonList("Bearer realm=\"proxy\", error=\"expired\"")); + + HttpResponse proxyAuthResponse = + new HttpResponse(407, "Proxy Authentication Required", proxyHeaders, null); + + doReturn(proxyAuthResponse).when(client).processRequest(any(), any()); + + ServerConfiguration serverConfig = new ServerConfiguration("https://api.example.com"); + + HttpRequest request = + new HttpRequest( + "https://api.example.com/v1/test", + HttpMethod.GET, + Collections.emptyList(), + Collections.emptyMap(), + Collections.emptyMap(), + Collections.emptyList(), + Collections.emptyList(), + Collections.singletonList("Bearer")); + + Map authManagers = new HashMap<>(); + authManagers.put(OAuthManager.SCHEMA_KEYWORD_BEARER, mockAuthManager); + when(mockAuthManager.getSchema()).thenReturn(OAuthManager.SCHEMA_KEYWORD_BEARER); + when(mockAuthManager.getAuthorizationHeaders(any(), any(), any(), any())) + .thenReturn(Collections.emptyList()); + + // WHEN: invokeAPI is called + HttpResponse response = client.invokeAPI(serverConfig, authManagers, request); + + // THEN: the 407 is returned as-is + assertEquals(407, response.getCode()); + + // AND: OAuth token reset must NOT be triggered by the proxy 407 + verify(mockAuthManager, never()).resetToken(); + + // AND: processRequest is called exactly once — no OAuth retry + verify(client, times(1)).processRequest(any(), any()); + } } diff --git a/client/src/test/java/com/sinch/sdk/models/ConfigurationBuilderTest.java b/client/src/test/java/com/sinch/sdk/models/ConfigurationBuilderTest.java index 772f49812..69c116765 100644 --- a/client/src/test/java/com/sinch/sdk/models/ConfigurationBuilderTest.java +++ b/client/src/test/java/com/sinch/sdk/models/ConfigurationBuilderTest.java @@ -14,6 +14,10 @@ class ConfigurationBuilderTest { static final ConversationRegion CONVERSATION_REGION = ConversationRegion.BR; static final String CONVERSATION_SERVER = "%sfooCONVERSATION_SERVER"; static final String CONVERSATION_TEMPLATE_SERVER = "%sfooCONVERSATION_TEMPLATE_SERVER"; + static final String PROXY_HOST = "proxy.corp.example.com"; + static final int PROXY_PORT = 3128; + static final String PROXY_USER = "proxyUser"; + static final String PROXY_PASS = "proxyPass"; @Test void build() { @@ -32,6 +36,13 @@ void build() { .setUrl(CONVERSATION_SERVER) .setTemplateManagementUrl(CONVERSATION_TEMPLATE_SERVER) .build()) + .setHttpProxyConfiguration( + HttpProxyConfiguration.builder() + .setHostname(PROXY_HOST) + .setPort(PROXY_PORT) + .setUsername(PROXY_USER) + .setPassword(PROXY_PASS) + .build()) .build(); Assertions.assertEquals(OAUTH_URL, builder.getOAuthServer().getUrl()); Assertions.assertEquals( @@ -67,5 +78,57 @@ void build() { .getUrl() .contains("fooCONVERSATION_TEMPLATE_SERVER"), "Conversation template server present within conversation template server URL"); + + Assertions.assertTrue( + builder.getHttpProxyConfiguration().isPresent(), "Proxy configuration should be present"); + Assertions.assertEquals( + PROXY_HOST, builder.getHttpProxyConfiguration().get().getHostname(), "Proxy hostname"); + Assertions.assertEquals( + PROXY_PORT, builder.getHttpProxyConfiguration().get().getPort(), "Proxy port"); + Assertions.assertEquals( + PROXY_USER, + builder.getHttpProxyConfiguration().get().getUsername().orElse(null), + "Proxy username"); + Assertions.assertArrayEquals( + PROXY_PASS.toCharArray(), + builder.getHttpProxyConfiguration().get().getPassword().orElse(null), + "Proxy password"); + } + + @Test + void buildWithoutProxy() { + Configuration config = + new Configuration.Builder() + .setKeyId(KEY) + .setKeySecret(SECRET) + .setProjectId(PROJECT) + .setOAuthUrl(OAUTH_URL) + .build(); + Assertions.assertFalse( + config.getHttpProxyConfiguration().isPresent(), + "Proxy configuration should be absent when not configured"); + } + + @Test + void builderCopyPreservesProxyConfiguration() { + HttpProxyConfiguration proxy = + HttpProxyConfiguration.builder().setHostname(PROXY_HOST).setPort(PROXY_PORT).build(); + Configuration original = + new Configuration.Builder() + .setKeyId(KEY) + .setKeySecret(SECRET) + .setProjectId(PROJECT) + .setOAuthUrl(OAUTH_URL) + .setHttpProxyConfiguration(proxy) + .build(); + + Configuration copy = Configuration.builder(original).build(); + Assertions.assertTrue(copy.getHttpProxyConfiguration().isPresent()); + Assertions.assertEquals( + PROXY_HOST, + copy.getHttpProxyConfiguration().get().getHostname(), + "Hostname preserved in copy"); + Assertions.assertEquals( + PROXY_PORT, copy.getHttpProxyConfiguration().get().getPort(), "Port preserved in copy"); } } diff --git a/client/src/test/java/com/sinch/sdk/models/HttpProxyConfigurationTest.java b/client/src/test/java/com/sinch/sdk/models/HttpProxyConfigurationTest.java new file mode 100644 index 000000000..1d17f5409 --- /dev/null +++ b/client/src/test/java/com/sinch/sdk/models/HttpProxyConfigurationTest.java @@ -0,0 +1,204 @@ +package com.sinch.sdk.models; + +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.Test; + +class HttpProxyConfigurationTest { + + static final String HOST = "proxy.corp.example.com"; + static final int PORT = 3128; + static final String USERNAME = "proxyUser"; + static final String PASSWORD = "proxyPass"; + + static final HttpProxyConfiguration fullSettings = + HttpProxyConfiguration.builder() + .setHostname(HOST) + .setPort(PORT) + .setUsername(USERNAME) + .setPassword(PASSWORD) + .build(); + + static final HttpProxyConfiguration minimalSettings = + HttpProxyConfiguration.builder().setHostname(HOST).setPort(PORT).build(); + + @Test + void getHostname() { + assertEquals(HOST, fullSettings.getHostname()); + } + + @Test + void getPort() { + assertEquals(PORT, fullSettings.getPort()); + } + + @Test + void getUsernameWhenConfigured() { + assertTrue(fullSettings.getUsername().isPresent()); + assertEquals(USERNAME, fullSettings.getUsername().get()); + } + + @Test + void getUsernameAbsentWhenNotConfigured() { + assertFalse(minimalSettings.getUsername().isPresent()); + } + + @Test + void getPasswordWhenConfigured() { + assertTrue(fullSettings.getPassword().isPresent()); + assertArrayEquals(PASSWORD.toCharArray(), fullSettings.getPassword().get()); + } + + @Test + void getPasswordAbsentWhenNotConfigured() { + assertFalse(minimalSettings.getPassword().isPresent()); + } + + @Test + void setPasswordCharArrayOverload() { + char[] pwd = PASSWORD.toCharArray(); + HttpProxyConfiguration config = + HttpProxyConfiguration.builder() + .setHostname(HOST) + .setPort(PORT) + .setUsername(USERNAME) + .setPassword(pwd) + .build(); + assertTrue(config.getPassword().isPresent()); + assertArrayEquals(PASSWORD.toCharArray(), config.getPassword().get()); + } + + @Test + void getPasswordReturnsDefensiveCopy() { + char[] first = fullSettings.getPassword().get(); + first[0] = 'X'; + char[] second = fullSettings.getPassword().get(); + assertEquals( + PASSWORD.charAt(0), + second[0], + "Mutating the returned array must not affect internal state"); + } + + @Test + void setPasswordCharArrayInputMutationDoesNotAffectConfig() { + char[] pwd = PASSWORD.toCharArray(); + HttpProxyConfiguration config = + HttpProxyConfiguration.builder() + .setHostname(HOST) + .setPort(PORT) + .setUsername(USERNAME) + .setPassword(pwd) + .build(); + pwd[0] = 'X'; + assertArrayEquals( + PASSWORD.toCharArray(), + config.getPassword().get(), + "Mutating the original char[] after build must not affect stored password"); + } + + @Test + void toStringSensitiveDataMasked() { + String value = fullSettings.toString(); + assertFalse(value.contains(USERNAME), "username must not appear in toString output"); + assertFalse(value.contains(PASSWORD), "password must not appear in toString output"); + assertTrue(value.contains(HOST), "hostname should be visible in toString output"); + } + + @Test + void builderCopyPreservesAllFields() { + HttpProxyConfiguration copy = HttpProxyConfiguration.builder(fullSettings).build(); + assertEquals(fullSettings.getHostname(), copy.getHostname()); + assertEquals(fullSettings.getPort(), copy.getPort()); + assertEquals(fullSettings.getUsername(), copy.getUsername()); + assertArrayEquals(fullSettings.getPassword().orElse(null), copy.getPassword().orElse(null)); + } + + @Test + void buildNullHostnameThrows() { + assertThrows( + IllegalArgumentException.class, + () -> HttpProxyConfiguration.builder().setPort(PORT).build()); + } + + @Test + void buildEmptyHostnameThrows() { + assertThrows( + IllegalArgumentException.class, + () -> HttpProxyConfiguration.builder().setHostname("").setPort(PORT).build()); + } + + @Test + void buildPortZeroThrows() { + assertThrows( + IllegalArgumentException.class, + () -> HttpProxyConfiguration.builder().setHostname(HOST).setPort(0).build()); + } + + @Test + void buildPortNegativeThrows() { + assertThrows( + IllegalArgumentException.class, + () -> HttpProxyConfiguration.builder().setHostname(HOST).setPort(-1).build()); + } + + @Test + void buildPortAboveMaxThrows() { + assertThrows( + IllegalArgumentException.class, + () -> HttpProxyConfiguration.builder().setHostname(HOST).setPort(65536).build()); + } + + @Test + void buildPortAtBoundaryAccepted() { + assertDoesNotThrow(() -> HttpProxyConfiguration.builder().setHostname(HOST).setPort(1).build()); + assertDoesNotThrow( + () -> HttpProxyConfiguration.builder().setHostname(HOST).setPort(65535).build()); + } + + @Test + void buildPasswordWithoutUsernameThrows() { + assertThrows( + IllegalArgumentException.class, + () -> + HttpProxyConfiguration.builder() + .setHostname(HOST) + .setPort(PORT) + .setPassword(PASSWORD) + .build()); + } + + @Test + void buildUsernameWithoutPasswordThrows() { + assertThrows( + IllegalArgumentException.class, + () -> + HttpProxyConfiguration.builder() + .setHostname(HOST) + .setPort(PORT) + .setUsername(USERNAME) + .build()); + } + + @Test + void buildHostnameWithWhitespaceOnlyThrows() { + assertThrows( + IllegalArgumentException.class, + () -> HttpProxyConfiguration.builder().setHostname(" ").setPort(PORT).build()); + } + + @Test + void buildHostnameWithLeadingTrailingSpacesIsTrimmed() { + HttpProxyConfiguration config = + HttpProxyConfiguration.builder().setHostname(" " + HOST + " ").setPort(PORT).build(); + assertEquals(HOST, config.getHostname(), "Hostname should be trimmed"); + } + + @Test + void builderCopyAllowsOverride() { + HttpProxyConfiguration modified = + HttpProxyConfiguration.builder(fullSettings).setHostname("other-proxy.example.com").build(); + assertEquals("other-proxy.example.com", modified.getHostname()); + assertEquals(PORT, modified.getPort()); + assertEquals(fullSettings.getUsername(), modified.getUsername()); + } +} diff --git a/examples/snippets/README.md b/examples/snippets/README.md index 6b832b4d3..bc9d380b8 100644 --- a/examples/snippets/README.md +++ b/examples/snippets/README.md @@ -38,6 +38,7 @@ launcher numbers/regions/List ## Available Snippets - Conversation: [README.md](src/main/java/conversation/README.md) +- Number Lookup: [README.md](src/main/java/numberlookup/README.md) - Numbers: [README.md](src/main/java/numbers/README.md) - SMS: [README.md](src/main/java/sms/README.md) - Verification: [README.md](src/main/java/verification/README.md) diff --git a/examples/snippets/src/main/java/conversation/README.md b/examples/snippets/src/main/java/conversation/README.md index c39413f40..161f1365f 100644 --- a/examples/snippets/src/main/java/conversation/README.md +++ b/examples/snippets/src/main/java/conversation/README.md @@ -11,6 +11,9 @@ See main [README.md](../../../../README.md) for how to execute snippets - [conversation/applications/Update](./applications/Update.java) - Capability - [conversation/capability/Capability](./capability/Capability.java) +- Consents + - [conversation/consents/ListIdentities](./consents/ListIdentities.java) + - [conversation/consents/ListAuditRecords](./consents/ListAuditRecords.java) - Contacts - [conversation/contacts/List](./contacts/List.java) - [conversation/contacts/Create](./contacts/Create.java) diff --git a/examples/snippets/src/main/java/conversation/consents/ListAuditRecords.java b/examples/snippets/src/main/java/conversation/consents/ListAuditRecords.java new file mode 100644 index 000000000..0663ce475 --- /dev/null +++ b/examples/snippets/src/main/java/conversation/consents/ListAuditRecords.java @@ -0,0 +1,53 @@ +/** + * Sinch Java Snippet + * + *

This snippet is available at https://github.com/sinch/sinch-sdk-java + * + *

See https://github.com/sinch/sinch-sdk-java/blob/main/examples/snippets/README.md for details + */ +package conversation.consents; + +import com.sinch.sdk.SinchClient; +import com.sinch.sdk.domains.conversation.api.v1.ConsentsService; +import com.sinch.sdk.domains.conversation.models.v1.consents.response.AuditRecordsResponse; +import com.sinch.sdk.models.Configuration; +import com.sinch.sdk.models.ConversationRegion; +import java.util.logging.Logger; +import utils.Settings; + +public class ListAuditRecords { + + private static final Logger LOGGER = Logger.getLogger(ListAuditRecords.class.getName()); + + public static void main(String[] args) { + + String projectId = Settings.getProjectId().orElse("MY_PROJECT_ID"); + String keyId = Settings.getKeyId().orElse("MY_KEY_ID"); + String keySecret = Settings.getKeySecret().orElse("MY_KEY_SECRET"); + String conversationRegion = Settings.getConversationRegion().orElse("MY_CONVERSATION_REGION"); + + // The ID of the Conversation App + String appId = "CONVERSATION_APP_ID"; + + // The identity to retrieve audit records for (e.g. a phone number) + String identity = "MY_IDENTITY"; + + Configuration configuration = + Configuration.builder() + .setProjectId(projectId) + .setKeyId(keyId) + .setKeySecret(keySecret) + .setConversationRegion(ConversationRegion.from(conversationRegion)) + .build(); + + SinchClient client = new SinchClient(configuration); + + ConsentsService consentsService = client.conversation().v1().consents(); + + LOGGER.info(String.format("List audit records for identity '%s' in app '%s'", identity, appId)); + + AuditRecordsResponse response = consentsService.listAuditRecords(appId, identity); + + LOGGER.info("Response: " + response); + } +} diff --git a/examples/snippets/src/main/java/conversation/consents/ListIdentities.java b/examples/snippets/src/main/java/conversation/consents/ListIdentities.java new file mode 100644 index 000000000..cbd0388be --- /dev/null +++ b/examples/snippets/src/main/java/conversation/consents/ListIdentities.java @@ -0,0 +1,57 @@ +/** + * Sinch Java Snippet + * + *

This snippet is available at https://github.com/sinch/sinch-sdk-java + * + *

See https://github.com/sinch/sinch-sdk-java/blob/main/examples/snippets/README.md for details + */ +package conversation.consents; + +import com.sinch.sdk.SinchClient; +import com.sinch.sdk.domains.conversation.api.v1.ConsentsService; +import com.sinch.sdk.domains.conversation.models.v1.consents.ConsentsListType; +import com.sinch.sdk.domains.conversation.models.v1.consents.response.ConsentsListResponse; +import com.sinch.sdk.models.Configuration; +import com.sinch.sdk.models.ConversationRegion; +import java.util.logging.Logger; +import utils.Settings; + +public class ListIdentities { + + private static final Logger LOGGER = Logger.getLogger(ListIdentities.class.getName()); + + public static void main(String[] args) { + + String projectId = Settings.getProjectId().orElse("MY_PROJECT_ID"); + String keyId = Settings.getKeyId().orElse("MY_KEY_ID"); + String keySecret = Settings.getKeySecret().orElse("MY_KEY_SECRET"); + String conversationRegion = Settings.getConversationRegion().orElse("MY_CONVERSATION_REGION"); + + // The ID of the Conversation App + String appId = "CONVERSATION_APP_ID"; + + // The consent list type to query + ConsentsListType listType = ConsentsListType.OPT_OUT_ALL; + + Configuration configuration = + Configuration.builder() + .setProjectId(projectId) + .setKeyId(keyId) + .setKeySecret(keySecret) + .setConversationRegion(ConversationRegion.from(conversationRegion)) + .build(); + + SinchClient client = new SinchClient(configuration); + + ConsentsService consentsService = client.conversation().v1().consents(); + + LOGGER.info( + String.format("List identities from consent list '%s' for app '%s'", listType, appId)); + + ConsentsListResponse response = consentsService.listIdentities(appId, listType); + + LOGGER.info("Response: "); + + response.iterator().forEachRemaining(f -> LOGGER.info(f.toString())); + } +} diff --git a/examples/snippets/src/main/java/conversation/conversations/Create.java b/examples/snippets/src/main/java/conversation/conversations/Create.java index 9461388eb..8a923575b 100644 --- a/examples/snippets/src/main/java/conversation/conversations/Create.java +++ b/examples/snippets/src/main/java/conversation/conversations/Create.java @@ -52,7 +52,7 @@ public static void main(String[] args) { LOGGER.info( String.format( - "Create conversation for applicatoin with ID '%s'", conversationApplicationId)); + "Create conversation for application with ID '%s'", conversationApplicationId)); Conversation response = conversationsService.create(request); diff --git a/examples/snippets/src/main/java/numberlookup/Lookup.java b/examples/snippets/src/main/java/numberlookup/Lookup.java new file mode 100644 index 000000000..40bf4dfaf --- /dev/null +++ b/examples/snippets/src/main/java/numberlookup/Lookup.java @@ -0,0 +1,56 @@ +/** + * Sinch Java Snippet + * + *

This snippet is available at https://github.com/sinch/sinch-sdk-java + * + *

See https://github.com/sinch/sinch-sdk-java/blob/main/examples/snippets/README.md for details + */ +package numberlookup; + +import com.sinch.sdk.SinchClient; +import com.sinch.sdk.domains.numberlookup.api.v2.NumberLookupV2Service; +import com.sinch.sdk.domains.numberlookup.models.v2.request.LookupFeatureType; +import com.sinch.sdk.domains.numberlookup.models.v2.request.NumberLookupRequest; +import com.sinch.sdk.domains.numberlookup.models.v2.response.NumberLookupResponse; +import com.sinch.sdk.models.Configuration; +import java.util.Collections; +import java.util.logging.Logger; +import utils.Settings; + +public class Lookup { + + private static final Logger LOGGER = Logger.getLogger(Lookup.class.getName()); + + public static void main(String[] args) { + + String projectId = Settings.getProjectId().orElse("MY_PROJECT_ID"); + String keyId = Settings.getKeyId().orElse("MY_KEY_ID"); + String keySecret = Settings.getKeySecret().orElse("MY_KEY_SECRET"); + + // The phone number you want to lookup in E.164 format + String phoneNumber = "PHONE_NUMBER"; + + Configuration configuration = + Configuration.builder() + .setProjectId(projectId) + .setKeyId(keyId) + .setKeySecret(keySecret) + .build(); + + SinchClient client = new SinchClient(configuration); + + NumberLookupV2Service numberLookupService = client.lookup().v2(); + + NumberLookupRequest request = + NumberLookupRequest.builder() + .setNumber(phoneNumber) + .setFeatures(Collections.singletonList(LookupFeatureType.LINE_TYPE)) + .build(); + + LOGGER.info("Lookup for: " + phoneNumber); + + NumberLookupResponse response = numberLookupService.lookup(request); + + LOGGER.info("Response: " + response); + } +} diff --git a/examples/snippets/src/main/java/numberlookup/README.md b/examples/snippets/src/main/java/numberlookup/README.md new file mode 100644 index 000000000..bbb2b0d1e --- /dev/null +++ b/examples/snippets/src/main/java/numberlookup/README.md @@ -0,0 +1,7 @@ +# Number Lookup snippets +Sinch Java SDK Code Snippets Repository for NumberLookup APIs + +See main [README.md](../../../../README.md) for how to execute snippets + +- Number Lookup + - [numberlookup/Lookup](Lookup.java) diff --git a/examples/snippets/src/main/java/voice/applications/GetEventDestinations.java b/examples/snippets/src/main/java/voice/applications/GetEventDestinations.java index 65caf228e..40f8a54c6 100644 --- a/examples/snippets/src/main/java/voice/applications/GetEventDestinations.java +++ b/examples/snippets/src/main/java/voice/applications/GetEventDestinations.java @@ -33,7 +33,7 @@ public static void main(String[] args) { ApplicationsService applicationsService = client.voice().v1().applications(); - LOGGER.info(String.format("Get even destinations for application key '%s'", applicationKey)); + LOGGER.info(String.format("Get event destinations for application key '%s'", applicationKey)); EventDestinations response = applicationsService.getEventDestinations(applicationKey); diff --git a/examples/snippets/src/main/java/voice/calls/ManageWithCallLeg.java b/examples/snippets/src/main/java/voice/calls/ManageWithCallLeg.java index 47c74a033..56207a989 100644 --- a/examples/snippets/src/main/java/voice/calls/ManageWithCallLeg.java +++ b/examples/snippets/src/main/java/voice/calls/ManageWithCallLeg.java @@ -10,8 +10,8 @@ import com.sinch.sdk.SinchClient; import com.sinch.sdk.domains.voice.api.v1.CallsService; import com.sinch.sdk.domains.voice.models.v1.calls.request.CallLeg; -import com.sinch.sdk.domains.voice.models.v1.svaml.SvamlControl; -import com.sinch.sdk.domains.voice.models.v1.svaml.action.SvamlAction; +import com.sinch.sdk.domains.voice.models.v1.calls.request.CallUpdateRequest; +import com.sinch.sdk.domains.voice.models.v1.svaml.action.ManagedCallSvamlAction; import com.sinch.sdk.domains.voice.models.v1.svaml.action.SvamlActionHangup; import com.sinch.sdk.domains.voice.models.v1.svaml.instruction.SvamlInstruction; import com.sinch.sdk.domains.voice.models.v1.svaml.instruction.SvamlInstructionSay; @@ -47,7 +47,7 @@ public static void main(String[] args) { LOGGER.info(String.format("Manage call with ID '%s'", callId)); - SvamlAction action = SvamlActionHangup.SVAML_ACTION_HANGUP; + ManagedCallSvamlAction action = SvamlActionHangup.SVAML_ACTION_HANGUP; Collection instructions = Collections.singletonList( @@ -55,8 +55,8 @@ public static void main(String[] args) { .setText("Hello, the call is over, hanging up now. Goodbye") .build()); - SvamlControl request = - SvamlControl.builder().setInstructions(instructions).setAction(action).build(); + CallUpdateRequest request = + CallUpdateRequest.builder().setInstructions(instructions).setAction(action).build(); callsService.manageWithCallLeg(callId, callLeg, request); diff --git a/examples/snippets/src/main/java/voice/calls/Update.java b/examples/snippets/src/main/java/voice/calls/Update.java index 9d5cbad45..bcd6c03c2 100644 --- a/examples/snippets/src/main/java/voice/calls/Update.java +++ b/examples/snippets/src/main/java/voice/calls/Update.java @@ -9,8 +9,8 @@ import com.sinch.sdk.SinchClient; import com.sinch.sdk.domains.voice.api.v1.CallsService; -import com.sinch.sdk.domains.voice.models.v1.svaml.SvamlControl; -import com.sinch.sdk.domains.voice.models.v1.svaml.action.SvamlAction; +import com.sinch.sdk.domains.voice.models.v1.calls.request.CallUpdateRequest; +import com.sinch.sdk.domains.voice.models.v1.svaml.action.ManagedCallSvamlAction; import com.sinch.sdk.domains.voice.models.v1.svaml.action.SvamlActionHangup; import com.sinch.sdk.domains.voice.models.v1.svaml.instruction.SvamlInstruction; import com.sinch.sdk.domains.voice.models.v1.svaml.instruction.SvamlInstructionSay; @@ -34,7 +34,7 @@ public static void main(String[] args) { // The instruction to be performed SvamlInstruction instruction = SvamlInstructionSay.builder().setText("Goodbye").build(); // The instruction to add to the call - SvamlAction action = SvamlActionHangup.SVAML_ACTION_HANGUP; + ManagedCallSvamlAction action = SvamlActionHangup.SVAML_ACTION_HANGUP; Configuration configuration = Configuration.builder() @@ -50,8 +50,8 @@ public static void main(String[] args) { Collection instructions = Collections.singletonList(instruction); - SvamlControl request = - SvamlControl.builder().setInstructions(instructions).setAction(action).build(); + CallUpdateRequest request = + CallUpdateRequest.builder().setInstructions(instructions).setAction(action).build(); callsService.update(callId, request); diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/api/v1/ConsentsService.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/api/v1/ConsentsService.java new file mode 100644 index 000000000..4e70cfb3b --- /dev/null +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/api/v1/ConsentsService.java @@ -0,0 +1,68 @@ +/* + * Conversation API | Sinch + * + * OpenAPI document version: 1.0 + * Contact: support@sinch.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * Do not edit the class manually. + */ + +package com.sinch.sdk.domains.conversation.api.v1; + +import com.sinch.sdk.core.exceptions.ApiException; +import com.sinch.sdk.domains.conversation.models.v1.consents.ConsentsListType; +import com.sinch.sdk.domains.conversation.models.v1.consents.request.ConsentsListQueryParameters; +import com.sinch.sdk.domains.conversation.models.v1.consents.response.AuditRecordsResponse; +import com.sinch.sdk.domains.conversation.models.v1.consents.response.ConsentsListResponse; + +/** Consents Service */ +public interface ConsentsService { + + /** + * Get audit records from consent lists + * + *

Get all audit records associated with the given identity from the consent lists within the + * specified project and app. + * + * @param appId The unique ID of the app. You can find this on the [Sinch + * Dashboard](https://dashboard.sinch.com/convapi/apps). (required) + * @param identity An identity to use on Consent audit records queries. (required) + * @return AuditRecordsResponse + * @throws ApiException if fails to make API call + */ + AuditRecordsResponse listAuditRecords(String appId, String identity) throws ApiException; + + /** + * Get identities from consent list (using default parameters) + * + *

Get all identities contained within a consent list for a given project id, app id, and list + * type. + * + * @param appId The unique ID of the app. You can find this on the [Sinch + * Dashboard](https://dashboard.sinch.com/convapi/apps). (required) + * @param listType The consent list type. One of `OPT_OUT_ALL`, + * `OPT_OUT_MARKETING`, and or `OPT_OUT_NOTIFICATION`. (required) + * @return ConsentsListResponse + * @throws ApiException if fails to make API call + */ + ConsentsListResponse listIdentities(String appId, ConsentsListType listType) throws ApiException; + + /** + * Get identities from consent list + * + *

Get all identities contained within a consent list for a given project id, app id, and list + * type. + * + * @param appId The unique ID of the app. You can find this on the [Sinch + * Dashboard](https://dashboard.sinch.com/convapi/apps). (required) + * @param listType The consent list type. One of `OPT_OUT_ALL`, + * `OPT_OUT_MARKETING`, and or `OPT_OUT_NOTIFICATION`. (required) + * @param queryParameter (optional) + * @return ConsentsListResponse + * @throws ApiException if fails to make API call + */ + ConsentsListResponse listIdentities( + String appId, ConsentsListType listType, ConsentsListQueryParameters queryParameter) + throws ApiException; +} diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/api/v1/ContactsService.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/api/v1/ContactsService.java index 6f2101292..5b423eff9 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/api/v1/ContactsService.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/api/v1/ContactsService.java @@ -168,7 +168,7 @@ IdentityConflictsListResponse listIdentityConflicts( * will be moved from the source contact to the destination contact only for channels that * weren't present there before. Moved channel identities will be placed at the bottom of the * channel priority list. Optional fields from the source contact will be copied only if - * corresponding fields in the destination contact are empty The contact being removed cannot be + * corresponding fields in the destination contact are empty. The contact being removed cannot be * referenced after this call. * * @param destinationId The unique ID of the contact that should be kept when merging two diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/api/v1/ConversationsService.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/api/v1/ConversationsService.java index f4751ae3e..9d39a8a92 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/api/v1/ConversationsService.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/api/v1/ConversationsService.java @@ -136,7 +136,7 @@ RecentConversationsListResponse listRecent(RecentConversationsListQueryParameter * Stop conversation * *

This operation stops the referenced conversation, if the conversation is still active. In - * Conversation mode, A new conversation will be created if a new message is exchanged between the + * Conversation mode, a new conversation will be created if a new message is exchanged between the * app or contact that was part of the stopped conversation. * * @param conversationId The unique ID of the conversation. This is generated by the system. diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/api/v1/adapters/ConsentsServiceImpl.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/api/v1/adapters/ConsentsServiceImpl.java new file mode 100644 index 000000000..20e4017c1 --- /dev/null +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/api/v1/adapters/ConsentsServiceImpl.java @@ -0,0 +1,271 @@ +/* + * Conversation API | Sinch + * + * OpenAPI document version: 1.0 + * Contact: support@sinch.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * Do not edit the class manually. + */ + +package com.sinch.sdk.domains.conversation.api.v1.adapters; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.sinch.sdk.core.exceptions.ApiException; +import com.sinch.sdk.core.exceptions.ApiExceptionBuilder; +import com.sinch.sdk.core.http.AuthManager; +import com.sinch.sdk.core.http.HttpClient; +import com.sinch.sdk.core.http.HttpMapper; +import com.sinch.sdk.core.http.HttpMethod; +import com.sinch.sdk.core.http.HttpRequest; +import com.sinch.sdk.core.http.HttpResponse; +import com.sinch.sdk.core.http.HttpStatus; +import com.sinch.sdk.core.http.URLParameter; +import com.sinch.sdk.core.http.URLParameterUtils; +import com.sinch.sdk.core.http.URLPathUtils; +import com.sinch.sdk.core.models.ServerConfiguration; +import com.sinch.sdk.core.models.pagination.Page; +import com.sinch.sdk.core.models.pagination.PageNavigator; +import com.sinch.sdk.core.utils.StringUtil; +import com.sinch.sdk.domains.conversation.models.v1.consents.ConsentsListType; +import com.sinch.sdk.domains.conversation.models.v1.consents.internal.ConsentsListResponseInternal; +import com.sinch.sdk.domains.conversation.models.v1.consents.request.ConsentsListQueryParameters; +import com.sinch.sdk.domains.conversation.models.v1.consents.response.AuditRecordsResponse; +import com.sinch.sdk.domains.conversation.models.v1.consents.response.ConsentsListResponse; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.logging.Logger; + +public class ConsentsServiceImpl + implements com.sinch.sdk.domains.conversation.api.v1.ConsentsService { + + private static final Logger LOGGER = Logger.getLogger(ConsentsServiceImpl.class.getName()); + private final HttpClient httpClient; + private final ServerConfiguration serverConfiguration; + private final Map authManagersByOasSecuritySchemes; + private final HttpMapper mapper; + + private final String projectId; + + public ConsentsServiceImpl( + HttpClient httpClient, + ServerConfiguration serverConfiguration, + Map authManagersByOasSecuritySchemes, + HttpMapper mapper, + String projectId) { + this.httpClient = httpClient; + this.serverConfiguration = serverConfiguration; + this.authManagersByOasSecuritySchemes = authManagersByOasSecuritySchemes; + this.mapper = mapper; + this.projectId = projectId; + } + + @Override + public AuditRecordsResponse listAuditRecords(String appId, String identity) throws ApiException { + + LOGGER.finest("[listAuditRecords]" + " " + "appId: " + appId + ", " + "identity: " + identity); + + HttpRequest httpRequest = listAuditRecordsRequestBuilder(appId, identity); + HttpResponse response = + httpClient.invokeAPI( + this.serverConfiguration, this.authManagersByOasSecuritySchemes, httpRequest); + + if (HttpStatus.isSuccessfulStatus(response.getCode())) { + return mapper.deserialize(response, new TypeReference() {}); + } + // fallback to default errors handling: + // all error cases definition are not required from specs: will try some "hardcoded" content + // parsing + throw ApiExceptionBuilder.build( + response.getMessage(), + response.getCode(), + mapper.deserialize(response, new TypeReference>() {})); + } + + private HttpRequest listAuditRecordsRequestBuilder(String appId, String identity) + throws ApiException { + // verify the required parameter 'this.projectId' is set + if (this.projectId == null) { + throw new ApiException( + 400, "Missing the required parameter 'this.projectId' when calling listAuditRecords"); + } + // verify the required parameter 'appId' is set + if (appId == null) { + throw new ApiException( + 400, "Missing the required parameter 'appId' when calling listAuditRecords"); + } + // verify the required parameter 'identity' is set + if (identity == null) { + throw new ApiException( + 400, "Missing the required parameter 'identity' when calling listAuditRecords"); + } + + String localVarPath = + "/v1/projects/{project_id}/apps/{app_id}/consents/identities/{identity}" + .replaceAll( + "\\{" + "project_id" + "\\}", + URLPathUtils.encodePathSegment(this.projectId.toString())) + .replaceAll("\\{" + "app_id" + "\\}", URLPathUtils.encodePathSegment(appId.toString())) + .replaceAll( + "\\{" + "identity" + "\\}", URLPathUtils.encodePathSegment(identity.toString())); + + List localVarQueryParams = new ArrayList<>(); + + Map localVarHeaderParams = new HashMap<>(); + + final Collection localVarAccepts = Arrays.asList("application/json"); + + final Collection localVarContentTypes = Arrays.asList(); + + final Collection localVarAuthNames = Arrays.asList("Basic", "oAuth2"); + final String serializedBody = null; + + return new HttpRequest( + localVarPath, + HttpMethod.GET, + localVarQueryParams, + serializedBody, + localVarHeaderParams, + localVarAccepts, + localVarContentTypes, + localVarAuthNames); + } + + @Override + public ConsentsListResponse listIdentities(String appId, ConsentsListType listType) + throws ApiException { + return listIdentities(appId, listType, (ConsentsListQueryParameters) null); + } + + @Override + public ConsentsListResponse listIdentities( + String appId, ConsentsListType listType, ConsentsListQueryParameters queryParameter) + throws ApiException { + + LOGGER.finest( + "[listIdentities]" + + " " + + "appId: " + + appId + + ", " + + "listType: " + + listType + + ", " + + "queryParameter: " + + queryParameter); + + HttpRequest httpRequest = listIdentitiesRequestBuilder(appId, listType, queryParameter); + return _fetchListIdentitiesPage( + (queryParameters) -> listIdentitiesRequestBuilder(appId, listType, queryParameters), + queryParameter, + httpRequest); + } + + private ConsentsListResponse _fetchListIdentitiesPage( + Function requestBuilder, + ConsentsListQueryParameters queryParameter, + HttpRequest httpRequest) + throws ApiException { + HttpResponse response = + httpClient.invokeAPI( + this.serverConfiguration, this.authManagersByOasSecuritySchemes, httpRequest); + + if (HttpStatus.isSuccessfulStatus(response.getCode())) { + + ConsentsListResponseInternal deserialized = + mapper.deserialize(response, new TypeReference() {}); + + String nextToken = deserialized.getNextPageToken(); + + ConsentsListQueryParameters nextParameters = + ConsentsListQueryParameters.builder(queryParameter).setPageToken(nextToken).build(); + + final HttpRequest nextHttpRequest = + !StringUtil.isEmpty(nextToken) ? requestBuilder.apply(nextParameters) : null; + + return new ConsentsListResponse( + () -> _fetchListIdentitiesPage(requestBuilder, nextParameters, nextHttpRequest), + new Page<>(deserialized.getIdentities(), new PageNavigator<>(nextHttpRequest))); + } + // fallback to default errors handling: + // all error cases definition are not required from specs: will try some "hardcoded" content + // parsing + throw ApiExceptionBuilder.build( + response.getMessage(), + response.getCode(), + mapper.deserialize(response, new TypeReference>() {})); + } + + private HttpRequest listIdentitiesRequestBuilder( + String appId, ConsentsListType listType, ConsentsListQueryParameters queryParameter) + throws ApiException { + // verify the required parameter 'this.projectId' is set + if (this.projectId == null) { + throw new ApiException( + 400, "Missing the required parameter 'this.projectId' when calling listIdentities"); + } + // verify the required parameter 'appId' is set + if (appId == null) { + throw new ApiException( + 400, "Missing the required parameter 'appId' when calling listIdentities"); + } + // verify the required parameter 'listType' is set + if (listType == null) { + throw new ApiException( + 400, "Missing the required parameter 'listType' when calling listIdentities"); + } + + String localVarPath = + "/v1/projects/{project_id}/apps/{app_id}/consents/{list_type}" + .replaceAll( + "\\{" + "project_id" + "\\}", + URLPathUtils.encodePathSegment(this.projectId.toString())) + .replaceAll("\\{" + "app_id" + "\\}", URLPathUtils.encodePathSegment(appId.toString())) + .replaceAll( + "\\{" + "list_type" + "\\}", URLPathUtils.encodePathSegment(listType.toString())); + + List localVarQueryParams = new ArrayList<>(); + if (null != queryParameter) { + + URLParameterUtils.addQueryParam( + queryParameter.getPageSize(), + "page_size", + URLParameter.form, + null, + localVarQueryParams, + true); + + URLParameterUtils.addQueryParam( + queryParameter.getPageToken(), + "page_token", + URLParameter.form, + null, + localVarQueryParams, + true); + } + + Map localVarHeaderParams = new HashMap<>(); + + final Collection localVarAccepts = Arrays.asList("application/json"); + + final Collection localVarContentTypes = Arrays.asList(); + + final Collection localVarAuthNames = Arrays.asList("Basic", "oAuth2"); + final String serializedBody = null; + + return new HttpRequest( + localVarPath, + HttpMethod.GET, + localVarQueryParams, + serializedBody, + localVarHeaderParams, + localVarAccepts, + localVarContentTypes, + localVarAuthNames); + } +} diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/api/v1/adapters/ContactsServiceImpl.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/api/v1/adapters/ContactsServiceImpl.java index 713266dff..9850bd462 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/api/v1/adapters/ContactsServiceImpl.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/api/v1/adapters/ContactsServiceImpl.java @@ -46,6 +46,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.function.Function; import java.util.logging.Logger; public class ContactsServiceImpl @@ -84,11 +85,15 @@ public ContactsListResponse list(ContactsListQueryParameters queryParameter) thr LOGGER.finest("[list]" + " " + "queryParameter: " + queryParameter); HttpRequest httpRequest = listRequestBuilder(queryParameter); - return _fetchListPage(queryParameter, httpRequest); + return _fetchListPage( + (queryParameters) -> listRequestBuilder(queryParameters), queryParameter, httpRequest); } private ContactsListResponse _fetchListPage( - ContactsListQueryParameters queryParameter, HttpRequest httpRequest) throws ApiException { + Function requestBuilder, + ContactsListQueryParameters queryParameter, + HttpRequest httpRequest) + throws ApiException { HttpResponse response = httpClient.invokeAPI( this.serverConfiguration, this.authManagersByOasSecuritySchemes, httpRequest); @@ -104,10 +109,10 @@ private ContactsListResponse _fetchListPage( ContactsListQueryParameters.builder(queryParameter).setPageToken(nextToken).build(); final HttpRequest nextHttpRequest = - !StringUtil.isEmpty(nextToken) ? listRequestBuilder(nextParameters) : null; + !StringUtil.isEmpty(nextToken) ? requestBuilder.apply(nextParameters) : null; return new ContactsListResponse( - () -> _fetchListPage(nextParameters, nextHttpRequest), + () -> _fetchListPage(requestBuilder, nextParameters, nextHttpRequest), new Page<>(deserialized.getContacts(), new PageNavigator<>(nextHttpRequest))); } // fallback to default errors handling: @@ -480,11 +485,16 @@ public IdentityConflictsListResponse listIdentityConflicts( LOGGER.finest("[listIdentityConflicts]" + " " + "queryParameter: " + queryParameter); HttpRequest httpRequest = listIdentityConflictsRequestBuilder(queryParameter); - return _fetchListIdentityConflictsPage(queryParameter, httpRequest); + return _fetchListIdentityConflictsPage( + (queryParameters) -> listIdentityConflictsRequestBuilder(queryParameters), + queryParameter, + httpRequest); } private IdentityConflictsListResponse _fetchListIdentityConflictsPage( - IdentityConflictsListQueryParameters queryParameter, HttpRequest httpRequest) + Function requestBuilder, + IdentityConflictsListQueryParameters queryParameter, + HttpRequest httpRequest) throws ApiException { HttpResponse response = httpClient.invokeAPI( @@ -504,12 +514,10 @@ private IdentityConflictsListResponse _fetchListIdentityConflictsPage( .build(); final HttpRequest nextHttpRequest = - !StringUtil.isEmpty(nextToken) - ? listIdentityConflictsRequestBuilder(nextParameters) - : null; + !StringUtil.isEmpty(nextToken) ? requestBuilder.apply(nextParameters) : null; return new IdentityConflictsListResponse( - () -> _fetchListIdentityConflictsPage(nextParameters, nextHttpRequest), + () -> _fetchListIdentityConflictsPage(requestBuilder, nextParameters, nextHttpRequest), new Page<>(deserialized.getConflicts(), new PageNavigator<>(nextHttpRequest))); } // fallback to default errors handling: diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/api/v1/adapters/ConversationsServiceImpl.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/api/v1/adapters/ConversationsServiceImpl.java index dae6bdfb0..1387c112a 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/api/v1/adapters/ConversationsServiceImpl.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/api/v1/adapters/ConversationsServiceImpl.java @@ -45,6 +45,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.function.Function; import java.util.logging.Logger; public class ConversationsServiceImpl @@ -84,11 +85,14 @@ public ConversationsListResponse list(ConversationsListQueryParameters queryPara LOGGER.finest("[list]" + " " + "queryParameter: " + queryParameter); HttpRequest httpRequest = listRequestBuilder(queryParameter); - return _fetchListPage(queryParameter, httpRequest); + return _fetchListPage( + (queryParameters) -> listRequestBuilder(queryParameters), queryParameter, httpRequest); } private ConversationsListResponse _fetchListPage( - ConversationsListQueryParameters queryParameter, HttpRequest httpRequest) + Function requestBuilder, + ConversationsListQueryParameters queryParameter, + HttpRequest httpRequest) throws ApiException { HttpResponse response = httpClient.invokeAPI( @@ -105,10 +109,10 @@ private ConversationsListResponse _fetchListPage( ConversationsListQueryParameters.builder(queryParameter).setPageToken(nextToken).build(); final HttpRequest nextHttpRequest = - !StringUtil.isEmpty(nextToken) ? listRequestBuilder(nextParameters) : null; + !StringUtil.isEmpty(nextToken) ? requestBuilder.apply(nextParameters) : null; return new ConversationsListResponse( - () -> _fetchListPage(nextParameters, nextHttpRequest), + () -> _fetchListPage(requestBuilder, nextParameters, nextHttpRequest), new Page<>(deserialized.getConversations(), new PageNavigator<>(nextHttpRequest))); } // fallback to default errors handling: @@ -563,11 +567,16 @@ public RecentConversationsListResponse listRecent( LOGGER.finest("[listRecent]" + " " + "queryParameter: " + queryParameter); HttpRequest httpRequest = listRecentRequestBuilder(queryParameter); - return _fetchListRecentPage(queryParameter, httpRequest); + return _fetchListRecentPage( + (queryParameters) -> listRecentRequestBuilder(queryParameters), + queryParameter, + httpRequest); } private RecentConversationsListResponse _fetchListRecentPage( - RecentConversationsListQueryParameters queryParameter, HttpRequest httpRequest) + Function requestBuilder, + RecentConversationsListQueryParameters queryParameter, + HttpRequest httpRequest) throws ApiException { HttpResponse response = httpClient.invokeAPI( @@ -587,10 +596,10 @@ private RecentConversationsListResponse _fetchListRecentPage( .build(); final HttpRequest nextHttpRequest = - !StringUtil.isEmpty(nextToken) ? listRecentRequestBuilder(nextParameters) : null; + !StringUtil.isEmpty(nextToken) ? requestBuilder.apply(nextParameters) : null; return new RecentConversationsListResponse( - () -> _fetchListRecentPage(nextParameters, nextHttpRequest), + () -> _fetchListRecentPage(requestBuilder, nextParameters, nextHttpRequest), new Page<>(deserialized.getConversations(), new PageNavigator<>(nextHttpRequest))); } // fallback to default errors handling: diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/api/v1/adapters/EventsServiceImpl.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/api/v1/adapters/EventsServiceImpl.java index e797c5dbc..a929ece67 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/api/v1/adapters/EventsServiceImpl.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/api/v1/adapters/EventsServiceImpl.java @@ -39,6 +39,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.function.Function; import java.util.logging.Logger; public class EventsServiceImpl implements com.sinch.sdk.domains.conversation.api.v1.EventsService { @@ -76,11 +77,15 @@ public EventsListResponse list(EventsListQueryParameters queryParameter) throws LOGGER.finest("[list]" + " " + "queryParameter: " + queryParameter); HttpRequest httpRequest = listRequestBuilder(queryParameter); - return _fetchListPage(queryParameter, httpRequest); + return _fetchListPage( + (queryParameters) -> listRequestBuilder(queryParameters), queryParameter, httpRequest); } private EventsListResponse _fetchListPage( - EventsListQueryParameters queryParameter, HttpRequest httpRequest) throws ApiException { + Function requestBuilder, + EventsListQueryParameters queryParameter, + HttpRequest httpRequest) + throws ApiException { HttpResponse response = httpClient.invokeAPI( this.serverConfiguration, this.authManagersByOasSecuritySchemes, httpRequest); @@ -96,10 +101,10 @@ private EventsListResponse _fetchListPage( EventsListQueryParameters.builder(queryParameter).setPageToken(nextToken).build(); final HttpRequest nextHttpRequest = - !StringUtil.isEmpty(nextToken) ? listRequestBuilder(nextParameters) : null; + !StringUtil.isEmpty(nextToken) ? requestBuilder.apply(nextParameters) : null; return new EventsListResponse( - () -> _fetchListPage(nextParameters, nextHttpRequest), + () -> _fetchListPage(requestBuilder, nextParameters, nextHttpRequest), new Page<>(deserialized.getEvents(), new PageNavigator<>(nextHttpRequest))); } // fallback to default errors handling: diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/api/v1/adapters/MessagesServiceImpl.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/api/v1/adapters/MessagesServiceImpl.java index 390b2cf0c..b152a134a 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/api/v1/adapters/MessagesServiceImpl.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/api/v1/adapters/MessagesServiceImpl.java @@ -54,6 +54,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.function.Function; import java.util.logging.Logger; public class MessagesServiceImpl @@ -92,11 +93,15 @@ public MessagesListResponse list(MessagesListQueryParameters queryParameter) thr LOGGER.finest("[list]" + " " + "queryParameter: " + queryParameter); HttpRequest httpRequest = listRequestBuilder(queryParameter); - return _fetchListPage(queryParameter, httpRequest); + return _fetchListPage( + (queryParameters) -> listRequestBuilder(queryParameters), queryParameter, httpRequest); } private MessagesListResponse _fetchListPage( - MessagesListQueryParameters queryParameter, HttpRequest httpRequest) throws ApiException { + Function requestBuilder, + MessagesListQueryParameters queryParameter, + HttpRequest httpRequest) + throws ApiException { HttpResponse response = httpClient.invokeAPI( this.serverConfiguration, this.authManagersByOasSecuritySchemes, httpRequest); @@ -112,10 +117,10 @@ private MessagesListResponse _fetchListPage( MessagesListQueryParameters.builder(queryParameter).setPageToken(nextToken).build(); final HttpRequest nextHttpRequest = - !StringUtil.isEmpty(nextToken) ? listRequestBuilder(nextParameters) : null; + !StringUtil.isEmpty(nextToken) ? requestBuilder.apply(nextParameters) : null; return new MessagesListResponse( - () -> _fetchListPage(nextParameters, nextHttpRequest), + () -> _fetchListPage(requestBuilder, nextParameters, nextHttpRequest), new Page<>(deserialized.getMessages(), new PageNavigator<>(nextHttpRequest))); } // fallback to default errors handling: @@ -438,11 +443,16 @@ public MessagesListResponse listLastMessagesByChannelIdentity( "[listLastMessagesByChannelIdentity]" + " " + "queryParameter: " + queryParameter); HttpRequest httpRequest = listLastMessagesByChannelIdentityRequestBuilder(queryParameter); - return _fetchListLastMessagesByChannelIdentityPage(queryParameter, httpRequest); + return _fetchListLastMessagesByChannelIdentityPage( + (queryParameters) -> listLastMessagesByChannelIdentityRequestBuilder(queryParameters), + queryParameter, + httpRequest); } private MessagesListResponse _fetchListLastMessagesByChannelIdentityPage( - LastMessagesByChannelIdentityListQueryParameters queryParameter, HttpRequest httpRequest) + Function requestBuilder, + LastMessagesByChannelIdentityListQueryParameters queryParameter, + HttpRequest httpRequest) throws ApiException { HttpResponse response = httpClient.invokeAPI( @@ -461,12 +471,12 @@ private MessagesListResponse _fetchListLastMessagesByChannelIdentityPage( .build(); final HttpRequest nextHttpRequest = - !StringUtil.isEmpty(nextToken) - ? listLastMessagesByChannelIdentityRequestBuilder(nextParameters) - : null; + !StringUtil.isEmpty(nextToken) ? requestBuilder.apply(nextParameters) : null; return new MessagesListResponse( - () -> _fetchListLastMessagesByChannelIdentityPage(nextParameters, nextHttpRequest), + () -> + _fetchListLastMessagesByChannelIdentityPage( + requestBuilder, nextParameters, nextHttpRequest), new Page<>(deserialized.getMessages(), new PageNavigator<>(nextHttpRequest))); } // fallback to default errors handling: diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/ReasonCode.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/ReasonCode.java index 4955f0dbd..6e9ab0086 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/ReasonCode.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/ReasonCode.java @@ -59,7 +59,7 @@ public class ReasonCode extends EnumDynamic { new ReasonCode("CHANNEL_CONFIGURATION_MISSING"); /** - * Some of the referenced media files is of a unsupported media type. Please read the channel support * documentation page to find out the limitations on media that the different channels impose. */ diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/apps/DeliveryReportBasedFallback.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/apps/DeliveryReportBasedFallback.java index 50c26ddda..ed11f8056 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/apps/DeliveryReportBasedFallback.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/apps/DeliveryReportBasedFallback.java @@ -15,8 +15,7 @@ /** * This object contains additional settings related to delivery - * report based fallback. Note that this paid functionality is available for - * open beta testing. + * report based fallback. Note that this is paid functionality. */ @JsonDeserialize(builder = DeliveryReportBasedFallbackImpl.Builder.class) public interface DeliveryReportBasedFallback { @@ -34,7 +33,11 @@ public interface DeliveryReportBasedFallback { /** * Optional. The time, in seconds, after which a message without a positive delivery report will - * fallback to the next channel. The valid values for this field are [60 - 259200]. + * fallback to the next channel. + * + *

Minimum: 10 + * + *

Maximum: 259200 * * @return deliveryReportWaitingTime */ diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/capability/response/QueryCapabilityResponse.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/capability/response/QueryCapabilityResponse.java index b8934c16c..e06991ff5 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/capability/response/QueryCapabilityResponse.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/capability/response/QueryCapabilityResponse.java @@ -14,8 +14,8 @@ import com.sinch.sdk.domains.conversation.models.v1.Recipient; /** - * An CapabilityResponse contains the identity of the recipient for which will be perform a - * capability lookup. + * A CapabilityResponse contains the identity of the recipient for which a capability lookup will be + * performed. */ @JsonDeserialize(builder = QueryCapabilityResponseImpl.Builder.class) public interface QueryCapabilityResponse { diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/consents/ConsentsListType.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/consents/ConsentsListType.java new file mode 100644 index 000000000..45a29e214 --- /dev/null +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/consents/ConsentsListType.java @@ -0,0 +1,47 @@ +package com.sinch.sdk.domains.conversation.models.v1.consents; + +import com.sinch.sdk.core.utils.EnumDynamic; +import com.sinch.sdk.core.utils.EnumSupportDynamic; +import java.util.Arrays; +import java.util.stream.Stream; + +/** + * The consent list type. See consent management + * page for more information. + */ +public class ConsentsListType extends EnumDynamic { + + /** List type that blocks all kinds of messages */ + public static final ConsentsListType OPT_OUT_ALL = new ConsentsListType("OPT_OUT_ALL"); + + /** List type that blocks only marketing messages */ + public static final ConsentsListType OPT_OUT_MARKETING = + new ConsentsListType("OPT_OUT_MARKETING"); + + /** List type that blocks only notification messages */ + public static final ConsentsListType OPT_OUT_NOTIFICATION = + new ConsentsListType("OPT_OUT_NOTIFICATION"); + + private static final EnumSupportDynamic ENUM_SUPPORT = + new EnumSupportDynamic<>( + ConsentsListType.class, + ConsentsListType::new, + Arrays.asList(OPT_OUT_ALL, OPT_OUT_MARKETING, OPT_OUT_NOTIFICATION)); + + private ConsentsListType(String value) { + super(value); + } + + public static Stream values() { + return ENUM_SUPPORT.values(); + } + + public static ConsentsListType from(String value) { + return ENUM_SUPPORT.from(value); + } + + public static String valueOf(ConsentsListType e) { + return ENUM_SUPPORT.valueOf(e); + } +} diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/consents/Identity.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/consents/Identity.java new file mode 100644 index 000000000..b04f75e05 --- /dev/null +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/consents/Identity.java @@ -0,0 +1,56 @@ +/* + * Conversation API | Sinch + * + * OpenAPI document version: 1.0 + * Contact: support@sinch.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * Do not edit the class manually. + */ + +package com.sinch.sdk.domains.conversation.models.v1.consents; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; + +/** Represents a identity from the Conversation API. */ +@JsonDeserialize(builder = IdentityImpl.Builder.class) +public interface Identity { + + /** + * The identity from Conversation API. + * + *

Field is required + * + * @return identity + */ + String getIdentity(); + + /** + * Getting builder + * + * @return New Builder instance + */ + static Builder builder() { + return new IdentityImpl.Builder(); + } + + /** Dedicated Builder */ + interface Builder { + + /** + * see getter + * + * @param identity see getter + * @return Current builder + * @see #getIdentity + */ + Builder setIdentity(String identity); + + /** + * Create instance + * + * @return The instance build with current builder values + */ + Identity build(); + } +} diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/consents/IdentityImpl.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/consents/IdentityImpl.java new file mode 100644 index 000000000..4d28c5203 --- /dev/null +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/consents/IdentityImpl.java @@ -0,0 +1,90 @@ +package com.sinch.sdk.domains.conversation.models.v1.consents; + +import com.fasterxml.jackson.annotation.JsonFilter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; +import com.sinch.sdk.core.models.OptionalValue; +import java.util.Objects; + +@JsonPropertyOrder({IdentityImpl.JSON_PROPERTY_IDENTITY}) +@JsonFilter("uninitializedFilter") +@JsonInclude(value = JsonInclude.Include.CUSTOM) +public class IdentityImpl implements Identity { + private static final long serialVersionUID = 1L; + + public static final String JSON_PROPERTY_IDENTITY = "identity"; + + private OptionalValue identity; + + public IdentityImpl() {} + + protected IdentityImpl(OptionalValue identity) { + this.identity = identity; + } + + @JsonIgnore + public String getIdentity() { + return identity.orElse(null); + } + + @JsonProperty(JSON_PROPERTY_IDENTITY) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public OptionalValue identity() { + return identity; + } + + /** Return true if this Identity object is equal to o. */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + IdentityImpl identity = (IdentityImpl) o; + return Objects.equals(this.identity, identity.identity); + } + + @Override + public int hashCode() { + return Objects.hash(identity); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class IdentityImpl {\n"); + sb.append(" identity: ").append(toIndentedString(identity)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + @JsonPOJOBuilder(withPrefix = "set") + static class Builder implements Identity.Builder { + OptionalValue identity = OptionalValue.empty(); + + @JsonProperty(value = JSON_PROPERTY_IDENTITY, required = true) + public Builder setIdentity(String identity) { + this.identity = OptionalValue.of(identity); + return this; + } + + public Identity build() { + return new IdentityImpl(identity); + } + } +} diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/consents/internal/ConsentsListResponseInternal.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/consents/internal/ConsentsListResponseInternal.java new file mode 100644 index 000000000..39dc2aa6e --- /dev/null +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/consents/internal/ConsentsListResponseInternal.java @@ -0,0 +1,72 @@ +/* + * Conversation API | Sinch + * + * OpenAPI document version: 1.0 + * Contact: support@sinch.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * Do not edit the class manually. + */ + +package com.sinch.sdk.domains.conversation.models.v1.consents.internal; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.sinch.sdk.domains.conversation.models.v1.consents.Identity; +import java.util.List; + +/** ConsentsListResponseInternal */ +@JsonDeserialize(builder = ConsentsListResponseInternalImpl.Builder.class) +public interface ConsentsListResponseInternal { + + /** + * List of identities belonging to a specific project ID, app ID, and list type + * + * @return identities + */ + List getIdentities(); + + /** + * Token for the next page of the search, to be used in the next call. + * + * @return nextPageToken + */ + String getNextPageToken(); + + /** + * Getting builder + * + * @return New Builder instance + */ + static Builder builder() { + return new ConsentsListResponseInternalImpl.Builder(); + } + + /** Dedicated Builder */ + interface Builder { + + /** + * see getter + * + * @param identities see getter + * @return Current builder + * @see #getIdentities + */ + Builder setIdentities(List identities); + + /** + * see getter + * + * @param nextPageToken see getter + * @return Current builder + * @see #getNextPageToken + */ + Builder setNextPageToken(String nextPageToken); + + /** + * Create instance + * + * @return The instance build with current builder values + */ + ConsentsListResponseInternal build(); + } +} diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/consents/internal/ConsentsListResponseInternalImpl.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/consents/internal/ConsentsListResponseInternalImpl.java new file mode 100644 index 000000000..13dddc29c --- /dev/null +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/consents/internal/ConsentsListResponseInternalImpl.java @@ -0,0 +1,122 @@ +package com.sinch.sdk.domains.conversation.models.v1.consents.internal; + +import com.fasterxml.jackson.annotation.JsonFilter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; +import com.sinch.sdk.core.models.OptionalValue; +import com.sinch.sdk.domains.conversation.models.v1.consents.Identity; +import java.util.List; +import java.util.Objects; + +@JsonPropertyOrder({ + ConsentsListResponseInternalImpl.JSON_PROPERTY_IDENTITIES, + ConsentsListResponseInternalImpl.JSON_PROPERTY_NEXT_PAGE_TOKEN +}) +@JsonFilter("uninitializedFilter") +@JsonInclude(value = JsonInclude.Include.CUSTOM) +public class ConsentsListResponseInternalImpl implements ConsentsListResponseInternal { + private static final long serialVersionUID = 1L; + + public static final String JSON_PROPERTY_IDENTITIES = "identities"; + + private OptionalValue> identities; + + public static final String JSON_PROPERTY_NEXT_PAGE_TOKEN = "next_page_token"; + + private OptionalValue nextPageToken; + + public ConsentsListResponseInternalImpl() {} + + protected ConsentsListResponseInternalImpl( + OptionalValue> identities, OptionalValue nextPageToken) { + this.identities = identities; + this.nextPageToken = nextPageToken; + } + + @JsonIgnore + public List getIdentities() { + return identities.orElse(null); + } + + @JsonProperty(JSON_PROPERTY_IDENTITIES) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public OptionalValue> identities() { + return identities; + } + + @JsonIgnore + public String getNextPageToken() { + return nextPageToken.orElse(null); + } + + @JsonProperty(JSON_PROPERTY_NEXT_PAGE_TOKEN) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public OptionalValue nextPageToken() { + return nextPageToken; + } + + /** Return true if this GetIdentitiesFromConsentResponse object is equal to o. */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ConsentsListResponseInternalImpl getIdentitiesFromConsentResponse = + (ConsentsListResponseInternalImpl) o; + return Objects.equals(this.identities, getIdentitiesFromConsentResponse.identities) + && Objects.equals(this.nextPageToken, getIdentitiesFromConsentResponse.nextPageToken); + } + + @Override + public int hashCode() { + return Objects.hash(identities, nextPageToken); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class ConsentsListResponseInternalImpl {\n"); + sb.append(" identities: ").append(toIndentedString(identities)).append("\n"); + sb.append(" nextPageToken: ").append(toIndentedString(nextPageToken)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + @JsonPOJOBuilder(withPrefix = "set") + static class Builder implements ConsentsListResponseInternal.Builder { + OptionalValue> identities = OptionalValue.empty(); + OptionalValue nextPageToken = OptionalValue.empty(); + + @JsonProperty(JSON_PROPERTY_IDENTITIES) + public Builder setIdentities(List identities) { + this.identities = OptionalValue.of(identities); + return this; + } + + @JsonProperty(JSON_PROPERTY_NEXT_PAGE_TOKEN) + public Builder setNextPageToken(String nextPageToken) { + this.nextPageToken = OptionalValue.of(nextPageToken); + return this; + } + + public ConsentsListResponseInternal build() { + return new ConsentsListResponseInternalImpl(identities, nextPageToken); + } + } +} diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/consents/request/ConsentsListQueryParameters.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/consents/request/ConsentsListQueryParameters.java new file mode 100644 index 000000000..6dfa04a86 --- /dev/null +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/consents/request/ConsentsListQueryParameters.java @@ -0,0 +1,78 @@ +/* + * Conversation API | Sinch + * + * OpenAPI document version: 1.0 + * Contact: support@sinch.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * Do not edit the class manually. + */ + +package com.sinch.sdk.domains.conversation.models.v1.consents.request; + +import com.sinch.sdk.core.models.OptionalValue; + +/** ConsentsListQueryParameters */ +public interface ConsentsListQueryParameters { + + /** + * Get pageSize + * + * @return pageSize + */ + OptionalValue getPageSize(); + + /** + * Get pageToken + * + * @return pageToken + */ + OptionalValue getPageToken(); + + /** + * Getting builder + * + * @return New Builder instance + */ + static Builder builder() { + return new ConsentsListQueryParametersImpl.Builder(); + } + + /** + * Getting builder from existing instance + * + * @return New Builder instance + */ + static Builder builder(ConsentsListQueryParameters parameters) { + return new ConsentsListQueryParametersImpl.Builder(parameters); + } + + /** Dedicated Builder */ + interface Builder { + + /** + * see getter + * + * @param pageSize see getter + * @return Current builder + * @see #getPageSize + */ + Builder setPageSize(Integer pageSize); + + /** + * see getter + * + * @param pageToken see getter + * @return Current builder + * @see #getPageToken + */ + Builder setPageToken(String pageToken); + + /** + * Create instance + * + * @return The instance build with current builder values + */ + ConsentsListQueryParameters build(); + } +} diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/consents/request/ConsentsListQueryParametersImpl.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/consents/request/ConsentsListQueryParametersImpl.java new file mode 100644 index 000000000..f2077f61a --- /dev/null +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/consents/request/ConsentsListQueryParametersImpl.java @@ -0,0 +1,94 @@ +package com.sinch.sdk.domains.conversation.models.v1.consents.request; + +import com.sinch.sdk.core.models.OptionalValue; +import java.util.Objects; + +public class ConsentsListQueryParametersImpl implements ConsentsListQueryParameters { + + private final OptionalValue pageSize; + private final OptionalValue pageToken; + + private ConsentsListQueryParametersImpl( + OptionalValue pageSize, OptionalValue pageToken) { + this.pageSize = pageSize; + this.pageToken = pageToken; + } + + public OptionalValue getPageSize() { + return pageSize; + } + + public OptionalValue getPageToken() { + return pageToken; + } + + /** Return true if this ConsentsGetConsentsQueryParameters object is equal to o. */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ConsentsListQueryParametersImpl consentsGetConsentsQueryParameters = + (ConsentsListQueryParametersImpl) o; + return Objects.equals(this.pageSize, consentsGetConsentsQueryParameters.pageSize) + && Objects.equals(this.pageToken, consentsGetConsentsQueryParameters.pageToken); + } + + @Override + public int hashCode() { + return Objects.hash(pageSize, pageToken); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class ConsentsListQueryParametersImpl {\n"); + sb.append(" pageSize: ").append(toIndentedString(pageSize)).append("\n"); + sb.append(" pageToken: ").append(toIndentedString(pageToken)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + static class Builder implements ConsentsListQueryParameters.Builder { + OptionalValue pageSize = OptionalValue.empty(); + OptionalValue pageToken = OptionalValue.empty(); + + protected Builder() {} + + protected Builder(ConsentsListQueryParameters _parameters) { + if (null == _parameters) { + return; + } + ConsentsListQueryParametersImpl parameters = (ConsentsListQueryParametersImpl) _parameters; + this.pageSize = parameters.getPageSize(); + this.pageToken = parameters.getPageToken(); + } + + public Builder setPageSize(Integer pageSize) { + this.pageSize = OptionalValue.of(pageSize); + return this; + } + + public Builder setPageToken(String pageToken) { + this.pageToken = OptionalValue.of(pageToken); + return this; + } + + public ConsentsListQueryParameters build() { + return new ConsentsListQueryParametersImpl(pageSize, pageToken); + } + } +} diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/consents/response/AuditRecord.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/consents/response/AuditRecord.java new file mode 100644 index 000000000..a48de1a32 --- /dev/null +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/consents/response/AuditRecord.java @@ -0,0 +1,219 @@ +/* + * Conversation API | Sinch + * + * OpenAPI document version: 1.0 + * Contact: support@sinch.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * Do not edit the class manually. + */ + +package com.sinch.sdk.domains.conversation.models.v1.consents.response; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.sinch.sdk.core.utils.EnumDynamic; +import com.sinch.sdk.core.utils.EnumSupportDynamic; +import com.sinch.sdk.domains.conversation.models.v1.consents.ConsentsListType; +import java.time.Instant; +import java.util.Arrays; +import java.util.stream.Stream; + +/** Represents a consent audit record from the Conversation API. */ +@JsonDeserialize(builder = AuditRecordImpl.Builder.class) +public interface AuditRecord { + + /** + * The origin from the opt-out or opt-in. This could be the Batch API or an MO (when matched with + * an end-user MO). + */ + public class OriginEnum extends EnumDynamic { + /** The opt-in or opt-out came from the API. */ + public static final OriginEnum ORIGIN_API = new OriginEnum("ORIGIN_API"); + + /** The opt-in or optout came from an MO. */ + public static final OriginEnum ORIGIN_MO = new OriginEnum("ORIGIN_MO"); + + private static final EnumSupportDynamic ENUM_SUPPORT = + new EnumSupportDynamic<>( + OriginEnum.class, OriginEnum::new, Arrays.asList(ORIGIN_API, ORIGIN_MO)); + + private OriginEnum(String value) { + super(value); + } + + public static Stream values() { + return ENUM_SUPPORT.values(); + } + + public static OriginEnum from(String value) { + return ENUM_SUPPORT.from(value); + } + + public static String valueOf(OriginEnum e) { + return ENUM_SUPPORT.valueOf(e); + } + } + + /** + * The origin from the opt-out or opt-in. This could be the Batch API or an MO (when matched with + * an end-user MO). + * + *

Field is required + * + * @return origin + */ + OriginEnum getOrigin(); + + /** The operation that the audit record refers to. Can be INSERT, UPDATE or DELETE. */ + public class OperationEnum extends EnumDynamic { + /** The Insert operation */ + public static final OperationEnum OPERATION_INSERT = new OperationEnum("OPERATION_INSERT"); + + /** The Update operation */ + public static final OperationEnum OPERATION_UPDATE = new OperationEnum("OPERATION_UPDATE"); + + /** The Delete operation */ + public static final OperationEnum OPERATION_DELETE = new OperationEnum("OPERATION_DELETE"); + + private static final EnumSupportDynamic ENUM_SUPPORT = + new EnumSupportDynamic<>( + OperationEnum.class, + OperationEnum::new, + Arrays.asList(OPERATION_INSERT, OPERATION_UPDATE, OPERATION_DELETE)); + + private OperationEnum(String value) { + super(value); + } + + public static Stream values() { + return ENUM_SUPPORT.values(); + } + + public static OperationEnum from(String value) { + return ENUM_SUPPORT.from(value); + } + + public static String valueOf(OperationEnum e) { + return ENUM_SUPPORT.valueOf(e); + } + } + + /** + * The operation that the audit record refers to. Can be INSERT, UPDATE or DELETE. + * + *

Field is required + * + * @return operation + */ + OperationEnum getOperation(); + + /** + * The list type of the consent list the audit record refers to. + * + *

Field is required + * + * @return listType + */ + ConsentsListType getListType(); + + /** + * The project ID associated with the consent list the audit record refers to. + * + *

Field is required + * + * @return projectId + */ + String getProjectId(); + + /** + * The app ID associated with the consent list the audit record refers to. + * + *

Field is required + * + * @return appId + */ + String getAppId(); + + /** + * Datetime of when the consent list audit record happened. + * + *

Field is required + * + * @return datetime + */ + Instant getDatetime(); + + /** + * Getting builder + * + * @return New Builder instance + */ + static Builder builder() { + return new AuditRecordImpl.Builder(); + } + + /** Dedicated Builder */ + interface Builder { + + /** + * see getter + * + * @param origin see getter + * @return Current builder + * @see #getOrigin + */ + Builder setOrigin(OriginEnum origin); + + /** + * see getter + * + * @param operation see getter + * @return Current builder + * @see #getOperation + */ + Builder setOperation(OperationEnum operation); + + /** + * see getter + * + * @param listType see getter + * @return Current builder + * @see #getListType + */ + Builder setListType(ConsentsListType listType); + + /** + * see getter + * + * @param projectId see getter + * @return Current builder + * @see #getProjectId + */ + Builder setProjectId(String projectId); + + /** + * see getter + * + * @param appId see getter + * @return Current builder + * @see #getAppId + */ + Builder setAppId(String appId); + + /** + * see getter + * + * @param datetime see getter + * @return Current builder + * @see #getDatetime + */ + Builder setDatetime(Instant datetime); + + /** + * Create instance + * + * @return The instance build with current builder values + */ + AuditRecord build(); + } +} diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/consents/response/AuditRecordImpl.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/consents/response/AuditRecordImpl.java new file mode 100644 index 000000000..3bab79796 --- /dev/null +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/consents/response/AuditRecordImpl.java @@ -0,0 +1,230 @@ +package com.sinch.sdk.domains.conversation.models.v1.consents.response; + +import com.fasterxml.jackson.annotation.JsonFilter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; +import com.sinch.sdk.core.models.OptionalValue; +import com.sinch.sdk.domains.conversation.models.v1.consents.ConsentsListType; +import java.time.Instant; +import java.util.Objects; + +@JsonPropertyOrder({ + AuditRecordImpl.JSON_PROPERTY_ORIGIN, + AuditRecordImpl.JSON_PROPERTY_OPERATION, + AuditRecordImpl.JSON_PROPERTY_LIST_TYPE, + AuditRecordImpl.JSON_PROPERTY_PROJECT_ID, + AuditRecordImpl.JSON_PROPERTY_APP_ID, + AuditRecordImpl.JSON_PROPERTY_DATETIME +}) +@JsonFilter("uninitializedFilter") +@JsonInclude(value = JsonInclude.Include.CUSTOM) +public class AuditRecordImpl implements AuditRecord { + private static final long serialVersionUID = 1L; + + public static final String JSON_PROPERTY_ORIGIN = "origin"; + + private OptionalValue origin; + + public static final String JSON_PROPERTY_OPERATION = "operation"; + + private OptionalValue operation; + + public static final String JSON_PROPERTY_LIST_TYPE = "list_type"; + + private OptionalValue listType; + + public static final String JSON_PROPERTY_PROJECT_ID = "project_id"; + + private OptionalValue projectId; + + public static final String JSON_PROPERTY_APP_ID = "app_id"; + + private OptionalValue appId; + + public static final String JSON_PROPERTY_DATETIME = "datetime"; + + private OptionalValue datetime; + + public AuditRecordImpl() {} + + protected AuditRecordImpl( + OptionalValue origin, + OptionalValue operation, + OptionalValue listType, + OptionalValue projectId, + OptionalValue appId, + OptionalValue datetime) { + this.origin = origin; + this.operation = operation; + this.listType = listType; + this.projectId = projectId; + this.appId = appId; + this.datetime = datetime; + } + + @JsonIgnore + public OriginEnum getOrigin() { + return origin.orElse(null); + } + + @JsonProperty(JSON_PROPERTY_ORIGIN) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public OptionalValue origin() { + return origin; + } + + @JsonIgnore + public OperationEnum getOperation() { + return operation.orElse(null); + } + + @JsonProperty(JSON_PROPERTY_OPERATION) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public OptionalValue operation() { + return operation; + } + + @JsonIgnore + public ConsentsListType getListType() { + return listType.orElse(null); + } + + @JsonProperty(JSON_PROPERTY_LIST_TYPE) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public OptionalValue listType() { + return listType; + } + + @JsonIgnore + public String getProjectId() { + return projectId.orElse(null); + } + + @JsonProperty(JSON_PROPERTY_PROJECT_ID) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public OptionalValue projectId() { + return projectId; + } + + @JsonIgnore + public String getAppId() { + return appId.orElse(null); + } + + @JsonProperty(JSON_PROPERTY_APP_ID) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public OptionalValue appId() { + return appId; + } + + @JsonIgnore + public Instant getDatetime() { + return datetime.orElse(null); + } + + @JsonProperty(JSON_PROPERTY_DATETIME) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public OptionalValue datetime() { + return datetime; + } + + /** Return true if this AuditRecord object is equal to o. */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + AuditRecordImpl auditRecord = (AuditRecordImpl) o; + return Objects.equals(this.origin, auditRecord.origin) + && Objects.equals(this.operation, auditRecord.operation) + && Objects.equals(this.listType, auditRecord.listType) + && Objects.equals(this.projectId, auditRecord.projectId) + && Objects.equals(this.appId, auditRecord.appId) + && Objects.equals(this.datetime, auditRecord.datetime); + } + + @Override + public int hashCode() { + return Objects.hash(origin, operation, listType, projectId, appId, datetime); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class AuditRecordImpl {\n"); + sb.append(" origin: ").append(toIndentedString(origin)).append("\n"); + sb.append(" operation: ").append(toIndentedString(operation)).append("\n"); + sb.append(" listType: ").append(toIndentedString(listType)).append("\n"); + sb.append(" projectId: ").append(toIndentedString(projectId)).append("\n"); + sb.append(" appId: ").append(toIndentedString(appId)).append("\n"); + sb.append(" datetime: ").append(toIndentedString(datetime)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + @JsonPOJOBuilder(withPrefix = "set") + static class Builder implements AuditRecord.Builder { + OptionalValue origin = OptionalValue.empty(); + OptionalValue operation = OptionalValue.empty(); + OptionalValue listType = OptionalValue.empty(); + OptionalValue projectId = OptionalValue.empty(); + OptionalValue appId = OptionalValue.empty(); + OptionalValue datetime = OptionalValue.empty(); + + @JsonProperty(value = JSON_PROPERTY_ORIGIN, required = true) + public Builder setOrigin(OriginEnum origin) { + this.origin = OptionalValue.of(origin); + return this; + } + + @JsonProperty(value = JSON_PROPERTY_OPERATION, required = true) + public Builder setOperation(OperationEnum operation) { + this.operation = OptionalValue.of(operation); + return this; + } + + @JsonProperty(value = JSON_PROPERTY_LIST_TYPE, required = true) + public Builder setListType(ConsentsListType listType) { + this.listType = OptionalValue.of(listType); + return this; + } + + @JsonProperty(value = JSON_PROPERTY_PROJECT_ID, required = true) + public Builder setProjectId(String projectId) { + this.projectId = OptionalValue.of(projectId); + return this; + } + + @JsonProperty(value = JSON_PROPERTY_APP_ID, required = true) + public Builder setAppId(String appId) { + this.appId = OptionalValue.of(appId); + return this; + } + + @JsonProperty(value = JSON_PROPERTY_DATETIME, required = true) + public Builder setDatetime(Instant datetime) { + this.datetime = OptionalValue.of(datetime); + return this; + } + + public AuditRecord build() { + return new AuditRecordImpl(origin, operation, listType, projectId, appId, datetime); + } + } +} diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/consents/response/AuditRecordsResponse.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/consents/response/AuditRecordsResponse.java new file mode 100644 index 000000000..3ad8a1753 --- /dev/null +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/consents/response/AuditRecordsResponse.java @@ -0,0 +1,72 @@ +/* + * Conversation API | Sinch + * + * OpenAPI document version: 1.0 + * Contact: support@sinch.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * Do not edit the class manually. + */ + +package com.sinch.sdk.domains.conversation.models.v1.consents.response; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.sinch.sdk.domains.conversation.models.v1.consents.Identity; +import java.util.List; + +/** AuditRecordsResponse */ +@JsonDeserialize(builder = AuditRecordsResponseImpl.Builder.class) +public interface AuditRecordsResponse { + + /** + * Get identity + * + * @return identity + */ + Identity getIdentity(); + + /** + * List of audit records associated with the given identity + * + * @return auditRecords + */ + List getAuditRecords(); + + /** + * Getting builder + * + * @return New Builder instance + */ + static Builder builder() { + return new AuditRecordsResponseImpl.Builder(); + } + + /** Dedicated Builder */ + interface Builder { + + /** + * see getter + * + * @param identity see getter + * @return Current builder + * @see #getIdentity + */ + Builder setIdentity(Identity identity); + + /** + * see getter + * + * @param auditRecords see getter + * @return Current builder + * @see #getAuditRecords + */ + Builder setAuditRecords(List auditRecords); + + /** + * Create instance + * + * @return The instance build with current builder values + */ + AuditRecordsResponse build(); + } +} diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/consents/response/AuditRecordsResponseImpl.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/consents/response/AuditRecordsResponseImpl.java new file mode 100644 index 000000000..fdba1bd1a --- /dev/null +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/consents/response/AuditRecordsResponseImpl.java @@ -0,0 +1,121 @@ +package com.sinch.sdk.domains.conversation.models.v1.consents.response; + +import com.fasterxml.jackson.annotation.JsonFilter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; +import com.sinch.sdk.core.models.OptionalValue; +import com.sinch.sdk.domains.conversation.models.v1.consents.Identity; +import java.util.List; +import java.util.Objects; + +@JsonPropertyOrder({ + AuditRecordsResponseImpl.JSON_PROPERTY_IDENTITY, + AuditRecordsResponseImpl.JSON_PROPERTY_AUDIT_RECORDS +}) +@JsonFilter("uninitializedFilter") +@JsonInclude(value = JsonInclude.Include.CUSTOM) +public class AuditRecordsResponseImpl implements AuditRecordsResponse { + private static final long serialVersionUID = 1L; + + public static final String JSON_PROPERTY_IDENTITY = "identity"; + + private OptionalValue identity; + + public static final String JSON_PROPERTY_AUDIT_RECORDS = "audit_records"; + + private OptionalValue> auditRecords; + + public AuditRecordsResponseImpl() {} + + protected AuditRecordsResponseImpl( + OptionalValue identity, OptionalValue> auditRecords) { + this.identity = identity; + this.auditRecords = auditRecords; + } + + @JsonIgnore + public Identity getIdentity() { + return identity.orElse(null); + } + + @JsonProperty(JSON_PROPERTY_IDENTITY) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public OptionalValue identity() { + return identity; + } + + @JsonIgnore + public List getAuditRecords() { + return auditRecords.orElse(null); + } + + @JsonProperty(JSON_PROPERTY_AUDIT_RECORDS) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public OptionalValue> auditRecords() { + return auditRecords; + } + + /** Return true if this GetAuditRecordsFromConsentResponse object is equal to o. */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + AuditRecordsResponseImpl getAuditRecordsFromConsentResponse = (AuditRecordsResponseImpl) o; + return Objects.equals(this.identity, getAuditRecordsFromConsentResponse.identity) + && Objects.equals(this.auditRecords, getAuditRecordsFromConsentResponse.auditRecords); + } + + @Override + public int hashCode() { + return Objects.hash(identity, auditRecords); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class AuditRecordsResponseImpl {\n"); + sb.append(" identity: ").append(toIndentedString(identity)).append("\n"); + sb.append(" auditRecords: ").append(toIndentedString(auditRecords)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + @JsonPOJOBuilder(withPrefix = "set") + static class Builder implements AuditRecordsResponse.Builder { + OptionalValue identity = OptionalValue.empty(); + OptionalValue> auditRecords = OptionalValue.empty(); + + @JsonProperty(JSON_PROPERTY_IDENTITY) + public Builder setIdentity(Identity identity) { + this.identity = OptionalValue.of(identity); + return this; + } + + @JsonProperty(JSON_PROPERTY_AUDIT_RECORDS) + public Builder setAuditRecords(List auditRecords) { + this.auditRecords = OptionalValue.of(auditRecords); + return this; + } + + public AuditRecordsResponse build() { + return new AuditRecordsResponseImpl(identity, auditRecords); + } + } +} diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/consents/response/ConsentsListResponse.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/consents/response/ConsentsListResponse.java new file mode 100644 index 000000000..ae32a8ea0 --- /dev/null +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/consents/response/ConsentsListResponse.java @@ -0,0 +1,59 @@ +/* + * Conversation API | Sinch + * + * OpenAPI document version: 1.0 + * Contact: support@sinch.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * Do not edit the class manually. + */ + +package com.sinch.sdk.domains.conversation.models.v1.consents.response; + +import com.sinch.sdk.core.http.HttpRequest; +import com.sinch.sdk.core.models.pagination.ListResponse; +import com.sinch.sdk.core.models.pagination.Page; +import com.sinch.sdk.domains.conversation.models.v1.consents.Identity; +import java.util.Collection; +import java.util.Collections; +import java.util.NoSuchElementException; +import java.util.function.Supplier; + +/** Auto paginated response for list of Identity */ +public class ConsentsListResponse extends ListResponse { + + private final Page page; + private final Supplier supplier; + + public ConsentsListResponse( + Supplier supplier, Page page) { + this.supplier = supplier; + this.page = page; + } + + @Override + public boolean hasNextPage() { + if (null == page.getNextPageToken() || null == getContent() || getContent().isEmpty()) { + return false; + } + return true; + } + + @Override + public ConsentsListResponse nextPage() { + if (!hasNextPage()) { + throw new NoSuchElementException("Reached the last page of the API response"); + } + return supplier.get(); + } + + @Override + public Collection getContent() { + return page == null ? Collections.emptyList() : page.getEntities(); + } + + @Override + public String toString() { + return "ConsentsListResponse {" + "page=" + page + '}'; + } +} diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/conversations/request/RecentConversationsListQueryParameters.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/conversations/request/RecentConversationsListQueryParameters.java index 799523df9..2337f5e3e 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/conversations/request/RecentConversationsListQueryParameters.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/conversations/request/RecentConversationsListQueryParameters.java @@ -49,7 +49,10 @@ public interface RecentConversationsListQueryParameters { /** Gets or Sets order */ public class OrderEnum extends EnumDynamic { + /** Ascending order. Oldest first. */ public static final OrderEnum ASC = new OrderEnum("ASC"); + + /** Descending order. Newest first. */ public static final OrderEnum DESC = new OrderEnum("DESC"); private static final EnumSupportDynamic ENUM_SUPPORT = diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/credentials/ConversationChannelCredentials.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/credentials/ConversationChannelCredentials.java index 72fcaa573..7303cd727 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/credentials/ConversationChannelCredentials.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/credentials/ConversationChannelCredentials.java @@ -74,7 +74,9 @@ public interface ConversationChannelCredentials { * case in which there are multiple credential integrations per channel on a single app, this * field must have a unique value for each multi-credential channel entry. * - *

minimum: 0 maximum: 255 + *

Minimum: 0 + * + *

Maximum: 255 * * @return credentialOrdinalNumber */ diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/eventdestinations/ClientCredentials.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/eventdestinations/ClientCredentials.java index b9496e1e8..43cc43c0e 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/eventdestinations/ClientCredentials.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/eventdestinations/ClientCredentials.java @@ -72,7 +72,16 @@ public interface ClientCredentials { * BASIC is used by default. */ public class TokenRequestTypeEnum extends EnumDynamic { + /** + * Sent using the HTTP Authorization header (Basic auth). In this case, client_id + * and client_secret are NOT included in the form body. + */ public static final TokenRequestTypeEnum BASIC = new TokenRequestTypeEnum("BASIC"); + + /** + * Sent in the form body as client_id and client_secret. No + * Authorization header is added. + */ public static final TokenRequestTypeEnum FORM = new TokenRequestTypeEnum("FORM"); private static final EnumSupportDynamic ENUM_SUPPORT = diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/events/types/CommentEvent.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/events/types/CommentEvent.java index 704e651b1..f230e6926 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/events/types/CommentEvent.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/events/types/CommentEvent.java @@ -39,7 +39,10 @@ public interface CommentEvent /** Either LIVE or FEED. Indicates the type of media on which the comment was made. */ public class CommentTypeEnum extends EnumDynamic { + /** A comment was made on a Feed post. */ public static final CommentTypeEnum FEED = new CommentTypeEnum("FEED"); + + /** A comment was made during a Live. */ public static final CommentTypeEnum LIVE = new CommentTypeEnum("LIVE"); private static final EnumSupportDynamic ENUM_SUPPORT = diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/events/types/internal/CommentEventInternal.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/events/types/internal/CommentEventInternal.java index 86080d9c4..890450cbf 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/events/types/internal/CommentEventInternal.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/events/types/internal/CommentEventInternal.java @@ -42,7 +42,10 @@ public interface CommentEventInternal { /** Either LIVE or FEED. Indicates the type of media on which the comment was made. */ public class CommentTypeEnum extends EnumDynamic { + /** A comment was made on a Feed post. */ public static final CommentTypeEnum FEED = new CommentTypeEnum("FEED"); + + /** A comment was made during a Live. */ public static final CommentTypeEnum LIVE = new CommentTypeEnum("LIVE"); private static final EnumSupportDynamic ENUM_SUPPORT = diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/internal/ChannelSpecificMessageInternal.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/internal/ChannelSpecificMessageInternal.java index cdbbc2829..50e9138f5 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/internal/ChannelSpecificMessageInternal.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/internal/ChannelSpecificMessageInternal.java @@ -22,12 +22,23 @@ public interface ChannelSpecificMessageInternal { /** The type of the channel specific message. */ public class MessageTypeEnum extends EnumDynamic { + /** The WhatsApp Flows message type. */ public static final MessageTypeEnum FLOWS = new MessageTypeEnum("FLOWS"); + + /** The WhatsApp order details message type. */ public static final MessageTypeEnum ORDER_DETAILS = new MessageTypeEnum("ORDER_DETAILS"); + + /** The WhatsApp order status message type. */ public static final MessageTypeEnum ORDER_STATUS = new MessageTypeEnum("ORDER_STATUS"); + + /** KakaoTalk commerce channel specific message type */ public static final MessageTypeEnum COMMERCE = new MessageTypeEnum("COMMERCE"); + + /** KakaoTalk carousel commerce channel specific message type */ public static final MessageTypeEnum CAROUSEL_COMMERCE = new MessageTypeEnum("CAROUSEL_COMMERCE"); + + /** LINE notification message template type */ public static final MessageTypeEnum NOTIFICATION_MESSAGE_TEMPLATE = new MessageTypeEnum("NOTIFICATION_MESSAGE_TEMPLATE"); diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/ChannelSpecificContactMessage.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/ChannelSpecificContactMessage.java index 74bebb7b3..aa37551f1 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/ChannelSpecificContactMessage.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/ChannelSpecificContactMessage.java @@ -23,6 +23,7 @@ public interface ChannelSpecificContactMessage /** The message type. */ public class MessageTypeEnum extends EnumDynamic { + /** The nfm_reply message type. */ public static final MessageTypeEnum NFM_REPLY = new MessageTypeEnum("nfm_reply"); private static final EnumSupportDynamic ENUM_SUPPORT = @@ -54,7 +55,7 @@ public static String valueOf(MessageTypeEnum e) { MessageTypeEnum getMessageType(); /** - * Get message + * The message content. * * @return message */ diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/kakaotalk/commerce/DiscountFixedCommerce.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/kakaotalk/commerce/DiscountFixedCommerce.java index 58c5ad31c..8e82ed997 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/kakaotalk/commerce/DiscountFixedCommerce.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/kakaotalk/commerce/DiscountFixedCommerce.java @@ -24,6 +24,7 @@ public interface DiscountFixedCommerce /** Gets or Sets type */ public class TypeEnum extends EnumDynamic { + /** Commerce with fixed discount */ public static final TypeEnum FIXED_DISCOUNT_COMMERCE = new TypeEnum("FIXED_DISCOUNT_COMMERCE"); private static final EnumSupportDynamic ENUM_SUPPORT = @@ -59,9 +60,9 @@ public static String valueOf(TypeEnum e) { /** * Regular price of the product * - *

minimum: 0 maximum: 99999999 + *

Minimum: 0 * - *

Field is required + *

Maximum: 99999999 Field is required * * @return regularPrice */ @@ -70,9 +71,9 @@ public static String valueOf(TypeEnum e) { /** * Discounted price of the product * - *

minimum: 0 maximum: 99999999 + *

Minimum: 0 * - *

Field is required + *

Maximum: 99999999 Field is required * * @return discountPrice */ @@ -81,9 +82,9 @@ public static String valueOf(TypeEnum e) { /** * Fixed discount * - *

minimum: 0 maximum: 999999 + *

Minimum: 0 * - *

Field is required + *

Maximum: 999999 Field is required * * @return discountFixed */ diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/kakaotalk/commerce/DiscountRateCommerce.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/kakaotalk/commerce/DiscountRateCommerce.java index dcb5fe64e..6f26d736b 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/kakaotalk/commerce/DiscountRateCommerce.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/kakaotalk/commerce/DiscountRateCommerce.java @@ -24,6 +24,7 @@ public interface DiscountRateCommerce /** Gets or Sets type */ public class TypeEnum extends EnumDynamic { + /** Commerce with percentage discount */ public static final TypeEnum PERCENTAGE_DISCOUNT_COMMERCE = new TypeEnum("PERCENTAGE_DISCOUNT_COMMERCE"); @@ -60,9 +61,9 @@ public static String valueOf(TypeEnum e) { /** * Regular price of the product * - *

minimum: 0 maximum: 99999999 + *

Minimum: 0 * - *

Field is required + *

Maximum: 99999999 Field is required * * @return regularPrice */ @@ -71,9 +72,9 @@ public static String valueOf(TypeEnum e) { /** * Discounted price of the product * - *

minimum: 0 maximum: 99999999 + *

Minimum: 0 * - *

Field is required + *

Maximum: 99999999 Field is required * * @return discountPrice */ @@ -82,9 +83,9 @@ public static String valueOf(TypeEnum e) { /** * Discount rate (%) * - *

minimum: 0 maximum: 100 + *

Minimum: 0 * - *

Field is required + *

Maximum: 100 Field is required * * @return discountRate */ diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/kakaotalk/commerce/RegularPriceCommerce.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/kakaotalk/commerce/RegularPriceCommerce.java index 88505d33d..859340207 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/kakaotalk/commerce/RegularPriceCommerce.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/kakaotalk/commerce/RegularPriceCommerce.java @@ -24,6 +24,7 @@ public interface RegularPriceCommerce /** Gets or Sets type */ public class TypeEnum extends EnumDynamic { + /** Commerce with regular price */ public static final TypeEnum REGULAR_PRICE_COMMERCE = new TypeEnum("REGULAR_PRICE_COMMERCE"); private static final EnumSupportDynamic ENUM_SUPPORT = @@ -59,9 +60,9 @@ public static String valueOf(TypeEnum e) { /** * Regular price of the product * - *

minimum: 0 maximum: 99999999 + *

Minimum: 0 * - *

Field is required + *

Maximum: 99999999 Field is required * * @return regularPrice */ diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/kakaotalk/coupons/DiscountFixedCoupon.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/kakaotalk/coupons/DiscountFixedCoupon.java index c77b07546..369fd11e6 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/kakaotalk/coupons/DiscountFixedCoupon.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/kakaotalk/coupons/DiscountFixedCoupon.java @@ -91,9 +91,9 @@ public static String valueOf(TypeEnum e) { /** * Fixed discount * - *

minimum: 0 maximum: 999999 + *

Minimum: 0 * - *

Field is required + *

Maximum: 999999 Field is required * * @return discountFixed */ diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/kakaotalk/coupons/DiscountRateCoupon.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/kakaotalk/coupons/DiscountRateCoupon.java index 1623ca6ac..563ebed74 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/kakaotalk/coupons/DiscountRateCoupon.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/kakaotalk/coupons/DiscountRateCoupon.java @@ -92,9 +92,9 @@ public static String valueOf(TypeEnum e) { /** * Discount rate (%) * - *

minimum: 0 maximum: 100 + *

Minimum: 0 * - *

Field is required + *

Maximum: 100 Field is required * * @return discountRate */ diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/whatsapp/flows/FlowChannelSpecificMessage.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/whatsapp/flows/FlowChannelSpecificMessage.java index d3e4e7b8f..512033b35 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/whatsapp/flows/FlowChannelSpecificMessage.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/whatsapp/flows/FlowChannelSpecificMessage.java @@ -61,7 +61,10 @@ public interface FlowChannelSpecificMessage /** The mode in which the flow is. */ public class FlowModeEnum extends EnumDynamic { + /** The flow is in draft mode. */ public static final FlowModeEnum DRAFT = new FlowModeEnum("draft"); + + /** The flow is published. */ public static final FlowModeEnum PUBLISHED = new FlowModeEnum("published"); private static final EnumSupportDynamic ENUM_SUPPORT = @@ -104,7 +107,10 @@ public static String valueOf(FlowModeEnum e) { /** Gets or Sets flowAction */ public class FlowActionEnum extends EnumDynamic { + /** The navigate flow action. */ public static final FlowActionEnum NAVIGATE = new FlowActionEnum("navigate"); + + /** The data exchange flow action. */ public static final FlowActionEnum DATA_EXCHANGE = new FlowActionEnum("data_exchange"); private static final EnumSupportDynamic ENUM_SUPPORT = diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/whatsapp/flows/WhatsAppInteractiveHeaderDocument.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/whatsapp/flows/WhatsAppInteractiveHeaderDocument.java index f16aa24b2..88107c002 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/whatsapp/flows/WhatsAppInteractiveHeaderDocument.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/whatsapp/flows/WhatsAppInteractiveHeaderDocument.java @@ -24,6 +24,7 @@ public interface WhatsAppInteractiveHeaderDocument /** Gets or Sets type */ public class TypeEnum extends EnumDynamic { + /** The document associated with the header. */ public static final TypeEnum DOCUMENT = new TypeEnum("document"); private static final EnumSupportDynamic ENUM_SUPPORT = diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/whatsapp/flows/WhatsAppInteractiveHeaderImage.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/whatsapp/flows/WhatsAppInteractiveHeaderImage.java index 7d32b04de..5ce5ecdbe 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/whatsapp/flows/WhatsAppInteractiveHeaderImage.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/whatsapp/flows/WhatsAppInteractiveHeaderImage.java @@ -24,6 +24,7 @@ public interface WhatsAppInteractiveHeaderImage /** Gets or Sets type */ public class TypeEnum extends EnumDynamic { + /** The image associated with the header. */ public static final TypeEnum IMAGE = new TypeEnum("image"); private static final EnumSupportDynamic ENUM_SUPPORT = diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/whatsapp/flows/WhatsAppInteractiveHeaderText.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/whatsapp/flows/WhatsAppInteractiveHeaderText.java index fd8cd253d..40f3365b9 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/whatsapp/flows/WhatsAppInteractiveHeaderText.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/whatsapp/flows/WhatsAppInteractiveHeaderText.java @@ -24,6 +24,7 @@ public interface WhatsAppInteractiveHeaderText /** Gets or Sets type */ public class TypeEnum extends EnumDynamic { + /** The text of the header. */ public static final TypeEnum TEXT = new TypeEnum("text"); private static final EnumSupportDynamic ENUM_SUPPORT = diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/whatsapp/flows/WhatsAppInteractiveHeaderVideo.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/whatsapp/flows/WhatsAppInteractiveHeaderVideo.java index 146efe8f0..0e22dc03e 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/whatsapp/flows/WhatsAppInteractiveHeaderVideo.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/whatsapp/flows/WhatsAppInteractiveHeaderVideo.java @@ -24,6 +24,7 @@ public interface WhatsAppInteractiveHeaderVideo /** Gets or Sets type */ public class TypeEnum extends EnumDynamic { + /** The video associated with the header. */ public static final TypeEnum VIDEO = new TypeEnum("video"); private static final EnumSupportDynamic ENUM_SUPPORT = diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/whatsapp/nfmreply/WhatsAppInteractiveNfmReply.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/whatsapp/nfmreply/WhatsAppInteractiveNfmReply.java index a0d51d844..147e2a8ec 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/whatsapp/nfmreply/WhatsAppInteractiveNfmReply.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/whatsapp/nfmreply/WhatsAppInteractiveNfmReply.java @@ -22,7 +22,10 @@ public interface WhatsAppInteractiveNfmReply { /** The nfm reply message type. */ public class NameEnum extends EnumDynamic { + /** The WhatsApp flow nfm reply message type. */ public static final NameEnum FLOW = new NameEnum("flow"); + + /** The address nfm reply message type. */ public static final NameEnum ADDRESS_MESSAGE = new NameEnum("address_message"); private static final EnumSupportDynamic ENUM_SUPPORT = diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/whatsapp/nfmreply/WhatsAppInteractiveNfmReplyChannelSpecificContactMessage.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/whatsapp/nfmreply/WhatsAppInteractiveNfmReplyChannelSpecificContactMessage.java index 000df7a5c..68826b94a 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/whatsapp/nfmreply/WhatsAppInteractiveNfmReplyChannelSpecificContactMessage.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/whatsapp/nfmreply/WhatsAppInteractiveNfmReplyChannelSpecificContactMessage.java @@ -25,6 +25,7 @@ public interface WhatsAppInteractiveNfmReplyChannelSpecificContactMessage /** The interactive message type. */ public class TypeEnum extends EnumDynamic { + /** The interactive nfm reply type. */ public static final TypeEnum NFM_REPLY = new TypeEnum("nfm_reply"); private static final EnumSupportDynamic ENUM_SUPPORT = diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/whatsapp/payment/OrderDetailsPayment.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/whatsapp/payment/OrderDetailsPayment.java index eeabfc043..56158b778 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/whatsapp/payment/OrderDetailsPayment.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/whatsapp/payment/OrderDetailsPayment.java @@ -23,7 +23,10 @@ public interface OrderDetailsPayment { /** The country/currency associated with the payment message. */ public class TypeEnum extends EnumDynamic { + /** Brazil */ public static final TypeEnum BR = new TypeEnum("br"); + + /** Singapore */ public static final TypeEnum SG = new TypeEnum("sg"); private static final EnumSupportDynamic ENUM_SUPPORT = @@ -66,7 +69,10 @@ public static String valueOf(TypeEnum e) { /** The type of good associated with this order. */ public class TypeOfGoodsEnum extends EnumDynamic { + /** Digital goods. */ public static final TypeOfGoodsEnum DIGITAL_GOODS = new TypeOfGoodsEnum("digital-goods"); + + /** Physical goods. */ public static final TypeOfGoodsEnum PHYSICAL_GOODS = new TypeOfGoodsEnum("physical-goods"); private static final EnumSupportDynamic ENUM_SUPPORT = diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/whatsapp/payment/OrderDetailsPaymentButtonBoleto.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/whatsapp/payment/OrderDetailsPaymentButtonBoleto.java index ac2e3a51e..16bc54de6 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/whatsapp/payment/OrderDetailsPaymentButtonBoleto.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/whatsapp/payment/OrderDetailsPaymentButtonBoleto.java @@ -24,6 +24,7 @@ public interface OrderDetailsPaymentButtonBoleto /** Gets or Sets type */ public class TypeEnum extends EnumDynamic { + /** The Boleto button identifier */ public static final TypeEnum BOLETO = new TypeEnum("boleto"); private static final EnumSupportDynamic ENUM_SUPPORT = diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/whatsapp/payment/OrderDetailsPaymentButtonDynamicPix.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/whatsapp/payment/OrderDetailsPaymentButtonDynamicPix.java index fc7f0779b..f1ddb5519 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/whatsapp/payment/OrderDetailsPaymentButtonDynamicPix.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/whatsapp/payment/OrderDetailsPaymentButtonDynamicPix.java @@ -24,6 +24,7 @@ public interface OrderDetailsPaymentButtonDynamicPix /** Gets or Sets type */ public class TypeEnum extends EnumDynamic { + /** The dynamic Pix code button identifier */ public static final TypeEnum PIX_DYNAMIC_CODE = new TypeEnum("pix_dynamic_code"); private static final EnumSupportDynamic ENUM_SUPPORT = @@ -75,10 +76,19 @@ public static String valueOf(TypeEnum e) { /** Pix key type. */ public class KeyTypeEnum extends EnumDynamic { + /** The CPF key type. */ public static final KeyTypeEnum CPF = new KeyTypeEnum("CPF"); + + /** The CNPJ key type. */ public static final KeyTypeEnum CNPJ = new KeyTypeEnum("CNPJ"); + + /** The EMAIL key type. */ public static final KeyTypeEnum EMAIL = new KeyTypeEnum("EMAIL"); + + /** The PHONE key type. */ public static final KeyTypeEnum PHONE = new KeyTypeEnum("PHONE"); + + /** The EVP key type. */ public static final KeyTypeEnum EVP = new KeyTypeEnum("EVP"); private static final EnumSupportDynamic ENUM_SUPPORT = diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/whatsapp/payment/OrderDetailsPaymentButtonPaymentLink.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/whatsapp/payment/OrderDetailsPaymentButtonPaymentLink.java index 7715388b9..1d44bde44 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/whatsapp/payment/OrderDetailsPaymentButtonPaymentLink.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/whatsapp/payment/OrderDetailsPaymentButtonPaymentLink.java @@ -24,6 +24,7 @@ public interface OrderDetailsPaymentButtonPaymentLink /** Gets or Sets type */ public class TypeEnum extends EnumDynamic { + /** The payment link button identifier */ public static final TypeEnum PAYMENT_LINK = new TypeEnum("payment_link"); private static final EnumSupportDynamic ENUM_SUPPORT = diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/whatsapp/payment/OrderStatusPaymentDetails.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/whatsapp/payment/OrderStatusPaymentDetails.java index 89f11d943..24184fc3b 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/whatsapp/payment/OrderStatusPaymentDetails.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/whatsapp/payment/OrderStatusPaymentDetails.java @@ -22,11 +22,22 @@ public interface OrderStatusPaymentDetails { /** The new payment message status. */ public class StatusEnum extends EnumDynamic { + /** The order is pending. */ public static final StatusEnum PENDING = new StatusEnum("pending"); + + /** The order is processing. */ public static final StatusEnum PROCESSING = new StatusEnum("processing"); + + /** A portion of the order has been shipped. */ public static final StatusEnum PARTIALLY_SHIPPED = new StatusEnum("partially-shipped"); + + /** The order has been shipped. */ public static final StatusEnum SHIPPED = new StatusEnum("shipped"); + + /** The order is complete. */ public static final StatusEnum COMPLETED = new StatusEnum("completed"); + + /** The order was canceled. */ public static final StatusEnum CANCELED = new StatusEnum("canceled"); private static final EnumSupportDynamic ENUM_SUPPORT = diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/internal/ChannelSpecificContactMessageMessageInternal.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/internal/ChannelSpecificContactMessageMessageInternal.java index ca74a564f..96c86d4a0 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/internal/ChannelSpecificContactMessageMessageInternal.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/messages/types/internal/ChannelSpecificContactMessageMessageInternal.java @@ -23,6 +23,7 @@ public interface ChannelSpecificContactMessageMessageInternal { /** The message type. */ public class MessageTypeEnum extends EnumDynamic { + /** The nfm_reply message type. */ public static final MessageTypeEnum NFM_REPLY = new MessageTypeEnum("nfm_reply"); private static final EnumSupportDynamic ENUM_SUPPORT = @@ -54,7 +55,7 @@ public static String valueOf(MessageTypeEnum e) { MessageTypeEnum getMessageType(); /** - * Get message + * The message content. * * @return message */ diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/sinchevents/capability/CapabilityEventNotification.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/sinchevents/capability/CapabilityEventNotification.java index 776831862..fc7586868 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/sinchevents/capability/CapabilityEventNotification.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/sinchevents/capability/CapabilityEventNotification.java @@ -53,12 +53,22 @@ public interface CapabilityEventNotification { /** Status indicating the recipient's capability on the channel. */ public class CapabilityStatusEnum extends EnumDynamic { + /** + * The channel capability for the contact is unknown due to the underlying channel not making + * this information available. + */ public static final CapabilityStatusEnum CAPABILITY_UNKNOWN = new CapabilityStatusEnum("CAPABILITY_UNKNOWN"); + + /** The specified contact supports all the features of the channel. */ public static final CapabilityStatusEnum CAPABILITY_FULL = new CapabilityStatusEnum("CAPABILITY_FULL"); + + /** The specified contact supports a subset of the channel features. */ public static final CapabilityStatusEnum CAPABILITY_PARTIAL = new CapabilityStatusEnum("CAPABILITY_PARTIAL"); + + /** The specified contact has no capability on the channel. */ public static final CapabilityStatusEnum NO_CAPABILITY = new CapabilityStatusEnum("NO_CAPABILITY"); diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/sinchevents/contact/ContactDeleteEvent.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/sinchevents/contact/ContactDeleteEvent.java index 96b509c99..83264ea89 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/sinchevents/contact/ContactDeleteEvent.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/sinchevents/contact/ContactDeleteEvent.java @@ -13,7 +13,7 @@ import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import java.time.Instant; -/** This callback is sent when a new contact is deleted. */ +/** This callback is sent when a contact is deleted. */ @JsonDeserialize(builder = ContactDeleteEventImpl.Builder.class) public interface ContactDeleteEvent extends com.sinch.sdk.domains.conversation.models.v1.sinchevents.ConversationSinchEvent { diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/sinchevents/contact/ContactUpdateEvent.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/sinchevents/contact/ContactUpdateEvent.java index 924e111c8..6b08cf3d7 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/sinchevents/contact/ContactUpdateEvent.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/sinchevents/contact/ContactUpdateEvent.java @@ -13,7 +13,7 @@ import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import java.time.Instant; -/** This callback is sent when a new contact is updated. */ +/** This callback is sent when a contact is updated. */ @JsonDeserialize(builder = ContactUpdateEventImpl.Builder.class) public interface ContactUpdateEvent extends com.sinch.sdk.domains.conversation.models.v1.sinchevents.ConversationSinchEvent { diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/sinchevents/delivery/DeliveryStatus.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/sinchevents/delivery/DeliveryStatus.java index 3e1ff8740..09564f4f7 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/sinchevents/delivery/DeliveryStatus.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/sinchevents/delivery/DeliveryStatus.java @@ -20,7 +20,7 @@ public class DeliveryStatus extends EnumDynamic { /** Message delivery failed. */ public static final DeliveryStatus FAILED = new DeliveryStatus("FAILED"); - /** The Conversation API app is switch to a different channel to deliver the message. */ + /** The Conversation API app is switching to a different channel to deliver the message. */ public static final DeliveryStatus SWITCHING_CHANNEL = new DeliveryStatus("SWITCHING_CHANNEL"); private static final EnumSupportDynamic ENUM_SUPPORT = diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/sinchevents/inbound/Event.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/sinchevents/inbound/Event.java index 3b18fbeaa..8cbcfa488 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/sinchevents/inbound/Event.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/sinchevents/inbound/Event.java @@ -34,6 +34,7 @@ public interface Event { /** The direction of the event. It's always TO_APP for contact events. */ public class DirectionEnum extends EnumDynamic { + /** An event sent to a Conversation API app. */ public static final DirectionEnum TO_APP = new DirectionEnum("TO_APP"); private static final EnumSupportDynamic ENUM_SUPPORT = diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/sinchevents/message/MessageInboundEventMessage.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/sinchevents/message/MessageInboundEventMessage.java index dbde95e7a..b77e79ffc 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/sinchevents/message/MessageInboundEventMessage.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/sinchevents/message/MessageInboundEventMessage.java @@ -33,6 +33,7 @@ public interface MessageInboundEventMessage { /** The direction of the message, it's always TO_APP for contact messages. */ public class DirectionEnum extends EnumDynamic { + /** A message sent to a Conversation API app. */ public static final DirectionEnum TO_APP = new DirectionEnum("TO_APP"); private static final EnumSupportDynamic ENUM_SUPPORT = diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/sinchevents/opting/OptInEventNotification.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/sinchevents/opting/OptInEventNotification.java index a481ea38e..75ef533ce 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/sinchevents/opting/OptInEventNotification.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/sinchevents/opting/OptInEventNotification.java @@ -53,8 +53,13 @@ public interface OptInEventNotification { /** Status of the opt-in registration. */ public class StatusEnum extends EnumDynamic { + /** The opt-in registration succeeded. */ public static final StatusEnum OPT_IN_SUCCEEDED = new StatusEnum("OPT_IN_SUCCEEDED"); + + /** The opt-in registration failed. */ public static final StatusEnum OPT_IN_FAILED = new StatusEnum("OPT_IN_FAILED"); + + /** The status of the opt-in registration is unknown. */ public static final StatusEnum OPT_IN_STATUS_UNSPECIFIED = new StatusEnum("OPT_IN_STATUS_UNSPECIFIED"); diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/sinchevents/opting/OptOutEventNotification.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/sinchevents/opting/OptOutEventNotification.java index 79bc483b7..ba9d7a6ec 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/sinchevents/opting/OptOutEventNotification.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/sinchevents/opting/OptOutEventNotification.java @@ -53,8 +53,13 @@ public interface OptOutEventNotification { /** Status of the opt-out registration. */ public class StatusEnum extends EnumDynamic { + /** The opt-out registration succeeded. */ public static final StatusEnum OPT_OUT_SUCCEEDED = new StatusEnum("OPT_OUT_SUCCEEDED"); + + /** The opt-out registration failed. */ public static final StatusEnum OPT_OUT_FAILED = new StatusEnum("OPT_OUT_FAILED"); + + /** The status of the opt-out registration is unknown. */ public static final StatusEnum OPT_OUT_STATUS_UNSPECIFIED = new StatusEnum("OPT_OUT_STATUS_UNSPECIFIED"); diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/sinchevents/record/RecordNotificationEventNotification.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/sinchevents/record/RecordNotificationEventNotification.java index 77082f361..1431af2bb 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/sinchevents/record/RecordNotificationEventNotification.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/sinchevents/record/RecordNotificationEventNotification.java @@ -32,8 +32,11 @@ public interface RecordNotificationEventNotification { /** Record status for a specific entity */ public class RecordStatusEnum extends EnumDynamic { + /** The record status is unknown. */ public static final RecordStatusEnum RECORD_STATUS_UNSPECIFIED = new RecordStatusEnum("RECORD_STATUS_UNSPECIFIED"); + + /** The record for the entity has been stored. */ public static final RecordStatusEnum EVENT_RECORD_STORED = new RecordStatusEnum("EVENT_RECORD_STORED"); diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/sinchevents/smartconversations/OffensiveAnalysis.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/sinchevents/smartconversations/OffensiveAnalysis.java index b61eaebbf..4296ee165 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/sinchevents/smartconversations/OffensiveAnalysis.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/sinchevents/smartconversations/OffensiveAnalysis.java @@ -36,7 +36,10 @@ public interface OffensiveAnalysis { /** A label, either SAFE or UNSAFE, that classifies the analyzed content. */ public class EvaluationEnum extends EnumDynamic { + /** The analysis of the content indicates that it is most likely safe. */ public static final EvaluationEnum SAFE = new EvaluationEnum("SAFE"); + + /** The analysis of the content indicates that it is most likely unsafe. */ public static final EvaluationEnum UNSAFE = new EvaluationEnum("UNSAFE"); private static final EnumSupportDynamic ENUM_SUPPORT = diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/transcoding/request/TranscodeMessageRequest.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/transcoding/request/TranscodeMessageRequest.java index 1948e234e..4ac3f3ec6 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/transcoding/request/TranscodeMessageRequest.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/models/v1/transcoding/request/TranscodeMessageRequest.java @@ -38,7 +38,7 @@ public interface TranscodeMessageRequest { AppMessage getAppMessage(); /** - * The list of channels for which the message shall be transcoded to. + * The list of channels for which the message shall be transcoded. * *

Field is required * diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/templates/api/v2/TemplatesV2Service.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/templates/api/v2/TemplatesV2Service.java index ca3d93423..517af4e12 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/templates/api/v2/TemplatesV2Service.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/templates/api/v2/TemplatesV2Service.java @@ -1,7 +1,7 @@ /* * Template Management API * - * OpenAPI document version: 1.0 + * OpenAPI document version: 2.0 * Contact: support@sinch.com * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/templates/api/v2/adapters/TemplatesV2ServiceImpl.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/templates/api/v2/adapters/TemplatesV2ServiceImpl.java index 024c95949..edbced9c9 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/templates/api/v2/adapters/TemplatesV2ServiceImpl.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/templates/api/v2/adapters/TemplatesV2ServiceImpl.java @@ -1,7 +1,7 @@ /* * Template Management API * - * OpenAPI document version: 1.0 + * OpenAPI document version: 2.0 * Contact: support@sinch.com * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -37,6 +37,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.function.Function; import java.util.logging.Logger; public class TemplatesV2ServiceImpl @@ -339,11 +340,17 @@ public TranslationsV2ListResponse listTranslations( + queryParameter); HttpRequest httpRequest = listTranslationsRequestBuilder(templateId, queryParameter); - return _fetchListTranslationsPage(queryParameter, httpRequest); + return _fetchListTranslationsPage( + (queryParameters) -> listTranslationsRequestBuilder(templateId, queryParameters), + queryParameter, + httpRequest); } private TranslationsV2ListResponse _fetchListTranslationsPage( - ListTranslationsQueryParameters queryParameter, HttpRequest httpRequest) throws ApiException { + Function requestBuilder, + ListTranslationsQueryParameters queryParameter, + HttpRequest httpRequest) + throws ApiException { HttpResponse response = httpClient.invokeAPI( this.serverConfiguration, this.authManagersByOasSecuritySchemes, httpRequest); diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/templates/models/TemplateVariable.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/templates/models/TemplateVariable.java index 246c856c7..dc2e53366 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/templates/models/TemplateVariable.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/templates/models/TemplateVariable.java @@ -1,7 +1,7 @@ /* * Template Management API * - * OpenAPI document version: 1.0 + * OpenAPI document version: 2.0 * Contact: support@sinch.com * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/templates/models/v2/ChannelTemplateOverride.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/templates/models/v2/ChannelTemplateOverride.java index bbe5d4159..32ee28835 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/templates/models/v2/ChannelTemplateOverride.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/templates/models/v2/ChannelTemplateOverride.java @@ -1,7 +1,7 @@ /* * Template Management API * - * OpenAPI document version: 1.0 + * OpenAPI document version: 2.0 * Contact: support@sinch.com * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/templates/models/v2/TemplateTranslationBase.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/templates/models/v2/TemplateTranslationBase.java index fef52a013..e2f9894bb 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/templates/models/v2/TemplateTranslationBase.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/templates/models/v2/TemplateTranslationBase.java @@ -1,7 +1,7 @@ /* * Template Management API * - * OpenAPI document version: 1.0 + * OpenAPI document version: 2.0 * Contact: support@sinch.com * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -58,6 +58,7 @@ public interface TemplateTranslationBase { * Timestamp when the translation was created. * * @return createTime + * @readOnly This field is returned by the server and cannot be modified */ Instant getCreateTime(); @@ -65,6 +66,7 @@ public interface TemplateTranslationBase { * Timestamp of when the translation was updated. * * @return updateTime + * @readOnly This field is returned by the server and cannot be modified */ Instant getUpdateTime(); @@ -114,6 +116,7 @@ B setChannelTemplateOverrides( * @param createTime see getter * @return Current builder * @see #getCreateTime + * @readOnly This field is returned by the server and cannot be modified */ B setCreateTime(Instant createTime); @@ -123,6 +126,7 @@ B setChannelTemplateOverrides( * @param updateTime see getter * @return Current builder * @see #getUpdateTime + * @readOnly This field is returned by the server and cannot be modified */ B setUpdateTime(Instant updateTime); diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/templates/models/v2/TemplateTranslationBaseImpl.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/templates/models/v2/TemplateTranslationBaseImpl.java index 66be0479c..0414e2b14 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/templates/models/v2/TemplateTranslationBaseImpl.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/templates/models/v2/TemplateTranslationBaseImpl.java @@ -191,8 +191,7 @@ public Instant getCreateTime() { return createTime.orElse(null); } - @JsonProperty(JSON_PROPERTY_CREATE_TIME) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonIgnore public OptionalValue createTime() { return createTime; } @@ -202,8 +201,7 @@ public Instant getUpdateTime() { return updateTime.orElse(null); } - @JsonProperty(JSON_PROPERTY_UPDATE_TIME) - @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + @JsonIgnore public OptionalValue updateTime() { return updateTime; } diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/templates/models/v2/TemplateV2.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/templates/models/v2/TemplateV2.java index 12fa3721b..a69a20e70 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/templates/models/v2/TemplateV2.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/templates/models/v2/TemplateV2.java @@ -1,7 +1,7 @@ /* * Template Management API * - * OpenAPI document version: 1.0 + * OpenAPI document version: 2.0 * Contact: support@sinch.com * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/templates/models/v2/internal/ListTemplatesResponseInternal.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/templates/models/v2/internal/ListTemplatesResponseInternal.java index dc718b171..e1f5bbcac 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/templates/models/v2/internal/ListTemplatesResponseInternal.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/templates/models/v2/internal/ListTemplatesResponseInternal.java @@ -1,7 +1,7 @@ /* * Template Management API * - * OpenAPI document version: 1.0 + * OpenAPI document version: 2.0 * Contact: support@sinch.com * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/templates/models/v2/internal/ListTranslationsResponseInternal.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/templates/models/v2/internal/ListTranslationsResponseInternal.java index e8cbab1c2..0e7697ca9 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/templates/models/v2/internal/ListTranslationsResponseInternal.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/templates/models/v2/internal/ListTranslationsResponseInternal.java @@ -1,7 +1,7 @@ /* * Template Management API * - * OpenAPI document version: 1.0 + * OpenAPI document version: 2.0 * Contact: support@sinch.com * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/templates/models/v2/request/ListTranslationsQueryParameters.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/templates/models/v2/request/ListTranslationsQueryParameters.java index 6d387dda1..3e8e59b26 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/templates/models/v2/request/ListTranslationsQueryParameters.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/templates/models/v2/request/ListTranslationsQueryParameters.java @@ -1,7 +1,7 @@ /* * Template Management API * - * OpenAPI document version: 1.0 + * OpenAPI document version: 2.0 * Contact: support@sinch.com * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/templates/models/v2/response/TemplatesV2ListResponse.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/templates/models/v2/response/TemplatesV2ListResponse.java index 035f9badc..47727daa6 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/templates/models/v2/response/TemplatesV2ListResponse.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/templates/models/v2/response/TemplatesV2ListResponse.java @@ -1,7 +1,7 @@ /* * Template Management API * - * OpenAPI document version: 1.0 + * OpenAPI document version: 2.0 * Contact: support@sinch.com * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/templates/models/v2/response/TranslationsV2ListResponse.java b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/templates/models/v2/response/TranslationsV2ListResponse.java index b037b030b..e7bf1f618 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/templates/models/v2/response/TranslationsV2ListResponse.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/conversation/templates/models/v2/response/TranslationsV2ListResponse.java @@ -1,7 +1,7 @@ /* * Template Management API * - * OpenAPI document version: 1.0 + * OpenAPI document version: 2.0 * Contact: support@sinch.com * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/api/v2/NumberLookupV2Service.java b/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/api/v2/NumberLookupV2Service.java new file mode 100644 index 000000000..9cf5d65e1 --- /dev/null +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/api/v2/NumberLookupV2Service.java @@ -0,0 +1,28 @@ +/* + * Number Lookup Api v2 + * + * OpenAPI document version: 0.1.0 + * Contact: support@sinch.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * Do not edit the class manually. + */ + +package com.sinch.sdk.domains.numberlookup.api.v2; + +import com.sinch.sdk.core.exceptions.ApiException; +import com.sinch.sdk.domains.numberlookup.models.v2.request.NumberLookupRequest; +import com.sinch.sdk.domains.numberlookup.models.v2.response.NumberLookupResponse; + +/** NumberLookupV2 Service */ +public interface NumberLookupV2Service { + + /** + * Performs a number lookup. + * + * @param numberLookupRequest (optional) + * @return NumberLookupResponse + * @throws ApiException if fails to make API call + */ + NumberLookupResponse lookup(NumberLookupRequest numberLookupRequest) throws ApiException; +} diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/api/v2/adapters/NumberLookupV2ServiceImpl.java b/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/api/v2/adapters/NumberLookupV2ServiceImpl.java new file mode 100644 index 000000000..6f74a84dd --- /dev/null +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/api/v2/adapters/NumberLookupV2ServiceImpl.java @@ -0,0 +1,117 @@ +/* + * Number Lookup Api v2 + * + * OpenAPI document version: 0.1.0 + * Contact: support@sinch.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * Do not edit the class manually. + */ + +package com.sinch.sdk.domains.numberlookup.api.v2.adapters; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.sinch.sdk.core.exceptions.ApiException; +import com.sinch.sdk.core.exceptions.ApiExceptionBuilder; +import com.sinch.sdk.core.http.AuthManager; +import com.sinch.sdk.core.http.HttpClient; +import com.sinch.sdk.core.http.HttpMapper; +import com.sinch.sdk.core.http.HttpMethod; +import com.sinch.sdk.core.http.HttpRequest; +import com.sinch.sdk.core.http.HttpResponse; +import com.sinch.sdk.core.http.HttpStatus; +import com.sinch.sdk.core.http.URLParameter; +import com.sinch.sdk.core.http.URLPathUtils; +import com.sinch.sdk.core.models.ServerConfiguration; +import com.sinch.sdk.domains.numberlookup.models.v2.request.NumberLookupRequest; +import com.sinch.sdk.domains.numberlookup.models.v2.response.NumberLookupResponse; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.logging.Logger; + +public class NumberLookupV2ServiceImpl + implements com.sinch.sdk.domains.numberlookup.api.v2.NumberLookupV2Service { + + private static final Logger LOGGER = Logger.getLogger(NumberLookupV2ServiceImpl.class.getName()); + private final HttpClient httpClient; + private final ServerConfiguration serverConfiguration; + private final Map authManagersByOasSecuritySchemes; + private final HttpMapper mapper; + + private final String projectId; + + public NumberLookupV2ServiceImpl( + HttpClient httpClient, + ServerConfiguration serverConfiguration, + Map authManagersByOasSecuritySchemes, + HttpMapper mapper, + String projectId) { + this.httpClient = httpClient; + this.serverConfiguration = serverConfiguration; + this.authManagersByOasSecuritySchemes = authManagersByOasSecuritySchemes; + this.mapper = mapper; + this.projectId = projectId; + } + + @Override + public NumberLookupResponse lookup(NumberLookupRequest numberLookupRequest) throws ApiException { + + LOGGER.finest("[lookup]" + " " + "numberLookupRequest: " + numberLookupRequest); + + HttpRequest httpRequest = lookupRequestBuilder(numberLookupRequest); + HttpResponse response = + httpClient.invokeAPI( + this.serverConfiguration, this.authManagersByOasSecuritySchemes, httpRequest); + + if (HttpStatus.isSuccessfulStatus(response.getCode())) { + return mapper.deserialize(response, new TypeReference() {}); + } + // fallback to default errors handling: + // all error cases definition are not required from specs: will try some "hardcoded" content + // parsing + throw ApiExceptionBuilder.build( + response.getMessage(), + response.getCode(), + mapper.deserialize(response, new TypeReference>() {})); + } + + private HttpRequest lookupRequestBuilder(NumberLookupRequest numberLookupRequest) + throws ApiException { + // verify the required parameter 'this.projectId' is set + if (this.projectId == null) { + throw new ApiException( + 400, "Missing the required parameter 'this.projectId' when calling lookup"); + } + + String localVarPath = + "/v2/projects/{projectId}/lookups" + .replaceAll( + "\\{" + "projectId" + "\\}", + URLPathUtils.encodePathSegment(this.projectId.toString())); + + List localVarQueryParams = new ArrayList<>(); + + Map localVarHeaderParams = new HashMap<>(); + + final Collection localVarAccepts = Arrays.asList("application/json"); + + final Collection localVarContentTypes = Arrays.asList("application/json"); + + final Collection localVarAuthNames = Arrays.asList("Basic", "OAuth2"); + final String serializedBody = mapper.serialize(localVarContentTypes, numberLookupRequest); + + return new HttpRequest( + localVarPath, + HttpMethod.POST, + localVarQueryParams, + serializedBody, + localVarHeaderParams, + localVarAccepts, + localVarContentTypes, + localVarAuthNames); + } +} diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/errors/LookupError.java b/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/errors/LookupError.java new file mode 100644 index 000000000..d6c42a708 --- /dev/null +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/errors/LookupError.java @@ -0,0 +1,102 @@ +/* + * Number Lookup Api v2 + * + * OpenAPI document version: 0.1.0 + * Contact: support@sinch.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * Do not edit the class manually. + */ + +package com.sinch.sdk.domains.numberlookup.models.v2.errors; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; + +/** LookupError */ +@JsonDeserialize(builder = LookupErrorImpl.Builder.class) +public interface LookupError { + + /** + * The error status code. + * + * @return status + */ + Integer getStatus(); + + /** + * A short, human-readable summary of the error type. + * + * @return title + */ + String getTitle(); + + /** + * A human-readable explanation specific to this occurrence of the error. + * + * @return detail + */ + String getDetail(); + + /** + * A URI reference that identifies the error type. + * + * @return type + */ + String getType(); + + /** + * Getting builder + * + * @return New Builder instance + */ + static Builder builder() { + return new LookupErrorImpl.Builder(); + } + + /** Dedicated Builder */ + interface Builder { + + /** + * see getter + * + * @param status see getter + * @return Current builder + * @see #getStatus + */ + Builder setStatus(Integer status); + + /** + * see getter + * + * @param title see getter + * @return Current builder + * @see #getTitle + */ + Builder setTitle(String title); + + /** + * see getter + * + * @param detail see getter + * @return Current builder + * @see #getDetail + */ + Builder setDetail(String detail); + + /** + * see getter + * + * @param type see getter + * @return Current builder + * @see #getType + */ + Builder setType(String type); + + /** + * Create instance + * + * @return The instance build with current builder values + */ + LookupError build(); + } +} diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/errors/LookupErrorImpl.java b/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/errors/LookupErrorImpl.java new file mode 100644 index 000000000..8501d0679 --- /dev/null +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/errors/LookupErrorImpl.java @@ -0,0 +1,174 @@ +package com.sinch.sdk.domains.numberlookup.models.v2.errors; + +import com.fasterxml.jackson.annotation.JsonFilter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; +import com.sinch.sdk.core.models.OptionalValue; +import java.util.Objects; + +@JsonPropertyOrder({ + LookupErrorImpl.JSON_PROPERTY_STATUS, + LookupErrorImpl.JSON_PROPERTY_TITLE, + LookupErrorImpl.JSON_PROPERTY_DETAIL, + LookupErrorImpl.JSON_PROPERTY_TYPE +}) +@JsonFilter("uninitializedFilter") +@JsonInclude(value = JsonInclude.Include.CUSTOM) +public class LookupErrorImpl implements LookupError { + private static final long serialVersionUID = 1L; + + public static final String JSON_PROPERTY_STATUS = "status"; + + private OptionalValue status; + + public static final String JSON_PROPERTY_TITLE = "title"; + + private OptionalValue title; + + public static final String JSON_PROPERTY_DETAIL = "detail"; + + private OptionalValue detail; + + public static final String JSON_PROPERTY_TYPE = "type"; + + private OptionalValue type; + + public LookupErrorImpl() {} + + protected LookupErrorImpl( + OptionalValue status, + OptionalValue title, + OptionalValue detail, + OptionalValue type) { + this.status = status; + this.title = title; + this.detail = detail; + this.type = type; + } + + @JsonIgnore + public Integer getStatus() { + return status.orElse(null); + } + + @JsonProperty(JSON_PROPERTY_STATUS) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public OptionalValue status() { + return status; + } + + @JsonIgnore + public String getTitle() { + return title.orElse(null); + } + + @JsonProperty(JSON_PROPERTY_TITLE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public OptionalValue title() { + return title; + } + + @JsonIgnore + public String getDetail() { + return detail.orElse(null); + } + + @JsonProperty(JSON_PROPERTY_DETAIL) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public OptionalValue detail() { + return detail; + } + + @JsonIgnore + public String getType() { + return type.orElse(null); + } + + @JsonProperty(JSON_PROPERTY_TYPE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public OptionalValue type() { + return type; + } + + /** Return true if this ErrorResponse object is equal to o. */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + LookupErrorImpl errorResponse = (LookupErrorImpl) o; + return Objects.equals(this.status, errorResponse.status) + && Objects.equals(this.title, errorResponse.title) + && Objects.equals(this.detail, errorResponse.detail) + && Objects.equals(this.type, errorResponse.type); + } + + @Override + public int hashCode() { + return Objects.hash(status, title, detail, type); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class LookupErrorImpl {\n"); + sb.append(" status: ").append(toIndentedString(status)).append("\n"); + sb.append(" title: ").append(toIndentedString(title)).append("\n"); + sb.append(" detail: ").append(toIndentedString(detail)).append("\n"); + sb.append(" type: ").append(toIndentedString(type)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + @JsonPOJOBuilder(withPrefix = "set") + static class Builder implements LookupError.Builder { + OptionalValue status = OptionalValue.empty(); + OptionalValue title = OptionalValue.empty(); + OptionalValue detail = OptionalValue.empty(); + OptionalValue type = OptionalValue.empty(); + + @JsonProperty(JSON_PROPERTY_STATUS) + public Builder setStatus(Integer status) { + this.status = OptionalValue.of(status); + return this; + } + + @JsonProperty(JSON_PROPERTY_TITLE) + public Builder setTitle(String title) { + this.title = OptionalValue.of(title); + return this; + } + + @JsonProperty(JSON_PROPERTY_DETAIL) + public Builder setDetail(String detail) { + this.detail = OptionalValue.of(detail); + return this; + } + + @JsonProperty(JSON_PROPERTY_TYPE) + public Builder setType(String type) { + this.type = OptionalValue.of(type); + return this; + } + + public LookupError build() { + return new LookupErrorImpl(status, title, detail, type); + } + } +} diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/errors/ProblemDetails.java b/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/errors/ProblemDetails.java new file mode 100644 index 000000000..db503a96a --- /dev/null +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/errors/ProblemDetails.java @@ -0,0 +1,102 @@ +/* + * Number Lookup Api v2 + * + * OpenAPI document version: 0.1.0 + * Contact: support@sinch.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * Do not edit the class manually. + */ + +package com.sinch.sdk.domains.numberlookup.models.v2.errors; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; + +/** ProblemDetails */ +@JsonDeserialize(builder = ProblemDetailsImpl.Builder.class) +public interface ProblemDetails { + + /** + * A URI reference that identifies the problem type. + * + * @return type + */ + String getType(); + + /** + * A short, human-readable summary of the problem type. + * + * @return title + */ + String getTitle(); + + /** + * The HTTP status code. + * + * @return status + */ + Integer getStatus(); + + /** + * The identifier for a trace. + * + * @return traceId + */ + String getTraceId(); + + /** + * Getting builder + * + * @return New Builder instance + */ + static Builder builder() { + return new ProblemDetailsImpl.Builder(); + } + + /** Dedicated Builder */ + interface Builder { + + /** + * see getter + * + * @param type see getter + * @return Current builder + * @see #getType + */ + Builder setType(String type); + + /** + * see getter + * + * @param title see getter + * @return Current builder + * @see #getTitle + */ + Builder setTitle(String title); + + /** + * see getter + * + * @param status see getter + * @return Current builder + * @see #getStatus + */ + Builder setStatus(Integer status); + + /** + * see getter + * + * @param traceId see getter + * @return Current builder + * @see #getTraceId + */ + Builder setTraceId(String traceId); + + /** + * Create instance + * + * @return The instance build with current builder values + */ + ProblemDetails build(); + } +} diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/errors/ProblemDetailsImpl.java b/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/errors/ProblemDetailsImpl.java new file mode 100644 index 000000000..0ba6140b3 --- /dev/null +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/errors/ProblemDetailsImpl.java @@ -0,0 +1,174 @@ +package com.sinch.sdk.domains.numberlookup.models.v2.errors; + +import com.fasterxml.jackson.annotation.JsonFilter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; +import com.sinch.sdk.core.models.OptionalValue; +import java.util.Objects; + +@JsonPropertyOrder({ + ProblemDetailsImpl.JSON_PROPERTY_TYPE, + ProblemDetailsImpl.JSON_PROPERTY_TITLE, + ProblemDetailsImpl.JSON_PROPERTY_STATUS, + ProblemDetailsImpl.JSON_PROPERTY_TRACE_ID +}) +@JsonFilter("uninitializedFilter") +@JsonInclude(value = JsonInclude.Include.CUSTOM) +public class ProblemDetailsImpl implements ProblemDetails { + private static final long serialVersionUID = 1L; + + public static final String JSON_PROPERTY_TYPE = "type"; + + private OptionalValue type; + + public static final String JSON_PROPERTY_TITLE = "title"; + + private OptionalValue title; + + public static final String JSON_PROPERTY_STATUS = "status"; + + private OptionalValue status; + + public static final String JSON_PROPERTY_TRACE_ID = "traceId"; + + private OptionalValue traceId; + + public ProblemDetailsImpl() {} + + protected ProblemDetailsImpl( + OptionalValue type, + OptionalValue title, + OptionalValue status, + OptionalValue traceId) { + this.type = type; + this.title = title; + this.status = status; + this.traceId = traceId; + } + + @JsonIgnore + public String getType() { + return type.orElse(null); + } + + @JsonProperty(JSON_PROPERTY_TYPE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public OptionalValue type() { + return type; + } + + @JsonIgnore + public String getTitle() { + return title.orElse(null); + } + + @JsonProperty(JSON_PROPERTY_TITLE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public OptionalValue title() { + return title; + } + + @JsonIgnore + public Integer getStatus() { + return status.orElse(null); + } + + @JsonProperty(JSON_PROPERTY_STATUS) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public OptionalValue status() { + return status; + } + + @JsonIgnore + public String getTraceId() { + return traceId.orElse(null); + } + + @JsonProperty(JSON_PROPERTY_TRACE_ID) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public OptionalValue traceId() { + return traceId; + } + + /** Return true if this ProblemDetails object is equal to o. */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ProblemDetailsImpl problemDetails = (ProblemDetailsImpl) o; + return Objects.equals(this.type, problemDetails.type) + && Objects.equals(this.title, problemDetails.title) + && Objects.equals(this.status, problemDetails.status) + && Objects.equals(this.traceId, problemDetails.traceId); + } + + @Override + public int hashCode() { + return Objects.hash(type, title, status, traceId); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class ProblemDetailsImpl {\n"); + sb.append(" type: ").append(toIndentedString(type)).append("\n"); + sb.append(" title: ").append(toIndentedString(title)).append("\n"); + sb.append(" status: ").append(toIndentedString(status)).append("\n"); + sb.append(" traceId: ").append(toIndentedString(traceId)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + @JsonPOJOBuilder(withPrefix = "set") + static class Builder implements ProblemDetails.Builder { + OptionalValue type = OptionalValue.empty(); + OptionalValue title = OptionalValue.empty(); + OptionalValue status = OptionalValue.empty(); + OptionalValue traceId = OptionalValue.empty(); + + @JsonProperty(JSON_PROPERTY_TYPE) + public Builder setType(String type) { + this.type = OptionalValue.of(type); + return this; + } + + @JsonProperty(JSON_PROPERTY_TITLE) + public Builder setTitle(String title) { + this.title = OptionalValue.of(title); + return this; + } + + @JsonProperty(JSON_PROPERTY_STATUS) + public Builder setStatus(Integer status) { + this.status = OptionalValue.of(status); + return this; + } + + @JsonProperty(JSON_PROPERTY_TRACE_ID) + public Builder setTraceId(String traceId) { + this.traceId = OptionalValue.of(traceId); + return this; + } + + public ProblemDetails build() { + return new ProblemDetailsImpl(type, title, status, traceId); + } + } +} diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/request/LookupFeatureType.java b/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/request/LookupFeatureType.java new file mode 100644 index 000000000..c93224cc9 --- /dev/null +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/request/LookupFeatureType.java @@ -0,0 +1,44 @@ +package com.sinch.sdk.domains.numberlookup.models.v2.request; + +import com.sinch.sdk.core.utils.EnumDynamic; +import com.sinch.sdk.core.utils.EnumSupportDynamic; +import java.util.Arrays; +import java.util.stream.Stream; + +/** */ +public class LookupFeatureType extends EnumDynamic { + + /** Use to return line type information for the phone number. */ + public static final LookupFeatureType LINE_TYPE = new LookupFeatureType("LineType"); + + /** Use to determine whether the phone number is SIM swapped. */ + public static final LookupFeatureType SIM_SWAP = new LookupFeatureType("SimSwap"); + + /** Use to determine if the carrier is associated with a VoIP provider (alpha). */ + public static final LookupFeatureType VO_IP_DETECTION = new LookupFeatureType("VoIPDetection"); + + /** Use to determine whether the phone number has been disconnected (alpha). */ + public static final LookupFeatureType RND = new LookupFeatureType("RND"); + + private static final EnumSupportDynamic ENUM_SUPPORT = + new EnumSupportDynamic<>( + LookupFeatureType.class, + LookupFeatureType::new, + Arrays.asList(LINE_TYPE, SIM_SWAP, VO_IP_DETECTION, RND)); + + private LookupFeatureType(String value) { + super(value); + } + + public static Stream values() { + return ENUM_SUPPORT.values(); + } + + public static LookupFeatureType from(String value) { + return ENUM_SUPPORT.from(value); + } + + public static String valueOf(LookupFeatureType e) { + return ENUM_SUPPORT.valueOf(e); + } +} diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/request/NumberLookupRequest.java b/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/request/NumberLookupRequest.java new file mode 100644 index 000000000..94d358a3b --- /dev/null +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/request/NumberLookupRequest.java @@ -0,0 +1,89 @@ +/* + * Number Lookup Api v2 + * + * OpenAPI document version: 0.1.0 + * Contact: support@sinch.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * Do not edit the class manually. + */ + +package com.sinch.sdk.domains.numberlookup.models.v2.request; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import java.util.List; + +/** NumberLookupRequest */ +@JsonDeserialize(builder = NumberLookupRequestImpl.Builder.class) +public interface NumberLookupRequest { + + /** + * MSISDN in E.164 format to query. + * + *

Field is required + * + * @return number + */ + String getNumber(); + + /** + * Contains requested features. Fallback to LineType if not provided. + * + * @return features + */ + List getFeatures(); + + /** + * Required when RND feature is requested. + * + * @return rndFeatureOptions + */ + RndFeatureOptions getRndFeatureOptions(); + + /** + * Getting builder + * + * @return New Builder instance + */ + static Builder builder() { + return new NumberLookupRequestImpl.Builder(); + } + + /** Dedicated Builder */ + interface Builder { + + /** + * see getter + * + * @param number see getter + * @return Current builder + * @see #getNumber + */ + Builder setNumber(String number); + + /** + * see getter + * + * @param features see getter + * @return Current builder + * @see #getFeatures + */ + Builder setFeatures(List features); + + /** + * see getter + * + * @param rndFeatureOptions see getter + * @return Current builder + * @see #getRndFeatureOptions + */ + Builder setRndFeatureOptions(RndFeatureOptions rndFeatureOptions); + + /** + * Create instance + * + * @return The instance build with current builder values + */ + NumberLookupRequest build(); + } +} diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/request/NumberLookupRequestImpl.java b/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/request/NumberLookupRequestImpl.java new file mode 100644 index 000000000..53a6f397b --- /dev/null +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/request/NumberLookupRequestImpl.java @@ -0,0 +1,148 @@ +package com.sinch.sdk.domains.numberlookup.models.v2.request; + +import com.fasterxml.jackson.annotation.JsonFilter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; +import com.sinch.sdk.core.models.OptionalValue; +import java.util.List; +import java.util.Objects; + +@JsonPropertyOrder({ + NumberLookupRequestImpl.JSON_PROPERTY_NUMBER, + NumberLookupRequestImpl.JSON_PROPERTY_FEATURES, + NumberLookupRequestImpl.JSON_PROPERTY_RND_FEATURE_OPTIONS +}) +@JsonFilter("uninitializedFilter") +@JsonInclude(value = JsonInclude.Include.CUSTOM) +public class NumberLookupRequestImpl implements NumberLookupRequest { + private static final long serialVersionUID = 1L; + + public static final String JSON_PROPERTY_NUMBER = "number"; + + private OptionalValue number; + + public static final String JSON_PROPERTY_FEATURES = "features"; + + private OptionalValue> features; + + public static final String JSON_PROPERTY_RND_FEATURE_OPTIONS = "rndFeatureOptions"; + + private OptionalValue rndFeatureOptions; + + public NumberLookupRequestImpl() {} + + protected NumberLookupRequestImpl( + OptionalValue number, + OptionalValue> features, + OptionalValue rndFeatureOptions) { + this.number = number; + this.features = features; + this.rndFeatureOptions = rndFeatureOptions; + } + + @JsonIgnore + public String getNumber() { + return number.orElse(null); + } + + @JsonProperty(JSON_PROPERTY_NUMBER) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public OptionalValue number() { + return number; + } + + @JsonIgnore + public List getFeatures() { + return features.orElse(null); + } + + @JsonProperty(JSON_PROPERTY_FEATURES) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public OptionalValue> features() { + return features; + } + + @JsonIgnore + public RndFeatureOptions getRndFeatureOptions() { + return rndFeatureOptions.orElse(null); + } + + @JsonProperty(JSON_PROPERTY_RND_FEATURE_OPTIONS) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public OptionalValue rndFeatureOptions() { + return rndFeatureOptions; + } + + /** Return true if this NumberLookupRequest object is equal to o. */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + NumberLookupRequestImpl numberLookupRequest = (NumberLookupRequestImpl) o; + return Objects.equals(this.number, numberLookupRequest.number) + && Objects.equals(this.features, numberLookupRequest.features) + && Objects.equals(this.rndFeatureOptions, numberLookupRequest.rndFeatureOptions); + } + + @Override + public int hashCode() { + return Objects.hash(number, features, rndFeatureOptions); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class NumberLookupRequestImpl {\n"); + sb.append(" number: ").append(toIndentedString(number)).append("\n"); + sb.append(" features: ").append(toIndentedString(features)).append("\n"); + sb.append(" rndFeatureOptions: ").append(toIndentedString(rndFeatureOptions)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + @JsonPOJOBuilder(withPrefix = "set") + static class Builder implements NumberLookupRequest.Builder { + OptionalValue number = OptionalValue.empty(); + OptionalValue> features = OptionalValue.empty(); + OptionalValue rndFeatureOptions = OptionalValue.empty(); + + @JsonProperty(value = JSON_PROPERTY_NUMBER, required = true) + public Builder setNumber(String number) { + this.number = OptionalValue.of(number); + return this; + } + + @JsonProperty(JSON_PROPERTY_FEATURES) + public Builder setFeatures(List features) { + this.features = OptionalValue.of(features); + return this; + } + + @JsonProperty(JSON_PROPERTY_RND_FEATURE_OPTIONS) + public Builder setRndFeatureOptions(RndFeatureOptions rndFeatureOptions) { + this.rndFeatureOptions = OptionalValue.of(rndFeatureOptions); + return this; + } + + public NumberLookupRequest build() { + return new NumberLookupRequestImpl(number, features, rndFeatureOptions); + } + } +} diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/request/RndFeatureOptions.java b/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/request/RndFeatureOptions.java new file mode 100644 index 000000000..0c120d1ec --- /dev/null +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/request/RndFeatureOptions.java @@ -0,0 +1,55 @@ +/* + * Number Lookup Api v2 + * + * OpenAPI document version: 0.1.0 + * Contact: support@sinch.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * Do not edit the class manually. + */ + +package com.sinch.sdk.domains.numberlookup.models.v2.request; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import java.time.LocalDate; + +/** RndFeatureOptions */ +@JsonDeserialize(builder = RndFeatureOptionsImpl.Builder.class) +public interface RndFeatureOptions { + + /** + * Last contact date in YYYY-MM-DD format. + * + * @return contactDate + */ + LocalDate getContactDate(); + + /** + * Getting builder + * + * @return New Builder instance + */ + static Builder builder() { + return new RndFeatureOptionsImpl.Builder(); + } + + /** Dedicated Builder */ + interface Builder { + + /** + * see getter + * + * @param contactDate see getter + * @return Current builder + * @see #getContactDate + */ + Builder setContactDate(LocalDate contactDate); + + /** + * Create instance + * + * @return The instance build with current builder values + */ + RndFeatureOptions build(); + } +} diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/request/RndFeatureOptionsImpl.java b/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/request/RndFeatureOptionsImpl.java new file mode 100644 index 000000000..e4c1856b8 --- /dev/null +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/request/RndFeatureOptionsImpl.java @@ -0,0 +1,91 @@ +package com.sinch.sdk.domains.numberlookup.models.v2.request; + +import com.fasterxml.jackson.annotation.JsonFilter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; +import com.sinch.sdk.core.models.OptionalValue; +import java.time.LocalDate; +import java.util.Objects; + +@JsonPropertyOrder({RndFeatureOptionsImpl.JSON_PROPERTY_CONTACT_DATE}) +@JsonFilter("uninitializedFilter") +@JsonInclude(value = JsonInclude.Include.CUSTOM) +public class RndFeatureOptionsImpl implements RndFeatureOptions { + private static final long serialVersionUID = 1L; + + public static final String JSON_PROPERTY_CONTACT_DATE = "contactDate"; + + private OptionalValue contactDate; + + public RndFeatureOptionsImpl() {} + + protected RndFeatureOptionsImpl(OptionalValue contactDate) { + this.contactDate = contactDate; + } + + @JsonIgnore + public LocalDate getContactDate() { + return contactDate.orElse(null); + } + + @JsonProperty(JSON_PROPERTY_CONTACT_DATE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public OptionalValue contactDate() { + return contactDate; + } + + /** Return true if this RndFeatureOptions object is equal to o. */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + RndFeatureOptionsImpl rndFeatureOptions = (RndFeatureOptionsImpl) o; + return Objects.equals(this.contactDate, rndFeatureOptions.contactDate); + } + + @Override + public int hashCode() { + return Objects.hash(contactDate); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class RndFeatureOptionsImpl {\n"); + sb.append(" contactDate: ").append(toIndentedString(contactDate)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + @JsonPOJOBuilder(withPrefix = "set") + static class Builder implements RndFeatureOptions.Builder { + OptionalValue contactDate = OptionalValue.empty(); + + @JsonProperty(JSON_PROPERTY_CONTACT_DATE) + public Builder setContactDate(LocalDate contactDate) { + this.contactDate = OptionalValue.of(contactDate); + return this; + } + + public RndFeatureOptions build() { + return new RndFeatureOptionsImpl(contactDate); + } + } +} diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/response/Line.java b/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/response/Line.java new file mode 100644 index 000000000..183787d36 --- /dev/null +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/response/Line.java @@ -0,0 +1,156 @@ +/* + * Number Lookup Api v2 + * + * OpenAPI document version: 0.1.0 + * Contact: support@sinch.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * Do not edit the class manually. + */ + +package com.sinch.sdk.domains.numberlookup.models.v2.response; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.sinch.sdk.domains.numberlookup.models.v2.errors.LookupError; +import java.time.Instant; + +/** Line */ +@JsonDeserialize(builder = LineImpl.Builder.class) +public interface Line { + + /** + * Name of the carrier. + * + * @return carrier + */ + String getCarrier(); + + /** + * Number type e.g. wireless, mobile, fixed. + * + * @return type + */ + LineType getType(); + + /** + * A numeric code (MCC) that uniquely identifies a country within the international + * telecommunications network. + * + * @return mobileCountryCode + */ + String getMobileCountryCode(); + + /** + * A distinct identifier assigned to a mobile network operator within a specific country, used in + * combination with MCC. + * + * @return mobileNetworkCode + */ + String getMobileNetworkCode(); + + /** + * Indicates if a phone number has been transferred from its original network to a different + * provider. + * + * @return ported + */ + Boolean getPorted(); + + /** + * Specifies the date, in ISO 8601 format, when a phone number was transferred from its original + * network to a new provider. + * + * @return portingDate + */ + Instant getPortingDate(); + + /** + * Get error + * + * @return error + */ + LookupError getError(); + + /** + * Getting builder + * + * @return New Builder instance + */ + static Builder builder() { + return new LineImpl.Builder(); + } + + /** Dedicated Builder */ + interface Builder { + + /** + * see getter + * + * @param carrier see getter + * @return Current builder + * @see #getCarrier + */ + Builder setCarrier(String carrier); + + /** + * see getter + * + * @param type see getter + * @return Current builder + * @see #getType + */ + Builder setType(LineType type); + + /** + * see getter + * + * @param mobileCountryCode see getter + * @return Current builder + * @see #getMobileCountryCode + */ + Builder setMobileCountryCode(String mobileCountryCode); + + /** + * see getter + * + * @param mobileNetworkCode see getter + * @return Current builder + * @see #getMobileNetworkCode + */ + Builder setMobileNetworkCode(String mobileNetworkCode); + + /** + * see getter + * + * @param ported see getter + * @return Current builder + * @see #getPorted + */ + Builder setPorted(Boolean ported); + + /** + * see getter + * + * @param portingDate see getter + * @return Current builder + * @see #getPortingDate + */ + Builder setPortingDate(Instant portingDate); + + /** + * see getter + * + * @param error see getter + * @return Current builder + * @see #getError + */ + Builder setError(LookupError error); + + /** + * Create instance + * + * @return The instance build with current builder values + */ + Line build(); + } +} diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/response/LineImpl.java b/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/response/LineImpl.java new file mode 100644 index 000000000..0cf94544b --- /dev/null +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/response/LineImpl.java @@ -0,0 +1,259 @@ +package com.sinch.sdk.domains.numberlookup.models.v2.response; + +import com.fasterxml.jackson.annotation.JsonFilter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; +import com.sinch.sdk.core.models.OptionalValue; +import com.sinch.sdk.domains.numberlookup.models.v2.errors.LookupError; +import java.time.Instant; +import java.util.Objects; + +@JsonPropertyOrder({ + LineImpl.JSON_PROPERTY_CARRIER, + LineImpl.JSON_PROPERTY_TYPE, + LineImpl.JSON_PROPERTY_MOBILE_COUNTRY_CODE, + LineImpl.JSON_PROPERTY_MOBILE_NETWORK_CODE, + LineImpl.JSON_PROPERTY_PORTED, + LineImpl.JSON_PROPERTY_PORTING_DATE, + LineImpl.JSON_PROPERTY_ERROR +}) +@JsonFilter("uninitializedFilter") +@JsonInclude(value = JsonInclude.Include.CUSTOM) +public class LineImpl implements Line { + private static final long serialVersionUID = 1L; + + public static final String JSON_PROPERTY_CARRIER = "carrier"; + + private OptionalValue carrier; + + public static final String JSON_PROPERTY_TYPE = "type"; + + private OptionalValue type; + + public static final String JSON_PROPERTY_MOBILE_COUNTRY_CODE = "mobileCountryCode"; + + private OptionalValue mobileCountryCode; + + public static final String JSON_PROPERTY_MOBILE_NETWORK_CODE = "mobileNetworkCode"; + + private OptionalValue mobileNetworkCode; + + public static final String JSON_PROPERTY_PORTED = "ported"; + + private OptionalValue ported; + + public static final String JSON_PROPERTY_PORTING_DATE = "portingDate"; + + private OptionalValue portingDate; + + public static final String JSON_PROPERTY_ERROR = "error"; + + private OptionalValue error; + + public LineImpl() {} + + protected LineImpl( + OptionalValue carrier, + OptionalValue type, + OptionalValue mobileCountryCode, + OptionalValue mobileNetworkCode, + OptionalValue ported, + OptionalValue portingDate, + OptionalValue error) { + this.carrier = carrier; + this.type = type; + this.mobileCountryCode = mobileCountryCode; + this.mobileNetworkCode = mobileNetworkCode; + this.ported = ported; + this.portingDate = portingDate; + this.error = error; + } + + @JsonIgnore + public String getCarrier() { + return carrier.orElse(null); + } + + @JsonProperty(JSON_PROPERTY_CARRIER) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public OptionalValue carrier() { + return carrier; + } + + @JsonIgnore + public LineType getType() { + return type.orElse(null); + } + + @JsonProperty(JSON_PROPERTY_TYPE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public OptionalValue type() { + return type; + } + + @JsonIgnore + public String getMobileCountryCode() { + return mobileCountryCode.orElse(null); + } + + @JsonProperty(JSON_PROPERTY_MOBILE_COUNTRY_CODE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public OptionalValue mobileCountryCode() { + return mobileCountryCode; + } + + @JsonIgnore + public String getMobileNetworkCode() { + return mobileNetworkCode.orElse(null); + } + + @JsonProperty(JSON_PROPERTY_MOBILE_NETWORK_CODE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public OptionalValue mobileNetworkCode() { + return mobileNetworkCode; + } + + @JsonIgnore + public Boolean getPorted() { + return ported.orElse(null); + } + + @JsonProperty(JSON_PROPERTY_PORTED) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public OptionalValue ported() { + return ported; + } + + @JsonIgnore + public Instant getPortingDate() { + return portingDate.orElse(null); + } + + @JsonProperty(JSON_PROPERTY_PORTING_DATE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public OptionalValue portingDate() { + return portingDate; + } + + @JsonIgnore + public LookupError getError() { + return error.orElse(null); + } + + @JsonProperty(JSON_PROPERTY_ERROR) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public OptionalValue error() { + return error; + } + + /** Return true if this LineResponse object is equal to o. */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + LineImpl lineResponse = (LineImpl) o; + return Objects.equals(this.carrier, lineResponse.carrier) + && Objects.equals(this.type, lineResponse.type) + && Objects.equals(this.mobileCountryCode, lineResponse.mobileCountryCode) + && Objects.equals(this.mobileNetworkCode, lineResponse.mobileNetworkCode) + && Objects.equals(this.ported, lineResponse.ported) + && Objects.equals(this.portingDate, lineResponse.portingDate) + && Objects.equals(this.error, lineResponse.error); + } + + @Override + public int hashCode() { + return Objects.hash( + carrier, type, mobileCountryCode, mobileNetworkCode, ported, portingDate, error); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class LineImpl {\n"); + sb.append(" carrier: ").append(toIndentedString(carrier)).append("\n"); + sb.append(" type: ").append(toIndentedString(type)).append("\n"); + sb.append(" mobileCountryCode: ").append(toIndentedString(mobileCountryCode)).append("\n"); + sb.append(" mobileNetworkCode: ").append(toIndentedString(mobileNetworkCode)).append("\n"); + sb.append(" ported: ").append(toIndentedString(ported)).append("\n"); + sb.append(" portingDate: ").append(toIndentedString(portingDate)).append("\n"); + sb.append(" error: ").append(toIndentedString(error)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + @JsonPOJOBuilder(withPrefix = "set") + static class Builder implements Line.Builder { + OptionalValue carrier = OptionalValue.empty(); + OptionalValue type = OptionalValue.empty(); + OptionalValue mobileCountryCode = OptionalValue.empty(); + OptionalValue mobileNetworkCode = OptionalValue.empty(); + OptionalValue ported = OptionalValue.empty(); + OptionalValue portingDate = OptionalValue.empty(); + OptionalValue error = OptionalValue.empty(); + + @JsonProperty(JSON_PROPERTY_CARRIER) + public Builder setCarrier(String carrier) { + this.carrier = OptionalValue.of(carrier); + return this; + } + + @JsonProperty(JSON_PROPERTY_TYPE) + public Builder setType(LineType type) { + this.type = OptionalValue.of(type); + return this; + } + + @JsonProperty(JSON_PROPERTY_MOBILE_COUNTRY_CODE) + public Builder setMobileCountryCode(String mobileCountryCode) { + this.mobileCountryCode = OptionalValue.of(mobileCountryCode); + return this; + } + + @JsonProperty(JSON_PROPERTY_MOBILE_NETWORK_CODE) + public Builder setMobileNetworkCode(String mobileNetworkCode) { + this.mobileNetworkCode = OptionalValue.of(mobileNetworkCode); + return this; + } + + @JsonProperty(JSON_PROPERTY_PORTED) + public Builder setPorted(Boolean ported) { + this.ported = OptionalValue.of(ported); + return this; + } + + @JsonProperty(JSON_PROPERTY_PORTING_DATE) + public Builder setPortingDate(Instant portingDate) { + this.portingDate = OptionalValue.of(portingDate); + return this; + } + + @JsonProperty(JSON_PROPERTY_ERROR) + public Builder setError(LookupError error) { + this.error = OptionalValue.of(error); + return this; + } + + public Line build() { + return new LineImpl( + carrier, type, mobileCountryCode, mobileNetworkCode, ported, portingDate, error); + } + } +} diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/response/LineType.java b/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/response/LineType.java new file mode 100644 index 000000000..7dc2cc9f4 --- /dev/null +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/response/LineType.java @@ -0,0 +1,50 @@ +package com.sinch.sdk.domains.numberlookup.models.v2.response; + +import com.sinch.sdk.core.utils.EnumDynamic; +import com.sinch.sdk.core.utils.EnumSupportDynamic; +import java.util.Arrays; +import java.util.stream.Stream; + +/** Represents the type of a phone line. */ +public class LineType extends EnumDynamic { + + /** A landline phone number. */ + public static final LineType LANDLINE = new LineType("Landline"); + + /** A mobile network phone number. */ + public static final LineType MOBILE = new LineType("Mobile"); + + /** A Voice over IP phone number. */ + public static final LineType VO_IP = new LineType("VoIP"); + + /** A specialty type of number, such as a satellite phone or fax line. */ + public static final LineType SPECIAL = new LineType("Special"); + + /** A freephone type phone number. */ + public static final LineType FREEPHONE = new LineType("Freephone"); + + /** Another type. */ + public static final LineType OTHER = new LineType("Other"); + + private static final EnumSupportDynamic ENUM_SUPPORT = + new EnumSupportDynamic<>( + LineType.class, + LineType::new, + Arrays.asList(LANDLINE, MOBILE, VO_IP, SPECIAL, FREEPHONE, OTHER)); + + private LineType(String value) { + super(value); + } + + public static Stream values() { + return ENUM_SUPPORT.values(); + } + + public static LineType from(String value) { + return ENUM_SUPPORT.from(value); + } + + public static String valueOf(LineType e) { + return ENUM_SUPPORT.valueOf(e); + } +} diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/response/NumberLookupResponse.java b/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/response/NumberLookupResponse.java new file mode 100644 index 000000000..cf692ca44 --- /dev/null +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/response/NumberLookupResponse.java @@ -0,0 +1,150 @@ +/* + * Number Lookup Api v2 + * + * OpenAPI document version: 0.1.0 + * Contact: support@sinch.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * Do not edit the class manually. + */ + +package com.sinch.sdk.domains.numberlookup.models.v2.response; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; + +/** NumberLookupResponse */ +@JsonDeserialize(builder = NumberLookupResponseImpl.Builder.class) +public interface NumberLookupResponse { + + /** + * An object containing information about the line type of the number. + * + * @return line + */ + Line getLine(); + + /** + * An object containing information about the SimSwap verification performed on the number. + * + * @return simSwap + */ + SimSwap getSimSwap(); + + /** + * An object containing information about the VoIP detection performed on the number. + * + * @return voIPDetection + */ + VoIPDetection getVoIPDetection(); + + /** + * An object containing information whether number is disconnected. + * + * @return rnd + */ + Rnd getRnd(); + + /** + * ISO 3166-1 alpha-2 two-letter country identifier + * + * @return countryCode + */ + String getCountryCode(); + + /** + * The identifier for a trace. + * + * @return traceId + */ + String getTraceId(); + + /** + * Requested MSISDN in E.164 format. + * + * @return number + */ + String getNumber(); + + /** + * Getting builder + * + * @return New Builder instance + */ + static Builder builder() { + return new NumberLookupResponseImpl.Builder(); + } + + /** Dedicated Builder */ + interface Builder { + + /** + * see getter + * + * @param line see getter + * @return Current builder + * @see #getLine + */ + Builder setLine(Line line); + + /** + * see getter + * + * @param simSwap see getter + * @return Current builder + * @see #getSimSwap + */ + Builder setSimSwap(SimSwap simSwap); + + /** + * see getter + * + * @param voIPDetection see getter + * @return Current builder + * @see #getVoIPDetection + */ + Builder setVoIPDetection(VoIPDetection voIPDetection); + + /** + * see getter + * + * @param rnd see getter + * @return Current builder + * @see #getRnd + */ + Builder setRnd(Rnd rnd); + + /** + * see getter + * + * @param countryCode see getter + * @return Current builder + * @see #getCountryCode + */ + Builder setCountryCode(String countryCode); + + /** + * see getter + * + * @param traceId see getter + * @return Current builder + * @see #getTraceId + */ + Builder setTraceId(String traceId); + + /** + * see getter + * + * @param number see getter + * @return Current builder + * @see #getNumber + */ + Builder setNumber(String number); + + /** + * Create instance + * + * @return The instance build with current builder values + */ + NumberLookupResponse build(); + } +} diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/response/NumberLookupResponseImpl.java b/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/response/NumberLookupResponseImpl.java new file mode 100644 index 000000000..a7168f17e --- /dev/null +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/response/NumberLookupResponseImpl.java @@ -0,0 +1,256 @@ +package com.sinch.sdk.domains.numberlookup.models.v2.response; + +import com.fasterxml.jackson.annotation.JsonFilter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; +import com.sinch.sdk.core.models.OptionalValue; +import java.util.Objects; + +@JsonPropertyOrder({ + NumberLookupResponseImpl.JSON_PROPERTY_LINE, + NumberLookupResponseImpl.JSON_PROPERTY_SIM_SWAP, + NumberLookupResponseImpl.JSON_PROPERTY_VO_I_P_DETECTION, + NumberLookupResponseImpl.JSON_PROPERTY_RND, + NumberLookupResponseImpl.JSON_PROPERTY_COUNTRY_CODE, + NumberLookupResponseImpl.JSON_PROPERTY_TRACE_ID, + NumberLookupResponseImpl.JSON_PROPERTY_NUMBER +}) +@JsonFilter("uninitializedFilter") +@JsonInclude(value = JsonInclude.Include.CUSTOM) +public class NumberLookupResponseImpl implements NumberLookupResponse { + private static final long serialVersionUID = 1L; + + public static final String JSON_PROPERTY_LINE = "line"; + + private OptionalValue line; + + public static final String JSON_PROPERTY_SIM_SWAP = "simSwap"; + + private OptionalValue simSwap; + + public static final String JSON_PROPERTY_VO_I_P_DETECTION = "voIPDetection"; + + private OptionalValue voIPDetection; + + public static final String JSON_PROPERTY_RND = "rnd"; + + private OptionalValue rnd; + + public static final String JSON_PROPERTY_COUNTRY_CODE = "countryCode"; + + private OptionalValue countryCode; + + public static final String JSON_PROPERTY_TRACE_ID = "traceId"; + + private OptionalValue traceId; + + public static final String JSON_PROPERTY_NUMBER = "number"; + + private OptionalValue number; + + public NumberLookupResponseImpl() {} + + protected NumberLookupResponseImpl( + OptionalValue line, + OptionalValue simSwap, + OptionalValue voIPDetection, + OptionalValue rnd, + OptionalValue countryCode, + OptionalValue traceId, + OptionalValue number) { + this.line = line; + this.simSwap = simSwap; + this.voIPDetection = voIPDetection; + this.rnd = rnd; + this.countryCode = countryCode; + this.traceId = traceId; + this.number = number; + } + + @JsonIgnore + public Line getLine() { + return line.orElse(null); + } + + @JsonProperty(JSON_PROPERTY_LINE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public OptionalValue line() { + return line; + } + + @JsonIgnore + public SimSwap getSimSwap() { + return simSwap.orElse(null); + } + + @JsonProperty(JSON_PROPERTY_SIM_SWAP) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public OptionalValue simSwap() { + return simSwap; + } + + @JsonIgnore + public VoIPDetection getVoIPDetection() { + return voIPDetection.orElse(null); + } + + @JsonProperty(JSON_PROPERTY_VO_I_P_DETECTION) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public OptionalValue voIPDetection() { + return voIPDetection; + } + + @JsonIgnore + public Rnd getRnd() { + return rnd.orElse(null); + } + + @JsonProperty(JSON_PROPERTY_RND) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public OptionalValue rnd() { + return rnd; + } + + @JsonIgnore + public String getCountryCode() { + return countryCode.orElse(null); + } + + @JsonProperty(JSON_PROPERTY_COUNTRY_CODE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public OptionalValue countryCode() { + return countryCode; + } + + @JsonIgnore + public String getTraceId() { + return traceId.orElse(null); + } + + @JsonProperty(JSON_PROPERTY_TRACE_ID) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public OptionalValue traceId() { + return traceId; + } + + @JsonIgnore + public String getNumber() { + return number.orElse(null); + } + + @JsonProperty(JSON_PROPERTY_NUMBER) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public OptionalValue number() { + return number; + } + + /** Return true if this NumberLookupResponse object is equal to o. */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + NumberLookupResponseImpl numberLookupResponse = (NumberLookupResponseImpl) o; + return Objects.equals(this.line, numberLookupResponse.line) + && Objects.equals(this.simSwap, numberLookupResponse.simSwap) + && Objects.equals(this.voIPDetection, numberLookupResponse.voIPDetection) + && Objects.equals(this.rnd, numberLookupResponse.rnd) + && Objects.equals(this.countryCode, numberLookupResponse.countryCode) + && Objects.equals(this.traceId, numberLookupResponse.traceId) + && Objects.equals(this.number, numberLookupResponse.number); + } + + @Override + public int hashCode() { + return Objects.hash(line, simSwap, voIPDetection, rnd, countryCode, traceId, number); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class NumberLookupResponseImpl {\n"); + sb.append(" line: ").append(toIndentedString(line)).append("\n"); + sb.append(" simSwap: ").append(toIndentedString(simSwap)).append("\n"); + sb.append(" voIPDetection: ").append(toIndentedString(voIPDetection)).append("\n"); + sb.append(" rnd: ").append(toIndentedString(rnd)).append("\n"); + sb.append(" countryCode: ").append(toIndentedString(countryCode)).append("\n"); + sb.append(" traceId: ").append(toIndentedString(traceId)).append("\n"); + sb.append(" number: ").append(toIndentedString(number)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + @JsonPOJOBuilder(withPrefix = "set") + static class Builder implements NumberLookupResponse.Builder { + OptionalValue line = OptionalValue.empty(); + OptionalValue simSwap = OptionalValue.empty(); + OptionalValue voIPDetection = OptionalValue.empty(); + OptionalValue rnd = OptionalValue.empty(); + OptionalValue countryCode = OptionalValue.empty(); + OptionalValue traceId = OptionalValue.empty(); + OptionalValue number = OptionalValue.empty(); + + @JsonProperty(JSON_PROPERTY_LINE) + public Builder setLine(Line line) { + this.line = OptionalValue.of(line); + return this; + } + + @JsonProperty(JSON_PROPERTY_SIM_SWAP) + public Builder setSimSwap(SimSwap simSwap) { + this.simSwap = OptionalValue.of(simSwap); + return this; + } + + @JsonProperty(JSON_PROPERTY_VO_I_P_DETECTION) + public Builder setVoIPDetection(VoIPDetection voIPDetection) { + this.voIPDetection = OptionalValue.of(voIPDetection); + return this; + } + + @JsonProperty(JSON_PROPERTY_RND) + public Builder setRnd(Rnd rnd) { + this.rnd = OptionalValue.of(rnd); + return this; + } + + @JsonProperty(JSON_PROPERTY_COUNTRY_CODE) + public Builder setCountryCode(String countryCode) { + this.countryCode = OptionalValue.of(countryCode); + return this; + } + + @JsonProperty(JSON_PROPERTY_TRACE_ID) + public Builder setTraceId(String traceId) { + this.traceId = OptionalValue.of(traceId); + return this; + } + + @JsonProperty(JSON_PROPERTY_NUMBER) + public Builder setNumber(String number) { + this.number = OptionalValue.of(number); + return this; + } + + public NumberLookupResponse build() { + return new NumberLookupResponseImpl( + line, simSwap, voIPDetection, rnd, countryCode, traceId, number); + } + } +} diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/response/Rnd.java b/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/response/Rnd.java new file mode 100644 index 000000000..28dfb1be8 --- /dev/null +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/response/Rnd.java @@ -0,0 +1,71 @@ +/* + * Number Lookup Api v2 + * + * OpenAPI document version: 0.1.0 + * Contact: support@sinch.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * Do not edit the class manually. + */ + +package com.sinch.sdk.domains.numberlookup.models.v2.response; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.sinch.sdk.domains.numberlookup.models.v2.errors.LookupError; + +/** Rnd */ +@JsonDeserialize(builder = RndImpl.Builder.class) +public interface Rnd { + + /** + * Provides information whether the number was disconnected after provided last contact date. + * + * @return disconnected + */ + Boolean getDisconnected(); + + /** + * Get error + * + * @return error + */ + LookupError getError(); + + /** + * Getting builder + * + * @return New Builder instance + */ + static Builder builder() { + return new RndImpl.Builder(); + } + + /** Dedicated Builder */ + interface Builder { + + /** + * see getter + * + * @param disconnected see getter + * @return Current builder + * @see #getDisconnected + */ + Builder setDisconnected(Boolean disconnected); + + /** + * see getter + * + * @param error see getter + * @return Current builder + * @see #getError + */ + Builder setError(LookupError error); + + /** + * Create instance + * + * @return The instance build with current builder values + */ + Rnd build(); + } +} diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/response/RndImpl.java b/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/response/RndImpl.java new file mode 100644 index 000000000..5b8d83a71 --- /dev/null +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/response/RndImpl.java @@ -0,0 +1,116 @@ +package com.sinch.sdk.domains.numberlookup.models.v2.response; + +import com.fasterxml.jackson.annotation.JsonFilter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; +import com.sinch.sdk.core.models.OptionalValue; +import com.sinch.sdk.domains.numberlookup.models.v2.errors.LookupError; +import java.util.Objects; + +@JsonPropertyOrder({RndImpl.JSON_PROPERTY_DISCONNECTED, RndImpl.JSON_PROPERTY_ERROR}) +@JsonFilter("uninitializedFilter") +@JsonInclude(value = JsonInclude.Include.CUSTOM) +public class RndImpl implements Rnd { + private static final long serialVersionUID = 1L; + + public static final String JSON_PROPERTY_DISCONNECTED = "disconnected"; + + private OptionalValue disconnected; + + public static final String JSON_PROPERTY_ERROR = "error"; + + private OptionalValue error; + + public RndImpl() {} + + protected RndImpl(OptionalValue disconnected, OptionalValue error) { + this.disconnected = disconnected; + this.error = error; + } + + @JsonIgnore + public Boolean getDisconnected() { + return disconnected.orElse(null); + } + + @JsonProperty(JSON_PROPERTY_DISCONNECTED) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public OptionalValue disconnected() { + return disconnected; + } + + @JsonIgnore + public LookupError getError() { + return error.orElse(null); + } + + @JsonProperty(JSON_PROPERTY_ERROR) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public OptionalValue error() { + return error; + } + + /** Return true if this RndResponse object is equal to o. */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + RndImpl rndResponse = (RndImpl) o; + return Objects.equals(this.disconnected, rndResponse.disconnected) + && Objects.equals(this.error, rndResponse.error); + } + + @Override + public int hashCode() { + return Objects.hash(disconnected, error); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class RndImpl {\n"); + sb.append(" disconnected: ").append(toIndentedString(disconnected)).append("\n"); + sb.append(" error: ").append(toIndentedString(error)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + @JsonPOJOBuilder(withPrefix = "set") + static class Builder implements Rnd.Builder { + OptionalValue disconnected = OptionalValue.empty(); + OptionalValue error = OptionalValue.empty(); + + @JsonProperty(JSON_PROPERTY_DISCONNECTED) + public Builder setDisconnected(Boolean disconnected) { + this.disconnected = OptionalValue.of(disconnected); + return this; + } + + @JsonProperty(JSON_PROPERTY_ERROR) + public Builder setError(LookupError error) { + this.error = OptionalValue.of(error); + return this; + } + + public Rnd build() { + return new RndImpl(disconnected, error); + } + } +} diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/response/SimSwap.java b/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/response/SimSwap.java new file mode 100644 index 000000000..ad7872612 --- /dev/null +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/response/SimSwap.java @@ -0,0 +1,87 @@ +/* + * Number Lookup Api v2 + * + * OpenAPI document version: 0.1.0 + * Contact: support@sinch.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * Do not edit the class manually. + */ + +package com.sinch.sdk.domains.numberlookup.models.v2.response; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.sinch.sdk.domains.numberlookup.models.v2.errors.LookupError; + +/** SimSwap */ +@JsonDeserialize(builder = SimSwapImpl.Builder.class) +public interface SimSwap { + + /** + * Indicates whether SIM was changed. + * + * @return swapped + */ + Boolean getSwapped(); + + /** + * Threshold for sim swap check. + * + * @return swapPeriod + */ + SwapPeriodType getSwapPeriod(); + + /** + * Get error + * + * @return error + */ + LookupError getError(); + + /** + * Getting builder + * + * @return New Builder instance + */ + static Builder builder() { + return new SimSwapImpl.Builder(); + } + + /** Dedicated Builder */ + interface Builder { + + /** + * see getter + * + * @param swapped see getter + * @return Current builder + * @see #getSwapped + */ + Builder setSwapped(Boolean swapped); + + /** + * see getter + * + * @param swapPeriod see getter + * @return Current builder + * @see #getSwapPeriod + */ + Builder setSwapPeriod(SwapPeriodType swapPeriod); + + /** + * see getter + * + * @param error see getter + * @return Current builder + * @see #getError + */ + Builder setError(LookupError error); + + /** + * Create instance + * + * @return The instance build with current builder values + */ + SimSwap build(); + } +} diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/response/SimSwapImpl.java b/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/response/SimSwapImpl.java new file mode 100644 index 000000000..e0ab9aab4 --- /dev/null +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/response/SimSwapImpl.java @@ -0,0 +1,148 @@ +package com.sinch.sdk.domains.numberlookup.models.v2.response; + +import com.fasterxml.jackson.annotation.JsonFilter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; +import com.sinch.sdk.core.models.OptionalValue; +import com.sinch.sdk.domains.numberlookup.models.v2.errors.LookupError; +import java.util.Objects; + +@JsonPropertyOrder({ + SimSwapImpl.JSON_PROPERTY_SWAPPED, + SimSwapImpl.JSON_PROPERTY_SWAP_PERIOD, + SimSwapImpl.JSON_PROPERTY_ERROR +}) +@JsonFilter("uninitializedFilter") +@JsonInclude(value = JsonInclude.Include.CUSTOM) +public class SimSwapImpl implements SimSwap { + private static final long serialVersionUID = 1L; + + public static final String JSON_PROPERTY_SWAPPED = "swapped"; + + private OptionalValue swapped; + + public static final String JSON_PROPERTY_SWAP_PERIOD = "swapPeriod"; + + private OptionalValue swapPeriod; + + public static final String JSON_PROPERTY_ERROR = "error"; + + private OptionalValue error; + + public SimSwapImpl() {} + + protected SimSwapImpl( + OptionalValue swapped, + OptionalValue swapPeriod, + OptionalValue error) { + this.swapped = swapped; + this.swapPeriod = swapPeriod; + this.error = error; + } + + @JsonIgnore + public Boolean getSwapped() { + return swapped.orElse(null); + } + + @JsonProperty(JSON_PROPERTY_SWAPPED) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public OptionalValue swapped() { + return swapped; + } + + @JsonIgnore + public SwapPeriodType getSwapPeriod() { + return swapPeriod.orElse(null); + } + + @JsonProperty(JSON_PROPERTY_SWAP_PERIOD) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public OptionalValue swapPeriod() { + return swapPeriod; + } + + @JsonIgnore + public LookupError getError() { + return error.orElse(null); + } + + @JsonProperty(JSON_PROPERTY_ERROR) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public OptionalValue error() { + return error; + } + + /** Return true if this SimSwapResponse object is equal to o. */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + SimSwapImpl simSwapResponse = (SimSwapImpl) o; + return Objects.equals(this.swapped, simSwapResponse.swapped) + && Objects.equals(this.swapPeriod, simSwapResponse.swapPeriod) + && Objects.equals(this.error, simSwapResponse.error); + } + + @Override + public int hashCode() { + return Objects.hash(swapped, swapPeriod, error); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class SimSwapImpl {\n"); + sb.append(" swapped: ").append(toIndentedString(swapped)).append("\n"); + sb.append(" swapPeriod: ").append(toIndentedString(swapPeriod)).append("\n"); + sb.append(" error: ").append(toIndentedString(error)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + @JsonPOJOBuilder(withPrefix = "set") + static class Builder implements SimSwap.Builder { + OptionalValue swapped = OptionalValue.empty(); + OptionalValue swapPeriod = OptionalValue.empty(); + OptionalValue error = OptionalValue.empty(); + + @JsonProperty(JSON_PROPERTY_SWAPPED) + public Builder setSwapped(Boolean swapped) { + this.swapped = OptionalValue.of(swapped); + return this; + } + + @JsonProperty(JSON_PROPERTY_SWAP_PERIOD) + public Builder setSwapPeriod(SwapPeriodType swapPeriod) { + this.swapPeriod = OptionalValue.of(swapPeriod); + return this; + } + + @JsonProperty(JSON_PROPERTY_ERROR) + public Builder setError(LookupError error) { + this.error = OptionalValue.of(error); + return this; + } + + public SimSwap build() { + return new SimSwapImpl(swapped, swapPeriod, error); + } + } +} diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/response/SwapPeriodType.java b/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/response/SwapPeriodType.java new file mode 100644 index 000000000..c5a1de7b2 --- /dev/null +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/response/SwapPeriodType.java @@ -0,0 +1,63 @@ +package com.sinch.sdk.domains.numberlookup.models.v2.response; + +import com.sinch.sdk.core.utils.EnumDynamic; +import com.sinch.sdk.core.utils.EnumSupportDynamic; +import java.util.Arrays; +import java.util.stream.Stream; + +/** */ +public class SwapPeriodType extends EnumDynamic { + + /** Undefined */ + public static final SwapPeriodType UNDEFINED = new SwapPeriodType("Undefined"); + + /** 4 Hours */ + public static final SwapPeriodType SP4_H = new SwapPeriodType("SP4H"); + + /** 12 Hours */ + public static final SwapPeriodType SP12_H = new SwapPeriodType("SP12H"); + + /** 24 Hours */ + public static final SwapPeriodType SP24_H = new SwapPeriodType("SP24H"); + + /** 48 Hours */ + public static final SwapPeriodType SP48_H = new SwapPeriodType("SP48H"); + + /** 5 Days */ + public static final SwapPeriodType SP5_D = new SwapPeriodType("SP5D"); + + /** 7 Days */ + public static final SwapPeriodType SP7_D = new SwapPeriodType("SP7D"); + + /** 14 Days */ + public static final SwapPeriodType SP14_D = new SwapPeriodType("SP14D"); + + /** 30 Days */ + public static final SwapPeriodType SP30_D = new SwapPeriodType("SP30D"); + + /** Maximum */ + public static final SwapPeriodType SPMAX = new SwapPeriodType("SPMAX"); + + private static final EnumSupportDynamic ENUM_SUPPORT = + new EnumSupportDynamic<>( + SwapPeriodType.class, + SwapPeriodType::new, + Arrays.asList( + UNDEFINED, SP4_H, SP12_H, SP24_H, SP48_H, SP5_D, SP7_D, SP14_D, SP30_D, SPMAX)); + + private SwapPeriodType(String value) { + super(value); + } + + public static Stream values() { + return ENUM_SUPPORT.values(); + } + + public static SwapPeriodType from(String value) { + return ENUM_SUPPORT.from(value); + } + + public static String valueOf(SwapPeriodType e) { + return ENUM_SUPPORT.valueOf(e); + } +} diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/response/VoIPDetection.java b/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/response/VoIPDetection.java new file mode 100644 index 000000000..f5814dc5c --- /dev/null +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/response/VoIPDetection.java @@ -0,0 +1,71 @@ +/* + * Number Lookup Api v2 + * + * OpenAPI document version: 0.1.0 + * Contact: support@sinch.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * Do not edit the class manually. + */ + +package com.sinch.sdk.domains.numberlookup.models.v2.response; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.sinch.sdk.domains.numberlookup.models.v2.errors.LookupError; + +/** VoIPDetection */ +@JsonDeserialize(builder = VoIPDetectionImpl.Builder.class) +public interface VoIPDetection { + + /** + * Probability of number being VoIP based on the AI analysis. + * + * @return probability + */ + VoIPProbabilityType getProbability(); + + /** + * Get error + * + * @return error + */ + LookupError getError(); + + /** + * Getting builder + * + * @return New Builder instance + */ + static Builder builder() { + return new VoIPDetectionImpl.Builder(); + } + + /** Dedicated Builder */ + interface Builder { + + /** + * see getter + * + * @param probability see getter + * @return Current builder + * @see #getProbability + */ + Builder setProbability(VoIPProbabilityType probability); + + /** + * see getter + * + * @param error see getter + * @return Current builder + * @see #getError + */ + Builder setError(LookupError error); + + /** + * Create instance + * + * @return The instance build with current builder values + */ + VoIPDetection build(); + } +} diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/response/VoIPDetectionImpl.java b/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/response/VoIPDetectionImpl.java new file mode 100644 index 000000000..e6ebe85d9 --- /dev/null +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/response/VoIPDetectionImpl.java @@ -0,0 +1,120 @@ +package com.sinch.sdk.domains.numberlookup.models.v2.response; + +import com.fasterxml.jackson.annotation.JsonFilter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; +import com.sinch.sdk.core.models.OptionalValue; +import com.sinch.sdk.domains.numberlookup.models.v2.errors.LookupError; +import java.util.Objects; + +@JsonPropertyOrder({ + VoIPDetectionImpl.JSON_PROPERTY_PROBABILITY, + VoIPDetectionImpl.JSON_PROPERTY_ERROR +}) +@JsonFilter("uninitializedFilter") +@JsonInclude(value = JsonInclude.Include.CUSTOM) +public class VoIPDetectionImpl implements VoIPDetection { + private static final long serialVersionUID = 1L; + + public static final String JSON_PROPERTY_PROBABILITY = "probability"; + + private OptionalValue probability; + + public static final String JSON_PROPERTY_ERROR = "error"; + + private OptionalValue error; + + public VoIPDetectionImpl() {} + + protected VoIPDetectionImpl( + OptionalValue probability, OptionalValue error) { + this.probability = probability; + this.error = error; + } + + @JsonIgnore + public VoIPProbabilityType getProbability() { + return probability.orElse(null); + } + + @JsonProperty(JSON_PROPERTY_PROBABILITY) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public OptionalValue probability() { + return probability; + } + + @JsonIgnore + public LookupError getError() { + return error.orElse(null); + } + + @JsonProperty(JSON_PROPERTY_ERROR) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public OptionalValue error() { + return error; + } + + /** Return true if this VoIPDetectionResponse object is equal to o. */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + VoIPDetectionImpl voIPDetectionResponse = (VoIPDetectionImpl) o; + return Objects.equals(this.probability, voIPDetectionResponse.probability) + && Objects.equals(this.error, voIPDetectionResponse.error); + } + + @Override + public int hashCode() { + return Objects.hash(probability, error); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class VoIPDetectionImpl {\n"); + sb.append(" probability: ").append(toIndentedString(probability)).append("\n"); + sb.append(" error: ").append(toIndentedString(error)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + @JsonPOJOBuilder(withPrefix = "set") + static class Builder implements VoIPDetection.Builder { + OptionalValue probability = OptionalValue.empty(); + OptionalValue error = OptionalValue.empty(); + + @JsonProperty(JSON_PROPERTY_PROBABILITY) + public Builder setProbability(VoIPProbabilityType probability) { + this.probability = OptionalValue.of(probability); + return this; + } + + @JsonProperty(JSON_PROPERTY_ERROR) + public Builder setError(LookupError error) { + this.error = OptionalValue.of(error); + return this; + } + + public VoIPDetection build() { + return new VoIPDetectionImpl(probability, error); + } + } +} diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/response/VoIPProbabilityType.java b/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/response/VoIPProbabilityType.java new file mode 100644 index 000000000..d6e81a332 --- /dev/null +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/numberlookup/models/v2/response/VoIPProbabilityType.java @@ -0,0 +1,44 @@ +package com.sinch.sdk.domains.numberlookup.models.v2.response; + +import com.sinch.sdk.core.utils.EnumDynamic; +import com.sinch.sdk.core.utils.EnumSupportDynamic; +import java.util.Arrays; +import java.util.stream.Stream; + +/** */ +public class VoIPProbabilityType extends EnumDynamic { + + /** Undefined */ + public static final VoIPProbabilityType UNKNOWN = new VoIPProbabilityType("Unknown"); + + /** Low */ + public static final VoIPProbabilityType LOW = new VoIPProbabilityType("Low"); + + /** Likely */ + public static final VoIPProbabilityType LIKELY = new VoIPProbabilityType("Likely"); + + /** High */ + public static final VoIPProbabilityType HIGH = new VoIPProbabilityType("High"); + + private static final EnumSupportDynamic ENUM_SUPPORT = + new EnumSupportDynamic<>( + VoIPProbabilityType.class, + VoIPProbabilityType::new, + Arrays.asList(UNKNOWN, LOW, LIKELY, HIGH)); + + private VoIPProbabilityType(String value) { + super(value); + } + + public static Stream values() { + return ENUM_SUPPORT.values(); + } + + public static VoIPProbabilityType from(String value) { + return ENUM_SUPPORT.from(value); + } + + public static String valueOf(VoIPProbabilityType e) { + return ENUM_SUPPORT.valueOf(e); + } +} diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/numbers/api/v1/adapters/ActiveNumberServiceImpl.java b/openapi-contracts/src/main/com/sinch/sdk/domains/numbers/api/v1/adapters/ActiveNumberServiceImpl.java index 21d74b1d4..e8a54731a 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/numbers/api/v1/adapters/ActiveNumberServiceImpl.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/numbers/api/v1/adapters/ActiveNumberServiceImpl.java @@ -41,6 +41,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.function.Function; import java.util.logging.Logger; public class ActiveNumberServiceImpl @@ -84,11 +85,14 @@ public ActiveNumbersListResponse list(ActiveNumbersListQueryParameters queryPara LOGGER.finest("[list]" + " " + "queryParameter: " + queryParameter); HttpRequest httpRequest = listRequestBuilder(queryParameter); - return _fetchListPage(queryParameter, httpRequest); + return _fetchListPage( + (queryParameters) -> listRequestBuilder(queryParameters), queryParameter, httpRequest); } private ActiveNumbersListResponse _fetchListPage( - ActiveNumbersListQueryParameters queryParameter, HttpRequest httpRequest) + Function requestBuilder, + ActiveNumbersListQueryParameters queryParameter, + HttpRequest httpRequest) throws ApiException { HttpResponse response = httpClient.invokeAPI( @@ -105,10 +109,10 @@ private ActiveNumbersListResponse _fetchListPage( ActiveNumbersListQueryParameters.builder(queryParameter).setPageToken(nextToken).build(); final HttpRequest nextHttpRequest = - !StringUtil.isEmpty(nextToken) ? listRequestBuilder(nextParameters) : null; + !StringUtil.isEmpty(nextToken) ? requestBuilder.apply(nextParameters) : null; return new ActiveNumbersListResponse( - () -> _fetchListPage(nextParameters, nextHttpRequest), + () -> _fetchListPage(requestBuilder, nextParameters, nextHttpRequest), new Page<>(deserialized.getActiveNumbers(), new PageNavigator<>(nextHttpRequest))); } // fallback to default errors handling: diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/numbers/api/v1/adapters/AvailableNumberServiceImpl.java b/openapi-contracts/src/main/com/sinch/sdk/domains/numbers/api/v1/adapters/AvailableNumberServiceImpl.java index d12668042..8e8d48791 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/numbers/api/v1/adapters/AvailableNumberServiceImpl.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/numbers/api/v1/adapters/AvailableNumberServiceImpl.java @@ -38,6 +38,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.function.Function; import java.util.logging.Logger; public class AvailableNumberServiceImpl @@ -284,11 +285,16 @@ public AvailableNumbersListResponse searchForAvailableNumbers( LOGGER.finest("[searchForAvailableNumbers]" + " " + "queryParameter: " + queryParameter); HttpRequest httpRequest = searchForAvailableNumbersRequestBuilder(queryParameter); - return _fetchSearchForAvailableNumbersPage(queryParameter, httpRequest); + return _fetchSearchForAvailableNumbersPage( + (queryParameters) -> searchForAvailableNumbersRequestBuilder(queryParameters), + queryParameter, + httpRequest); } private AvailableNumbersListResponse _fetchSearchForAvailableNumbersPage( - AvailableNumbersListQueryParameters queryParameter, HttpRequest httpRequest) + Function requestBuilder, + AvailableNumbersListQueryParameters queryParameter, + HttpRequest httpRequest) throws ApiException { HttpResponse response = httpClient.invokeAPI( diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/numbers/api/v1/adapters/AvailableRegionsServiceImpl.java b/openapi-contracts/src/main/com/sinch/sdk/domains/numbers/api/v1/adapters/AvailableRegionsServiceImpl.java index 8e2ce0c64..2d94e25a3 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/numbers/api/v1/adapters/AvailableRegionsServiceImpl.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/numbers/api/v1/adapters/AvailableRegionsServiceImpl.java @@ -34,6 +34,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.function.Function; import java.util.logging.Logger; public class AvailableRegionsServiceImpl @@ -74,11 +75,14 @@ public AvailableRegionsListResponse list(AvailableRegionsListQueryParameters que LOGGER.finest("[list]" + " " + "queryParameter: " + queryParameter); HttpRequest httpRequest = listRequestBuilder(queryParameter); - return _fetchListPage(queryParameter, httpRequest); + return _fetchListPage( + (queryParameters) -> listRequestBuilder(queryParameters), queryParameter, httpRequest); } private AvailableRegionsListResponse _fetchListPage( - AvailableRegionsListQueryParameters queryParameter, HttpRequest httpRequest) + Function requestBuilder, + AvailableRegionsListQueryParameters queryParameter, + HttpRequest httpRequest) throws ApiException { HttpResponse response = httpClient.invokeAPI( diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/numbers/models/v1/errors/BadRequest.java b/openapi-contracts/src/main/com/sinch/sdk/domains/numbers/models/v1/errors/BadRequest.java index d852e6610..243f28b26 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/numbers/models/v1/errors/BadRequest.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/numbers/models/v1/errors/BadRequest.java @@ -23,6 +23,7 @@ public interface BadRequest { /** Gets or Sets type */ public class TypeEnum extends EnumDynamic { + /** The request was malformed in some way. */ public static final TypeEnum BAD_REQUEST = new TypeEnum("BadRequest"); private static final EnumSupportDynamic ENUM_SUPPORT = diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/numbers/models/v1/errors/InternalError.java b/openapi-contracts/src/main/com/sinch/sdk/domains/numbers/models/v1/errors/InternalError.java index cf929c17b..4c77289a8 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/numbers/models/v1/errors/InternalError.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/numbers/models/v1/errors/InternalError.java @@ -23,6 +23,7 @@ public interface InternalError { /** Gets or Sets code */ public class CodeEnum extends EnumDynamic { + /** The HTTP status code for an internal server error. */ public static final CodeEnum NUMBER_500 = new CodeEnum(500); private static final EnumSupportDynamic ENUM_SUPPORT = @@ -61,7 +62,10 @@ public static Integer valueOf(CodeEnum e) { /** Gets or Sets status */ public class StatusEnum extends EnumDynamic { + /** An internal server error. */ public static final StatusEnum INTERNAL = new StatusEnum("INTERNAL"); + + /** Some unknown error. */ public static final StatusEnum UNKNOWN = new StatusEnum("UNKNOWN"); private static final EnumSupportDynamic ENUM_SUPPORT = diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/numbers/models/v1/errors/InvalidArgument.java b/openapi-contracts/src/main/com/sinch/sdk/domains/numbers/models/v1/errors/InvalidArgument.java index 002733b2d..5e0e5d41e 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/numbers/models/v1/errors/InvalidArgument.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/numbers/models/v1/errors/InvalidArgument.java @@ -23,6 +23,7 @@ public interface InvalidArgument { /** Gets or Sets code */ public class CodeEnum extends EnumDynamic { + /** The HTTP status code for invalid arguments. */ public static final CodeEnum NUMBER_400 = new CodeEnum(400); private static final EnumSupportDynamic ENUM_SUPPORT = @@ -61,6 +62,7 @@ public static Integer valueOf(CodeEnum e) { /** Gets or Sets status */ public class StatusEnum extends EnumDynamic { + /** The request contained invalid arguments. */ public static final StatusEnum INVALID_ARGUMENT = new StatusEnum("INVALID_ARGUMENT"); private static final EnumSupportDynamic ENUM_SUPPORT = diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/numbers/models/v1/errors/NotFound.java b/openapi-contracts/src/main/com/sinch/sdk/domains/numbers/models/v1/errors/NotFound.java index 43351bc95..1d6bb1416 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/numbers/models/v1/errors/NotFound.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/numbers/models/v1/errors/NotFound.java @@ -23,6 +23,7 @@ public interface NotFound { /** Gets or Sets code */ public class CodeEnum extends EnumDynamic { + /** The HTTP status code for a resource not found. */ public static final CodeEnum NUMBER_404 = new CodeEnum(404); private static final EnumSupportDynamic ENUM_SUPPORT = @@ -61,6 +62,7 @@ public static Integer valueOf(CodeEnum e) { /** Gets or Sets status */ public class StatusEnum extends EnumDynamic { + /** The request resource could not be found. */ public static final StatusEnum NOT_FOUND = new StatusEnum("NOT_FOUND"); private static final EnumSupportDynamic ENUM_SUPPORT = diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/numbers/models/v1/errors/internal/InternalErrorError.java b/openapi-contracts/src/main/com/sinch/sdk/domains/numbers/models/v1/errors/internal/InternalErrorError.java index a60ecf0b4..b013639f2 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/numbers/models/v1/errors/internal/InternalErrorError.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/numbers/models/v1/errors/internal/InternalErrorError.java @@ -23,6 +23,7 @@ public interface InternalErrorError { /** Gets or Sets code */ public class CodeEnum extends EnumDynamic { + /** The HTTP status code for an internal server error. */ public static final CodeEnum NUMBER_500 = new CodeEnum(500); private static final EnumSupportDynamic ENUM_SUPPORT = @@ -61,7 +62,10 @@ public static Integer valueOf(CodeEnum e) { /** Gets or Sets status */ public class StatusEnum extends EnumDynamic { + /** An internal server error. */ public static final StatusEnum INTERNAL = new StatusEnum("INTERNAL"); + + /** Some unknown error. */ public static final StatusEnum UNKNOWN = new StatusEnum("UNKNOWN"); private static final EnumSupportDynamic ENUM_SUPPORT = diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/numbers/models/v1/errors/internal/InvalidArgumentError.java b/openapi-contracts/src/main/com/sinch/sdk/domains/numbers/models/v1/errors/internal/InvalidArgumentError.java index 6c1ef6f4d..85e04a439 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/numbers/models/v1/errors/internal/InvalidArgumentError.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/numbers/models/v1/errors/internal/InvalidArgumentError.java @@ -24,6 +24,7 @@ public interface InvalidArgumentError { /** Gets or Sets code */ public class CodeEnum extends EnumDynamic { + /** The HTTP status code for invalid arguments. */ public static final CodeEnum NUMBER_400 = new CodeEnum(400); private static final EnumSupportDynamic ENUM_SUPPORT = @@ -62,6 +63,7 @@ public static Integer valueOf(CodeEnum e) { /** Gets or Sets status */ public class StatusEnum extends EnumDynamic { + /** The request contained invalid arguments. */ public static final StatusEnum INVALID_ARGUMENT = new StatusEnum("INVALID_ARGUMENT"); private static final EnumSupportDynamic ENUM_SUPPORT = diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/numbers/models/v1/errors/internal/NotFoundError.java b/openapi-contracts/src/main/com/sinch/sdk/domains/numbers/models/v1/errors/internal/NotFoundError.java index 3813ceb5a..7e4f032e6 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/numbers/models/v1/errors/internal/NotFoundError.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/numbers/models/v1/errors/internal/NotFoundError.java @@ -24,6 +24,7 @@ public interface NotFoundError { /** Gets or Sets code */ public class CodeEnum extends EnumDynamic { + /** The HTTP status code for a resource not found. */ public static final CodeEnum NUMBER_404 = new CodeEnum(404); private static final EnumSupportDynamic ENUM_SUPPORT = @@ -62,6 +63,7 @@ public static Integer valueOf(CodeEnum e) { /** Gets or Sets status */ public class StatusEnum extends EnumDynamic { + /** The request resource could not be found. */ public static final StatusEnum NOT_FOUND = new StatusEnum("NOT_FOUND"); private static final EnumSupportDynamic ENUM_SUPPORT = diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/numbers/models/v1/eventdestinations/request/EventDestinationUpdateRequest.java b/openapi-contracts/src/main/com/sinch/sdk/domains/numbers/models/v1/eventdestinations/request/EventDestinationUpdateRequest.java index aeca3cb64..15c163234 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/numbers/models/v1/eventdestinations/request/EventDestinationUpdateRequest.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/numbers/models/v1/eventdestinations/request/EventDestinationUpdateRequest.java @@ -17,7 +17,9 @@ public interface EventDestinationUpdateRequest { /** - * The HMAC secret to be updated for the specified project + * The HMAC secret to be updated for the specified project. It must be between 32 and 64 + * characters, alphanumeric (A-Z, a-z, 0-9) and hyphens (-) only. Regex pattern: + * ^[a-zA-Z0-9-]{32,64}$ * * @return hmacSecret */ diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/numbers/models/v1/sinchevents/NumberSinchEvent.java b/openapi-contracts/src/main/com/sinch/sdk/domains/numbers/models/v1/sinchevents/NumberSinchEvent.java index 3492004d6..f66eb20d4 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/numbers/models/v1/sinchevents/NumberSinchEvent.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/numbers/models/v1/sinchevents/NumberSinchEvent.java @@ -59,16 +59,35 @@ public interface NumberSinchEvent { /** The type of the event. */ public class EventTypeEnum extends EnumDynamic { + /** An event that occurs when a number is linked to a Service Plan ID. */ public static final EventTypeEnum PROVISIONING_TO_SMS_PLATFORM = new EventTypeEnum("PROVISIONING_TO_SMS_PLATFORM"); + + /** An event that occurs when a number is unlinked from a Service Plan ID. */ public static final EventTypeEnum DEPROVISIONING_FROM_SMS_PLATFORM = new EventTypeEnum("DEPROVISIONING_FROM_SMS_PLATFORM"); + + /** An event that occurs when a number is linked to a Campaign. */ public static final EventTypeEnum PROVISIONING_TO_CAMPAIGN = new EventTypeEnum("PROVISIONING_TO_CAMPAIGN"); + + /** An event that occurs when a number is unlinked from a Campaign. */ public static final EventTypeEnum DEPROVISIONING_FROM_CAMPAIGN = new EventTypeEnum("DEPROVISIONING_FROM_CAMPAIGN"); + + /** An event that occurs when a number is enabled for Voice operations. */ public static final EventTypeEnum PROVISIONING_TO_VOICE_PLATFORM = new EventTypeEnum("PROVISIONING_TO_VOICE_PLATFORM"); + + /** An event that occurs when a number is disabled for Voice operations. */ + public static final EventTypeEnum DEPROVISIONING_FROM_VOICE_PLATFORM = + new EventTypeEnum("DEPROVISIONING_FROM_VOICE_PLATFORM"); + + /** An event that occurs when a Number Order transitions to a new state. */ + public static final EventTypeEnum NUMBER_ORDER_PROCESSING = + new EventTypeEnum("NUMBER_ORDER_PROCESSING"); + + /** Deprecated. Replaced by DEPROVISIONING_FROM_VOICE_PLATFORM. */ public static final EventTypeEnum DEPROVISIONING_TO_VOICE_PLATFORM = new EventTypeEnum("DEPROVISIONING_TO_VOICE_PLATFORM"); @@ -82,6 +101,8 @@ public class EventTypeEnum extends EnumDynamic { PROVISIONING_TO_CAMPAIGN, DEPROVISIONING_FROM_CAMPAIGN, PROVISIONING_TO_VOICE_PLATFORM, + DEPROVISIONING_FROM_VOICE_PLATFORM, + NUMBER_ORDER_PROCESSING, DEPROVISIONING_TO_VOICE_PLATFORM)); private EventTypeEnum(String value) { @@ -108,14 +129,34 @@ public static String valueOf(EventTypeEnum e) { */ EventTypeEnum getEventType(); - /** The status of the event. For example, SUCCEEDED or FAILED. */ + /** The status of the event or the state transition it represents. */ public class StatusEnum extends EnumDynamic { + /** The event has succeeded. */ public static final StatusEnum SUCCEEDED = new StatusEnum("SUCCEEDED"); + + /** The event has failed. */ public static final StatusEnum FAILED = new StatusEnum("FAILED"); + /** The Number Order transitioned to the IN_REVIEW state. */ + public static final StatusEnum IN_REVIEW = new StatusEnum("IN_REVIEW"); + + /** The Number Order transitioned to the BLOCKED state. */ + public static final StatusEnum BLOCKED = new StatusEnum("BLOCKED"); + + /** The Number Order transitioned to the COMPLETED state. */ + public static final StatusEnum COMPLETED = new StatusEnum("COMPLETED"); + + /** The Number Order transitioned to the REJECTED state. */ + public static final StatusEnum REJECTED = new StatusEnum("REJECTED"); + + /** The Number Order transitioned to the EXPIRED state. */ + public static final StatusEnum EXPIRED = new StatusEnum("EXPIRED"); + private static final EnumSupportDynamic ENUM_SUPPORT = new EnumSupportDynamic<>( - StatusEnum.class, StatusEnum::new, Arrays.asList(SUCCEEDED, FAILED)); + StatusEnum.class, + StatusEnum::new, + Arrays.asList(SUCCEEDED, FAILED, IN_REVIEW, BLOCKED, COMPLETED, REJECTED, EXPIRED)); private StatusEnum(String value) { super(value); @@ -135,7 +176,7 @@ public static String valueOf(StatusEnum e) { } /** - * The status of the event. For example, SUCCEEDED or FAILED. + * The status of the event or the state transition it represents. * * @return status */ @@ -147,32 +188,61 @@ public static String valueOf(StatusEnum e) { * campaign provisioning-related failures, refer to the list for the possible values. */ public class FailureCodeEnum extends EnumDynamic { + /** The specified campaign is not available. */ public static final FailureCodeEnum CAMPAIGN_NOT_AVAILABLE = new FailureCodeEnum("CAMPAIGN_NOT_AVAILABLE"); + + /** Exceeded the limit for 10DLC. */ public static final FailureCodeEnum EXCEEDED_10_DLC_LIMIT = new FailureCodeEnum("EXCEEDED_10DLC_LIMIT"); + + /** Provisioning the number failed. */ public static final FailureCodeEnum NUMBER_PROVISIONING_FAILED = new FailureCodeEnum("NUMBER_PROVISIONING_FAILED"); + + /** The third party service is unavailable. */ public static final FailureCodeEnum PARTNER_SERVICE_UNAVAILABLE = new FailureCodeEnum("PARTNER_SERVICE_UNAVAILABLE"); + + /** The campaign is not yet accepted. */ public static final FailureCodeEnum CAMPAIGN_PENDING_ACCEPTANCE = new FailureCodeEnum("CAMPAIGN_PENDING_ACCEPTANCE"); + + /** Error with MNO. */ public static final FailureCodeEnum MNO_SHARING_ERROR = new FailureCodeEnum("MNO_SHARING_ERROR"); + + /** The campaign failed to provision. */ public static final FailureCodeEnum CAMPAIGN_PROVISIONING_FAILED = new FailureCodeEnum("CAMPAIGN_PROVISIONING_FAILED"); + + /** The campaign expired. */ public static final FailureCodeEnum CAMPAIGN_EXPIRED = new FailureCodeEnum("CAMPAIGN_EXPIRED"); + + /** The campaign MNO was rejected. */ public static final FailureCodeEnum CAMPAIGN_MNO_REJECTED = new FailureCodeEnum("CAMPAIGN_MNO_REJECTED"); + + /** The campaign MNO was suspended. */ public static final FailureCodeEnum CAMPAIGN_MNO_SUSPENDED = new FailureCodeEnum("CAMPAIGN_MNO_SUSPENDED"); + + /** The campaign MNO is under review. */ public static final FailureCodeEnum CAMPAIGN_MNO_REVIEW = new FailureCodeEnum("CAMPAIGN_MNO_REVIEW"); + + /** Not enough credit in the account. */ public static final FailureCodeEnum INSUFFICIENT_BALANCE = new FailureCodeEnum("INSUFFICIENT_BALANCE"); + + /** Provisioning not allowed for mock campaigns. */ public static final FailureCodeEnum MOCK_CAMPAIGN_NOT_ALLOWED = new FailureCodeEnum("MOCK_CAMPAIGN_NOT_ALLOWED"); + + /** Toll free numbers not allowed. */ public static final FailureCodeEnum TFN_NOT_ALLOWED = new FailureCodeEnum("TFN_NOT_ALLOWED"); + + /** Invalid NNID. */ public static final FailureCodeEnum INVALID_NNID = new FailureCodeEnum("INVALID_NNID"); private static final EnumSupportDynamic ENUM_SUPPORT = @@ -222,6 +292,16 @@ public static String valueOf(FailureCodeEnum e) { */ FailureCodeEnum getFailureCode(); + /** + * If the status is FAILED, certain processes (eg. number to campaign provisioning) will have an + * internalFailureCode in the payload. The details of these codes can be found in our dedicated Provisioning + * errors documentation. + * + * @return internalFailureCode + */ + String getInternalFailureCode(); + /** * Getting builder * @@ -306,6 +386,15 @@ interface Builder { */ Builder setFailureCode(FailureCodeEnum failureCode); + /** + * see getter + * + * @param internalFailureCode see getter + * @return Current builder + * @see #getInternalFailureCode + */ + Builder setInternalFailureCode(String internalFailureCode); + /** * Create instance * diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/numbers/models/v1/sinchevents/NumberSinchEventImpl.java b/openapi-contracts/src/main/com/sinch/sdk/domains/numbers/models/v1/sinchevents/NumberSinchEventImpl.java index fb7003b65..122fd950a 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/numbers/models/v1/sinchevents/NumberSinchEventImpl.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/numbers/models/v1/sinchevents/NumberSinchEventImpl.java @@ -18,7 +18,8 @@ NumberSinchEventImpl.JSON_PROPERTY_RESOURCE_TYPE, NumberSinchEventImpl.JSON_PROPERTY_EVENT_TYPE, NumberSinchEventImpl.JSON_PROPERTY_STATUS, - NumberSinchEventImpl.JSON_PROPERTY_FAILURE_CODE + NumberSinchEventImpl.JSON_PROPERTY_FAILURE_CODE, + NumberSinchEventImpl.JSON_PROPERTY_INTERNAL_FAILURE_CODE }) @JsonFilter("uninitializedFilter") @JsonInclude(value = JsonInclude.Include.CUSTOM) @@ -57,6 +58,10 @@ public class NumberSinchEventImpl implements NumberSinchEvent { private OptionalValue failureCode; + public static final String JSON_PROPERTY_INTERNAL_FAILURE_CODE = "internalFailureCode"; + + private OptionalValue internalFailureCode; + public NumberSinchEventImpl() {} protected NumberSinchEventImpl( @@ -67,7 +72,8 @@ protected NumberSinchEventImpl( OptionalValue resourceType, OptionalValue eventType, OptionalValue status, - OptionalValue failureCode) { + OptionalValue failureCode, + OptionalValue internalFailureCode) { this.eventId = eventId; this.timestamp = timestamp; this.projectId = projectId; @@ -76,6 +82,7 @@ protected NumberSinchEventImpl( this.eventType = eventType; this.status = status; this.failureCode = failureCode; + this.internalFailureCode = internalFailureCode; } @JsonIgnore @@ -166,6 +173,17 @@ public OptionalValue failureCode() { return failureCode; } + @JsonIgnore + public String getInternalFailureCode() { + return internalFailureCode.orElse(null); + } + + @JsonProperty(JSON_PROPERTY_INTERNAL_FAILURE_CODE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public OptionalValue internalFailureCode() { + return internalFailureCode; + } + /** Return true if this CallbackPayload object is equal to o. */ @Override public boolean equals(Object o) { @@ -183,13 +201,22 @@ public boolean equals(Object o) { && Objects.equals(this.resourceType, callbackPayload.resourceType) && Objects.equals(this.eventType, callbackPayload.eventType) && Objects.equals(this.status, callbackPayload.status) - && Objects.equals(this.failureCode, callbackPayload.failureCode); + && Objects.equals(this.failureCode, callbackPayload.failureCode) + && Objects.equals(this.internalFailureCode, callbackPayload.internalFailureCode); } @Override public int hashCode() { return Objects.hash( - eventId, timestamp, projectId, resourceId, resourceType, eventType, status, failureCode); + eventId, + timestamp, + projectId, + resourceId, + resourceType, + eventType, + status, + failureCode, + internalFailureCode); } @Override @@ -204,6 +231,9 @@ public String toString() { sb.append(" eventType: ").append(toIndentedString(eventType)).append("\n"); sb.append(" status: ").append(toIndentedString(status)).append("\n"); sb.append(" failureCode: ").append(toIndentedString(failureCode)).append("\n"); + sb.append(" internalFailureCode: ") + .append(toIndentedString(internalFailureCode)) + .append("\n"); sb.append("}"); return sb.toString(); } @@ -228,6 +258,7 @@ static class Builder implements NumberSinchEvent.Builder { OptionalValue eventType = OptionalValue.empty(); OptionalValue status = OptionalValue.empty(); OptionalValue failureCode = OptionalValue.empty(); + OptionalValue internalFailureCode = OptionalValue.empty(); @JsonProperty(JSON_PROPERTY_EVENT_ID) public Builder setEventId(String eventId) { @@ -277,9 +308,23 @@ public Builder setFailureCode(FailureCodeEnum failureCode) { return this; } + @JsonProperty(JSON_PROPERTY_INTERNAL_FAILURE_CODE) + public Builder setInternalFailureCode(String internalFailureCode) { + this.internalFailureCode = OptionalValue.of(internalFailureCode); + return this; + } + public NumberSinchEvent build() { return new NumberSinchEventImpl( - eventId, timestamp, projectId, resourceId, resourceType, eventType, status, failureCode); + eventId, + timestamp, + projectId, + resourceId, + resourceType, + eventType, + status, + failureCode, + internalFailureCode); } } } diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/sms/api/v1/adapters/BatchesServiceImpl.java b/openapi-contracts/src/main/com/sinch/sdk/domains/sms/api/v1/adapters/BatchesServiceImpl.java index 660f9866a..427fe7d8c 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/sms/api/v1/adapters/BatchesServiceImpl.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/sms/api/v1/adapters/BatchesServiceImpl.java @@ -42,6 +42,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.function.Function; import java.util.logging.Logger; public class BatchesServiceImpl implements com.sinch.sdk.domains.sms.api.v1.BatchesService { @@ -79,11 +80,15 @@ public ListBatchesResponse list(ListBatchesQueryParameters queryParameter) throw LOGGER.finest("[list]" + " " + "queryParameter: " + queryParameter); HttpRequest httpRequest = listRequestBuilder(queryParameter); - return _fetchListPage(queryParameter, httpRequest); + return _fetchListPage( + (queryParameters) -> listRequestBuilder(queryParameters), queryParameter, httpRequest); } private ListBatchesResponse _fetchListPage( - ListBatchesQueryParameters queryParameter, HttpRequest httpRequest) throws ApiException { + Function requestBuilder, + ListBatchesQueryParameters queryParameter, + HttpRequest httpRequest) + throws ApiException { HttpResponse response = httpClient.invokeAPI( this.serverConfiguration, this.authManagersByOasSecuritySchemes, httpRequest); @@ -113,9 +118,10 @@ private ListBatchesResponse _fetchListPage( ListBatchesQueryParameters.builder(queryParameter).setPage(nextPage).build(); final HttpRequest nextHttpRequest = - nextPage != null ? listRequestBuilder(nextParameters) : null; + nextPage != null ? requestBuilder.apply(nextParameters) : null; - return new ListBatchesResponse(() -> _fetchListPage(nextParameters, nextHttpRequest), page); + return new ListBatchesResponse( + () -> _fetchListPage(requestBuilder, nextParameters, nextHttpRequest), page); } // fallback to default errors handling: // all error cases definition are not required from specs: will try some "hardcoded" content diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/sms/api/v1/adapters/DeliveryReportsServiceImpl.java b/openapi-contracts/src/main/com/sinch/sdk/domains/sms/api/v1/adapters/DeliveryReportsServiceImpl.java index 1624a0fd3..4887acfcb 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/sms/api/v1/adapters/DeliveryReportsServiceImpl.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/sms/api/v1/adapters/DeliveryReportsServiceImpl.java @@ -39,6 +39,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.function.Function; import java.util.logging.Logger; public class DeliveryReportsServiceImpl @@ -78,11 +79,14 @@ public ListDeliveryReportsResponse list(ListDeliveryReportsQueryParameters query LOGGER.finest("[list]" + " " + "queryParameter: " + queryParameter); HttpRequest httpRequest = listRequestBuilder(queryParameter); - return _fetchListPage(queryParameter, httpRequest); + return _fetchListPage( + (queryParameters) -> listRequestBuilder(queryParameters), queryParameter, httpRequest); } private ListDeliveryReportsResponse _fetchListPage( - ListDeliveryReportsQueryParameters queryParameter, HttpRequest httpRequest) + Function requestBuilder, + ListDeliveryReportsQueryParameters queryParameter, + HttpRequest httpRequest) throws ApiException { HttpResponse response = httpClient.invokeAPI( @@ -113,10 +117,10 @@ private ListDeliveryReportsResponse _fetchListPage( ListDeliveryReportsQueryParameters.builder(queryParameter).setPage(nextPage).build(); final HttpRequest nextHttpRequest = - nextPage != null ? listRequestBuilder(nextParameters) : null; + nextPage != null ? requestBuilder.apply(nextParameters) : null; return new ListDeliveryReportsResponse( - () -> _fetchListPage(nextParameters, nextHttpRequest), page); + () -> _fetchListPage(requestBuilder, nextParameters, nextHttpRequest), page); } // fallback to default errors handling: // all error cases definition are not required from specs: will try some "hardcoded" content diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/sms/api/v1/adapters/GroupsServiceImpl.java b/openapi-contracts/src/main/com/sinch/sdk/domains/sms/api/v1/adapters/GroupsServiceImpl.java index 790fd9a69..f2e103992 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/sms/api/v1/adapters/GroupsServiceImpl.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/sms/api/v1/adapters/GroupsServiceImpl.java @@ -38,6 +38,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.function.Function; import java.util.logging.Logger; public class GroupsServiceImpl implements com.sinch.sdk.domains.sms.api.v1.GroupsService { @@ -75,11 +76,15 @@ public ListGroupsResponse list(ListGroupsQueryParameters queryParameter) throws LOGGER.finest("[list]" + " " + "queryParameter: " + queryParameter); HttpRequest httpRequest = listRequestBuilder(queryParameter); - return _fetchListPage(queryParameter, httpRequest); + return _fetchListPage( + (queryParameters) -> listRequestBuilder(queryParameters), queryParameter, httpRequest); } private ListGroupsResponse _fetchListPage( - ListGroupsQueryParameters queryParameter, HttpRequest httpRequest) throws ApiException { + Function requestBuilder, + ListGroupsQueryParameters queryParameter, + HttpRequest httpRequest) + throws ApiException { HttpResponse response = httpClient.invokeAPI( this.serverConfiguration, this.authManagersByOasSecuritySchemes, httpRequest); @@ -109,9 +114,10 @@ private ListGroupsResponse _fetchListPage( ListGroupsQueryParameters.builder(queryParameter).setPage(nextPage).build(); final HttpRequest nextHttpRequest = - nextPage != null ? listRequestBuilder(nextParameters) : null; + nextPage != null ? requestBuilder.apply(nextParameters) : null; - return new ListGroupsResponse(() -> _fetchListPage(nextParameters, nextHttpRequest), page); + return new ListGroupsResponse( + () -> _fetchListPage(requestBuilder, nextParameters, nextHttpRequest), page); } // fallback to default errors handling: // all error cases definition are not required from specs: will try some "hardcoded" content diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/sms/api/v1/adapters/InboundsServiceImpl.java b/openapi-contracts/src/main/com/sinch/sdk/domains/sms/api/v1/adapters/InboundsServiceImpl.java index 6a24d5b3b..7d2193d1a 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/sms/api/v1/adapters/InboundsServiceImpl.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/sms/api/v1/adapters/InboundsServiceImpl.java @@ -37,6 +37,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.function.Function; import java.util.logging.Logger; public class InboundsServiceImpl implements com.sinch.sdk.domains.sms.api.v1.InboundsService { @@ -75,11 +76,14 @@ public ListInboundsResponse list(ListInboundMessagesQueryParameters queryParamet LOGGER.finest("[list]" + " " + "queryParameter: " + queryParameter); HttpRequest httpRequest = listRequestBuilder(queryParameter); - return _fetchListPage(queryParameter, httpRequest); + return _fetchListPage( + (queryParameters) -> listRequestBuilder(queryParameters), queryParameter, httpRequest); } private ListInboundsResponse _fetchListPage( - ListInboundMessagesQueryParameters queryParameter, HttpRequest httpRequest) + Function requestBuilder, + ListInboundMessagesQueryParameters queryParameter, + HttpRequest httpRequest) throws ApiException { HttpResponse response = httpClient.invokeAPI( @@ -110,9 +114,10 @@ private ListInboundsResponse _fetchListPage( ListInboundMessagesQueryParameters.builder(queryParameter).setPage(nextPage).build(); final HttpRequest nextHttpRequest = - nextPage != null ? listRequestBuilder(nextParameters) : null; + nextPage != null ? requestBuilder.apply(nextParameters) : null; - return new ListInboundsResponse(() -> _fetchListPage(nextParameters, nextHttpRequest), page); + return new ListInboundsResponse( + () -> _fetchListPage(requestBuilder, nextParameters, nextHttpRequest), page); } // fallback to default errors handling: // all error cases definition are not required from specs: will try some "hardcoded" content diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/voice/api/v1/CallsService.java b/openapi-contracts/src/main/com/sinch/sdk/domains/voice/api/v1/CallsService.java index 6aa50ceb5..680128532 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/voice/api/v1/CallsService.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/voice/api/v1/CallsService.java @@ -12,6 +12,7 @@ import com.sinch.sdk.core.exceptions.ApiException; import com.sinch.sdk.domains.voice.models.v1.calls.request.CallLeg; +import com.sinch.sdk.domains.voice.models.v1.calls.request.CallUpdateRequest; import com.sinch.sdk.domains.voice.models.v1.calls.response.CallInformation; import com.sinch.sdk.domains.voice.models.v1.svaml.SvamlControl; @@ -53,10 +54,10 @@ public interface CallsService { * `caller`.<br><Warning>The `callLeg` identifier is ignored * for calls that are part of a conference and calls initiated using the Callout * API.</Warning> (required) - * @param svamlControl (optional) + * @param callUpdateRequest (optional) * @throws ApiException if fails to make API call */ - void manageWithCallLeg(String callId, CallLeg callLeg, SvamlControl svamlControl) + void manageWithCallLeg(String callId, CallLeg callLeg, CallUpdateRequest callUpdateRequest) throws ApiException; /** @@ -70,8 +71,43 @@ void manageWithCallLeg(String callId, CallLeg callLeg, SvamlControl svamlControl * * @param callId The unique identifier of the call. This value is generated by the system. * (required) + * @param callUpdateRequest (optional) + * @throws ApiException if fails to make API call + */ + void update(String callId, CallUpdateRequest callUpdateRequest) throws ApiException; + + /** + * Manage Call with `callLeg` + * + *

This method is deprecated replaced by {@link #manageWithCallLeg(String, CallLeg, + * CallUpdateRequest)} + * + * @param callId The unique identifier of the call. This value is generated by the system. + * (required) + * @param callLeg Specifies which part of the call will be managed. This option is used only by + * the `PlayFiles` and `Say` instructions to indicate which channel the + * sound will be played on. Valid options are `caller`, `callee` or + * `both`. If not specified, the default value is + * `caller`.<br><Warning>The `callLeg` identifier is ignored + * for calls that are part of a conference and calls initiated using the Callout + * API.</Warning> (required) + * @param svamlControl (optional) + * @throws ApiException if fails to make API call + * @deprecated + */ + void manageWithCallLeg(String callId, CallLeg callLeg, SvamlControl svamlControl) + throws ApiException; + + /** + * Update a call in progress + * + *

This method is deprecated replaced by {@link #update(String, CallUpdateRequest)} + * + * @param callId The unique identifier of the call. This value is generated by the system. + * (required) * @param svamlControl (optional) * @throws ApiException if fails to make API call + * @deprecated */ void update(String callId, SvamlControl svamlControl) throws ApiException; } diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/voice/api/v1/adapters/CallsServiceImpl.java b/openapi-contracts/src/main/com/sinch/sdk/domains/voice/api/v1/adapters/CallsServiceImpl.java index afd380188..5eabae47c 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/voice/api/v1/adapters/CallsServiceImpl.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/voice/api/v1/adapters/CallsServiceImpl.java @@ -24,6 +24,7 @@ import com.sinch.sdk.core.http.URLPathUtils; import com.sinch.sdk.core.models.ServerConfiguration; import com.sinch.sdk.domains.voice.models.v1.calls.request.CallLeg; +import com.sinch.sdk.domains.voice.models.v1.calls.request.CallUpdateRequest; import com.sinch.sdk.domains.voice.models.v1.calls.response.CallInformation; import com.sinch.sdk.domains.voice.models.v1.svaml.SvamlControl; import java.util.ArrayList; @@ -108,6 +109,137 @@ private HttpRequest getRequestBuilder(String callId) throws ApiException { localVarAuthNames); } + @Override + public void manageWithCallLeg(String callId, CallLeg callLeg, CallUpdateRequest callUpdateRequest) + throws ApiException { + + LOGGER.finest( + "[manageWithCallLeg]" + + " " + + "callId: " + + callId + + ", " + + "callLeg: " + + callLeg + + ", " + + "callUpdateRequest: " + + callUpdateRequest); + + HttpRequest httpRequest = manageWithCallLegRequestBuilder(callId, callLeg, callUpdateRequest); + HttpResponse response = + httpClient.invokeAPI( + this.serverConfiguration, this.authManagersByOasSecuritySchemes, httpRequest); + + if (HttpStatus.isSuccessfulStatus(response.getCode())) { + return; + } + // fallback to default errors handling: + // all error cases definition are not required from specs: will try some "hardcoded" content + // parsing + throw ApiExceptionBuilder.build( + response.getMessage(), + response.getCode(), + mapper.deserialize(response, new TypeReference>() {})); + } + + private HttpRequest manageWithCallLegRequestBuilder( + String callId, CallLeg callLeg, CallUpdateRequest callUpdateRequest) throws ApiException { + // verify the required parameter 'callId' is set + if (callId == null) { + throw new ApiException( + 400, "Missing the required parameter 'callId' when calling manageWithCallLeg"); + } + // verify the required parameter 'callLeg' is set + if (callLeg == null) { + throw new ApiException( + 400, "Missing the required parameter 'callLeg' when calling manageWithCallLeg"); + } + + String localVarPath = + "/calling/v1/calls/id/{callId}/leg/{callLeg}" + .replaceAll("\\{" + "callId" + "\\}", URLPathUtils.encodePathSegment(callId.toString())) + .replaceAll( + "\\{" + "callLeg" + "\\}", URLPathUtils.encodePathSegment(callLeg.toString())); + + List localVarQueryParams = new ArrayList<>(); + + Map localVarHeaderParams = new HashMap<>(); + + final Collection localVarAccepts = Arrays.asList("application/json"); + + final Collection localVarContentTypes = Arrays.asList("application/json"); + + final Collection localVarAuthNames = Arrays.asList("Basic", "Signed"); + final String serializedBody = mapper.serialize(localVarContentTypes, callUpdateRequest); + + return new HttpRequest( + localVarPath, + HttpMethod.PATCH, + localVarQueryParams, + serializedBody, + localVarHeaderParams, + localVarAccepts, + localVarContentTypes, + localVarAuthNames); + } + + @Override + public void update(String callId, CallUpdateRequest callUpdateRequest) throws ApiException { + + LOGGER.finest( + "[update]" + " " + "callId: " + callId + ", " + "callUpdateRequest: " + callUpdateRequest); + + HttpRequest httpRequest = updateRequestBuilder(callId, callUpdateRequest); + HttpResponse response = + httpClient.invokeAPI( + this.serverConfiguration, this.authManagersByOasSecuritySchemes, httpRequest); + + if (HttpStatus.isSuccessfulStatus(response.getCode())) { + return; + } + // fallback to default errors handling: + // all error cases definition are not required from specs: will try some "hardcoded" content + // parsing + throw ApiExceptionBuilder.build( + response.getMessage(), + response.getCode(), + mapper.deserialize(response, new TypeReference>() {})); + } + + private HttpRequest updateRequestBuilder(String callId, CallUpdateRequest callUpdateRequest) + throws ApiException { + // verify the required parameter 'callId' is set + if (callId == null) { + throw new ApiException(400, "Missing the required parameter 'callId' when calling update"); + } + + String localVarPath = + "/calling/v1/calls/id/{callId}" + .replaceAll( + "\\{" + "callId" + "\\}", URLPathUtils.encodePathSegment(callId.toString())); + + List localVarQueryParams = new ArrayList<>(); + + Map localVarHeaderParams = new HashMap<>(); + + final Collection localVarAccepts = Arrays.asList(); + + final Collection localVarContentTypes = Arrays.asList("application/json"); + + final Collection localVarAuthNames = Arrays.asList("Basic", "Signed"); + final String serializedBody = mapper.serialize(localVarContentTypes, callUpdateRequest); + + return new HttpRequest( + localVarPath, + HttpMethod.PATCH, + localVarQueryParams, + serializedBody, + localVarHeaderParams, + localVarAccepts, + localVarContentTypes, + localVarAuthNames); + } + @Override public void manageWithCallLeg(String callId, CallLeg callLeg, SvamlControl svamlControl) throws ApiException { diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/voice/models/v1/calls/request/CallUpdateRequest.java b/openapi-contracts/src/main/com/sinch/sdk/domains/voice/models/v1/calls/request/CallUpdateRequest.java new file mode 100644 index 000000000..6d8645fc6 --- /dev/null +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/voice/models/v1/calls/request/CallUpdateRequest.java @@ -0,0 +1,78 @@ +/* + * Voice API | Sinch + * + * OpenAPI document version: 1.0.1 + * Contact: support@sinch.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * Do not edit the class manually. + */ + +package com.sinch.sdk.domains.voice.models.v1.calls.request; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.sinch.sdk.domains.voice.models.v1.svaml.action.ManagedCallSvamlAction; +import com.sinch.sdk.domains.voice.models.v1.svaml.instruction.SvamlInstruction; +import java.util.Collection; + +/** + * SVAML is a call control markup language. When a server receives a callback event from the Sinch + * platform, it can respond with a SVAML object to control the voice call. The following is an + * example of a SVAML object type and its contents. + */ +@JsonDeserialize(builder = CallUpdateRequestImpl.Builder.class) +public interface CallUpdateRequest { + + /** + * The collection of instructions that can perform various tasks during the call. You can include + * as many instructions as necessary. + * + * @return instructions + */ + Collection getInstructions(); + + /** + * Get action + * + * @return action + */ + ManagedCallSvamlAction getAction(); + + /** + * Getting builder + * + * @return New Builder instance + */ + static Builder builder() { + return new CallUpdateRequestImpl.Builder(); + } + + /** Dedicated Builder */ + interface Builder { + + /** + * see getter + * + * @param instructions see getter + * @return Current builder + * @see #getInstructions + */ + Builder setInstructions(Collection instructions); + + /** + * see getter + * + * @param action see getter + * @return Current builder + * @see #getAction + */ + Builder setAction(ManagedCallSvamlAction action); + + /** + * Create instance + * + * @return The instance build with current builder values + */ + CallUpdateRequest build(); + } +} diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/voice/models/v1/calls/request/CallUpdateRequestImpl.java b/openapi-contracts/src/main/com/sinch/sdk/domains/voice/models/v1/calls/request/CallUpdateRequestImpl.java new file mode 100644 index 000000000..86be341d7 --- /dev/null +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/voice/models/v1/calls/request/CallUpdateRequestImpl.java @@ -0,0 +1,123 @@ +package com.sinch.sdk.domains.voice.models.v1.calls.request; + +import com.fasterxml.jackson.annotation.JsonFilter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; +import com.sinch.sdk.core.models.OptionalValue; +import com.sinch.sdk.domains.voice.models.v1.svaml.action.ManagedCallSvamlAction; +import com.sinch.sdk.domains.voice.models.v1.svaml.instruction.SvamlInstruction; +import java.util.Collection; +import java.util.Objects; + +@JsonPropertyOrder({ + CallUpdateRequestImpl.JSON_PROPERTY_INSTRUCTIONS, + CallUpdateRequestImpl.JSON_PROPERTY_ACTION +}) +@JsonFilter("uninitializedFilter") +@JsonInclude(value = JsonInclude.Include.CUSTOM) +public class CallUpdateRequestImpl implements CallUpdateRequest { + private static final long serialVersionUID = 1L; + + public static final String JSON_PROPERTY_INSTRUCTIONS = "instructions"; + + private OptionalValue> instructions; + + public static final String JSON_PROPERTY_ACTION = "action"; + + private OptionalValue action; + + public CallUpdateRequestImpl() {} + + protected CallUpdateRequestImpl( + OptionalValue> instructions, + OptionalValue action) { + this.instructions = instructions; + this.action = action; + } + + @JsonIgnore + public Collection getInstructions() { + return instructions.orElse(null); + } + + @JsonProperty(JSON_PROPERTY_INSTRUCTIONS) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public OptionalValue> instructions() { + return instructions; + } + + @JsonIgnore + public ManagedCallSvamlAction getAction() { + return action.orElse(null); + } + + @JsonProperty(JSON_PROPERTY_ACTION) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public OptionalValue action() { + return action; + } + + /** Return true if this PATCHSVAMLRequestBody object is equal to o. */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + CallUpdateRequestImpl paTCHSVAMLRequestBody = (CallUpdateRequestImpl) o; + return Objects.equals(this.instructions, paTCHSVAMLRequestBody.instructions) + && Objects.equals(this.action, paTCHSVAMLRequestBody.action); + } + + @Override + public int hashCode() { + return Objects.hash(instructions, action); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class CallUpdateRequestImpl {\n"); + sb.append(" instructions: ").append(toIndentedString(instructions)).append("\n"); + sb.append(" action: ").append(toIndentedString(action)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + @JsonPOJOBuilder(withPrefix = "set") + static class Builder implements CallUpdateRequest.Builder { + OptionalValue> instructions = OptionalValue.empty(); + OptionalValue action = OptionalValue.empty(); + + @JsonProperty(JSON_PROPERTY_INSTRUCTIONS) + public Builder setInstructions(Collection instructions) { + this.instructions = OptionalValue.of(instructions); + return this; + } + + @JsonProperty(JSON_PROPERTY_ACTION) + public Builder setAction(ManagedCallSvamlAction action) { + this.action = OptionalValue.of(action); + return this; + } + + public CallUpdateRequest build() { + return new CallUpdateRequestImpl(instructions, action); + } + } +} diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/voice/models/v1/svaml/action/SvamlActionContinue.java b/openapi-contracts/src/main/com/sinch/sdk/domains/voice/models/v1/svaml/action/SvamlActionContinue.java index 37240e504..8c9ed6c40 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/voice/models/v1/svaml/action/SvamlActionContinue.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/voice/models/v1/svaml/action/SvamlActionContinue.java @@ -23,7 +23,8 @@ */ @JsonDeserialize(builder = SvamlActionContinueImpl.Builder.class) public interface SvamlActionContinue - extends com.sinch.sdk.domains.voice.models.v1.svaml.action.SvamlAction { + extends com.sinch.sdk.domains.voice.models.v1.svaml.action.SvamlAction, + com.sinch.sdk.domains.voice.models.v1.svaml.action.ManagedCallSvamlAction { /** ready to use action to send a `continue` */ SvamlActionContinue SVAML_ACTION_CONTINUE = SvamlActionContinue.builder().build(); diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/voice/models/v1/svaml/action/SvamlActionContinueImpl.java b/openapi-contracts/src/main/com/sinch/sdk/domains/voice/models/v1/svaml/action/SvamlActionContinueImpl.java index 09c3450e7..54b1c9b2c 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/voice/models/v1/svaml/action/SvamlActionContinueImpl.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/voice/models/v1/svaml/action/SvamlActionContinueImpl.java @@ -13,7 +13,9 @@ @JsonFilter("uninitializedFilter") @JsonInclude(value = JsonInclude.Include.CUSTOM) public class SvamlActionContinueImpl - implements SvamlActionContinue, com.sinch.sdk.domains.voice.models.v1.svaml.action.SvamlAction { + implements SvamlActionContinue, + com.sinch.sdk.domains.voice.models.v1.svaml.action.SvamlAction, + com.sinch.sdk.domains.voice.models.v1.svaml.action.ManagedCallSvamlAction { private static final long serialVersionUID = 1L; public static final String JSON_PROPERTY_NAME = "name"; diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/voice/models/v1/svaml/action/SvamlActionHangup.java b/openapi-contracts/src/main/com/sinch/sdk/domains/voice/models/v1/svaml/action/SvamlActionHangup.java index c40d66663..9433b1099 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/voice/models/v1/svaml/action/SvamlActionHangup.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/voice/models/v1/svaml/action/SvamlActionHangup.java @@ -25,7 +25,8 @@ */ @JsonDeserialize(builder = SvamlActionHangupImpl.Builder.class) public interface SvamlActionHangup - extends com.sinch.sdk.domains.voice.models.v1.svaml.action.SvamlAction { + extends com.sinch.sdk.domains.voice.models.v1.svaml.action.SvamlAction, + com.sinch.sdk.domains.voice.models.v1.svaml.action.ManagedCallSvamlAction { /** ready to use action to send a `hangup` */ SvamlActionHangup SVAML_ACTION_HANGUP = SvamlActionHangup.builder().build(); diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/voice/models/v1/svaml/action/SvamlActionHangupImpl.java b/openapi-contracts/src/main/com/sinch/sdk/domains/voice/models/v1/svaml/action/SvamlActionHangupImpl.java index 9cdac58e9..abdf61e9b 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/voice/models/v1/svaml/action/SvamlActionHangupImpl.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/voice/models/v1/svaml/action/SvamlActionHangupImpl.java @@ -13,7 +13,9 @@ @JsonFilter("uninitializedFilter") @JsonInclude(value = JsonInclude.Include.CUSTOM) public class SvamlActionHangupImpl - implements SvamlActionHangup, com.sinch.sdk.domains.voice.models.v1.svaml.action.SvamlAction { + implements SvamlActionHangup, + com.sinch.sdk.domains.voice.models.v1.svaml.action.SvamlAction, + com.sinch.sdk.domains.voice.models.v1.svaml.action.ManagedCallSvamlAction { private static final long serialVersionUID = 1L; public static final String JSON_PROPERTY_NAME = "name"; diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/voice/models/v1/svaml/action/SvamlActionPark.java b/openapi-contracts/src/main/com/sinch/sdk/domains/voice/models/v1/svaml/action/SvamlActionPark.java index db8f2bdf2..74161aa2a 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/voice/models/v1/svaml/action/SvamlActionPark.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/voice/models/v1/svaml/action/SvamlActionPark.java @@ -24,7 +24,8 @@ */ @JsonDeserialize(builder = SvamlActionParkImpl.Builder.class) public interface SvamlActionPark - extends com.sinch.sdk.domains.voice.models.v1.svaml.action.SvamlAction { + extends com.sinch.sdk.domains.voice.models.v1.svaml.action.SvamlAction, + com.sinch.sdk.domains.voice.models.v1.svaml.action.ManagedCallSvamlAction { /** The name property. Must have the value park. */ public class NameEnum extends EnumDynamic { diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/voice/models/v1/svaml/action/SvamlActionParkImpl.java b/openapi-contracts/src/main/com/sinch/sdk/domains/voice/models/v1/svaml/action/SvamlActionParkImpl.java index d66651404..73577fdc3 100644 --- a/openapi-contracts/src/main/com/sinch/sdk/domains/voice/models/v1/svaml/action/SvamlActionParkImpl.java +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/voice/models/v1/svaml/action/SvamlActionParkImpl.java @@ -19,7 +19,9 @@ @JsonFilter("uninitializedFilter") @JsonInclude(value = JsonInclude.Include.CUSTOM) public class SvamlActionParkImpl - implements SvamlActionPark, com.sinch.sdk.domains.voice.models.v1.svaml.action.SvamlAction { + implements SvamlActionPark, + com.sinch.sdk.domains.voice.models.v1.svaml.action.SvamlAction, + com.sinch.sdk.domains.voice.models.v1.svaml.action.ManagedCallSvamlAction { private static final long serialVersionUID = 1L; public static final String JSON_PROPERTY_NAME = "name"; diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/voice/models/v1/svaml/internal/SvamlActionPatchInternal.java b/openapi-contracts/src/main/com/sinch/sdk/domains/voice/models/v1/svaml/internal/SvamlActionPatchInternal.java new file mode 100644 index 000000000..8fcd49233 --- /dev/null +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/voice/models/v1/svaml/internal/SvamlActionPatchInternal.java @@ -0,0 +1,17 @@ +/* + * Voice API | Sinch + * + * OpenAPI document version: 1.0.1 + * Contact: support@sinch.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * Do not edit the class manually. + */ + +package com.sinch.sdk.domains.voice.models.v1.svaml.internal; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; + +@JsonDeserialize( + using = SvamlActionPatchInternalImpl.SvamlActionPatchInternalImplDeserializer.class) +public interface SvamlActionPatchInternal {} diff --git a/openapi-contracts/src/main/com/sinch/sdk/domains/voice/models/v1/svaml/internal/SvamlActionPatchInternalImpl.java b/openapi-contracts/src/main/com/sinch/sdk/domains/voice/models/v1/svaml/internal/SvamlActionPatchInternalImpl.java new file mode 100644 index 000000000..5fadaa722 --- /dev/null +++ b/openapi-contracts/src/main/com/sinch/sdk/domains/voice/models/v1/svaml/internal/SvamlActionPatchInternalImpl.java @@ -0,0 +1,366 @@ +package com.sinch.sdk.domains.voice.models.v1.svaml.internal; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.JsonToken; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.MapperFeature; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; +import com.sinch.sdk.core.models.AbstractOpenApiSchema; +import com.sinch.sdk.core.utils.databind.JSONNavigator; +import com.sinch.sdk.domains.voice.models.v1.svaml.action.SvamlActionContinueImpl; +import com.sinch.sdk.domains.voice.models.v1.svaml.action.SvamlActionHangupImpl; +import com.sinch.sdk.domains.voice.models.v1.svaml.action.SvamlActionParkImpl; +import java.io.IOException; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; + +@JsonDeserialize( + using = SvamlActionPatchInternalImpl.SvamlActionPatchInternalImplDeserializer.class) +@JsonSerialize(using = SvamlActionPatchInternalImpl.SvamlActionPatchInternalImplSerializer.class) +public class SvamlActionPatchInternalImpl extends AbstractOpenApiSchema + implements SvamlActionPatchInternal { + private static final Logger log = Logger.getLogger(SvamlActionPatchInternalImpl.class.getName()); + + public static final class SvamlActionPatchInternalImplSerializer + extends StdSerializer { + private static final long serialVersionUID = 1L; + + public SvamlActionPatchInternalImplSerializer(Class t) { + super(t); + } + + public SvamlActionPatchInternalImplSerializer() { + this(null); + } + + @Override + public void serialize( + SvamlActionPatchInternalImpl value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonProcessingException { + jgen.writeObject(value.getActualInstance()); + } + } + + public static final class SvamlActionPatchInternalImplDeserializer + extends StdDeserializer { + + private static final long serialVersionUID = 1L; + + public SvamlActionPatchInternalImplDeserializer() { + this(SvamlActionPatchInternalImpl.class); + } + + public SvamlActionPatchInternalImplDeserializer(Class vc) { + super(vc); + } + + @Override + public SvamlActionPatchInternalImpl deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException { + JsonNode tree = jp.readValueAsTree(); + Object deserialized = null; + SvamlActionPatchInternalImpl newSvamlActionPatchInternalImpl = + new SvamlActionPatchInternalImpl(); + Map result2 = + tree.traverse(jp.getCodec()).readValueAs(new TypeReference>() {}); + String discriminatorValue = (String) result2.get("name"); + switch (discriminatorValue) { + case "continue": + deserialized = tree.traverse(jp.getCodec()).readValueAs(SvamlActionContinueImpl.class); + newSvamlActionPatchInternalImpl.setActualInstance(deserialized); + return newSvamlActionPatchInternalImpl; + case "hangup": + deserialized = tree.traverse(jp.getCodec()).readValueAs(SvamlActionHangupImpl.class); + newSvamlActionPatchInternalImpl.setActualInstance(deserialized); + return newSvamlActionPatchInternalImpl; + case "park": + deserialized = tree.traverse(jp.getCodec()).readValueAs(SvamlActionParkImpl.class); + newSvamlActionPatchInternalImpl.setActualInstance(deserialized); + return newSvamlActionPatchInternalImpl; + default: + log.log( + Level.WARNING, + String.format( + "Failed to lookup discriminator value `%s` for SvamlActionPatchInternalImpl." + + " Possible values: continue hangup park", + discriminatorValue)); + } + + boolean typeCoercion = ctxt.isEnabled(MapperFeature.ALLOW_COERCION_OF_SCALARS); + int match = 0; + JsonToken token = tree.traverse(jp.getCodec()).nextToken(); + // deserialize SvamlActionContinueImpl + try { + boolean attemptParsing = true; + // ensure that we respect type coercion as set on the client ObjectMapper + if (SvamlActionContinueImpl.class.equals(Integer.class) + || SvamlActionContinueImpl.class.equals(Long.class) + || SvamlActionContinueImpl.class.equals(Float.class) + || SvamlActionContinueImpl.class.equals(Double.class) + || SvamlActionContinueImpl.class.equals(Boolean.class) + || SvamlActionContinueImpl.class.equals(String.class)) { + attemptParsing = typeCoercion; + if (!attemptParsing) { + attemptParsing |= + ((SvamlActionContinueImpl.class.equals(Integer.class) + || SvamlActionContinueImpl.class.equals(Long.class)) + && token == JsonToken.VALUE_NUMBER_INT); + attemptParsing |= + ((SvamlActionContinueImpl.class.equals(Float.class) + || SvamlActionContinueImpl.class.equals(Double.class)) + && token == JsonToken.VALUE_NUMBER_FLOAT); + attemptParsing |= + (SvamlActionContinueImpl.class.equals(Boolean.class) + && (token == JsonToken.VALUE_FALSE || token == JsonToken.VALUE_TRUE)); + attemptParsing |= + (SvamlActionContinueImpl.class.equals(String.class) + && token == JsonToken.VALUE_STRING); + } + } + if (attemptParsing) { + deserialized = tree.traverse(jp.getCodec()).readValueAs(SvamlActionContinueImpl.class); + // TODO: there is no validation against JSON schema constraints + // (min, max, enum, pattern...), this does not perform a strict JSON + // validation, which means the 'match' count may be higher than it should be. + match++; + log.log(Level.FINER, "Input data matches schema 'SvamlActionContinueImpl'"); + } + } catch (Exception e) { + // deserialization failed, continue + log.log(Level.FINER, "Input data does not match schema 'SvamlActionContinueImpl'", e); + } + + // deserialize SvamlActionHangupImpl + try { + boolean attemptParsing = true; + // ensure that we respect type coercion as set on the client ObjectMapper + if (SvamlActionHangupImpl.class.equals(Integer.class) + || SvamlActionHangupImpl.class.equals(Long.class) + || SvamlActionHangupImpl.class.equals(Float.class) + || SvamlActionHangupImpl.class.equals(Double.class) + || SvamlActionHangupImpl.class.equals(Boolean.class) + || SvamlActionHangupImpl.class.equals(String.class)) { + attemptParsing = typeCoercion; + if (!attemptParsing) { + attemptParsing |= + ((SvamlActionHangupImpl.class.equals(Integer.class) + || SvamlActionHangupImpl.class.equals(Long.class)) + && token == JsonToken.VALUE_NUMBER_INT); + attemptParsing |= + ((SvamlActionHangupImpl.class.equals(Float.class) + || SvamlActionHangupImpl.class.equals(Double.class)) + && token == JsonToken.VALUE_NUMBER_FLOAT); + attemptParsing |= + (SvamlActionHangupImpl.class.equals(Boolean.class) + && (token == JsonToken.VALUE_FALSE || token == JsonToken.VALUE_TRUE)); + attemptParsing |= + (SvamlActionHangupImpl.class.equals(String.class) + && token == JsonToken.VALUE_STRING); + } + } + if (attemptParsing) { + deserialized = tree.traverse(jp.getCodec()).readValueAs(SvamlActionHangupImpl.class); + // TODO: there is no validation against JSON schema constraints + // (min, max, enum, pattern...), this does not perform a strict JSON + // validation, which means the 'match' count may be higher than it should be. + match++; + log.log(Level.FINER, "Input data matches schema 'SvamlActionHangupImpl'"); + } + } catch (Exception e) { + // deserialization failed, continue + log.log(Level.FINER, "Input data does not match schema 'SvamlActionHangupImpl'", e); + } + + // deserialize SvamlActionParkImpl + try { + boolean attemptParsing = true; + // ensure that we respect type coercion as set on the client ObjectMapper + if (SvamlActionParkImpl.class.equals(Integer.class) + || SvamlActionParkImpl.class.equals(Long.class) + || SvamlActionParkImpl.class.equals(Float.class) + || SvamlActionParkImpl.class.equals(Double.class) + || SvamlActionParkImpl.class.equals(Boolean.class) + || SvamlActionParkImpl.class.equals(String.class)) { + attemptParsing = typeCoercion; + if (!attemptParsing) { + attemptParsing |= + ((SvamlActionParkImpl.class.equals(Integer.class) + || SvamlActionParkImpl.class.equals(Long.class)) + && token == JsonToken.VALUE_NUMBER_INT); + attemptParsing |= + ((SvamlActionParkImpl.class.equals(Float.class) + || SvamlActionParkImpl.class.equals(Double.class)) + && token == JsonToken.VALUE_NUMBER_FLOAT); + attemptParsing |= + (SvamlActionParkImpl.class.equals(Boolean.class) + && (token == JsonToken.VALUE_FALSE || token == JsonToken.VALUE_TRUE)); + attemptParsing |= + (SvamlActionParkImpl.class.equals(String.class) && token == JsonToken.VALUE_STRING); + } + } + if (attemptParsing) { + deserialized = tree.traverse(jp.getCodec()).readValueAs(SvamlActionParkImpl.class); + // TODO: there is no validation against JSON schema constraints + // (min, max, enum, pattern...), this does not perform a strict JSON + // validation, which means the 'match' count may be higher than it should be. + match++; + log.log(Level.FINER, "Input data matches schema 'SvamlActionParkImpl'"); + } + } catch (Exception e) { + // deserialization failed, continue + log.log(Level.FINER, "Input data does not match schema 'SvamlActionParkImpl'", e); + } + + if (match == 1) { + SvamlActionPatchInternalImpl ret = new SvamlActionPatchInternalImpl(); + ret.setActualInstance(deserialized); + return ret; + } + throw new IOException( + String.format( + "Failed deserialization for SvamlActionPatchInternalImpl: %d classes match result," + + " expected 1", + match)); + } + + /** Handle deserialization of the 'null' value. */ + @Override + public SvamlActionPatchInternalImpl getNullValue(DeserializationContext ctxt) + throws JsonMappingException { + throw new JsonMappingException( + ctxt.getParser(), "SvamlActionPatchInternalImpl cannot be null"); + } + } + + // store a list of schema names defined in oneOf + public static final Map> schemas = new HashMap<>(); + + public SvamlActionPatchInternalImpl() { + super("oneOf", Boolean.FALSE); + } + + public SvamlActionPatchInternalImpl(SvamlActionContinueImpl o) { + super("oneOf", Boolean.FALSE); + setActualInstance(o); + } + + public SvamlActionPatchInternalImpl(SvamlActionHangupImpl o) { + super("oneOf", Boolean.FALSE); + setActualInstance(o); + } + + public SvamlActionPatchInternalImpl(SvamlActionParkImpl o) { + super("oneOf", Boolean.FALSE); + setActualInstance(o); + } + + static { + schemas.put("SvamlActionContinueImpl", SvamlActionContinueImpl.class); + schemas.put("SvamlActionHangupImpl", SvamlActionHangupImpl.class); + schemas.put("SvamlActionParkImpl", SvamlActionParkImpl.class); + JSONNavigator.registerDescendants( + SvamlActionPatchInternalImpl.class, Collections.unmodifiableMap(schemas)); + // Initialize and register the discriminator mappings. + Map> mappings = new HashMap>(); + mappings.put("continue", SvamlActionContinueImpl.class); + mappings.put("hangup", SvamlActionHangupImpl.class); + mappings.put("park", SvamlActionParkImpl.class); + mappings.put("svaml.action.patch", SvamlActionPatchInternalImpl.class); + JSONNavigator.registerDiscriminator(SvamlActionPatchInternalImpl.class, "name", mappings); + } + + @Override + public Map> getSchemas() { + return SvamlActionPatchInternalImpl.schemas; + } + + /** + * Set the instance that matches the oneOf child schema, check the instance parameter is valid + * against the oneOf child schemas: SvamlActionContinueImpl, SvamlActionHangupImpl, + * SvamlActionParkImpl + * + *

It could be an instance of the 'oneOf' schemas. The oneOf child schemas may themselves be a + * composed schema (allOf, anyOf, oneOf). + */ + @Override + public void setActualInstance(Object instance) { + if (JSONNavigator.isInstanceOf( + SvamlActionContinueImpl.class, instance, new HashSet>())) { + super.setActualInstance(instance); + return; + } + + if (JSONNavigator.isInstanceOf( + SvamlActionHangupImpl.class, instance, new HashSet>())) { + super.setActualInstance(instance); + return; + } + + if (JSONNavigator.isInstanceOf(SvamlActionParkImpl.class, instance, new HashSet>())) { + super.setActualInstance(instance); + return; + } + + throw new RuntimeException( + "Invalid instance type. Must be SvamlActionContinueImpl, SvamlActionHangupImpl," + + " SvamlActionParkImpl"); + } + + /** + * Get the actual instance, which can be the following: SvamlActionContinueImpl, + * SvamlActionHangupImpl, SvamlActionParkImpl + * + * @return The actual instance (SvamlActionContinueImpl, SvamlActionHangupImpl, + * SvamlActionParkImpl) + */ + @Override + public Object getActualInstance() { + return super.getActualInstance(); + } + + /** + * Get the actual instance of `SvamlActionContinueImpl`. If the actual instance is not + * `SvamlActionContinueImpl`, the ClassCastException will be thrown. + * + * @return The actual instance of `SvamlActionContinueImpl` + * @throws ClassCastException if the instance is not `SvamlActionContinueImpl` + */ + public SvamlActionContinueImpl getSvamlActionContinueImpl() throws ClassCastException { + return (SvamlActionContinueImpl) super.getActualInstance(); + } + + /** + * Get the actual instance of `SvamlActionHangupImpl`. If the actual instance is not + * `SvamlActionHangupImpl`, the ClassCastException will be thrown. + * + * @return The actual instance of `SvamlActionHangupImpl` + * @throws ClassCastException if the instance is not `SvamlActionHangupImpl` + */ + public SvamlActionHangupImpl getSvamlActionHangupImpl() throws ClassCastException { + return (SvamlActionHangupImpl) super.getActualInstance(); + } + + /** + * Get the actual instance of `SvamlActionParkImpl`. If the actual instance is not + * `SvamlActionParkImpl`, the ClassCastException will be thrown. + * + * @return The actual instance of `SvamlActionParkImpl` + * @throws ClassCastException if the instance is not `SvamlActionParkImpl` + */ + public SvamlActionParkImpl getSvamlActionParkImpl() throws ClassCastException { + return (SvamlActionParkImpl) super.getActualInstance(); + } +} diff --git a/openapi-contracts/src/test/java/com/sinch/sdk/domains/conversation/models/v1/consents/ConsentsDtoTest.java b/openapi-contracts/src/test/java/com/sinch/sdk/domains/conversation/models/v1/consents/ConsentsDtoTest.java new file mode 100644 index 000000000..b9d25f487 --- /dev/null +++ b/openapi-contracts/src/test/java/com/sinch/sdk/domains/conversation/models/v1/consents/ConsentsDtoTest.java @@ -0,0 +1,79 @@ +package com.sinch.sdk.domains.conversation.models.v1.consents; + +import com.adelean.inject.resources.junit.jupiter.GivenJsonResource; +import com.adelean.inject.resources.junit.jupiter.TestWithResources; +import com.sinch.sdk.core.TestHelpers; +import com.sinch.sdk.domains.conversation.api.v1.adapters.ConversationBaseTest; +import com.sinch.sdk.domains.conversation.models.v1.consents.internal.ConsentsListResponseInternal; +import com.sinch.sdk.domains.conversation.models.v1.consents.response.AuditRecord; +import com.sinch.sdk.domains.conversation.models.v1.consents.response.AuditRecordsResponse; +import java.time.Instant; +import java.util.Arrays; +import java.util.Collections; +import org.junit.jupiter.api.Test; + +@TestWithResources +public class ConsentsDtoTest extends ConversationBaseTest { + + @GivenJsonResource("/domains/conversation/v1/consents/ConsentsListResponseDtoPage0.json") + ConsentsListResponseInternal loadedConsentsListResponseDtoPage0; + + @GivenJsonResource("/domains/conversation/v1/consents/ConsentsListResponseDtoPage1.json") + ConsentsListResponseInternal loadedConsentsListResponseDtoPage1; + + @GivenJsonResource("/domains/conversation/v1/consents/AuditRecordsResponseDto.json") + AuditRecordsResponse loadedAuditRecordsResponseDto; + + public static Identity expectedIdentityDto = + Identity.builder().setIdentity("an identity value").build(); + + public static ConsentsListResponseInternal expectedConsentsListResponseDtoPage0 = + ConsentsListResponseInternal.builder() + .setIdentities( + Arrays.asList( + expectedIdentityDto, + Identity.builder().setIdentity("a 2nd identity value").build())) + .setNextPageToken("the next page token value") + .build(); + + public static ConsentsListResponseInternal expectedConsentsListResponseDtoPage1 = + ConsentsListResponseInternal.builder() + .setIdentities( + Collections.singletonList( + Identity.builder().setIdentity("a 3rd identity value").build())) + .setNextPageToken("") + .build(); + + public static AuditRecord expectedAuditRecordDto = + AuditRecord.builder() + .setOrigin(AuditRecord.OriginEnum.ORIGIN_API) + .setOperation(AuditRecord.OperationEnum.OPERATION_INSERT) + .setListType(ConsentsListType.OPT_OUT_ALL) + .setProjectId("a project id") + .setAppId("an app id") + .setDatetime(Instant.parse("2025-06-06T14:42:56.031323Z")) + .build(); + + public static AuditRecordsResponse expectedAuditRecordsResponseDto = + AuditRecordsResponse.builder() + .setIdentity(expectedIdentityDto) + .setAuditRecords(Collections.singletonList(expectedAuditRecordDto)) + .build(); + + @Test + void deserializeConsentsListResponseDtoPage0() { + TestHelpers.recursiveEquals( + loadedConsentsListResponseDtoPage0, expectedConsentsListResponseDtoPage0); + } + + @Test + void deserializeConsentsListResponseDtoPage1() { + TestHelpers.recursiveEquals( + loadedConsentsListResponseDtoPage1, expectedConsentsListResponseDtoPage1); + } + + @Test + void deserializeAuditRecordsResponseDto() { + TestHelpers.recursiveEquals(loadedAuditRecordsResponseDto, expectedAuditRecordsResponseDto); + } +} diff --git a/openapi-contracts/src/test/java/com/sinch/sdk/domains/conversation/templates/models/v2/TemplateTranslationDtoTest.java b/openapi-contracts/src/test/java/com/sinch/sdk/domains/conversation/templates/models/v2/TemplateTranslationDtoTest.java index b993ba5d5..eefd2c69b 100644 --- a/openapi-contracts/src/test/java/com/sinch/sdk/domains/conversation/templates/models/v2/TemplateTranslationDtoTest.java +++ b/openapi-contracts/src/test/java/com/sinch/sdk/domains/conversation/templates/models/v2/TemplateTranslationDtoTest.java @@ -18,7 +18,19 @@ @TestWithResources public class TemplateTranslationDtoTest extends TemplatesBaseTest { - public static TemplateTranslation expectedDto = + public static TemplateTranslation expectedRequestDto = + TemplateTranslation.builder() + .setMessage(TemplateMessageDtoTest.templateMessageDto) + .setLanguageCode("fr-FR") + .setVersion("1") + .setChannelTemplateOverrides( + Collections.singletonMap( + ConversationChannel.KAKAOTALK, + ChannelTemplateOverrideDtoTest.expectedWithVersionDto)) + .setVariables(Arrays.asList(TemplateVariableDtoTest.expectedDto)) + .build(); + + public static TemplateTranslation expectedResponseDto = TemplateTranslation.builder() .setMessage(TemplateMessageDtoTest.templateMessageDto) .setLanguageCode("fr-FR") @@ -32,20 +44,25 @@ public class TemplateTranslationDtoTest extends TemplatesBaseTest { .setUpdateTime(Instant.parse("2024-07-07T06:07:44Z")) .build(); - @GivenTextResource("/domains/conversation/templates/v2/TemplateTranslationDto.json") - String json; + @GivenTextResource( + "/domains/conversation/templates/v2/request/TemplateTranslationV2RequestDto.json") + String jsonRequest; + + @GivenTextResource( + "/domains/conversation/templates/v2/response/TemplateTranslationV2ResponseDto.json") + String jsonResponse; @Test void serialize() throws JsonProcessingException, JSONException { - String serializedString = objectMapper.writeValueAsString(expectedDto); + String serializedString = objectMapper.writeValueAsString(expectedRequestDto); - JSONAssert.assertEquals(json, serializedString, true); + JSONAssert.assertEquals(jsonRequest, serializedString, true); } @Test void deserialize() throws JsonProcessingException { - Object deserialized = objectMapper.readValue(json, TemplateTranslation.class); + Object deserialized = objectMapper.readValue(jsonResponse, TemplateTranslation.class); - TestHelpers.recursiveEquals(deserialized, expectedDto); + TestHelpers.recursiveEquals(deserialized, expectedResponseDto); } } diff --git a/openapi-contracts/src/test/java/com/sinch/sdk/domains/conversation/templates/models/v2/TemplateV2DtoTest.java b/openapi-contracts/src/test/java/com/sinch/sdk/domains/conversation/templates/models/v2/TemplateV2DtoTest.java index 88fb8800e..e552014c3 100644 --- a/openapi-contracts/src/test/java/com/sinch/sdk/domains/conversation/templates/models/v2/TemplateV2DtoTest.java +++ b/openapi-contracts/src/test/java/com/sinch/sdk/domains/conversation/templates/models/v2/TemplateV2DtoTest.java @@ -17,13 +17,22 @@ public class TemplateV2DtoTest extends TemplatesBaseTest { @GivenTextResource("/domains/conversation/templates/v2/request/TemplateV2RequestDto.json") String requestJSON; - @GivenTextResource("/domains/conversation/templates/v2/TemplateV2Dto.json") - String responseSON; + @GivenTextResource("/domains/conversation/templates/v2/response/TemplateV2ResponseDto.json") + String responseJSON; - public static TemplateV2 expectedDto = + public static TemplateV2 expectedRequestDto = TemplateV2.builder() .setId("template ID") - .setTranslations(Arrays.asList(TemplateTranslationDtoTest.expectedDto)) + .setTranslations(Arrays.asList(TemplateTranslationDtoTest.expectedRequestDto)) + .setDefaultTranslation("fr-FR") + .setDescription("template description value") + .setVersion(1) + .build(); + + public static TemplateV2 expectedResponseDto = + TemplateV2.builder() + .setId("template ID") + .setTranslations(Arrays.asList(TemplateTranslationDtoTest.expectedResponseDto)) .setDefaultTranslation("fr-FR") .setDescription("template description value") .setVersion(1) @@ -33,15 +42,15 @@ public class TemplateV2DtoTest extends TemplatesBaseTest { @Test void serialize() throws JsonProcessingException, JSONException { - String serializedString = objectMapper.writeValueAsString(expectedDto); + String serializedString = objectMapper.writeValueAsString(expectedRequestDto); JSONAssert.assertEquals(requestJSON, serializedString, true); } @Test void deserialize() throws JsonProcessingException { - Object deserialized = objectMapper.readValue(responseSON, TemplateV2.class); + Object deserialized = objectMapper.readValue(responseJSON, TemplateV2.class); - TestHelpers.recursiveEquals(deserialized, expectedDto); + TestHelpers.recursiveEquals(deserialized, expectedResponseDto); } } diff --git a/openapi-contracts/src/test/java/com/sinch/sdk/domains/conversation/templates/models/v2/response/TemplatesV2ListResponseDtoTest.java b/openapi-contracts/src/test/java/com/sinch/sdk/domains/conversation/templates/models/v2/response/TemplatesV2ListResponseDtoTest.java index 13f169c23..0f8b93aa9 100644 --- a/openapi-contracts/src/test/java/com/sinch/sdk/domains/conversation/templates/models/v2/response/TemplatesV2ListResponseDtoTest.java +++ b/openapi-contracts/src/test/java/com/sinch/sdk/domains/conversation/templates/models/v2/response/TemplatesV2ListResponseDtoTest.java @@ -15,7 +15,7 @@ public class TemplatesV2ListResponseDtoTest extends TemplatesBaseTest { public static ListTemplatesResponseInternal expectedDto = ListTemplatesResponseInternal.builder() - .setTemplates(Arrays.asList(TemplateV2DtoTest.expectedDto)) + .setTemplates(Arrays.asList(TemplateV2DtoTest.expectedResponseDto)) .build(); @GivenTextResource("/domains/conversation/templates/v2/response/TemplatesV2ListResponseDto.json") diff --git a/openapi-contracts/src/test/java/com/sinch/sdk/domains/conversation/templates/models/v2/response/TranslationsV2ListResponseDtoTest.java b/openapi-contracts/src/test/java/com/sinch/sdk/domains/conversation/templates/models/v2/response/TranslationsV2ListResponseDtoTest.java index d9d17bf74..5890dc13a 100644 --- a/openapi-contracts/src/test/java/com/sinch/sdk/domains/conversation/templates/models/v2/response/TranslationsV2ListResponseDtoTest.java +++ b/openapi-contracts/src/test/java/com/sinch/sdk/domains/conversation/templates/models/v2/response/TranslationsV2ListResponseDtoTest.java @@ -8,29 +8,20 @@ import com.sinch.sdk.domains.conversation.templates.models.v2.TemplateTranslationDtoTest; import com.sinch.sdk.domains.conversation.templates.models.v2.internal.ListTranslationsResponseInternal; import java.util.Arrays; -import org.json.JSONException; import org.junit.jupiter.api.Test; -import org.skyscreamer.jsonassert.JSONAssert; @TestWithResources public class TranslationsV2ListResponseDtoTest extends TemplatesBaseTest { public static ListTranslationsResponseInternal expectedDto = ListTranslationsResponseInternal.builder() - .setTranslations(Arrays.asList(TemplateTranslationDtoTest.expectedDto)) + .setTranslations(Arrays.asList(TemplateTranslationDtoTest.expectedResponseDto)) .build(); @GivenTextResource( "/domains/conversation/templates/v2/response/TranslationsV2ListResponseDto.json") String json; - @Test - void serialize() throws JsonProcessingException, JSONException { - String serializedString = objectMapper.writeValueAsString(expectedDto); - - JSONAssert.assertEquals(json, serializedString, true); - } - @Test void deserialize() throws JsonProcessingException { Object deserialized = objectMapper.readValue(json, ListTranslationsResponseInternal.class); diff --git a/openapi-contracts/src/test/java/com/sinch/sdk/domains/numberlookup/models/v2/errors/LookupErrorDtoTest.java b/openapi-contracts/src/test/java/com/sinch/sdk/domains/numberlookup/models/v2/errors/LookupErrorDtoTest.java new file mode 100644 index 000000000..faf6e7261 --- /dev/null +++ b/openapi-contracts/src/test/java/com/sinch/sdk/domains/numberlookup/models/v2/errors/LookupErrorDtoTest.java @@ -0,0 +1,42 @@ +package com.sinch.sdk.domains.numberlookup.models.v2.errors; + +import com.adelean.inject.resources.junit.jupiter.GivenTextResource; +import com.adelean.inject.resources.junit.jupiter.TestWithResources; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.sinch.sdk.BaseTest; +import com.sinch.sdk.core.TestHelpers; +import org.junit.jupiter.api.Test; + +@TestWithResources +public class LookupErrorDtoTest extends BaseTest { + + public static LookupError lookupErrorDto = + LookupError.builder() + .setStatus(100) + .setTitle("Feature Disabled") + .setDetail("VoIPDetection feature is currently disabled.") + .setType("validation_error") + .build(); + + public static LookupError lookupErrorEmptyDto = LookupError.builder().build(); + + @GivenTextResource("/domains/numberlookup/v2/errors/LookupErrorDto.json") + String jsonLookupErrorDto; + + @GivenTextResource("/domains/numberlookup/v2/errors/LookupErrorEmptyDto.json") + String jsonLookupErrorEmptyDto; + + @Test + void deserializeDto() throws JsonProcessingException { + LookupError deserialized = objectMapper.readValue(jsonLookupErrorDto, LookupError.class); + + TestHelpers.recursiveEquals(deserialized, lookupErrorDto); + } + + @Test + void deserializeEmptyDto() throws JsonProcessingException { + LookupError deserialized = objectMapper.readValue(jsonLookupErrorEmptyDto, LookupError.class); + + TestHelpers.recursiveEquals(deserialized, lookupErrorEmptyDto); + } +} diff --git a/openapi-contracts/src/test/java/com/sinch/sdk/domains/numberlookup/models/v2/errors/ProblemDetailsDtoTest.java b/openapi-contracts/src/test/java/com/sinch/sdk/domains/numberlookup/models/v2/errors/ProblemDetailsDtoTest.java new file mode 100644 index 000000000..d94af3def --- /dev/null +++ b/openapi-contracts/src/test/java/com/sinch/sdk/domains/numberlookup/models/v2/errors/ProblemDetailsDtoTest.java @@ -0,0 +1,31 @@ +package com.sinch.sdk.domains.numberlookup.models.v2.errors; + +import com.adelean.inject.resources.junit.jupiter.GivenTextResource; +import com.adelean.inject.resources.junit.jupiter.TestWithResources; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.sinch.sdk.BaseTest; +import com.sinch.sdk.core.TestHelpers; +import org.junit.jupiter.api.Test; + +@TestWithResources +public class ProblemDetailsDtoTest extends BaseTest { + + public static ProblemDetails problemDetailsDto = + ProblemDetails.builder() + .setType("https://developers.sinch.com/docs/lookup/api/errors/validation") + .setTitle("Validation error") + .setStatus(400) + .setTraceId("84c1fd4063c38d9f3900d06e56542d48") + .build(); + + @GivenTextResource("/domains/numberlookup/v2/errors/ProblemDetailsDto.json") + String jsonProblemDetailsDto; + + @Test + void deserializeDto() throws JsonProcessingException { + ProblemDetails deserialized = + objectMapper.readValue(jsonProblemDetailsDto, ProblemDetails.class); + + TestHelpers.recursiveEquals(deserialized, problemDetailsDto); + } +} diff --git a/openapi-contracts/src/test/java/com/sinch/sdk/domains/numberlookup/models/v2/request/NumberLookupRequestDtoTest.java b/openapi-contracts/src/test/java/com/sinch/sdk/domains/numberlookup/models/v2/request/NumberLookupRequestDtoTest.java new file mode 100644 index 000000000..8d20f0465 --- /dev/null +++ b/openapi-contracts/src/test/java/com/sinch/sdk/domains/numberlookup/models/v2/request/NumberLookupRequestDtoTest.java @@ -0,0 +1,120 @@ +package com.sinch.sdk.domains.numberlookup.models.v2.request; + +import com.adelean.inject.resources.junit.jupiter.GivenTextResource; +import com.adelean.inject.resources.junit.jupiter.TestWithResources; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.sinch.sdk.BaseTest; +import com.sinch.sdk.core.TestHelpers; +import java.time.LocalDate; +import java.util.Arrays; +import org.json.JSONException; +import org.junit.jupiter.api.Test; +import org.skyscreamer.jsonassert.JSONAssert; + +@TestWithResources +public class NumberLookupRequestDtoTest extends BaseTest { + + public static NumberLookupRequest numberLookupRequestMinimalDto = + NumberLookupRequest.builder().setNumber("+15551234567").build(); + + public static NumberLookupRequest numberLookupRequestWithFeaturesDto = + NumberLookupRequest.builder() + .setNumber("+15552345678") + .setFeatures( + Arrays.asList( + LookupFeatureType.LINE_TYPE, + LookupFeatureType.SIM_SWAP, + LookupFeatureType.VO_IP_DETECTION)) + .build(); + + public static NumberLookupRequest numberLookupRequestWithRndOptionsDto = + NumberLookupRequest.builder() + .setNumber("+15553456789") + .setFeatures(Arrays.asList(LookupFeatureType.RND)) + .setRndFeatureOptions( + RndFeatureOptions.builder().setContactDate(LocalDate.parse("2025-01-01")).build()) + .build(); + + public static NumberLookupRequest numberLookupRequestAllFeaturesDto = + NumberLookupRequest.builder() + .setNumber("+15554567890") + .setFeatures( + Arrays.asList( + LookupFeatureType.LINE_TYPE, + LookupFeatureType.SIM_SWAP, + LookupFeatureType.VO_IP_DETECTION, + LookupFeatureType.RND)) + .build(); + + @GivenTextResource("/domains/numberlookup/v2/request/NumberLookupRequestMinimalDto.json") + String jsonNumberLookupRequestMinimalDto; + + @GivenTextResource("/domains/numberlookup/v2/request/NumberLookupRequestWithFeaturesDto.json") + String jsonNumberLookupRequestWithFeaturesDto; + + @GivenTextResource("/domains/numberlookup/v2/request/NumberLookupRequestWithRndOptionsDto.json") + String jsonNumberLookupRequestWithRndOptionsDto; + + @GivenTextResource("/domains/numberlookup/v2/request/NumberLookupRequestAllFeaturesDto.json") + String jsonNumberLookupRequestAllFeaturesDto; + + @Test + void serializeMinimalDto() throws JsonProcessingException, JSONException { + String serializedString = objectMapper.writeValueAsString(numberLookupRequestMinimalDto); + + JSONAssert.assertEquals(jsonNumberLookupRequestMinimalDto, serializedString, true); + } + + @Test + void deserializeMinimalDto() throws JsonProcessingException { + NumberLookupRequest deserialized = + objectMapper.readValue(jsonNumberLookupRequestMinimalDto, NumberLookupRequest.class); + + TestHelpers.recursiveEquals(deserialized, numberLookupRequestMinimalDto); + } + + @Test + void serializeWithFeaturesDto() throws JsonProcessingException, JSONException { + String serializedString = objectMapper.writeValueAsString(numberLookupRequestWithFeaturesDto); + + JSONAssert.assertEquals(jsonNumberLookupRequestWithFeaturesDto, serializedString, true); + } + + @Test + void deserializeWithFeaturesDto() throws JsonProcessingException { + NumberLookupRequest deserialized = + objectMapper.readValue(jsonNumberLookupRequestWithFeaturesDto, NumberLookupRequest.class); + + TestHelpers.recursiveEquals(deserialized, numberLookupRequestWithFeaturesDto); + } + + @Test + void serializeWithRndOptionsDto() throws JsonProcessingException, JSONException { + String serializedString = objectMapper.writeValueAsString(numberLookupRequestWithRndOptionsDto); + + JSONAssert.assertEquals(jsonNumberLookupRequestWithRndOptionsDto, serializedString, true); + } + + @Test + void deserializeWithRndOptionsDto() throws JsonProcessingException { + NumberLookupRequest deserialized = + objectMapper.readValue(jsonNumberLookupRequestWithRndOptionsDto, NumberLookupRequest.class); + + TestHelpers.recursiveEquals(deserialized, numberLookupRequestWithRndOptionsDto); + } + + @Test + void serializeAllFeaturesDto() throws JsonProcessingException, JSONException { + String serializedString = objectMapper.writeValueAsString(numberLookupRequestAllFeaturesDto); + + JSONAssert.assertEquals(jsonNumberLookupRequestAllFeaturesDto, serializedString, true); + } + + @Test + void deserializeAllFeaturesDto() throws JsonProcessingException { + NumberLookupRequest deserialized = + objectMapper.readValue(jsonNumberLookupRequestAllFeaturesDto, NumberLookupRequest.class); + + TestHelpers.recursiveEquals(deserialized, numberLookupRequestAllFeaturesDto); + } +} diff --git a/openapi-contracts/src/test/java/com/sinch/sdk/domains/numberlookup/models/v2/request/RndFeatureOptionsDtoTest.java b/openapi-contracts/src/test/java/com/sinch/sdk/domains/numberlookup/models/v2/request/RndFeatureOptionsDtoTest.java new file mode 100644 index 000000000..305d7d031 --- /dev/null +++ b/openapi-contracts/src/test/java/com/sinch/sdk/domains/numberlookup/models/v2/request/RndFeatureOptionsDtoTest.java @@ -0,0 +1,36 @@ +package com.sinch.sdk.domains.numberlookup.models.v2.request; + +import com.adelean.inject.resources.junit.jupiter.GivenTextResource; +import com.adelean.inject.resources.junit.jupiter.TestWithResources; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.sinch.sdk.BaseTest; +import com.sinch.sdk.core.TestHelpers; +import java.time.LocalDate; +import org.json.JSONException; +import org.junit.jupiter.api.Test; +import org.skyscreamer.jsonassert.JSONAssert; + +@TestWithResources +public class RndFeatureOptionsDtoTest extends BaseTest { + + public static RndFeatureOptions rndFeatureOptionsDto = + RndFeatureOptions.builder().setContactDate(LocalDate.parse("2025-01-15")).build(); + + @GivenTextResource("/domains/numberlookup/v2/request/RndFeatureOptionsDto.json") + String jsonRndFeatureOptionsDto; + + @Test + void serializeDto() throws JsonProcessingException, JSONException { + String serializedString = objectMapper.writeValueAsString(rndFeatureOptionsDto); + + JSONAssert.assertEquals(jsonRndFeatureOptionsDto, serializedString, true); + } + + @Test + void deserializeDto() throws JsonProcessingException { + RndFeatureOptions deserialized = + objectMapper.readValue(jsonRndFeatureOptionsDto, RndFeatureOptions.class); + + TestHelpers.recursiveEquals(deserialized, rndFeatureOptionsDto); + } +} diff --git a/openapi-contracts/src/test/java/com/sinch/sdk/domains/numberlookup/models/v2/response/LineResponseDtoTest.java b/openapi-contracts/src/test/java/com/sinch/sdk/domains/numberlookup/models/v2/response/LineResponseDtoTest.java new file mode 100644 index 000000000..b16e73c01 --- /dev/null +++ b/openapi-contracts/src/test/java/com/sinch/sdk/domains/numberlookup/models/v2/response/LineResponseDtoTest.java @@ -0,0 +1,54 @@ +package com.sinch.sdk.domains.numberlookup.models.v2.response; + +import com.adelean.inject.resources.junit.jupiter.GivenTextResource; +import com.adelean.inject.resources.junit.jupiter.TestWithResources; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.sinch.sdk.BaseTest; +import com.sinch.sdk.core.TestHelpers; +import java.time.Instant; +import org.json.JSONException; +import org.junit.jupiter.api.Test; +import org.skyscreamer.jsonassert.JSONAssert; + +@TestWithResources +public class LineResponseDtoTest extends BaseTest { + + public static Line lineResponseDto = + Line.builder() + .setCarrier("T-Mobile USA") + .setType(LineType.MOBILE) + .setMobileCountryCode("310") + .setMobileNetworkCode("260") + .setPorted(true) + .setPortingDate(Instant.parse("2024-06-15T14:30:00Z")) + .build(); + + public static Line lineResponseEmptyDto = Line.builder().build(); + + @GivenTextResource("/domains/numberlookup/v2/response/LineResponseDto.json") + String jsonLineResponseDto; + + @GivenTextResource("/domains/numberlookup/v2/response/LineResponseEmptyDto.json") + String jsonLineResponseEmptyDto; + + @Test + void serializeDto() throws JsonProcessingException, JSONException { + String serializedString = objectMapper.writeValueAsString(lineResponseDto); + + JSONAssert.assertEquals(jsonLineResponseDto, serializedString, true); + } + + @Test + void deserializeDto() throws JsonProcessingException { + Line deserialized = objectMapper.readValue(jsonLineResponseDto, Line.class); + + TestHelpers.recursiveEquals(deserialized, lineResponseDto); + } + + @Test + void deserializeEmptyDto() throws JsonProcessingException { + Line deserialized = objectMapper.readValue(jsonLineResponseEmptyDto, Line.class); + + TestHelpers.recursiveEquals(deserialized, lineResponseEmptyDto); + } +} diff --git a/openapi-contracts/src/test/java/com/sinch/sdk/domains/numberlookup/models/v2/response/NumberLookupResponseDtoTest.java b/openapi-contracts/src/test/java/com/sinch/sdk/domains/numberlookup/models/v2/response/NumberLookupResponseDtoTest.java new file mode 100644 index 000000000..1aa55dbc4 --- /dev/null +++ b/openapi-contracts/src/test/java/com/sinch/sdk/domains/numberlookup/models/v2/response/NumberLookupResponseDtoTest.java @@ -0,0 +1,63 @@ +package com.sinch.sdk.domains.numberlookup.models.v2.response; + +import com.adelean.inject.resources.junit.jupiter.GivenTextResource; +import com.adelean.inject.resources.junit.jupiter.TestWithResources; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.sinch.sdk.BaseTest; +import com.sinch.sdk.core.TestHelpers; +import java.time.Instant; +import org.junit.jupiter.api.Test; + +@TestWithResources +public class NumberLookupResponseDtoTest extends BaseTest { + + public static NumberLookupResponse numberLookupResponseMinimalDto = + NumberLookupResponse.builder() + .setNumber("+15551234567") + .setCountryCode("US") + .setTraceId("test-trace-id") + .build(); + + public static NumberLookupResponse numberLookupResponseFullDto = + NumberLookupResponse.builder() + .setLine( + Line.builder() + .setCarrier("T-Mobile USA") + .setType(LineType.MOBILE) + .setMobileCountryCode("310") + .setMobileNetworkCode("260") + .setPorted(true) + .setPortingDate(Instant.parse("2024-08-20T10:15:30Z")) + .build()) + .setSimSwap( + SimSwap.builder().setSwapped(true).setSwapPeriod(SwapPeriodType.SP24_H).build()) + .setVoIPDetection( + VoIPDetection.builder().setProbability(VoIPProbabilityType.HIGH).build()) + .setRnd(Rnd.builder().setDisconnected(true).build()) + .setCountryCode("US") + .setTraceId("84c1fd4063c38d9f3900d06e56542d48") + .setNumber("+15557890123") + .build(); + + @GivenTextResource("/domains/numberlookup/v2/response/NumberLookupResponseMinimalDto.json") + String jsonNumberLookupResponseMinimalDto; + + @GivenTextResource("/domains/numberlookup/v2/response/NumberLookupResponseFullDto.json") + String jsonNumberLookupResponseFullDto; + + @Test + void deserializeMinimalDto() throws JsonProcessingException { + NumberLookupResponse deserialized = + objectMapper.readValue(jsonNumberLookupResponseMinimalDto, NumberLookupResponse.class); + + TestHelpers.recursiveEquals(deserialized, numberLookupResponseMinimalDto); + } + + @Test + void deserializeFullDto() throws JsonProcessingException { + NumberLookupResponse deserialized = + objectMapper.readValue(jsonNumberLookupResponseFullDto, NumberLookupResponse.class); + + TestHelpers.recursiveEquals(deserialized, numberLookupResponseFullDto); + } +} diff --git a/openapi-contracts/src/test/java/com/sinch/sdk/domains/numberlookup/models/v2/response/RndResponseDtoTest.java b/openapi-contracts/src/test/java/com/sinch/sdk/domains/numberlookup/models/v2/response/RndResponseDtoTest.java new file mode 100644 index 000000000..36f25d8e4 --- /dev/null +++ b/openapi-contracts/src/test/java/com/sinch/sdk/domains/numberlookup/models/v2/response/RndResponseDtoTest.java @@ -0,0 +1,45 @@ +package com.sinch.sdk.domains.numberlookup.models.v2.response; + +import com.adelean.inject.resources.junit.jupiter.GivenTextResource; +import com.adelean.inject.resources.junit.jupiter.TestWithResources; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.sinch.sdk.BaseTest; +import com.sinch.sdk.core.TestHelpers; +import org.json.JSONException; +import org.junit.jupiter.api.Test; +import org.skyscreamer.jsonassert.JSONAssert; + +@TestWithResources +public class RndResponseDtoTest extends BaseTest { + + public static Rnd rndResponseDto = Rnd.builder().setDisconnected(true).build(); + + public static Rnd rndResponseEmptyDto = Rnd.builder().build(); + + @GivenTextResource("/domains/numberlookup/v2/response/RndResponseDto.json") + String jsonRndResponseDto; + + @GivenTextResource("/domains/numberlookup/v2/response/RndResponseEmptyDto.json") + String jsonRndResponseEmptyDto; + + @Test + void serializeDto() throws JsonProcessingException, JSONException { + String serializedString = objectMapper.writeValueAsString(rndResponseDto); + + JSONAssert.assertEquals(jsonRndResponseDto, serializedString, true); + } + + @Test + void deserializeDto() throws JsonProcessingException { + Rnd deserialized = objectMapper.readValue(jsonRndResponseDto, Rnd.class); + + TestHelpers.recursiveEquals(deserialized, rndResponseDto); + } + + @Test + void deserializeEmptyDto() throws JsonProcessingException { + Rnd deserialized = objectMapper.readValue(jsonRndResponseEmptyDto, Rnd.class); + + TestHelpers.recursiveEquals(deserialized, rndResponseEmptyDto); + } +} diff --git a/openapi-contracts/src/test/java/com/sinch/sdk/domains/numberlookup/models/v2/response/SimSwapResponseDtoTest.java b/openapi-contracts/src/test/java/com/sinch/sdk/domains/numberlookup/models/v2/response/SimSwapResponseDtoTest.java new file mode 100644 index 000000000..ff7a6d510 --- /dev/null +++ b/openapi-contracts/src/test/java/com/sinch/sdk/domains/numberlookup/models/v2/response/SimSwapResponseDtoTest.java @@ -0,0 +1,62 @@ +package com.sinch.sdk.domains.numberlookup.models.v2.response; + +import com.adelean.inject.resources.junit.jupiter.GivenTextResource; +import com.adelean.inject.resources.junit.jupiter.TestWithResources; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.sinch.sdk.BaseTest; +import com.sinch.sdk.core.TestHelpers; +import com.sinch.sdk.domains.numberlookup.models.v2.errors.LookupError; +import org.json.JSONException; +import org.junit.jupiter.api.Test; +import org.skyscreamer.jsonassert.JSONAssert; + +@TestWithResources +public class SimSwapResponseDtoTest extends BaseTest { + + public static SimSwap simSwapResponseDto = + SimSwap.builder().setSwapped(true).setSwapPeriod(SwapPeriodType.SP24_H).build(); + + public static SimSwap simSwapResponseWithErrorDto = + SimSwap.builder() + .setError( + LookupError.builder() + .setStatus(100) + .setTitle("Feature Disabled") + .setDetail("SimSwap feature is currently disabled.") + .build()) + .build(); + + @GivenTextResource("/domains/numberlookup/v2/response/SimSwapResponseDto.json") + String jsonSimSwapDto; + + @GivenTextResource("/domains/numberlookup/v2/response/SimSwapResponseWithErrorDto.json") + String jsonSimSwapWithErrorDto; + + @Test + void serializeDto() throws JsonProcessingException, JSONException { + String serializedString = objectMapper.writeValueAsString(simSwapResponseDto); + + JSONAssert.assertEquals(jsonSimSwapDto, serializedString, true); + } + + @Test + void deserializeDto() throws JsonProcessingException { + SimSwap deserialized = objectMapper.readValue(jsonSimSwapDto, SimSwap.class); + + TestHelpers.recursiveEquals(deserialized, simSwapResponseDto); + } + + @Test + void serializeWithErrorDto() throws JsonProcessingException, JSONException { + String serializedString = objectMapper.writeValueAsString(simSwapResponseWithErrorDto); + + JSONAssert.assertEquals(jsonSimSwapWithErrorDto, serializedString, true); + } + + @Test + void deserializeWithErrorDto() throws JsonProcessingException { + SimSwap deserialized = objectMapper.readValue(jsonSimSwapWithErrorDto, SimSwap.class); + + TestHelpers.recursiveEquals(deserialized, simSwapResponseWithErrorDto); + } +} diff --git a/openapi-contracts/src/test/java/com/sinch/sdk/domains/numberlookup/models/v2/response/VoIPDetectionResponseDtoTest.java b/openapi-contracts/src/test/java/com/sinch/sdk/domains/numberlookup/models/v2/response/VoIPDetectionResponseDtoTest.java new file mode 100644 index 000000000..d7e86ef47 --- /dev/null +++ b/openapi-contracts/src/test/java/com/sinch/sdk/domains/numberlookup/models/v2/response/VoIPDetectionResponseDtoTest.java @@ -0,0 +1,47 @@ +package com.sinch.sdk.domains.numberlookup.models.v2.response; + +import com.adelean.inject.resources.junit.jupiter.GivenTextResource; +import com.adelean.inject.resources.junit.jupiter.TestWithResources; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.sinch.sdk.BaseTest; +import com.sinch.sdk.core.TestHelpers; +import org.json.JSONException; +import org.junit.jupiter.api.Test; +import org.skyscreamer.jsonassert.JSONAssert; + +@TestWithResources +public class VoIPDetectionResponseDtoTest extends BaseTest { + + public static VoIPDetection voIPDetectionResponseDto = + VoIPDetection.builder().setProbability(VoIPProbabilityType.HIGH).build(); + + public static VoIPDetection voIPDetectionResponseEmptyDto = VoIPDetection.builder().build(); + + @GivenTextResource("/domains/numberlookup/v2/response/VoIPDetectionResponseDto.json") + String jsonVoIPDetectionDto; + + @GivenTextResource("/domains/numberlookup/v2/response/VoIPDetectionResponseEmptyDto.json") + String jsonVoIPDetectionEmptyDto; + + @Test + void serializeDto() throws JsonProcessingException, JSONException { + String serializedString = objectMapper.writeValueAsString(voIPDetectionResponseDto); + + JSONAssert.assertEquals(jsonVoIPDetectionDto, serializedString, true); + } + + @Test + void deserializeDto() throws JsonProcessingException { + VoIPDetection deserialized = objectMapper.readValue(jsonVoIPDetectionDto, VoIPDetection.class); + + TestHelpers.recursiveEquals(deserialized, voIPDetectionResponseDto); + } + + @Test + void deserializeEmptyDto() throws JsonProcessingException { + VoIPDetection deserialized = + objectMapper.readValue(jsonVoIPDetectionEmptyDto, VoIPDetection.class); + + TestHelpers.recursiveEquals(deserialized, voIPDetectionResponseEmptyDto); + } +} diff --git a/openapi-contracts/src/test/java/com/sinch/sdk/domains/numbers/models/v1/SinchEventsDtoTest.java b/openapi-contracts/src/test/java/com/sinch/sdk/domains/numbers/models/v1/SinchEventsDtoTest.java index 19cbcc587..915656ca6 100644 --- a/openapi-contracts/src/test/java/com/sinch/sdk/domains/numbers/models/v1/SinchEventsDtoTest.java +++ b/openapi-contracts/src/test/java/com/sinch/sdk/domains/numbers/models/v1/SinchEventsDtoTest.java @@ -29,6 +29,7 @@ public class SinchEventsDtoTest extends NumbersBaseTest { .setEventType(EventTypeEnum.PROVISIONING_TO_CAMPAIGN) .setStatus(StatusEnum.FAILED) .setFailureCode(FailureCodeEnum.CAMPAIGN_NOT_AVAILABLE) + .setInternalFailureCode("CRS0018") .build(); @Test diff --git a/openapi-contracts/src/test/java/com/sinch/sdk/domains/voice/models/v1/calls/request/CallUpdateRequestTest.java b/openapi-contracts/src/test/java/com/sinch/sdk/domains/voice/models/v1/calls/request/CallUpdateRequestTest.java new file mode 100644 index 000000000..5da9707ad --- /dev/null +++ b/openapi-contracts/src/test/java/com/sinch/sdk/domains/voice/models/v1/calls/request/CallUpdateRequestTest.java @@ -0,0 +1,38 @@ +package com.sinch.sdk.domains.voice.models.v1.calls.request; + +import com.adelean.inject.resources.junit.jupiter.GivenTextResource; +import com.adelean.inject.resources.junit.jupiter.TestWithResources; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.sinch.sdk.BaseTest; +import com.sinch.sdk.domains.voice.models.v1.svaml.action.SvamlActionHangup; +import com.sinch.sdk.domains.voice.models.v1.svaml.instruction.SvamlInstructionSay; +import java.util.Arrays; +import org.json.JSONException; +import org.junit.jupiter.api.Test; +import org.skyscreamer.jsonassert.JSONAssert; + +@TestWithResources +public class CallUpdateRequestTest extends BaseTest { + + public static CallUpdateRequest expectedCallUpdateRequest = + CallUpdateRequest.builder() + .setAction(SvamlActionHangup.SVAML_ACTION_HANGUP) + .setInstructions( + Arrays.asList( + SvamlInstructionSay.builder() + .setText("Sorry, the conference has been cancelled. The call will end now.") + .setLocale("en-US") + .build())) + .build(); + + @GivenTextResource("/domains/voice/v1/calls/request/CallUpdateRequestDto.json") + String jsonCallUpdateRequestDto; + + @Test + void serializeCallUpdateRequest() throws JsonProcessingException, JSONException { + + String serializedString = objectMapper.writeValueAsString(expectedCallUpdateRequest); + + JSONAssert.assertEquals(jsonCallUpdateRequestDto, serializedString, true); + } +} diff --git a/openapi-contracts/src/test/resources/domains/conversation/templates/v2/request/TemplateTranslationV2RequestDto.json b/openapi-contracts/src/test/resources/domains/conversation/templates/v2/request/TemplateTranslationV2RequestDto.json new file mode 100644 index 000000000..fdf376264 --- /dev/null +++ b/openapi-contracts/src/test/resources/domains/conversation/templates/v2/request/TemplateTranslationV2RequestDto.json @@ -0,0 +1,42 @@ +{ + "language_code": "fr-FR", + "version": "1", + "channel_template_overrides": { + "KAKAOTALK": { + "template_reference": { + "language_code": "another language", + "parameters": { + "name": "Value for the name parameter used in the version 1 and language \"en-US\" of the template" + }, + "template_id": "another template ID", + "version": "another version" + }, + "parameter_mappings": { + "a key": "a value" + } + } + }, + "variables": [ + { + "key": "key value", + "preview_value": "preview value" + } + ], + "template_message": { + "channel_template": { + "KAKAOTALK": { + "language_code": "en-US", + "template_id": "my template ID value", + "version": "a version" + } + }, + "omni_template": { + "language_code": "another language", + "parameters": { + "name": "Value for the name parameter used in the version 1 and language \"en-US\" of the template" + }, + "template_id": "another template ID", + "version": "another version" + } + } +} diff --git a/openapi-contracts/src/test/resources/domains/conversation/templates/v2/request/TemplateV2RequestDto.json b/openapi-contracts/src/test/resources/domains/conversation/templates/v2/request/TemplateV2RequestDto.json index f7628b229..a0d268849 100644 --- a/openapi-contracts/src/test/resources/domains/conversation/templates/v2/request/TemplateV2RequestDto.json +++ b/openapi-contracts/src/test/resources/domains/conversation/templates/v2/request/TemplateV2RequestDto.json @@ -28,8 +28,6 @@ "preview_value": "preview value" } ], - "create_time": "2024-07-07T02:59:59Z", - "update_time": "2024-07-07T06:07:44Z", "template_message": { "channel_template": { "KAKAOTALK": { diff --git a/openapi-contracts/src/test/resources/domains/conversation/templates/v2/TemplateTranslationDto.json b/openapi-contracts/src/test/resources/domains/conversation/templates/v2/response/TemplateTranslationV2ResponseDto.json similarity index 100% rename from openapi-contracts/src/test/resources/domains/conversation/templates/v2/TemplateTranslationDto.json rename to openapi-contracts/src/test/resources/domains/conversation/templates/v2/response/TemplateTranslationV2ResponseDto.json diff --git a/openapi-contracts/src/test/resources/domains/conversation/templates/v2/TemplateV2Dto.json b/openapi-contracts/src/test/resources/domains/conversation/templates/v2/response/TemplateV2ResponseDto.json similarity index 100% rename from openapi-contracts/src/test/resources/domains/conversation/templates/v2/TemplateV2Dto.json rename to openapi-contracts/src/test/resources/domains/conversation/templates/v2/response/TemplateV2ResponseDto.json diff --git a/openapi-contracts/src/test/resources/domains/conversation/templates/v2/response/TemplatesV2ListResponseDto.json b/openapi-contracts/src/test/resources/domains/conversation/templates/v2/response/TemplatesV2ListResponseDto.json index 035e34d34..36ee0d6cd 100644 --- a/openapi-contracts/src/test/resources/domains/conversation/templates/v2/response/TemplatesV2ListResponseDto.json +++ b/openapi-contracts/src/test/resources/domains/conversation/templates/v2/response/TemplatesV2ListResponseDto.json @@ -5,6 +5,8 @@ "description": "template description value", "version": 1, "default_translation": "fr-FR", + "create_time": "2024-08-26T06:00:00Z", + "update_time": "2024-08-26T06:07:44Z", "translations": [ { "language_code": "fr-FR", @@ -50,9 +52,7 @@ } } } - ], - "create_time": "2024-08-26T06:00:00Z", - "update_time": "2024-08-26T06:07:44Z" + ] } ] } diff --git a/openapi-contracts/src/test/resources/domains/conversation/v1/consents/AuditRecordsResponseDto.json b/openapi-contracts/src/test/resources/domains/conversation/v1/consents/AuditRecordsResponseDto.json new file mode 100644 index 000000000..186d70673 --- /dev/null +++ b/openapi-contracts/src/test/resources/domains/conversation/v1/consents/AuditRecordsResponseDto.json @@ -0,0 +1,15 @@ +{ + "identity": { + "identity": "an identity value" + }, + "audit_records": [ + { + "origin": "ORIGIN_API", + "operation": "OPERATION_INSERT", + "list_type": "OPT_OUT_ALL", + "project_id": "a project id", + "app_id": "an app id", + "datetime": "2025-06-06T14:42:56.031323Z" + } + ] +} diff --git a/openapi-contracts/src/test/resources/domains/conversation/v1/consents/ConsentsListResponseDtoPage0.json b/openapi-contracts/src/test/resources/domains/conversation/v1/consents/ConsentsListResponseDtoPage0.json new file mode 100644 index 000000000..8bcaa092d --- /dev/null +++ b/openapi-contracts/src/test/resources/domains/conversation/v1/consents/ConsentsListResponseDtoPage0.json @@ -0,0 +1,11 @@ +{ + "identities": [ + { + "identity": "an identity value" + }, + { + "identity": "a 2nd identity value" + } + ], + "next_page_token": "the next page token value" +} diff --git a/openapi-contracts/src/test/resources/domains/conversation/v1/consents/ConsentsListResponseDtoPage1.json b/openapi-contracts/src/test/resources/domains/conversation/v1/consents/ConsentsListResponseDtoPage1.json new file mode 100644 index 000000000..171b46a24 --- /dev/null +++ b/openapi-contracts/src/test/resources/domains/conversation/v1/consents/ConsentsListResponseDtoPage1.json @@ -0,0 +1,8 @@ +{ + "identities": [ + { + "identity": "a 3rd identity value" + } + ], + "next_page_token": "" +} diff --git a/openapi-contracts/src/test/resources/domains/numberlookup/v2/errors/LookupErrorDto.json b/openapi-contracts/src/test/resources/domains/numberlookup/v2/errors/LookupErrorDto.json new file mode 100644 index 000000000..86220e9d1 --- /dev/null +++ b/openapi-contracts/src/test/resources/domains/numberlookup/v2/errors/LookupErrorDto.json @@ -0,0 +1,6 @@ +{ + "status": 100, + "title": "Feature Disabled", + "detail": "VoIPDetection feature is currently disabled.", + "type": "validation_error" +} diff --git a/openapi-contracts/src/test/resources/domains/numberlookup/v2/errors/LookupErrorEmptyDto.json b/openapi-contracts/src/test/resources/domains/numberlookup/v2/errors/LookupErrorEmptyDto.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/openapi-contracts/src/test/resources/domains/numberlookup/v2/errors/LookupErrorEmptyDto.json @@ -0,0 +1 @@ +{} diff --git a/openapi-contracts/src/test/resources/domains/numberlookup/v2/errors/ProblemDetailsDto.json b/openapi-contracts/src/test/resources/domains/numberlookup/v2/errors/ProblemDetailsDto.json new file mode 100644 index 000000000..1e1590f3c --- /dev/null +++ b/openapi-contracts/src/test/resources/domains/numberlookup/v2/errors/ProblemDetailsDto.json @@ -0,0 +1,6 @@ +{ + "type": "https://developers.sinch.com/docs/lookup/api/errors/validation", + "title": "Validation error", + "status": 400, + "traceId": "84c1fd4063c38d9f3900d06e56542d48" +} diff --git a/openapi-contracts/src/test/resources/domains/numberlookup/v2/request/NumberLookupRequestAllFeaturesDto.json b/openapi-contracts/src/test/resources/domains/numberlookup/v2/request/NumberLookupRequestAllFeaturesDto.json new file mode 100644 index 000000000..84b20c39e --- /dev/null +++ b/openapi-contracts/src/test/resources/domains/numberlookup/v2/request/NumberLookupRequestAllFeaturesDto.json @@ -0,0 +1,9 @@ +{ + "number": "+15554567890", + "features": [ + "LineType", + "SimSwap", + "VoIPDetection", + "RND" + ] +} diff --git a/openapi-contracts/src/test/resources/domains/numberlookup/v2/request/NumberLookupRequestMinimalDto.json b/openapi-contracts/src/test/resources/domains/numberlookup/v2/request/NumberLookupRequestMinimalDto.json new file mode 100644 index 000000000..b190f89ba --- /dev/null +++ b/openapi-contracts/src/test/resources/domains/numberlookup/v2/request/NumberLookupRequestMinimalDto.json @@ -0,0 +1,3 @@ +{ + "number": "+15551234567" +} diff --git a/openapi-contracts/src/test/resources/domains/numberlookup/v2/request/NumberLookupRequestWithFeaturesDto.json b/openapi-contracts/src/test/resources/domains/numberlookup/v2/request/NumberLookupRequestWithFeaturesDto.json new file mode 100644 index 000000000..33bad4262 --- /dev/null +++ b/openapi-contracts/src/test/resources/domains/numberlookup/v2/request/NumberLookupRequestWithFeaturesDto.json @@ -0,0 +1,8 @@ +{ + "number": "+15552345678", + "features": [ + "LineType", + "SimSwap", + "VoIPDetection" + ] +} diff --git a/openapi-contracts/src/test/resources/domains/numberlookup/v2/request/NumberLookupRequestWithRndOptionsDto.json b/openapi-contracts/src/test/resources/domains/numberlookup/v2/request/NumberLookupRequestWithRndOptionsDto.json new file mode 100644 index 000000000..7ef54e3e4 --- /dev/null +++ b/openapi-contracts/src/test/resources/domains/numberlookup/v2/request/NumberLookupRequestWithRndOptionsDto.json @@ -0,0 +1,9 @@ +{ + "number": "+15553456789", + "features": [ + "RND" + ], + "rndFeatureOptions": { + "contactDate": "2025-01-01" + } +} diff --git a/openapi-contracts/src/test/resources/domains/numberlookup/v2/request/RndFeatureOptionsDto.json b/openapi-contracts/src/test/resources/domains/numberlookup/v2/request/RndFeatureOptionsDto.json new file mode 100644 index 000000000..45a365f9c --- /dev/null +++ b/openapi-contracts/src/test/resources/domains/numberlookup/v2/request/RndFeatureOptionsDto.json @@ -0,0 +1,3 @@ +{ + "contactDate": "2025-01-15" +} diff --git a/openapi-contracts/src/test/resources/domains/numberlookup/v2/response/LineResponseDto.json b/openapi-contracts/src/test/resources/domains/numberlookup/v2/response/LineResponseDto.json new file mode 100644 index 000000000..cc7ff9007 --- /dev/null +++ b/openapi-contracts/src/test/resources/domains/numberlookup/v2/response/LineResponseDto.json @@ -0,0 +1,8 @@ +{ + "carrier": "T-Mobile USA", + "type": "Mobile", + "mobileCountryCode": "310", + "mobileNetworkCode": "260", + "ported": true, + "portingDate": "2024-06-15T14:30:00Z" +} diff --git a/openapi-contracts/src/test/resources/domains/numberlookup/v2/response/LineResponseEmptyDto.json b/openapi-contracts/src/test/resources/domains/numberlookup/v2/response/LineResponseEmptyDto.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/openapi-contracts/src/test/resources/domains/numberlookup/v2/response/LineResponseEmptyDto.json @@ -0,0 +1 @@ +{} diff --git a/openapi-contracts/src/test/resources/domains/numberlookup/v2/response/NumberLookupResponseFullDto.json b/openapi-contracts/src/test/resources/domains/numberlookup/v2/response/NumberLookupResponseFullDto.json new file mode 100644 index 000000000..b43781206 --- /dev/null +++ b/openapi-contracts/src/test/resources/domains/numberlookup/v2/response/NumberLookupResponseFullDto.json @@ -0,0 +1,23 @@ +{ + "line": { + "carrier": "T-Mobile USA", + "type": "Mobile", + "mobileCountryCode": "310", + "mobileNetworkCode": "260", + "ported": true, + "portingDate": "2024-08-20T10:15:30Z" + }, + "simSwap": { + "swapped": true, + "swapPeriod": "SP24H" + }, + "voIPDetection": { + "probability": "High" + }, + "rnd": { + "disconnected": true + }, + "countryCode": "US", + "traceId": "84c1fd4063c38d9f3900d06e56542d48", + "number": "+15557890123" +} diff --git a/openapi-contracts/src/test/resources/domains/numberlookup/v2/response/NumberLookupResponseMinimalDto.json b/openapi-contracts/src/test/resources/domains/numberlookup/v2/response/NumberLookupResponseMinimalDto.json new file mode 100644 index 000000000..d6334b7e9 --- /dev/null +++ b/openapi-contracts/src/test/resources/domains/numberlookup/v2/response/NumberLookupResponseMinimalDto.json @@ -0,0 +1,5 @@ +{ + "countryCode": "US", + "traceId": "test-trace-id", + "number": "+15551234567" +} diff --git a/openapi-contracts/src/test/resources/domains/numberlookup/v2/response/RndResponseDto.json b/openapi-contracts/src/test/resources/domains/numberlookup/v2/response/RndResponseDto.json new file mode 100644 index 000000000..29102b577 --- /dev/null +++ b/openapi-contracts/src/test/resources/domains/numberlookup/v2/response/RndResponseDto.json @@ -0,0 +1,3 @@ +{ + "disconnected": true +} diff --git a/openapi-contracts/src/test/resources/domains/numberlookup/v2/response/RndResponseEmptyDto.json b/openapi-contracts/src/test/resources/domains/numberlookup/v2/response/RndResponseEmptyDto.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/openapi-contracts/src/test/resources/domains/numberlookup/v2/response/RndResponseEmptyDto.json @@ -0,0 +1 @@ +{} diff --git a/openapi-contracts/src/test/resources/domains/numberlookup/v2/response/SimSwapResponseDto.json b/openapi-contracts/src/test/resources/domains/numberlookup/v2/response/SimSwapResponseDto.json new file mode 100644 index 000000000..9815704d5 --- /dev/null +++ b/openapi-contracts/src/test/resources/domains/numberlookup/v2/response/SimSwapResponseDto.json @@ -0,0 +1,4 @@ +{ + "swapped": true, + "swapPeriod": "SP24H" +} diff --git a/openapi-contracts/src/test/resources/domains/numberlookup/v2/response/SimSwapResponseWithErrorDto.json b/openapi-contracts/src/test/resources/domains/numberlookup/v2/response/SimSwapResponseWithErrorDto.json new file mode 100644 index 000000000..4ef301ba4 --- /dev/null +++ b/openapi-contracts/src/test/resources/domains/numberlookup/v2/response/SimSwapResponseWithErrorDto.json @@ -0,0 +1,7 @@ +{ + "error": { + "status": 100, + "title": "Feature Disabled", + "detail": "SimSwap feature is currently disabled." + } +} diff --git a/openapi-contracts/src/test/resources/domains/numberlookup/v2/response/VoIPDetectionResponseDto.json b/openapi-contracts/src/test/resources/domains/numberlookup/v2/response/VoIPDetectionResponseDto.json new file mode 100644 index 000000000..792988b4c --- /dev/null +++ b/openapi-contracts/src/test/resources/domains/numberlookup/v2/response/VoIPDetectionResponseDto.json @@ -0,0 +1,3 @@ +{ + "probability": "High" +} diff --git a/openapi-contracts/src/test/resources/domains/numberlookup/v2/response/VoIPDetectionResponseEmptyDto.json b/openapi-contracts/src/test/resources/domains/numberlookup/v2/response/VoIPDetectionResponseEmptyDto.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/openapi-contracts/src/test/resources/domains/numberlookup/v2/response/VoIPDetectionResponseEmptyDto.json @@ -0,0 +1 @@ +{} diff --git a/openapi-contracts/src/test/resources/domains/numbers/v1/sinchevents/number-sinch-event.json b/openapi-contracts/src/test/resources/domains/numbers/v1/sinchevents/number-sinch-event.json index 55ce33569..3716b90f2 100644 --- a/openapi-contracts/src/test/resources/domains/numbers/v1/sinchevents/number-sinch-event.json +++ b/openapi-contracts/src/test/resources/domains/numbers/v1/sinchevents/number-sinch-event.json @@ -6,5 +6,6 @@ "resourceType": "ACTIVE_NUMBER", "eventType": "PROVISIONING_TO_CAMPAIGN", "status": "FAILED", - "failureCode": "CAMPAIGN_NOT_AVAILABLE" + "failureCode": "CAMPAIGN_NOT_AVAILABLE", + "internalFailureCode": "CRS0018" } \ No newline at end of file diff --git a/openapi-contracts/src/test/resources/domains/voice/v1/calls/request/CallUpdateRequestDto.json b/openapi-contracts/src/test/resources/domains/voice/v1/calls/request/CallUpdateRequestDto.json new file mode 100644 index 000000000..1640c9049 --- /dev/null +++ b/openapi-contracts/src/test/resources/domains/voice/v1/calls/request/CallUpdateRequestDto.json @@ -0,0 +1,12 @@ +{ + "instructions": [ + { + "name": "say", + "text": "Sorry, the conference has been cancelled. The call will end now.", + "locale": "en-US" + } + ], + "action": { + "name": "hangup" + } +} diff --git a/pom.xml b/pom.xml index 656cd3dda..44e1f524e 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ com.sinch.sdk sinch-sdk-java - 2.1.0-SNAPSHOT + 2.2.0-SNAPSHOT Sinch Java SDK @@ -74,7 +74,7 @@ 3.6.0 3.0.1 1.6 - 0.7.0 + 0.11.0 @@ -262,6 +262,9 @@ openapi-contracts/src/test/resources + + sinch-sdk-mockserver + @@ -280,10 +283,6 @@ maven-failsafe-plugin ${maven.failsafe.plugin.version} - - all - true - @@ -297,6 +296,9 @@ com.sinch.sdk.e2e.domains.sms.v1.SmsIT com.sinch.sdk.e2e.domains.voice.v1.VoiceIT com.sinch.sdk.e2e.domains.verification.v1.VerificationIT + com.sinch.sdk.e2e.domains.numberlookup.v2.NumberLookupIT + com.sinch.sdk.e2e.domains.proxy.ProxyIT + com.sinch.sdk.e2e.domains.proxy.HttpClientApacheProxyIT @@ -310,7 +312,6 @@ ${maven-surefire-plugin.version} ${skipUTs} - all