All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.commercetools.sync.customers.helpers.CustomerReferenceResolver Maven / Gradle / Ivy

package com.commercetools.sync.customers.helpers;

import static com.commercetools.sync.commons.utils.CompletableFutureUtils.collectionOfFuturesToFutureOfCollection;
import static io.vrap.rmf.base.client.utils.CompletableFutureUtils.exceptionallyCompletedFuture;
import static java.lang.String.format;
import static java.util.concurrent.CompletableFuture.completedFuture;
import static java.util.stream.Collectors.toList;

import com.commercetools.api.models.common.ResourceIdentifier;
import com.commercetools.api.models.customer.CustomerDraft;
import com.commercetools.api.models.customer.CustomerDraftBuilder;
import com.commercetools.api.models.customer_group.CustomerGroupResourceIdentifierBuilder;
import com.commercetools.api.models.store.StoreResourceIdentifier;
import com.commercetools.api.models.store.StoreResourceIdentifierBuilder;
import com.commercetools.sync.commons.exceptions.ReferenceResolutionException;
import com.commercetools.sync.commons.helpers.CustomReferenceResolver;
import com.commercetools.sync.customers.CustomerSyncOptions;
import com.commercetools.sync.services.CustomerGroupService;
import com.commercetools.sync.services.TypeService;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import javax.annotation.Nonnull;

public final class CustomerReferenceResolver
    extends CustomReferenceResolver {

  public static final String FAILED_TO_RESOLVE_CUSTOMER_GROUP_REFERENCE =
      "Failed to resolve customer group resource identifier on CustomerDraft with key:'%s'. Reason: %s";
  public static final String FAILED_TO_RESOLVE_STORE_REFERENCE =
      "Failed to resolve store resource identifier on CustomerDraft with key:'%s'. Reason: %s";
  public static final String FAILED_TO_RESOLVE_CUSTOM_TYPE =
      "Failed to resolve custom type reference on " + "CustomerDraft with key:'%s'.";
  public static final String CUSTOMER_GROUP_DOES_NOT_EXIST =
      "CustomerGroup with key '%s' doesn't exist.";

  private final TypeService typeService;
  private final CustomerGroupService customerGroupService;

  /**
   * Takes a {@link CustomerSyncOptions} instance, a {@link TypeService} and a {@link
   * CustomerGroupService} to instantiate a {@link CustomerReferenceResolver} instance that could be
   * used to resolve the customer drafts in the CTP project specified in the injected {@link
   * CustomerSyncOptions} instance.
   *
   * @param options the container of all the options of the sync process including the CTP project
   *     client and/or configuration and other sync-specific options.
   * @param typeService the service to fetch the custom types for reference resolution.
   * @param customerGroupService the service to fetch the customer groups for reference resolution.
   */
  public CustomerReferenceResolver(
      @Nonnull final CustomerSyncOptions options,
      @Nonnull final TypeService typeService,
      @Nonnull final CustomerGroupService customerGroupService) {
    super(options, typeService);
    this.typeService = typeService;
    this.customerGroupService = customerGroupService;
  }

  /**
   * Given a {@link CustomerDraft} this method attempts to resolve the stores, customer group and
   * custom type references to return a {@link CompletionStage} which contains a new instance of the
   * draft with the resolved references or, in case an error occurs during reference resolution, a
   * {@link ReferenceResolutionException}.
   *
   * @param customerDraft the draft to resolve its references.
   * @return a {@link CompletionStage} that contains as a result a new CustomerDraft instance with
   *     resolved custom type reference or, in case an error occurs during reference resolution, a
   *     {@link ReferenceResolutionException}.
   */
  @Override
  @Nonnull
  public CompletionStage resolveReferences(
      @Nonnull final CustomerDraft customerDraft) {
    return resolveCustomTypeReference(CustomerDraftBuilder.of(customerDraft))
        .thenCompose(this::resolveCustomerGroupReference)
        .thenCompose(this::resolveStoreReferences)
        .thenApply(CustomerDraftBuilder::build);
  }

  @Override
  protected CompletionStage resolveCustomTypeReference(
      @Nonnull final CustomerDraftBuilder draftBuilder) {

    return resolveCustomTypeReference(
        draftBuilder,
        CustomerDraftBuilder::getCustom,
        CustomerDraftBuilder::custom,
        format(FAILED_TO_RESOLVE_CUSTOM_TYPE, draftBuilder.getKey()));
  }

  /**
   * Given a {@link CustomerDraftBuilder} this method attempts to resolve the customer group to
   * return a {@link CompletionStage} which contains a new instance of the builder with the resolved
   * customer group reference.
   *
   * @param draftBuilder the customerDraft to resolve its customer group reference.
   * @return a {@link CompletionStage} that contains as a result a new builder instance with
   *     resolved customer group reference or, in case an error occurs during reference resolution,
   *     a {@link ReferenceResolutionException}.
   */
  @Nonnull
  public CompletionStage resolveCustomerGroupReference(
      @Nonnull final CustomerDraftBuilder draftBuilder) {

    final ResourceIdentifier customerGroupResourceIdentifier = draftBuilder.getCustomerGroup();
    if (customerGroupResourceIdentifier != null
        && customerGroupResourceIdentifier.getId() == null) {
      String customerGroupKey;
      try {
        customerGroupKey = getKeyFromResourceIdentifier(customerGroupResourceIdentifier);
      } catch (ReferenceResolutionException referenceResolutionException) {
        return exceptionallyCompletedFuture(
            new ReferenceResolutionException(
                format(
                    FAILED_TO_RESOLVE_CUSTOMER_GROUP_REFERENCE,
                    draftBuilder.getKey(),
                    referenceResolutionException.getMessage())));
      }

      return fetchAndResolveCustomerGroupReference(draftBuilder, customerGroupKey);
    }
    return completedFuture(draftBuilder);
  }

  @Nonnull
  private CompletionStage fetchAndResolveCustomerGroupReference(
      @Nonnull final CustomerDraftBuilder draftBuilder, @Nonnull final String customerGroupKey) {

    return customerGroupService
        .fetchCachedCustomerGroupId(customerGroupKey)
        .thenCompose(
            resolvedCustomerGroupIdOptional ->
                resolvedCustomerGroupIdOptional
                    .map(
                        resolvedCustomerGroupId ->
                            completedFuture(
                                draftBuilder.customerGroup(
                                    CustomerGroupResourceIdentifierBuilder.of()
                                        .id(resolvedCustomerGroupId)
                                        .build())))
                    .orElseGet(
                        () -> {
                          final String errorMessage =
                              format(CUSTOMER_GROUP_DOES_NOT_EXIST, customerGroupKey);
                          return exceptionallyCompletedFuture(
                              new ReferenceResolutionException(
                                  format(
                                      FAILED_TO_RESOLVE_CUSTOMER_GROUP_REFERENCE,
                                      draftBuilder.getKey(),
                                      errorMessage)));
                        }));
  }

  /**
   * Given a {@link CustomerDraftBuilder} this method attempts to resolve the stores and return a
   * {@link CompletionStage} which contains a new instance of the builder with the resolved
   * references.
   *
   * @param draftBuilder the customer draft to resolve its store references.
   * @return a {@link CompletionStage} that contains as a result a new builder instance with
   *     resolved references or, in case an error occurs during reference resolution, a {@link
   *     ReferenceResolutionException}.
   */
  @Nonnull
  public CompletionStage resolveStoreReferences(
      @Nonnull final CustomerDraftBuilder draftBuilder) {

    final List storeResourceIdentifiers = draftBuilder.getStores();
    if (storeResourceIdentifiers == null || storeResourceIdentifiers.isEmpty()) {
      return completedFuture(draftBuilder);
    }
    final List resolvedReferences = new ArrayList<>();
    for (StoreResourceIdentifier storeResourceIdentifier : storeResourceIdentifiers) {
      if (storeResourceIdentifier != null) {
        if (storeResourceIdentifier.getId() == null) {
          try {
            final String storeKey = getKeyFromResourceIdentifier(storeResourceIdentifier);
            resolvedReferences.add(StoreResourceIdentifierBuilder.of().key(storeKey).build());
          } catch (ReferenceResolutionException referenceResolutionException) {
            return exceptionallyCompletedFuture(
                new ReferenceResolutionException(
                    format(
                        FAILED_TO_RESOLVE_STORE_REFERENCE,
                        draftBuilder.getKey(),
                        referenceResolutionException.getMessage())));
          }
        } else {
          resolvedReferences.add(
              StoreResourceIdentifierBuilder.of().id(storeResourceIdentifier.getId()).build());
        }
      }
    }
    return completedFuture(draftBuilder.stores(resolvedReferences));
  }

  /**
   * Calls the {@code cacheKeysToIds} service methods to fetch all the referenced keys (i.e custom
   * type, customer group) from the commercetools to populate caches for the reference resolution.
   *
   * 

Note: This method is meant be only used internally by the library to improve performance. * * @param referencedKeys a wrapper for the product references to fetch and cache the id's for. * @return {@link CompletionStage}<{@link Map}<{@link String}>{@link String}>> in * which the results of it's completions contains a map of requested references keys -> ids * of customer references. */ @Nonnull public CompletableFuture>> populateKeyToIdCachesForReferencedKeys( @Nonnull final CustomerBatchValidator.ReferencedKeys referencedKeys) { final List>> futures = new ArrayList<>(); final Set typeKeys = referencedKeys.getTypeKeys(); if (!typeKeys.isEmpty()) { futures.add(typeService.cacheKeysToIds(typeKeys)); } final Set customerGroupKeys = referencedKeys.getCustomerGroupKeys(); if (!customerGroupKeys.isEmpty()) { futures.add(customerGroupService.cacheKeysToIds(customerGroupKeys)); } return collectionOfFuturesToFutureOfCollection(futures, toList()); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy