use of com.commercetools.sync.commons.exceptions.SyncException in project commercetools-sync-java by commercetools.
the class CustomUpdateActionUtils method buildCustomUpdateActions.
/**
* Compares the {@link CustomFields} of an old resource {@code T} (for example {@link Category},
* {@link io.sphere.sdk.products.Product}, etc..), to the {@link CustomFieldsDraft}, of a new
* resource draft {@code S} (for example {@link CategoryDraft}, {@link
* io.sphere.sdk.products.ProductVariantDraft}, etc..), and returns a {@link List}<{@link
* UpdateAction}> as a result. If no update action is needed, for example in the case where
* both the {@link CustomFields} and the {@link CustomFieldsDraft} are null, an empty {@link
* List}<{@link UpdateAction}> is returned. A {@link BaseSyncOptions} instance is injected
* into the method which is responsible for supplying the sync options to the sync utility method.
* For example, custom error callbacks for errors. The {@link TypeService} is injected also for
* fetching the key of the old resource type from it's cache (see {@link
* CustomUpdateActionUtils#buildNonNullCustomFieldsUpdateActions(CustomFields, CustomFieldsDraft,
* Custom, GenericCustomActionBuilder, Integer, Function, Function, Function, BaseSyncOptions)}).
*
* <p>An update action will be added to the result list in the following cases:-
*
* <ol>
* <li>If the new resources's custom type is set, but old resources's custom type is not. A
* "setCustomType" update actions is added, which sets the custom type (and all it's fields
* to the old resource).
* <li>If the new resource's custom type is not set, but the old resource's custom type is set.
* A "setCustomType" update action is added, which removes the type set on the old resource.
* <li>If both the resources custom types are the same and the custom fields are both set. The
* custom field values of both resources are then calculated. (see {@link
* CustomUpdateActionUtils#buildSetCustomFieldsUpdateActions(Map, Map, Custom,
* GenericCustomActionBuilder, Integer, Function)} )})
* <li>If the keys of both custom types are different, then a "setCustomType" update action is
* added, where the old resource's custom type is set to be as the new one's.
* <li>If both resources custom type keys are identical but the custom fields of the new
* resource's custom type is not set.
* </ol>
*
* <p>An update action will <b>not</b> be added to the result list in the following cases:-
*
* <ol>
* <li>If both the resources' custom types are not set.
* <li>If both the resources' custom type keys are not set.
* <li>Custom fields are both empty.
* <li>Custom field JSON values have different ordering.
* <li>Custom field values are identical.
* </ol>
*
* @param <D> the type of the new {@link Resource} which is the super {@link Resource} of the
* Resource to update.
* @param <T> the type of the old {@link Resource} which has the custom fields.
* @param <S> the type of the new resource {@link CustomDraft}.
* @param <U> the type of the resource in which the update actions will be applied on.
* @param newMainResourceDraft the main resource of the resource draft where we get the new custom
* fields.
* @param oldResource the resource which should be updated.
* @param newResourceDraft the resource draft where we get the new custom fields.
* @param customActionBuilder the builder instance responsible for building the custom update
* actions.
* @param variantId optional field representing the variant id in case the oldResource is an
* asset.
* @param resourceIdGetter a function used to get the id of the resource being updated.
* @param resourceTypeIdGetter a function used to get the Type id of the resource being updated.
* @param updateIdGetter a function used to get the id/key needed for updating the resource that
* has the custom fields.
* @param syncOptions responsible for supplying the sync options to the sync utility method.
* @return a list that contains all the update actions needed, otherwise an empty list if no
* update actions are needed.
*/
@SuppressWarnings("unchecked")
@Nonnull
public static <D, T extends Custom, S extends CustomDraft, U extends ResourceView> List<UpdateAction<U>> buildCustomUpdateActions(@Nullable final D newMainResourceDraft, @Nonnull final T oldResource, @Nonnull final S newResourceDraft, @Nonnull final GenericCustomActionBuilder<U> customActionBuilder, @Nullable final Integer variantId, @Nonnull final Function<T, String> resourceIdGetter, @Nonnull final Function<T, String> resourceTypeIdGetter, @Nonnull final Function<T, String> updateIdGetter, @Nonnull final BaseSyncOptions syncOptions) {
final CustomFields oldResourceCustomFields = oldResource.getCustom();
final CustomFieldsDraft newResourceCustomFields = newResourceDraft.getCustom();
if (oldResourceCustomFields != null && newResourceCustomFields != null) {
try {
return buildNonNullCustomFieldsUpdateActions(oldResourceCustomFields, newResourceCustomFields, oldResource, customActionBuilder, variantId, resourceIdGetter, resourceTypeIdGetter, updateIdGetter, syncOptions);
} catch (BuildUpdateActionException exception) {
final String errorMessage = format(CUSTOM_FIELDS_UPDATE_ACTIONS_BUILD_FAILED, resourceTypeIdGetter.apply(oldResource), resourceIdGetter.apply(oldResource), exception.getMessage());
syncOptions.applyErrorCallback(new SyncException(errorMessage, exception), oldResource, newMainResourceDraft != null ? newMainResourceDraft : newResourceDraft, null);
}
} else {
if (oldResourceCustomFields == null) {
if (newResourceCustomFields != null) {
// New resource's custom fields are set, but old resources's custom fields are not set. So
// we
// should set the custom type and fields of the new resource to the old one.
final String newCustomFieldsTypeId = newResourceCustomFields.getType().getId();
if (isBlank(newCustomFieldsTypeId)) {
final String errorMessage = format(CUSTOM_FIELDS_UPDATE_ACTIONS_BUILD_FAILED, resourceTypeIdGetter.apply(oldResource), resourceIdGetter.apply(oldResource), CUSTOM_TYPE_ID_IS_BLANK);
syncOptions.applyErrorCallback(new SyncException(errorMessage, null), oldResource, newMainResourceDraft != null ? newMainResourceDraft : newResourceDraft, null);
} else {
final Map<String, JsonNode> newCustomFieldsJsonMap = newResourceCustomFields.getFields();
final Optional<UpdateAction<U>> updateAction = buildTypedSetCustomTypeUpdateAction(newCustomFieldsTypeId, newCustomFieldsJsonMap, oldResource, customActionBuilder, variantId, resourceIdGetter, resourceTypeIdGetter, updateIdGetter, syncOptions);
return updateAction.map(Collections::singletonList).orElseGet(Collections::emptyList);
}
}
} else {
return singletonList(customActionBuilder.buildRemoveCustomTypeAction(variantId, updateIdGetter.apply(oldResource)));
}
}
return Collections.emptyList();
}
use of com.commercetools.sync.commons.exceptions.SyncException in project commercetools-sync-java by commercetools.
the class InventorySync method handleFailedToProcessError.
private void handleFailedToProcessError(@Nonnull final InventoryEntryDraft newInventoryEntry, @Nonnull final Throwable completionException) {
final String errorMessage = format(FAILED_TO_PROCESS, newInventoryEntry.getSku(), completionException.getMessage());
handleError(new SyncException(errorMessage, completionException), 1);
}
use of com.commercetools.sync.commons.exceptions.SyncException in project commercetools-sync-java by commercetools.
the class CategoryUpdateActionUtils method buildChangeParentUpdateAction.
/**
* Compares the parents {@link Reference}<{@link Category}> of a {@link Category} and a
* {@link CategoryDraft} and returns an {@link UpdateAction}<{@link Category}> as a result
* in an {@link Optional}. If both the {@link Category} and the {@link CategoryDraft} have the
* same parents, then no update action is needed and hence an empty {@link Optional} is returned.
*
* <p>Note: If the parent {@link Reference}<{@link Category}> of the new {@link
* CategoryDraft} is null, an empty {@link Optional} is returned with no update actions and a
* custom callback function, if set on the supplied {@link CategorySyncOptions}, is called.
*
* @param oldCategory the category which should be updated.
* @param newCategory the category draft where we get the new parent.
* @param syncOptions the sync syncOptions with which a custom callback function is called in case
* the parent is null.
* @return A filled optional with the update action or an empty optional if the parent references
* are identical.
*/
@Nonnull
public static Optional<UpdateAction<Category>> buildChangeParentUpdateAction(@Nonnull final Category oldCategory, @Nonnull final CategoryDraft newCategory, @Nonnull final CategorySyncOptions syncOptions) {
final Reference<Category> oldParent = oldCategory.getParent();
final ResourceIdentifier<Category> newParent = newCategory.getParent();
if (newParent == null && oldParent != null) {
syncOptions.applyWarningCallback(new SyncException(format(CATEGORY_CHANGE_PARENT_EMPTY_PARENT, oldCategory.getId())), oldCategory, newCategory);
return Optional.empty();
} else {
// being not null.
return buildUpdateActionForReferences(oldParent, newParent, () -> ChangeParent.of(ResourceIdentifier.ofId(newParent.getId())));
}
}
use of com.commercetools.sync.commons.exceptions.SyncException in project commercetools-sync-java by commercetools.
the class TaxCategoryBatchValidator method validateIfDuplicateCountryAndState.
private boolean validateIfDuplicateCountryAndState(final List<TaxRateDraft> taxRateDrafts) {
/*
For TaxRates uniqueness could be ensured by country code and states.
So in tax category sync are using country code and states for matching.
Representation of the commercetools platform error when country code is duplicated,
{
"statusCode": 400,
"message": "A duplicate value '{\"country\":\"DE\"}' exists for field 'country'.",
"errors": [
{
"code": "DuplicateField",
....
]
}
*/
Map<String, Map<String, Long>> map = taxRateDrafts.stream().collect(Collectors.groupingBy(draft -> Objects.toString(draft.getCountry(), ""), Collectors.groupingBy(draft -> Objects.toString(draft.getState(), ""), Collectors.counting())));
for (Map.Entry<String, Map<String, Long>> countryEntry : map.entrySet()) {
for (Map.Entry<String, Long> stateEntry : countryEntry.getValue().entrySet()) {
if (stateEntry.getValue() > 1L) {
String errorMessage = StringUtils.isBlank(stateEntry.getKey()) ? format(TAX_CATEGORY_DUPLICATED_COUNTRY, countryEntry.getKey()) : format(TAX_CATEGORY_DUPLICATED_COUNTRY_AND_STATE, countryEntry.getKey(), stateEntry.getKey());
handleError(new SyncException(errorMessage));
return false;
}
}
}
return true;
}
use of com.commercetools.sync.commons.exceptions.SyncException in project commercetools-sync-java by commercetools.
the class TypeSync method handleError.
/**
* Given a {@link String} {@code errorMessage} and a {@link Throwable} {@code exception}, this
* method calls the optional error callback specified in the {@code syncOptions} and updates the
* {@code statistics} instance by incrementing the total number of failed types to sync.
*
* @param errorMessage The error message describing the reason(s) of failure.
* @param exception The exception that called caused the failure, if any.
* @param failedTimes The number of times that the failed types counter is incremented.
*/
private void handleError(@Nonnull final String errorMessage, @Nonnull final Throwable exception, final int failedTimes) {
SyncException syncException = new SyncException(errorMessage, exception);
syncOptions.applyErrorCallback(syncException);
statistics.incrementFailed(failedTimes);
}
Aggregations