use of com.commercetools.sync.products.SyncFilter in project commercetools-sync-java by commercetools.
the class ProductSyncIT method sync_withProductTypeReference_ShouldUpdateProducts.
@Test
void sync_withProductTypeReference_ShouldUpdateProducts() {
// Preparation
// Create custom options with whitelisting and action filter callback..
final ProductSyncOptions customSyncOptions = ProductSyncOptionsBuilder.of(CTP_TARGET_CLIENT).errorCallback((exception, oldResource, newResource, updateActions) -> errorCallback(exception.getMessage(), exception.getCause())).warningCallback((exception, oldResource, newResources) -> warningCallBackMessages.add(exception.getMessage())).beforeUpdateCallback(this::beforeUpdateCallback).syncFilter(SyncFilter.ofWhiteList(ATTRIBUTES)).build();
final ProductSync customSync = new ProductSync(customSyncOptions);
// Create 3 existing products in target project with keys (productKey1, productKey2 and
// productKey3)
final ProductDraft existingProductDraft = createProductDraft(PRODUCT_KEY_1_RESOURCE_PATH, targetProductType.toReference(), targetTaxCategory.toReference(), targetProductState.toReference(), targetCategoryReferencesWithIds, createRandomCategoryOrderHints(targetCategoryReferencesWithIds));
CTP_TARGET_CLIENT.execute(ProductCreateCommand.of(existingProductDraft)).toCompletableFuture().join();
final ProductDraft existingProductDraft2 = createProductDraft(PRODUCT_KEY_2_RESOURCE_PATH, targetProductType.toReference(), targetTaxCategory.toReference(), targetProductState.toReference(), targetCategoryReferencesWithIds, createRandomCategoryOrderHints(targetCategoryReferencesWithIds));
CTP_TARGET_CLIENT.execute(ProductCreateCommand.of(existingProductDraft2)).toCompletableFuture().join();
final ProductDraft existingProductDraft3 = createProductDraftBuilder(PRODUCT_KEY_2_RESOURCE_PATH, targetProductType.toReference()).slug(ofEnglish("newSlug3")).key("productKey3").masterVariant(ProductVariantDraftBuilder.of().key("v3").sku("s3").build()).taxCategory(null).state(null).categories(Collections.emptySet()).categoryOrderHints(null).build();
CTP_TARGET_CLIENT.execute(ProductCreateCommand.of(existingProductDraft3)).toCompletableFuture().join();
// Create 2 existing products in source project with keys (productKey2 and productKey3)
final ProductDraft newProductDraft2 = createProductDraft(PRODUCT_KEY_2_RESOURCE_PATH, sourceProductType.toReference(), sourceTaxCategory.toReference(), sourceProductState.toReference(), sourceCategoryReferencesWithIds, createRandomCategoryOrderHints(sourceCategoryReferencesWithIds));
final Product product2 = CTP_SOURCE_CLIENT.execute(ProductCreateCommand.of(newProductDraft2)).toCompletableFuture().join();
final ProductDraft newProductDraft3 = createProductDraftBuilder(PRODUCT_KEY_2_RESOURCE_PATH, sourceProductType.toReference()).slug(ofEnglish("newSlug3")).key("productKey3").masterVariant(ProductVariantDraftBuilder.of().key("v3").sku("s3").build()).taxCategory(null).state(null).categories(Collections.emptySet()).categoryOrderHints(null).build();
final Product product3 = CTP_SOURCE_CLIENT.execute(ProductCreateCommand.of(newProductDraft3)).toCompletableFuture().join();
// Create existing product with productKey1 in source project that has references to products
// with keys
// (productKey2 and productKey3).
final ObjectNode productReferenceValue1 = getProductReferenceWithId(product2.getId());
final ObjectNode productReferenceValue2 = getProductReferenceWithId(product3.getId());
final AttributeDraft productRefAttr = AttributeDraft.of("product-reference", productReferenceValue1);
final AttributeDraft productSetRefAttr = getReferenceSetAttributeDraft("product-reference-set", productReferenceValue1, productReferenceValue2);
final List<AttributeDraft> attributeDrafts = existingProductDraft.getMasterVariant().getAttributes();
attributeDrafts.addAll(Arrays.asList(productRefAttr, productSetRefAttr));
final ProductVariantDraft masterVariant = ProductVariantDraftBuilder.of().key("v1").sku("s1").attributes(attributeDrafts).build();
final ProductDraft newProductDraftWithProductReference = createProductDraftBuilder(PRODUCT_KEY_1_CHANGED_RESOURCE_PATH, sourceProductType.toReference()).masterVariant(masterVariant).taxCategory(sourceTaxCategory.toReference()).state(sourceProductState.toReference()).categories(Collections.emptySet()).categoryOrderHints(null).build();
CTP_SOURCE_CLIENT.execute(ProductCreateCommand.of(newProductDraftWithProductReference)).toCompletableFuture().join();
// Test
final List<ProductProjection> products = CTP_SOURCE_CLIENT.execute(ProductProjectionQuery.ofStaged()).toCompletableFuture().join().getResults();
final List<ProductDraft> productDrafts = ProductTransformUtils.toProductDrafts(CTP_SOURCE_CLIENT, referenceIdToKeyCache, products).join();
final ProductSyncStatistics syncStatistics = customSync.sync(productDrafts).toCompletableFuture().join();
// Assertion
assertThat(syncStatistics).hasValues(3, 0, 1, 0);
assertThat(errorCallBackMessages).isEmpty();
assertThat(errorCallBackExceptions).isEmpty();
assertThat(warningCallBackMessages).isEmpty();
final Product targetProduct2 = CTP_TARGET_CLIENT.execute(ProductByKeyGet.of("productKey2")).toCompletableFuture().join();
final Product targetProduct3 = CTP_TARGET_CLIENT.execute(ProductByKeyGet.of("productKey3")).toCompletableFuture().join();
final ObjectNode targetProductReferenceValue2 = getProductReferenceWithId(targetProduct2.getId());
final ObjectNode targetProductReferenceValue3 = getProductReferenceWithId(targetProduct3.getId());
final AttributeDraft targetProductRefAttr = AttributeDraft.of("product-reference", targetProductReferenceValue2);
final AttributeDraft targetProductSetRefAttr = getReferenceSetAttributeDraft("product-reference-set", targetProductReferenceValue2, targetProductReferenceValue3);
assertThat(updateActions).containsExactlyInAnyOrder(SetAttributeInAllVariants.of(targetProductRefAttr.getName(), targetProductRefAttr.getValue(), true), SetAttributeInAllVariants.of(targetProductSetRefAttr.getName(), targetProductSetRefAttr.getValue(), true), Publish.of());
}
use of com.commercetools.sync.products.SyncFilter in project commercetools-sync-java by commercetools.
the class ProductUpdateActionUtilsTest method buildVariantsUpdateActions_doesNotRemoveMaster.
@Test
void buildVariantsUpdateActions_doesNotRemoveMaster() {
final ProductProjection productOld = createProductFromJson(OLD_PROD_WITH_VARIANTS);
final ProductDraft productDraftNew = createProductDraftFromJson(NEW_PROD_DRAFT_WITH_VARIANTS_MOVE_MASTER);
final ProductSyncOptions productSyncOptions = ProductSyncOptionsBuilder.of(mock(SphereClient.class)).syncFilter(SyncFilter.of()).build();
final Map<String, AttributeMetaData> attributesMetaData = new HashMap<>();
final AttributeMetaData priceInfo = AttributeMetaData.of(AttributeDefinitionBuilder.of("priceInfo", null, null).build());
attributesMetaData.put("priceInfo", priceInfo);
final List<UpdateAction<Product>> updateActions = buildVariantsUpdateActions(productOld, productDraftNew, productSyncOptions, attributesMetaData);
// check remove variants are the first in the list, but not the master variant
assertThat(updateActions.subList(0, 3)).containsExactlyInAnyOrder(RemoveVariant.ofVariantId(2, true), RemoveVariant.ofVariantId(3, true), RemoveVariant.ofVariantId(4, true));
// change master variant must be always after variants are added/updated,
// because it is set by SKU and we should be sure the master variant is already added and SKUs
// are actual.
assertThat(updateActions).endsWith(ChangeMasterVariant.ofSku("var-7-sku", true));
// Old master variant should NOT be removed because it exists in
// NEW_PROD_DRAFT_WITH_VARIANTS_MOVE_MASTER
final ProductVariant oldMasterVariant = productOld.getMasterVariant();
assertThat(updateActions).filteredOn(action -> {
// verify old master variant is not removed
if (action instanceof RemoveVariant) {
RemoveVariant removeVariantAction = (RemoveVariant) action;
return Objects.equals(oldMasterVariant.getId(), removeVariantAction.getId()) || Objects.equals(oldMasterVariant.getSku(), removeVariantAction.getSku());
}
return false;
}).isEmpty();
}
use of com.commercetools.sync.products.SyncFilter in project commercetools-sync-java by commercetools.
the class ProductUpdateActionUtils method collectAllVariantUpdateActions.
@Nonnull
private static List<UpdateAction<Product>> collectAllVariantUpdateActions(@Nonnull final List<UpdateAction<Product>> sameForAllUpdateActions, @Nonnull final ProductProjection oldProduct, @Nonnull final ProductDraft newProduct, @Nonnull final ProductVariant oldProductVariant, @Nonnull final ProductVariantDraft newProductVariant, @Nonnull final Map<String, AttributeMetaData> attributesMetaData, @Nonnull final ProductSyncOptions syncOptions) {
final ArrayList<UpdateAction<Product>> updateActions = new ArrayList<>();
final SyncFilter syncFilter = syncOptions.getSyncFilter();
updateActions.addAll(buildActionsIfPassesFilter(syncFilter, ATTRIBUTES, () -> emptyIfNull(buildProductVariantAttributesUpdateActions(oldProduct, newProduct, oldProductVariant, newProductVariant, attributesMetaData, syncOptions)).stream().filter(collectedUpdateAction -> hasDuplicateSameForAllAction(sameForAllUpdateActions, collectedUpdateAction)).collect(Collectors.toList())));
updateActions.addAll(buildActionsIfPassesFilter(syncFilter, IMAGES, () -> buildProductVariantImagesUpdateActions(oldProductVariant, newProductVariant)));
updateActions.addAll(buildActionsIfPassesFilter(syncFilter, PRICES, () -> buildProductVariantPricesUpdateActions(oldProduct, newProduct, oldProductVariant, newProductVariant, syncOptions)));
updateActions.addAll(buildActionsIfPassesFilter(syncFilter, ASSETS, () -> buildProductVariantAssetsUpdateActions(oldProduct, newProduct, oldProductVariant, newProductVariant, syncOptions)));
buildActionIfPassesFilter(syncFilter, SKU, () -> buildProductVariantSkuUpdateAction(oldProductVariant, newProductVariant)).ifPresent(updateActions::add);
return updateActions;
}
use of com.commercetools.sync.products.SyncFilter in project commercetools-sync-java by commercetools.
the class ProductSyncUtils method buildActions.
/**
* Compares all the fields (including the variants see {@link
* ProductUpdateActionUtils#buildVariantsUpdateActions(ProductProjection, ProductDraft,
* ProductSyncOptions, Map)}) of a {@link ProductProjection} and a {@link ProductDraft}, given
* that each of these fields pass the specified {@link SyncFilter}. It returns a {@link List} of
* {@link UpdateAction}<{@link Product}> as a result. If no update action is needed, for
* example in case where both the {@link ProductProjection} and the {@link ProductDraft} have the
* same names, an empty {@link List} is returned. Then it applies a specified filter function in
* the {@link ProductSyncOptions} instance on the resultant list and returns this result.
*
* @param oldProduct the productprojection which should be updated.
* @param newProduct the product draft where we get the new data.
* @param syncOptions the sync options wrapper which contains options related to the sync process
* supplied by the user. For example, custom callbacks to call in case of warnings or errors
* occurring on the build update action process. And other options (See {@link
* ProductSyncOptions} for more info).
* @param attributesMetaData a map of attribute name -> {@link AttributeMetaData}; which
* defines each attribute's information: its name and whether it has the constraint
* "SameForAll" or not.
* @return A list of product-specific update actions.
*/
@Nonnull
public static List<UpdateAction<Product>> buildActions(@Nonnull final ProductProjection oldProduct, @Nonnull final ProductDraft newProduct, @Nonnull final ProductSyncOptions syncOptions, @Nonnull final Map<String, AttributeMetaData> attributesMetaData) {
final SyncFilter syncFilter = syncOptions.getSyncFilter();
final List<UpdateAction<Product>> updateActions = new ArrayList<>(filterEmptyOptionals(buildActionIfPassesFilter(syncFilter, ActionGroup.NAME, () -> buildChangeNameUpdateAction(oldProduct, newProduct)), buildActionIfPassesFilter(syncFilter, ActionGroup.DESCRIPTION, () -> buildSetDescriptionUpdateAction(oldProduct, newProduct)), buildActionIfPassesFilter(syncFilter, ActionGroup.SLUG, () -> buildChangeSlugUpdateAction(oldProduct, newProduct)), buildActionIfPassesFilter(syncFilter, ActionGroup.SEARCHKEYWORDS, () -> buildSetSearchKeywordsUpdateAction(oldProduct, newProduct)), buildActionIfPassesFilter(syncFilter, ActionGroup.METATITLE, () -> buildSetMetaTitleUpdateAction(oldProduct, newProduct)), buildActionIfPassesFilter(syncFilter, ActionGroup.METADESCRIPTION, () -> buildSetMetaDescriptionUpdateAction(oldProduct, newProduct)), buildActionIfPassesFilter(syncFilter, ActionGroup.METAKEYWORDS, () -> buildSetMetaKeywordsUpdateAction(oldProduct, newProduct)), buildActionIfPassesFilter(syncFilter, ActionGroup.TAXCATEGORY, () -> buildSetTaxCategoryUpdateAction(oldProduct, newProduct).map(action -> (UpdateAction<Product>) action)), buildActionIfPassesFilter(syncFilter, ActionGroup.STATE, () -> buildTransitionStateUpdateAction(oldProduct, newProduct).map(action -> (UpdateAction<Product>) action))));
final List<UpdateAction<Product>> productCategoryUpdateActions = buildActionsIfPassesFilter(syncFilter, ActionGroup.CATEGORIES, () -> buildCategoryActions(oldProduct, newProduct));
updateActions.addAll(productCategoryUpdateActions);
updateActions.addAll(buildVariantsUpdateActions(oldProduct, newProduct, syncOptions, attributesMetaData));
// lastly publish/unpublish product
final boolean hasNewUpdateActions = updateActions.size() > 0;
buildPublishOrUnpublishUpdateAction(oldProduct, newProduct, hasNewUpdateActions).ifPresent(updateActions::add);
return prioritizeUpdateActions(updateActions, oldProduct.getMasterVariant().getId());
}
use of com.commercetools.sync.products.SyncFilter in project commercetools-sync-java by commercetools.
the class FilterUtilsTest method executeSupplierIfPassesFilter_WithGroupInWhiteList_ShouldFilterInOnlyThisGroup.
@Test
void executeSupplierIfPassesFilter_WithGroupInWhiteList_ShouldFilterInOnlyThisGroup() {
final SyncFilter syncFilter = SyncFilter.ofWhiteList(PRICES);
final List<UpdateAction<Product>> updateActionsAfterPricesFilter = executeSupplierIfPassesFilter(syncFilter, PRICES, () -> passingUpdateActions, () -> defaultActions);
assertThat(updateActionsAfterPricesFilter).hasSize(2);
assertThat(updateActionsAfterPricesFilter).isSameAs(passingUpdateActions);
final List<UpdateAction<Product>> updateActionsAfterImagesFilter = executeSupplierIfPassesFilter(syncFilter, IMAGES, () -> passingUpdateActions, () -> defaultActions);
assertThat(updateActionsAfterImagesFilter).hasSize(1);
assertThat(updateActionsAfterImagesFilter).isSameAs(defaultActions);
final List<UpdateAction<Product>> updateActionsAfterCategoriesFilter = executeSupplierIfPassesFilter(syncFilter, CATEGORIES, () -> passingUpdateActions, () -> defaultActions);
assertThat(updateActionsAfterCategoriesFilter).hasSize(1);
assertThat(updateActionsAfterCategoriesFilter).isSameAs(defaultActions);
}
Aggregations