diff --git a/algoliasearch-apache/src/main/java/com/algolia/search/DefaultPersonalizationClient.java b/algoliasearch-apache/src/main/java/com/algolia/search/DefaultPersonalizationClient.java new file mode 100644 index 000000000..2c40e8c20 --- /dev/null +++ b/algoliasearch-apache/src/main/java/com/algolia/search/DefaultPersonalizationClient.java @@ -0,0 +1,47 @@ +package com.algolia.search; + +import javax.annotation.Nonnull; + +/** + * Algolia's REST recommendation client that wraps an instance of the transporter {@link + * HttpTransport} which wraps the HTTP Client This client allows to build typed requests and read + * typed responses. Requests are made under the Algolia's retry-strategy. This client is intended to + * be reused and it's thread-safe. + * + * @see Algolia.com + */ +public class DefaultPersonalizationClient { + + // Suppress default constructor for noninstantiability + private DefaultPersonalizationClient() { + throw new AssertionError(); + } + + /** + * Creates a {@link PersonalizationClient} with the given credentials The default HttpClient + * implementation is {@link ApacheHttpRequester} + * + * @param applicationID The Algolia Application ID + * @param apiKey The Algolia API Key + * @param region Region where your personalization data is stored and processed. + * @throws NullPointerException If one of the following ApplicationID/ApiKey is null + * @throws IllegalArgumentException If the ApplicationID or the APIKey are empty + */ + public static PersonalizationClient create( + @Nonnull String applicationID, @Nonnull String apiKey, @Nonnull String region) { + return create(new PersonalizationConfig.Builder(applicationID, apiKey, region).build()); + } + + /** + * Creates a default {@link PersonalizationClient} with the given {@link SearchConfig}. The + * default HttpClient implementation is {@link ApacheHttpRequester} + * + * @param config The configuration allows you to advanced configuration of the clients such as + * batch size or custom hosts and timeout. + * @throws NullPointerException If one of the following ApplicationID/ApiKey/Config is null + * @throws IllegalArgumentException If the ApplicationID or the APIKey are empty + */ + public static PersonalizationClient create(@Nonnull PersonalizationConfig config) { + return new PersonalizationClient(config, new ApacheHttpRequester(config)); + } +} diff --git a/algoliasearch-apache/src/main/java/com/algolia/search/DefaultRecommendationClient.java b/algoliasearch-apache/src/main/java/com/algolia/search/DefaultRecommendationClient.java index f1863ae58..edc0ba721 100644 --- a/algoliasearch-apache/src/main/java/com/algolia/search/DefaultRecommendationClient.java +++ b/algoliasearch-apache/src/main/java/com/algolia/search/DefaultRecommendationClient.java @@ -9,8 +9,10 @@ * be reused and it's thread-safe. * * @see Algolia.com + * @deprecated use {@link DefaultPersonalizationClient} instead */ @SuppressWarnings("WeakerAccess") +@Deprecated public class DefaultRecommendationClient { /** diff --git a/algoliasearch-apache/src/test/java/com/algolia/search/personalization/PersonalizationTest.java b/algoliasearch-apache/src/test/java/com/algolia/search/personalization/PersonalizationTest.java new file mode 100644 index 000000000..9eefa05f9 --- /dev/null +++ b/algoliasearch-apache/src/test/java/com/algolia/search/personalization/PersonalizationTest.java @@ -0,0 +1,27 @@ +package com.algolia.search.personalization; + +import com.algolia.search.DefaultPersonalizationClient; +import com.algolia.search.IntegrationTestExtension; +import com.algolia.search.PersonalizationClient; +import com.algolia.search.integration.TestHelpers; +import java.io.IOException; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.extension.ExtendWith; + +@ExtendWith({IntegrationTestExtension.class}) +class PersonalizationTest + extends com.algolia.search.integration.personalization.PersonalizationTest { + + private static final PersonalizationClient personalizationClient = + DefaultPersonalizationClient.create( + TestHelpers.ALGOLIA_APPLICATION_ID_1, TestHelpers.ALGOLIA_ADMIN_KEY_1, "eu"); + + PersonalizationTest() { + super(personalizationClient); + } + + @AfterAll + static void close() throws IOException { + personalizationClient.close(); + } +} diff --git a/algoliasearch-apache/src/test/java/com/algolia/search/recommendation/RecommendationTest.java b/algoliasearch-apache/src/test/java/com/algolia/search/recommendation/RecommendationTest.java deleted file mode 100644 index cc23475dc..000000000 --- a/algoliasearch-apache/src/test/java/com/algolia/search/recommendation/RecommendationTest.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.algolia.search.recommendation; - -import com.algolia.search.DefaultRecommendationClient; -import com.algolia.search.IntegrationTestExtension; -import com.algolia.search.RecommendationClient; -import com.algolia.search.integration.TestHelpers; -import java.io.IOException; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.extension.ExtendWith; - -@ExtendWith({IntegrationTestExtension.class}) -class RecommendationTest extends com.algolia.search.integration.recommendation.RecommendationTest { - - private static RecommendationClient recommendationClient = - DefaultRecommendationClient.create( - TestHelpers.ALGOLIA_APPLICATION_ID_1, TestHelpers.ALGOLIA_ADMIN_KEY_1, "eu"); - - RecommendationTest() { - super(recommendationClient); - } - - @AfterAll - static void close() throws IOException { - recommendationClient.close(); - } -} diff --git a/algoliasearch-core/src/main/java/com/algolia/search/PersonalizationClient.java b/algoliasearch-core/src/main/java/com/algolia/search/PersonalizationClient.java new file mode 100644 index 000000000..9d3146ea5 --- /dev/null +++ b/algoliasearch-core/src/main/java/com/algolia/search/PersonalizationClient.java @@ -0,0 +1,358 @@ +package com.algolia.search; + +import com.algolia.search.exceptions.AlgoliaApiException; +import com.algolia.search.exceptions.AlgoliaRetryException; +import com.algolia.search.exceptions.AlgoliaRuntimeException; +import com.algolia.search.exceptions.LaunderThrowable; +import com.algolia.search.models.HttpMethod; +import com.algolia.search.models.RequestOptions; +import com.algolia.search.models.common.CallType; +import com.algolia.search.models.recommendation.DeletePersonalizationProfileResponse; +import com.algolia.search.models.recommendation.GetStrategyResponse; +import com.algolia.search.models.recommendation.PersonalizationProfileResponse; +import com.algolia.search.models.recommendation.SetStrategyRequest; +import com.algolia.search.models.recommendation.SetStrategyResponse; +import java.io.Closeable; +import java.io.IOException; +import java.util.Objects; +import java.util.concurrent.CompletableFuture; +import javax.annotation.Nonnull; + +/** + * Algolia's REST recommendation client that wraps an instance of the transporter {@link + * HttpTransport} which wraps the HTTP Client This client allows to build typed requests and read + * typed responses. Requests are made under the Algolia's retry-strategy. This client is intended to + * be reused and it's thread-safe. + * + * @see Algolia.com + */ +@SuppressWarnings("unused") +public class PersonalizationClient implements Closeable { + + /** The transport layer. Must be reused. */ + private final HttpTransport transport; + + /** Client's configuration. Must be reused. */ + private final ConfigBase config; + + /** + * Creates a custom {@link PersonalizationClient} with the given {@link PersonalizationConfig} and + * the given {@link HttpRequester} + * + * @param config The configuration allows you to advanced configuration of the clients such as + * batch size or custom hosts and timeout. + * @param httpRequester Another HTTP Client than the default one. Must be an implementation of + * {@link HttpRequester}. + * @throws NullPointerException If one of the following + * ApplicationID/ApiKey/Configuration/Requester is null + * @throws IllegalArgumentException If the ApplicationID or the APIKey are empty + */ + public PersonalizationClient( + @Nonnull PersonalizationConfig config, @Nonnull HttpRequester httpRequester) { + + Objects.requireNonNull(httpRequester, "An httpRequester is required."); + Objects.requireNonNull(config, "A configuration is required."); + + this.config = config; + this.transport = new HttpTransport(config, httpRequester); + } + + /** + * Close the underlying Http Client + * + * @throws IOException if an I/O error occurs + */ + @Override + public void close() throws IOException { + transport.close(); + } + + /** + * Returns the personalization strategy of the application + * + * @throws AlgoliaRetryException When the retry has failed on all hosts + * @throws AlgoliaApiException When the API sends an http error code + * @throws AlgoliaRuntimeException When an error occurred during the serialization + */ + public GetStrategyResponse getPersonalizationStrategy() { + return LaunderThrowable.await(getPersonalizationStrategyAsync()); + } + + /** + * Returns the personalization strategy of the application + * + * @param requestOptions Options to pass to this request + * @throws AlgoliaRetryException When the retry has failed on all hosts + * @throws AlgoliaApiException When the API sends an http error code + * @throws AlgoliaRuntimeException When an error occurred during the serialization + */ + public GetStrategyResponse getPersonalizationStrategy(RequestOptions requestOptions) { + return LaunderThrowable.await(getPersonalizationStrategyAsync(requestOptions)); + } + + /** + * Returns the personalization strategy of the application + * + * @throws AlgoliaRetryException When the retry has failed on all hosts + * @throws AlgoliaApiException When the API sends an http error code + * @throws AlgoliaRuntimeException When an error occurred during the serialization + */ + public CompletableFuture getPersonalizationStrategyAsync() { + return getPersonalizationStrategyAsync(null); + } + + /** + * Returns the personalization strategy of the application + * + * @param requestOptions Options to pass to this request + * @throws AlgoliaRetryException When the retry has failed on all hosts + * @throws AlgoliaApiException When the API sends an http error code + * @throws AlgoliaRuntimeException When an error occurred during the serialization + */ + public CompletableFuture getPersonalizationStrategyAsync( + RequestOptions requestOptions) { + return transport.executeRequestAsync( + HttpMethod.GET, + "/1/strategies/personalization", + CallType.READ, + GetStrategyResponse.class, + requestOptions); + } + + /** + * This command configures the personalization strategy + * + * @param request The personalization strategy + * @throws AlgoliaRetryException When the retry has failed on all hosts + * @throws AlgoliaApiException When the API sends an http error code + * @throws AlgoliaRuntimeException When an error occurred during the serialization + */ + public SetStrategyResponse setPersonalizationStrategy(@Nonnull SetStrategyRequest request) { + return LaunderThrowable.await(setPersonalizationStrategyAsync(request)); + } + + /** + * This command configures the personalization strategy + * + * @param request The personalization strategy + * @param requestOptions Options to pass to this request + * @throws AlgoliaRetryException When the retry has failed on all hosts + * @throws AlgoliaApiException When the API sends an http error code + * @throws AlgoliaRuntimeException When an error occurred during the serialization + */ + public SetStrategyResponse setPersonalizationStrategy( + @Nonnull SetStrategyRequest request, RequestOptions requestOptions) { + return LaunderThrowable.await(setPersonalizationStrategyAsync(request, requestOptions)); + } + + /** + * This command configures the personalization strategy + * + * @param request The personalization strategy + * @throws AlgoliaRetryException When the retry has failed on all hosts + * @throws AlgoliaApiException When the API sends an http error code + * @throws AlgoliaRuntimeException When an error occurred during the serialization + */ + public CompletableFuture setPersonalizationStrategyAsync( + @Nonnull SetStrategyRequest request) { + return setPersonalizationStrategyAsync(request, null); + } + + /** + * This command configures the personalization strategy + * + * @param request The personalization strategy + * @param requestOptions Options to pass to this request + * @throws AlgoliaRetryException When the retry has failed on all hosts + * @throws AlgoliaApiException When the API sends an http error code + * @throws AlgoliaRuntimeException When an error occurred during the serialization + */ + public CompletableFuture setPersonalizationStrategyAsync( + @Nonnull SetStrategyRequest request, RequestOptions requestOptions) { + Objects.requireNonNull(request, "strategy request is required."); + + return transport.executeRequestAsync( + HttpMethod.POST, + "/1/strategies/personalization", + CallType.WRITE, + request, + SetStrategyResponse.class, + requestOptions); + } + + /** + * Get the user profile built from Personalization strategy. + * + *

The profile is structured by facet name used in the strategy. Each facet value is mapped to + * its score. Each score represents the user affinity for a specific facet value given the + * userToken past events and the Personalization strategy defined. Scores are bounded to 20. The + * last processed event timestamp is provided using the ISO 8601 format for debugging purposes. + * + * @param userToken userToken representing the user for which to fetch the Personalization profile + * @throws AlgoliaRetryException When the retry has failed on all hosts + * @throws AlgoliaApiException When the API sends an http error code + * @throws AlgoliaRuntimeException When an error occurred during the serialization + */ + public PersonalizationProfileResponse getPersonalizationProfile(@Nonnull String userToken) { + return LaunderThrowable.await(getPersonalizationProfileAsync(userToken)); + } + + /** + * Get the user profile built from Personalization strategy. + * + *

The profile is structured by facet name used in the strategy. Each facet value is mapped to + * its score. Each score represents the user affinity for a specific facet value given the + * userToken past events and the Personalization strategy defined. Scores are bounded to 20. The + * last processed event timestamp is provided using the ISO 8601 format for debugging purposes. + * + * @param userToken userToken representing the user for which to fetch the Personalization profile + * @param requestOptions Options to pass to this request + * @throws AlgoliaRetryException When the retry has failed on all hosts + * @throws AlgoliaApiException When the API sends an http error code + * @throws AlgoliaRuntimeException When an error occurred during the serialization + */ + public PersonalizationProfileResponse getPersonalizationProfile( + @Nonnull String userToken, RequestOptions requestOptions) { + return LaunderThrowable.await(getPersonalizationProfileAsync(userToken, requestOptions)); + } + + /** + * Get the user profile built from Personalization strategy. + * + *

The profile is structured by facet name used in the strategy. Each facet value is mapped to + * its score. Each score represents the user affinity for a specific facet value given the + * userToken past events and the Personalization strategy defined. Scores are bounded to 20. The + * last processed event timestamp is provided using the ISO 8601 format for debugging purposes. + * + * @param userToken userToken representing the user for which to fetch the Personalization profile + * @throws AlgoliaRetryException When the retry has failed on all hosts + * @throws AlgoliaApiException When the API sends an http error code + * @throws AlgoliaRuntimeException When an error occurred during the serialization + */ + public CompletableFuture getPersonalizationProfileAsync( + @Nonnull String userToken) { + return getPersonalizationProfileAsync(userToken, null); + } + + /** + * Get the user profile built from Personalization strategy. + * + *

The profile is structured by facet name used in the strategy. Each facet value is mapped to + * its score. Each score represents the user affinity for a specific facet value given the + * userToken past events and the Personalization strategy defined. Scores are bounded to 20. The + * last processed event timestamp is provided using the ISO 8601 format for debugging purposes. + * + * @param userToken userToken representing the user for which to fetch the Personalization profile + * @param requestOptions Options to pass to this request + * @throws AlgoliaRetryException When the retry has failed on all hosts + * @throws AlgoliaApiException When the API sends an http error code + * @throws AlgoliaRuntimeException When an error occurred during the serialization + */ + public CompletableFuture getPersonalizationProfileAsync( + @Nonnull String userToken, RequestOptions requestOptions) { + Objects.requireNonNull(userToken, "userToken is required."); + return transport.executeRequestAsync( + HttpMethod.GET, + "1/profiles/personalization/" + userToken, + CallType.READ, + PersonalizationProfileResponse.class, + requestOptions); + } + + /** + * Delete the user profile and all its associated data. + * + *

Returns, as part of the response, a date until which the data can safely be considered as + * deleted for the given user. This means that if you send events for the given user before this + * date, they will be ignored. Any data received after the deletedUntil date will start building a + * new user profile. + * + *

It might take a couple hours before for the deletion request to be fully processed. + * + * @param userToken userToken representing the user for which to delete the Personalization + * profile and associated data. + * @throws AlgoliaRetryException When the retry has failed on all hosts + * @throws AlgoliaApiException When the API sends an http error code + * @throws AlgoliaRuntimeException When an error occurred during the serialization + */ + public DeletePersonalizationProfileResponse deletePersonalizationProfile( + @Nonnull String userToken) { + return LaunderThrowable.await(deletePersonalizationProfileAsync(userToken)); + } + + /** + * Delete the user profile and all its associated data. + * + *

Returns, as part of the response, a date until which the data can safely be considered as + * deleted for the given user. This means that if you send events for the given user before this + * date, they will be ignored. Any data received after the deletedUntil date will start building a + * new user profile. + * + *

It might take a couple hours before for the deletion request to be fully processed. + * + * @param userToken userToken representing the user for which to delete the Personalization + * profile and associated data. + * @param requestOptions Options to pass to this request + * @throws AlgoliaRetryException When the retry has failed on all hosts + * @throws AlgoliaApiException When the API sends an http error code + * @throws AlgoliaRuntimeException When an error occurred during the serialization + */ + public DeletePersonalizationProfileResponse deletePersonalizationProfile( + @Nonnull String userToken, RequestOptions requestOptions) { + return LaunderThrowable.await(deletePersonalizationProfileAsync(userToken, requestOptions)); + } + + /** + * Delete the user profile and all its associated data. + * + *

Returns, as part of the response, a date until which the data can safely be considered as + * deleted for the given user. This means that if you send events for the given user before this + * date, they will be ignored. Any data received after the deletedUntil date will start building a + * new user profile. + * + *

It might take a couple hours before for the deletion request to be fully processed. + * + * @param userToken userToken representing the user for which to delete the Personalization + * profile and associated data. + * @throws AlgoliaRetryException When the retry has failed on all hosts + * @throws AlgoliaApiException When the API sends an http error code + * @throws AlgoliaRuntimeException When an error occurred during the serialization + */ + public CompletableFuture deletePersonalizationProfileAsync( + @Nonnull String userToken) { + return deletePersonalizationProfileAsync(userToken, null); + } + + /** + * Delete the user profile and all its associated data. + * + *

Returns, as part of the response, a date until which the data can safely be considered as + * deleted for the given user. This means that if you send events for the given user before this + * date, they will be ignored. Any data received after the deletedUntil date will start building a + * new user profile. + * + *

It might take a couple hours before for the deletion request to be fully processed. + * + * @param userToken userToken representing the user for which to delete the Personalization + * profile and associated data. + * @param requestOptions Options to pass to this request + * @throws AlgoliaRetryException When the retry has failed on all hosts + * @throws AlgoliaApiException When the API sends an http error code + * @throws AlgoliaRuntimeException When an error occurred during the serialization + */ + public CompletableFuture deletePersonalizationProfileAsync( + @Nonnull String userToken, RequestOptions requestOptions) { + Objects.requireNonNull(userToken, "userToken is required."); + return transport.executeRequestAsync( + HttpMethod.DELETE, + "1/profiles/" + userToken, + CallType.WRITE, + DeletePersonalizationProfileResponse.class, + requestOptions); + } + + /** Get Client's configuration */ + public ConfigBase getConfig() { + return config; + } +} diff --git a/algoliasearch-core/src/main/java/com/algolia/search/PersonalizationConfig.java b/algoliasearch-core/src/main/java/com/algolia/search/PersonalizationConfig.java new file mode 100644 index 000000000..455be30c4 --- /dev/null +++ b/algoliasearch-core/src/main/java/com/algolia/search/PersonalizationConfig.java @@ -0,0 +1,54 @@ +package com.algolia.search; + +import com.algolia.search.models.common.CallType; +import com.algolia.search.models.common.CompressionType; +import com.algolia.search.util.AlgoliaUtils; +import java.util.Collections; +import java.util.EnumSet; +import java.util.List; +import java.util.Objects; +import javax.annotation.Nonnull; + +public class PersonalizationConfig extends ConfigBase { + + public static class Builder extends ConfigBase.Builder { + /** + * Creates an {@link PersonalizationConfig} with the default hosts + * + * @param applicationID The Application ID + * @param apiKey The API Key + * @param region Region where your personalization data is stored and processed. + */ + public Builder(@Nonnull String applicationID, @Nonnull String apiKey, @Nonnull String region) { + super(applicationID, apiKey, createPersonalizationHosts(region), CompressionType.NONE); + } + + @Override + public PersonalizationConfig.Builder getThis() { + return this; + } + + public PersonalizationConfig build() { + return new PersonalizationConfig(this); + } + + /** Create hosts for the recommendation configuration */ + private static List createPersonalizationHosts(@Nonnull String region) { + + Objects.requireNonNull(region, "The region can't be null"); + + if (AlgoliaUtils.isEmptyWhiteSpace(region)) { + throw new IllegalArgumentException("The region is required. It can't be empty."); + } + + return Collections.singletonList( + new StatefulHost( + String.format("personalization.%s.algolia.com", region), + EnumSet.of(CallType.READ, CallType.WRITE))); + } + } + + private PersonalizationConfig(Builder builder) { + super(builder); + } +} diff --git a/algoliasearch-core/src/main/java/com/algolia/search/RecommendationClient.java b/algoliasearch-core/src/main/java/com/algolia/search/RecommendationClient.java index 109688ec2..f915aac34 100644 --- a/algoliasearch-core/src/main/java/com/algolia/search/RecommendationClient.java +++ b/algoliasearch-core/src/main/java/com/algolia/search/RecommendationClient.java @@ -1,6 +1,8 @@ package com.algolia.search; -import com.algolia.search.exceptions.*; +import com.algolia.search.exceptions.AlgoliaApiException; +import com.algolia.search.exceptions.AlgoliaRetryException; +import com.algolia.search.exceptions.AlgoliaRuntimeException; import com.algolia.search.exceptions.LaunderThrowable; import com.algolia.search.models.HttpMethod; import com.algolia.search.models.RequestOptions; @@ -21,8 +23,10 @@ * be reused and it's thread-safe. * * @see Algolia.com + * @deprecated use {@link PersonalizationClient} instead */ @SuppressWarnings({"WeakerAccess", "Unused"}) +@Deprecated public class RecommendationClient implements Closeable { /** The transport layer. Must be reused. */ diff --git a/algoliasearch-core/src/main/java/com/algolia/search/RecommendationConfig.java b/algoliasearch-core/src/main/java/com/algolia/search/RecommendationConfig.java index 7ed4ddfd9..8493db9f2 100644 --- a/algoliasearch-core/src/main/java/com/algolia/search/RecommendationConfig.java +++ b/algoliasearch-core/src/main/java/com/algolia/search/RecommendationConfig.java @@ -9,6 +9,8 @@ import java.util.Objects; import javax.annotation.Nonnull; +/** @deprecated use {@link PersonalizationConfig} instead */ +@Deprecated public class RecommendationConfig extends ConfigBase { public static class Builder extends ConfigBase.Builder { diff --git a/algoliasearch-core/src/main/java/com/algolia/search/SearchClientPersonalization.java b/algoliasearch-core/src/main/java/com/algolia/search/SearchClientPersonalization.java index b6d8e8998..90cad4b0e 100644 --- a/algoliasearch-core/src/main/java/com/algolia/search/SearchClientPersonalization.java +++ b/algoliasearch-core/src/main/java/com/algolia/search/SearchClientPersonalization.java @@ -22,7 +22,7 @@ public interface SearchClientPersonalization extends SearchClientBase { * @throws AlgoliaRetryException When the retry has failed on all hosts * @throws AlgoliaApiException When the API sends an http error code * @throws AlgoliaRuntimeException When an error occurred during the serialization - * @deprecated Endpoint will be deprecated. Please use {@link RecommendationConfig} instead. + * @deprecated Endpoint will be deprecated. Please use {@link PersonalizationConfig} instead. */ @Deprecated default GetStrategyResponse getPersonalizationStrategy() { @@ -36,7 +36,7 @@ default GetStrategyResponse getPersonalizationStrategy() { * @throws AlgoliaRetryException When the retry has failed on all hosts * @throws AlgoliaApiException When the API sends an http error code * @throws AlgoliaRuntimeException When an error occurred during the serialization - * @deprecated Endpoint will be deprecated. Please use {@link RecommendationConfig} instead. + * @deprecated Endpoint will be deprecated. Please use {@link PersonalizationConfig} instead. */ @Deprecated default GetStrategyResponse getPersonalizationStrategy(RequestOptions requestOptions) { @@ -49,7 +49,7 @@ default GetStrategyResponse getPersonalizationStrategy(RequestOptions requestOpt * @throws AlgoliaRetryException When the retry has failed on all hosts * @throws AlgoliaApiException When the API sends an http error code * @throws AlgoliaRuntimeException When an error occurred during the serialization - * @deprecated Endpoint will be deprecated. Please use {@link RecommendationConfig} instead. + * @deprecated Endpoint will be deprecated. Please use {@link PersonalizationConfig} instead. */ @Deprecated default CompletableFuture getPersonalizationStrategyAsync() { @@ -63,7 +63,7 @@ default CompletableFuture getPersonalizationStrategyAsync() * @throws AlgoliaRetryException When the retry has failed on all hosts * @throws AlgoliaApiException When the API sends an http error code * @throws AlgoliaRuntimeException When an error occurred during the serialization - * @deprecated Endpoint will be deprecated. Please use {@link RecommendationConfig} instead. + * @deprecated Endpoint will be deprecated. Please use {@link PersonalizationConfig} instead. */ @Deprecated default CompletableFuture getPersonalizationStrategyAsync( @@ -84,7 +84,7 @@ default CompletableFuture getPersonalizationStrategyAsync( * @throws AlgoliaRetryException When the retry has failed on all hosts * @throws AlgoliaApiException When the API sends an http error code * @throws AlgoliaRuntimeException When an error occurred during the serialization - * @deprecated Endpoint will be deprecated. Please use {@link RecommendationConfig} instead. + * @deprecated Endpoint will be deprecated. Please use {@link PersonalizationConfig} instead. */ @Deprecated default SetStrategyResponse setPersonalizationStrategy(@Nonnull SetStrategyRequest request) { @@ -99,7 +99,7 @@ default SetStrategyResponse setPersonalizationStrategy(@Nonnull SetStrategyReque * @throws AlgoliaRetryException When the retry has failed on all hosts * @throws AlgoliaApiException When the API sends an http error code * @throws AlgoliaRuntimeException When an error occurred during the serialization - * @deprecated Endpoint will be deprecated. Please use {@link RecommendationConfig} instead. + * @deprecated Endpoint will be deprecated. Please use {@link PersonalizationConfig} instead. */ @Deprecated default SetStrategyResponse setPersonalizationStrategy( @@ -114,7 +114,7 @@ default SetStrategyResponse setPersonalizationStrategy( * @throws AlgoliaRetryException When the retry has failed on all hosts * @throws AlgoliaApiException When the API sends an http error code * @throws AlgoliaRuntimeException When an error occurred during the serialization - * @deprecated Endpoint will be deprecated. Please use {@link RecommendationConfig} instead. + * @deprecated Endpoint will be deprecated. Please use {@link PersonalizationConfig} instead. */ @Deprecated default CompletableFuture setPersonalizationStrategyAsync( @@ -130,7 +130,7 @@ default CompletableFuture setPersonalizationStrategyAsync( * @throws AlgoliaRetryException When the retry has failed on all hosts * @throws AlgoliaApiException When the API sends an http error code * @throws AlgoliaRuntimeException When an error occurred during the serialization - * @deprecated Endpoint will be deprecated. Please use {@link RecommendationConfig} instead. + * @deprecated Endpoint will be deprecated. Please use {@link PersonalizationConfig} instead. */ @Deprecated default CompletableFuture setPersonalizationStrategyAsync( diff --git a/algoliasearch-core/src/main/java/com/algolia/search/models/recommendation/DeletePersonalizationProfileResponse.java b/algoliasearch-core/src/main/java/com/algolia/search/models/recommendation/DeletePersonalizationProfileResponse.java new file mode 100644 index 000000000..2e23364d9 --- /dev/null +++ b/algoliasearch-core/src/main/java/com/algolia/search/models/recommendation/DeletePersonalizationProfileResponse.java @@ -0,0 +1,28 @@ +package com.algolia.search.models.recommendation; + +/** Delete the user profile response. */ +public class DeletePersonalizationProfileResponse { + + /** The user token representing the user and associated data. */ + private String userToken; + /** Date until which the data can safely be considered as deleted for the given use. */ + private String deletedUntil; + + public String getUserToken() { + return userToken; + } + + public DeletePersonalizationProfileResponse setUserToken(String userToken) { + this.userToken = userToken; + return this; + } + + public String getDeletedUntil() { + return deletedUntil; + } + + public DeletePersonalizationProfileResponse setDeletedUntil(String deletedUntil) { + this.deletedUntil = deletedUntil; + return this; + } +} diff --git a/algoliasearch-core/src/main/java/com/algolia/search/models/recommendation/PersonalizationProfileResponse.java b/algoliasearch-core/src/main/java/com/algolia/search/models/recommendation/PersonalizationProfileResponse.java new file mode 100644 index 000000000..39bb6c4bc --- /dev/null +++ b/algoliasearch-core/src/main/java/com/algolia/search/models/recommendation/PersonalizationProfileResponse.java @@ -0,0 +1,45 @@ +package com.algolia.search.models.recommendation; + +import java.util.Map; + +/** User profile built from Personalization strategy. */ +public class PersonalizationProfileResponse { + + /** The user token representing the user and associated data. */ + private String userToken; + /** The last processed event timestamp using the ISO 8601 format. */ + private String lastEventAt; + /** + * The profile is structured by facet name used in the strategy. Each facet value is mapped to its + * score. Each score represents the user affinity for a specific facet value given the {@link + * #userToken} past events and the Personalization strategy defined. Scores are bounded to 20. + */ + private Map scores; + + public String getUserToken() { + return userToken; + } + + public PersonalizationProfileResponse setUserToken(String userToken) { + this.userToken = userToken; + return this; + } + + public String getLastEventAt() { + return lastEventAt; + } + + public PersonalizationProfileResponse setLastEventAt(String lastEventAt) { + this.lastEventAt = lastEventAt; + return this; + } + + public Map getScores() { + return scores; + } + + public PersonalizationProfileResponse setScores(Map scores) { + this.scores = scores; + return this; + } +} diff --git a/algoliasearch-core/src/test/java/com/algolia/search/integration/recommendation/RecommendationTest.java b/algoliasearch-core/src/test/java/com/algolia/search/integration/personalization/PersonalizationTest.java similarity index 81% rename from algoliasearch-core/src/test/java/com/algolia/search/integration/recommendation/RecommendationTest.java rename to algoliasearch-core/src/test/java/com/algolia/search/integration/personalization/PersonalizationTest.java index 89a5be689..dd2ffb733 100644 --- a/algoliasearch-core/src/test/java/com/algolia/search/integration/recommendation/RecommendationTest.java +++ b/algoliasearch-core/src/test/java/com/algolia/search/integration/personalization/PersonalizationTest.java @@ -1,9 +1,9 @@ -package com.algolia.search.integration.recommendation; +package com.algolia.search.integration.personalization; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; import com.algolia.search.Defaults; -import com.algolia.search.RecommendationClient; +import com.algolia.search.PersonalizationClient; import com.algolia.search.models.recommendation.EventsScoring; import com.algolia.search.models.recommendation.FacetsScoring; import com.algolia.search.models.recommendation.GetStrategyResponse; @@ -14,16 +14,16 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -public abstract class RecommendationTest { +public abstract class PersonalizationTest { - private final RecommendationClient recommendationClient; + private final PersonalizationClient personalizationClient; - protected RecommendationTest(RecommendationClient recommendationClient) { - this.recommendationClient = recommendationClient; + protected PersonalizationTest(PersonalizationClient personalizationClient) { + this.personalizationClient = personalizationClient; } @Test - void testRecommendationClient() { + void testPersonalizationClient() { SetStrategyRequest request = new SetStrategyRequest() .setEventsScoring( @@ -33,9 +33,9 @@ void testRecommendationClient() { .setFacetsScoring( Arrays.asList(new FacetsScoring("brand", 100), new FacetsScoring("categories", 10))) .setPersonalizationImpact(0); - Assertions.assertDoesNotThrow(() -> recommendationClient.setPersonalizationStrategy(request)); + Assertions.assertDoesNotThrow(() -> personalizationClient.setPersonalizationStrategy(request)); - GetStrategyResponse response = recommendationClient.getPersonalizationStrategy(); + GetStrategyResponse response = personalizationClient.getPersonalizationStrategy(); assertThat(response.getEventsScoring()) .usingRecursiveComparison()