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

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

package com.commercetools.sync.customers.helpers;

import static java.lang.String.format;
import static java.util.stream.Collectors.toSet;
import static org.apache.commons.lang3.StringUtils.isBlank;

import com.commercetools.api.models.common.BaseAddress;
import com.commercetools.api.models.customer.CustomerDraft;
import com.commercetools.sync.commons.helpers.BaseBatchValidator;
import com.commercetools.sync.customers.CustomerSyncOptions;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.function.Predicate;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.apache.commons.lang3.tuple.ImmutablePair;

public class CustomerBatchValidator
    extends BaseBatchValidator {

  public static final String CUSTOMER_DRAFT_IS_NULL = "CustomerDraft is null.";
  public static final String CUSTOMER_DRAFT_KEY_NOT_SET =
      "CustomerDraft with email: %s doesn't have a key. "
          + "Please make sure all customer drafts have keys.";
  public static final String CUSTOMER_DRAFT_EMAIL_NOT_SET =
      "CustomerDraft with key: %s doesn't have an email. "
          + "Please make sure all customer drafts have emails.";
  static final String CUSTOMER_DRAFT_PASSWORD_NOT_SET =
      "CustomerDraft with key: %s doesn't have a password. "
          + "Please make sure all customer drafts have passwords.";

  static final String ADDRESSES_ARE_NULL =
      "CustomerDraft with key: '%s' has null addresses on indexes: '%s'. "
          + "Please make sure each address is set in the addresses list.";
  static final String ADDRESSES_THAT_KEYS_NOT_SET =
      "CustomerDraft with key: '%s' has blank address keys on indexes: "
          + "'%s'. Please make sure each address has a key in the addresses list";
  static final String ADDRESSES_THAT_KEYS_NOT_UNIQUE =
      "CustomerDraft with key: '%s' has duplicate address keys on "
          + "indexes: '%s'. Please make sure each address key is unique in the addresses list.";

  static final String BILLING_ADDRESSES_ARE_NOT_VALID =
      "CustomerDraft with key: '%s' does not contain indices: '%s' "
          + "of the 'billingAddresses' in the addresses list. "
          + "Please make sure all customer drafts have valid index values for the 'billingAddresses'.";

  static final String SHIPPING_ADDRESSES_ARE_NOT_VALID =
      "CustomerDraft with key: '%s' does not contain indices: '%s'"
          + " of the 'shippingAddresses' in the addresses list. "
          + "Please make sure all customer drafts have valid index values for the 'shippingAddresses'.";

  public CustomerBatchValidator(
      @Nonnull final CustomerSyncOptions syncOptions,
      @Nonnull final CustomerSyncStatistics syncStatistics) {
    super(syncOptions, syncStatistics);
  }

  /**
   * Given the {@link List}<{@link CustomerDraft}> of drafts this method attempts to validate
   * drafts and return an {@link ImmutablePair}<{@link Set}<{@link CustomerDraft}>, {@link
   * ReferencedKeys}> which contains the {@link Set} of valid drafts and referenced keys within a
   * wrapper.
   *
   * 

A valid customer draft is one which satisfies the following conditions: * *

    *
  1. It is not null *
  2. It has a key which is not blank (null/empty) *
  3. It has a email which is not blank (null/empty) *
  4. Each address in the addresses list satisfies the following conditions: *
      *
    1. It is not null *
    2. It has a key which is not blank (null/empty) *
    3. It has a unique key *
    *
  5. Each address index in the 'billing' and 'shipping' addresses list are valid and * contained in the addresses list. *
* * @param customerDrafts the customer drafts to validate and collect referenced keys. * @return {@link ImmutablePair}<{@link Set}<{@link CustomerDraft}>, {@link * ReferencedKeys}> which contains the {@link Set} of valid drafts and referenced keys * within a wrapper. */ @Override public ImmutablePair, ReferencedKeys> validateAndCollectReferencedKeys( @Nonnull final List customerDrafts) { final ReferencedKeys referencedKeys = new ReferencedKeys(); final Set validDrafts = customerDrafts.stream() .filter(this::isValidCustomerDraft) .peek(customerDraft -> collectReferencedKeys(referencedKeys, customerDraft)) .collect(toSet()); return ImmutablePair.of(validDrafts, referencedKeys); } private boolean isValidCustomerDraft(@Nullable final CustomerDraft customerDraft) { if (customerDraft == null) { handleError(CUSTOMER_DRAFT_IS_NULL); } else if (isBlank(customerDraft.getKey())) { handleError(format(CUSTOMER_DRAFT_KEY_NOT_SET, customerDraft.getEmail())); } else if (isBlank(customerDraft.getEmail())) { handleError(format(CUSTOMER_DRAFT_EMAIL_NOT_SET, customerDraft.getKey())); } else if (isBlank(customerDraft.getPassword())) { handleError(format(CUSTOMER_DRAFT_PASSWORD_NOT_SET, customerDraft.getKey())); } else if (hasValidAddresses(customerDraft)) { return hasValidBillingAndShippingAddresses(customerDraft); } return false; } private boolean hasValidAddresses(@Nonnull final CustomerDraft customerDraft) { final List addressList = customerDraft.getAddresses(); if (addressList == null || addressList.isEmpty()) { return true; } if (addressList.stream().noneMatch(Objects::nonNull)) { return true; } final List indexesOfNullAddresses = getIndexes(addressList, Objects::isNull); if (!indexesOfNullAddresses.isEmpty()) { handleError(format(ADDRESSES_ARE_NULL, customerDraft.getKey(), indexesOfNullAddresses)); return false; } final List indexesOfBlankAddressKeys = getIndexes(addressList, address -> isBlank(address.getKey())); if (!indexesOfBlankAddressKeys.isEmpty()) { handleError( format(ADDRESSES_THAT_KEYS_NOT_SET, customerDraft.getKey(), indexesOfBlankAddressKeys)); return false; } final Predicate searchDuplicateKeys = (BaseAddress address) -> addressList.stream().filter(a -> Objects.equals(a.getKey(), address.getKey())).count() > 1; final List indexesOfDuplicateAddressKeys = getIndexes(addressList, searchDuplicateKeys); if (!indexesOfDuplicateAddressKeys.isEmpty()) { handleError( format( ADDRESSES_THAT_KEYS_NOT_UNIQUE, customerDraft.getKey(), indexesOfDuplicateAddressKeys)); return false; } return true; } @Nonnull private List getIndexes( @Nonnull final List list, @Nonnull final Predicate predicate) { final List indexes = new ArrayList<>(); for (int i = 0; i < list.size(); i++) { if (predicate.test(list.get(i))) { indexes.add(i); } } return indexes; } private boolean hasValidBillingAndShippingAddresses(@Nonnull final CustomerDraft customerDraft) { /* An example error response from the API, when the indexes are not valid: { "statusCode": 400, "message": "Customer does not contain an address at index '1'.", "errors": [{ "code": "InvalidOperation", "message": "Customer does not contain an address at index '-1'." }, { "code": "InvalidOperation", "message": "Customer does not contain an address at index '1'." }] } */ final List addressList = customerDraft.getAddresses(); final Predicate isInvalidIndex = index -> index == null || addressList == null || addressList.isEmpty() || index < 0 || index > addressList.size() - 1; if (customerDraft.getBillingAddresses() != null && !customerDraft.getBillingAddresses().isEmpty()) { final List invalidIndexes = getIndexValues(customerDraft.getBillingAddresses(), isInvalidIndex); if (!invalidIndexes.isEmpty()) { handleError( format(BILLING_ADDRESSES_ARE_NOT_VALID, customerDraft.getKey(), invalidIndexes)); return false; } } if (customerDraft.getShippingAddresses() != null && !customerDraft.getShippingAddresses().isEmpty()) { final List invalidIndexes = getIndexValues(customerDraft.getShippingAddresses(), isInvalidIndex); if (!invalidIndexes.isEmpty()) { handleError( format(SHIPPING_ADDRESSES_ARE_NOT_VALID, customerDraft.getKey(), invalidIndexes)); return false; } } return true; } @Nonnull private List getIndexValues( @Nonnull final List list, @Nonnull final Predicate predicate) { final List indexes = new ArrayList<>(); for (Integer integer : list) { if (predicate.test(integer)) { indexes.add(integer); } } return indexes; } private void collectReferencedKeys( @Nonnull final ReferencedKeys referencedKeys, @Nonnull final CustomerDraft customerDraft) { collectReferencedKeyFromResourceIdentifier( customerDraft.getCustomerGroup(), referencedKeys.customerGroupKeys::add); collectReferencedKeyFromCustomFieldsDraft( customerDraft.getCustom(), referencedKeys.typeKeys::add); } public static class ReferencedKeys { private final Set customerGroupKeys = new HashSet<>(); private final Set typeKeys = new HashSet<>(); public Set getTypeKeys() { return typeKeys; } public Set getCustomerGroupKeys() { return customerGroupKeys; } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy