From e04ab1737c92db0a507fa1db57b0bc93bba20af9 Mon Sep 17 00:00:00 2001 From: Lam Tran Date: Wed, 20 Nov 2024 13:04:20 +0100 Subject: [PATCH] SUPPORT-28804 add custom deserializer for attrs in import api (#748) --- .git-blame-ignore-revs | 1 + .../DeleteEverythingIntegrationTest.java | 6 +- .../CartDiscountIntegrationTests.java | 9 + .../com/commercetools/api/json/ApiModule.java | 2 +- .../api/json/AtrributeDeserializer.java | 243 +------ .../api/json/AttributeDeserializer.java | 247 +++++++ .../importapi/json/AttributeMixin.java | 8 + .../json/ErrorAttributeDeserializer.java | 183 +++++ .../importapi/json/ImportApiModule.java | 2 + .../importapi/DeserializerTest.java | 656 ++++++++++++++++++ 10 files changed, 1118 insertions(+), 239 deletions(-) create mode 100644 commercetools/commercetools-sdk-java-api/src/main/java/com/commercetools/api/json/AttributeDeserializer.java create mode 100644 commercetools/commercetools-sdk-java-importapi/src/main/java/com/commercetools/importapi/json/AttributeMixin.java create mode 100644 commercetools/commercetools-sdk-java-importapi/src/main/java/com/commercetools/importapi/json/ErrorAttributeDeserializer.java create mode 100644 commercetools/commercetools-sdk-java-importapi/src/test/java/com/commerctools/importapi/DeserializerTest.java diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index 066cfd71cda..15c3c507357 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -4,3 +4,4 @@ a8ec45c8ea4ba559247b654d01b0d35b21a68865 d0129c1095216d5c830900c8a6223ef5d4274de1 4bc5c823b8ebf5a00491c7e63e1ea49d29bf5ee7 352051999507bd78542e177d67ce1548a0752691 +bbe9f971763ca1b27687a6a51067a385a0d23b04 diff --git a/commercetools/commercetools-sdk-java-api/src/integrationTest/java/cleanup/DeleteEverythingIntegrationTest.java b/commercetools/commercetools-sdk-java-api/src/integrationTest/java/cleanup/DeleteEverythingIntegrationTest.java index 59304d38bce..e75673506dc 100644 --- a/commercetools/commercetools-sdk-java-api/src/integrationTest/java/cleanup/DeleteEverythingIntegrationTest.java +++ b/commercetools/commercetools-sdk-java-api/src/integrationTest/java/cleanup/DeleteEverythingIntegrationTest.java @@ -82,7 +82,7 @@ public void execute() { } } - private , TResult extends ResourcePagedQueryResponse, TElement extends DomainResource> void deleteAllResources( + private static , TResult extends ResourcePagedQueryResponse, TElement extends DomainResource> void deleteAllResources( SimplePagedQueryResourceRequest request, Consumer deleteFn) { QueryUtils.queryAll(request, list -> { @@ -90,7 +90,7 @@ public void execute() { }, 100).toCompletableFuture().join(); } - private void checkDepends(Runnable block) { + public static void checkDepends(Runnable block) { assertEventually(Duration.ofSeconds(60), Duration.ofMillis(1000), block); } @@ -212,7 +212,7 @@ private void deleteAllCategories() { } while (response.getResults().size() != 0); } - private void deleteAllCartDiscounts() { + public static void deleteAllCartDiscounts() { checkDepends(() -> Assertions.assertThat( CommercetoolsTestUtils.getProjectApiRoot().discountCodes().get().executeBlocking().getBody().getCount()) .isZero()); diff --git a/commercetools/commercetools-sdk-java-api/src/integrationTest/java/commercetools/cart_discount/CartDiscountIntegrationTests.java b/commercetools/commercetools-sdk-java-api/src/integrationTest/java/commercetools/cart_discount/CartDiscountIntegrationTests.java index b161c1f5b0f..70aadef3ef4 100644 --- a/commercetools/commercetools-sdk-java-api/src/integrationTest/java/commercetools/cart_discount/CartDiscountIntegrationTests.java +++ b/commercetools/commercetools-sdk-java-api/src/integrationTest/java/commercetools/cart_discount/CartDiscountIntegrationTests.java @@ -1,6 +1,7 @@ package commercetools.cart_discount; +import static cleanup.DeleteEverythingIntegrationTest.deleteAllCartDiscounts; import static commercetools.cart_discount.CartDiscountFixtures.*; import static commercetools.type.TypeFixtures.getFieldName; @@ -16,10 +17,18 @@ import commercetools.utils.CommercetoolsTestUtils; import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; public class CartDiscountIntegrationTests { + @BeforeAll + @AfterAll + public static void deleteCartDiscounts() { + deleteAllCartDiscounts(); + } + @Test public void ref() { Optional optional = ReferenceTypeId.findEnumViaJsonName("product-type"); diff --git a/commercetools/commercetools-sdk-java-api/src/main/java/com/commercetools/api/json/ApiModule.java b/commercetools/commercetools-sdk-java-api/src/main/java/com/commercetools/api/json/ApiModule.java index 771b96451de..3451f9a352a 100644 --- a/commercetools/commercetools-sdk-java-api/src/main/java/com/commercetools/api/json/ApiModule.java +++ b/commercetools/commercetools-sdk-java-api/src/main/java/com/commercetools/api/json/ApiModule.java @@ -42,7 +42,7 @@ public ApiModule(ModuleOptions options) { } else { addDeserializer(AttributeImpl.class, - new AtrributeDeserializer(attributeAsDateString, attributeNumberAsDouble)); + new AttributeDeserializer(attributeAsDateString, attributeNumberAsDouble)); } if (customFieldAsJsonNode) { addDeserializer(FieldContainerImpl.class, new CustomFieldJsonNodeDeserializer()); diff --git a/commercetools/commercetools-sdk-java-api/src/main/java/com/commercetools/api/json/AtrributeDeserializer.java b/commercetools/commercetools-sdk-java-api/src/main/java/com/commercetools/api/json/AtrributeDeserializer.java index cb9d6b48083..1c6365f3168 100644 --- a/commercetools/commercetools-sdk-java-api/src/main/java/com/commercetools/api/json/AtrributeDeserializer.java +++ b/commercetools/commercetools-sdk-java-api/src/main/java/com/commercetools/api/json/AtrributeDeserializer.java @@ -1,247 +1,20 @@ package com.commercetools.api.json; -import java.io.IOException; -import java.time.LocalDate; -import java.time.LocalTime; -import java.time.ZonedDateTime; -import java.util.List; -import java.util.regex.Pattern; - -import com.commercetools.api.models.common.LocalizedString; -import com.commercetools.api.models.common.Reference; -import com.commercetools.api.models.common.TypedMoney; -import com.commercetools.api.models.product.*; -import com.commercetools.api.models.product_type.AttributeLocalizedEnumValue; -import com.commercetools.api.models.product_type.AttributePlainEnumValue; -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.JsonDeserializer; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.JsonNodeType; - -public class AtrributeDeserializer extends JsonDeserializer { - - private static Pattern p = Pattern.compile("^[0-9]"); - private static Pattern dateTime = Pattern - .compile("^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}([.][0-9]{1,6})?(Z|[+-][0-9]{2}:[0-9]{2})"); - private static Pattern date = Pattern.compile("^[0-9]{4}-[0-9]{2}-[0-9]{2}"); - private static Pattern time = Pattern.compile("^[0-9]{2}:[0-9]{2}:[0-9]{2}([.][0-9]{1,6})?"); - - private final boolean deserializeAsDate; - - private final boolean deserializeNumberAsDouble; - +/** + * @deprecated typo in the class name, use AttributeDeserializer instead + */ +@Deprecated +public class AtrributeDeserializer extends AttributeDeserializer { public AtrributeDeserializer(boolean deserializeAsDateString) { - this.deserializeAsDate = !deserializeAsDateString; - this.deserializeNumberAsDouble = false; + super(deserializeAsDateString); } public AtrributeDeserializer(boolean deserializeAsDateString, boolean deserializeNumberAsDouble) { - this.deserializeAsDate = !deserializeAsDateString; - this.deserializeNumberAsDouble = deserializeNumberAsDouble; + super(deserializeAsDateString, deserializeNumberAsDouble); } public AtrributeDeserializer() { - this.deserializeAsDate = true; - this.deserializeNumberAsDouble = false; - } - - @Override - public AttributeImpl deserialize(JsonParser p, DeserializationContext ctx) throws IOException { - - JsonNode node = p.readValueAsTree(); - JsonNode valueNode = node.get("value"); - - AttributeBuilder builder = Attribute.builder(); - builder.name(node.get("name").asText()); - - return (AttributeImpl) builder.value(p.getCodec().treeAsTokens(valueNode).readValueAs(typeRef(valueNode))) - .build(); - } - - private TypeReference typeRef(JsonNode valueNode) { - JsonNodeType valueNodeType = valueNode.getNodeType(); - switch (valueNodeType) { - case BOOLEAN: - return new TypeReference() { - }; - case NUMBER: - if (!deserializeNumberAsDouble && (valueNode.isInt() || valueNode.isLong())) { - return new TypeReference() { - }; - } - return new TypeReference() { - }; - case STRING: - if (deserializeAsDate) { - String val = valueNode.asText(); - if (p.matcher(val).find()) { - if (dateTime.matcher(val).find()) { - return new TypeReference() { - }; - } - if (date.matcher(val).matches()) { - return new TypeReference() { - }; - } - if (time.matcher(val).matches()) { - return new TypeReference() { - }; - } - } - } - return new TypeReference() { - }; - case OBJECT: - if (valueNode.has("key") && valueNode.has("label")) { - JsonNode label = valueNode.get("label"); - if (label.getNodeType() == JsonNodeType.OBJECT) { - return new TypeReference() { - }; - } - return new TypeReference() { - }; - } - if (valueNode.has("currencyCode")) { - return new TypeReference() { - }; - } - if (valueNode.has("typeId")) { - return new TypeReference() { - }; - } - if (valueNode.has("value")) { - return new TypeReference() { - }; - } - return new TypeReference() { - }; - case ARRAY: - JsonNode first = valueNode.get(0); - switch (elemType(first)) { - case STRING: - return new TypeReference>() { - }; - case DATE: - return new TypeReference>() { - }; - case DATETIME: - return new TypeReference>() { - }; - case TIME: - return new TypeReference>() { - }; - case NUMBER: - return new TypeReference>() { - }; - case LONG: - return new TypeReference>() { - }; - case BOOLEAN: - return new TypeReference>() { - }; - case ENUM: - return new TypeReference>() { - }; - case LOCALIZED_ENUM: - return new TypeReference>() { - }; - case LOCALIZED_STRING: - return new TypeReference>() { - }; - case MONEY: - return new TypeReference>() { - }; - case REFERENCE: - return new TypeReference>() { - }; - case NESTED: - return new TypeReference>() { - }; - case SET_NESTED: - return new TypeReference>>() { - }; - default: - return new TypeReference>() { - }; - } - default: - return new TypeReference() { - }; - } - } - - private ElemType elemType(JsonNode valueNode) { - if (valueNode == null) { - return ElemType.JSON_NODE; - } - JsonNodeType valueNodeType = valueNode.getNodeType(); - switch (valueNodeType) { - case OBJECT: - if (valueNode.has("key") && valueNode.has("label")) { - JsonNode label = valueNode.get("label"); - if (label.getNodeType() == JsonNodeType.OBJECT) { - return ElemType.LOCALIZED_ENUM; - } - return ElemType.ENUM; - } - if (valueNode.has("currencyCode")) { - return ElemType.MONEY; - } - if (valueNode.has("typeId")) { - return ElemType.REFERENCE; - } - if (valueNode.has("value")) { - return ElemType.NESTED; - } - return ElemType.LOCALIZED_STRING; - case NUMBER: - if (!deserializeNumberAsDouble && (valueNode.isInt() || valueNode.isLong())) { - return ElemType.LONG; - } - return ElemType.NUMBER; - case STRING: - if (deserializeAsDate) { - String val = valueNode.asText(); - if (p.matcher(val).find()) { - if (dateTime.matcher(val).find()) { - return ElemType.DATETIME; - } - if (date.matcher(val).matches()) { - return ElemType.DATE; - } - if (time.matcher(val).matches()) { - return ElemType.TIME; - } - } - } - return ElemType.STRING; - case ARRAY: - return ElemType.SET_NESTED; - case BOOLEAN: - return ElemType.BOOLEAN; - default: - return ElemType.JSON_NODE; - } - } - - private enum ElemType { - STRING, - DATE, - DATETIME, - TIME, - NUMBER, - LONG, - BOOLEAN, - ENUM, - LOCALIZED_ENUM, - LOCALIZED_STRING, - REFERENCE, - MONEY, - JSON_NODE, - NESTED, - SET_NESTED + super(); } } diff --git a/commercetools/commercetools-sdk-java-api/src/main/java/com/commercetools/api/json/AttributeDeserializer.java b/commercetools/commercetools-sdk-java-api/src/main/java/com/commercetools/api/json/AttributeDeserializer.java new file mode 100644 index 00000000000..5a09e241485 --- /dev/null +++ b/commercetools/commercetools-sdk-java-api/src/main/java/com/commercetools/api/json/AttributeDeserializer.java @@ -0,0 +1,247 @@ + +package com.commercetools.api.json; + +import java.io.IOException; +import java.time.LocalDate; +import java.time.LocalTime; +import java.time.ZonedDateTime; +import java.util.List; +import java.util.regex.Pattern; + +import com.commercetools.api.models.common.LocalizedString; +import com.commercetools.api.models.common.Reference; +import com.commercetools.api.models.common.TypedMoney; +import com.commercetools.api.models.product.*; +import com.commercetools.api.models.product_type.AttributeLocalizedEnumValue; +import com.commercetools.api.models.product_type.AttributePlainEnumValue; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.JsonNodeType; + +public class AttributeDeserializer extends JsonDeserializer { + + private static Pattern p = Pattern.compile("^[0-9]"); + private static Pattern dateTime = Pattern + .compile("^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}([.][0-9]{1,6})?(Z|[+-][0-9]{2}:[0-9]{2})"); + private static Pattern date = Pattern.compile("^[0-9]{4}-[0-9]{2}-[0-9]{2}"); + private static Pattern time = Pattern.compile("^[0-9]{2}:[0-9]{2}:[0-9]{2}([.][0-9]{1,6})?"); + + private final boolean deserializeAsDate; + + private final boolean deserializeNumberAsDouble; + + public AttributeDeserializer(boolean deserializeAsDateString) { + this.deserializeAsDate = !deserializeAsDateString; + this.deserializeNumberAsDouble = false; + } + + public AttributeDeserializer(boolean deserializeAsDateString, boolean deserializeNumberAsDouble) { + this.deserializeAsDate = !deserializeAsDateString; + this.deserializeNumberAsDouble = deserializeNumberAsDouble; + } + + public AttributeDeserializer() { + this.deserializeAsDate = true; + this.deserializeNumberAsDouble = false; + } + + @Override + public AttributeImpl deserialize(JsonParser p, DeserializationContext ctx) throws IOException { + + JsonNode node = p.readValueAsTree(); + JsonNode valueNode = node.get("value"); + + AttributeBuilder builder = Attribute.builder(); + builder.name(node.get("name").asText()); + + return (AttributeImpl) builder.value(p.getCodec().treeAsTokens(valueNode).readValueAs(typeRef(valueNode))) + .build(); + } + + private TypeReference typeRef(JsonNode valueNode) { + JsonNodeType valueNodeType = valueNode.getNodeType(); + switch (valueNodeType) { + case BOOLEAN: + return new TypeReference() { + }; + case NUMBER: + if (!deserializeNumberAsDouble && (valueNode.isInt() || valueNode.isLong())) { + return new TypeReference() { + }; + } + return new TypeReference() { + }; + case STRING: + if (deserializeAsDate) { + String val = valueNode.asText(); + if (p.matcher(val).find()) { + if (dateTime.matcher(val).find()) { + return new TypeReference() { + }; + } + if (date.matcher(val).matches()) { + return new TypeReference() { + }; + } + if (time.matcher(val).matches()) { + return new TypeReference() { + }; + } + } + } + return new TypeReference() { + }; + case OBJECT: + if (valueNode.has("key") && valueNode.has("label")) { + JsonNode label = valueNode.get("label"); + if (label.getNodeType() == JsonNodeType.OBJECT) { + return new TypeReference() { + }; + } + return new TypeReference() { + }; + } + if (valueNode.has("currencyCode")) { + return new TypeReference() { + }; + } + if (valueNode.has("typeId")) { + return new TypeReference() { + }; + } + if (valueNode.has("value")) { + return new TypeReference() { + }; + } + return new TypeReference() { + }; + case ARRAY: + JsonNode first = valueNode.get(0); + switch (elemType(first)) { + case STRING: + return new TypeReference>() { + }; + case DATE: + return new TypeReference>() { + }; + case DATETIME: + return new TypeReference>() { + }; + case TIME: + return new TypeReference>() { + }; + case NUMBER: + return new TypeReference>() { + }; + case LONG: + return new TypeReference>() { + }; + case BOOLEAN: + return new TypeReference>() { + }; + case ENUM: + return new TypeReference>() { + }; + case LOCALIZED_ENUM: + return new TypeReference>() { + }; + case LOCALIZED_STRING: + return new TypeReference>() { + }; + case MONEY: + return new TypeReference>() { + }; + case REFERENCE: + return new TypeReference>() { + }; + case NESTED: + return new TypeReference>() { + }; + case SET_NESTED: + return new TypeReference>>() { + }; + default: + return new TypeReference>() { + }; + } + default: + return new TypeReference() { + }; + } + } + + private ElemType elemType(JsonNode valueNode) { + if (valueNode == null) { + return ElemType.JSON_NODE; + } + JsonNodeType valueNodeType = valueNode.getNodeType(); + switch (valueNodeType) { + case OBJECT: + if (valueNode.has("key") && valueNode.has("label")) { + JsonNode label = valueNode.get("label"); + if (label.getNodeType() == JsonNodeType.OBJECT) { + return ElemType.LOCALIZED_ENUM; + } + return ElemType.ENUM; + } + if (valueNode.has("currencyCode")) { + return ElemType.MONEY; + } + if (valueNode.has("typeId")) { + return ElemType.REFERENCE; + } + if (valueNode.has("value")) { + return ElemType.NESTED; + } + return ElemType.LOCALIZED_STRING; + case NUMBER: + if (!deserializeNumberAsDouble && (valueNode.isInt() || valueNode.isLong())) { + return ElemType.LONG; + } + return ElemType.NUMBER; + case STRING: + if (deserializeAsDate) { + String val = valueNode.asText(); + if (p.matcher(val).find()) { + if (dateTime.matcher(val).find()) { + return ElemType.DATETIME; + } + if (date.matcher(val).matches()) { + return ElemType.DATE; + } + if (time.matcher(val).matches()) { + return ElemType.TIME; + } + } + } + return ElemType.STRING; + case ARRAY: + return ElemType.SET_NESTED; + case BOOLEAN: + return ElemType.BOOLEAN; + default: + return ElemType.JSON_NODE; + } + } + + private enum ElemType { + STRING, + DATE, + DATETIME, + TIME, + NUMBER, + LONG, + BOOLEAN, + ENUM, + LOCALIZED_ENUM, + LOCALIZED_STRING, + REFERENCE, + MONEY, + JSON_NODE, + NESTED, + SET_NESTED + } +} diff --git a/commercetools/commercetools-sdk-java-importapi/src/main/java/com/commercetools/importapi/json/AttributeMixin.java b/commercetools/commercetools-sdk-java-importapi/src/main/java/com/commercetools/importapi/json/AttributeMixin.java new file mode 100644 index 00000000000..64886ddcdfd --- /dev/null +++ b/commercetools/commercetools-sdk-java-importapi/src/main/java/com/commercetools/importapi/json/AttributeMixin.java @@ -0,0 +1,8 @@ + +package com.commercetools.importapi.json; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; + +@JsonDeserialize(using = ErrorAttributeDeserializer.class) +public interface AttributeMixin { +} diff --git a/commercetools/commercetools-sdk-java-importapi/src/main/java/com/commercetools/importapi/json/ErrorAttributeDeserializer.java b/commercetools/commercetools-sdk-java-importapi/src/main/java/com/commercetools/importapi/json/ErrorAttributeDeserializer.java new file mode 100644 index 00000000000..4d8596c165c --- /dev/null +++ b/commercetools/commercetools-sdk-java-importapi/src/main/java/com/commercetools/importapi/json/ErrorAttributeDeserializer.java @@ -0,0 +1,183 @@ + +package com.commercetools.importapi.json; + +import static com.fasterxml.jackson.databind.node.JsonNodeType.OBJECT; + +import java.io.IOException; +import java.util.*; + +import com.commercetools.importapi.models.common.*; +import com.commercetools.importapi.models.productvariants.*; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.JsonNodeType; + +public class ErrorAttributeDeserializer extends JsonDeserializer { + protected ErrorAttributeDeserializer() { + } + + @Override + public Attribute deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { + JsonNode node = p.readValueAsTree(); + JsonNode valueNode = node.get("value"); + + JsonNodeType valueNodeType = valueNode.getNodeType(); + switch (valueNodeType) { + case BOOLEAN: + return BooleanAttributeBuilder.of() + .name(node.get("name").asText()) + .value(valueNode.asBoolean()) + .build(); + + case NUMBER: + return NumberAttributeBuilder.of().name(node.get("name").asText()).value(valueNode.asDouble()).build(); + case STRING: + return TextAttributeBuilder.of().name(node.get("name").asText()).value(valueNode.asText()).build(); + case OBJECT: + return createAttributeFromObject(node); + case ARRAY: + JsonNode firstElement = valueNode.get(0); + JsonNodeType firstElementNodeType = firstElement.getNodeType(); + switch (firstElementNodeType) { + case STRING: + List stringValues = new ArrayList<>(); + valueNode.elements().forEachRemaining(element -> stringValues.add(element.asText())); + return TextSetAttributeBuilder.of().name(node.get("name").asText()).value(stringValues).build(); + case NUMBER: + List numberValues = new ArrayList<>(); + valueNode.elements().forEachRemaining(element -> numberValues.add(element.asDouble())); + return NumberSetAttributeBuilder.of() + .name(node.get("name").asText()) + .value(numberValues) + .build(); + case BOOLEAN: + List booleanValues = new ArrayList<>(); + valueNode.elements().forEachRemaining(element -> booleanValues.add(element.asBoolean())); + return BooleanSetAttributeBuilder.of() + .name(node.get("name").asText()) + .value(booleanValues) + .build(); + case OBJECT: + return createSetAttributeFromObject(node); + } + default: + AttributeImpl attribute = new AttributeImpl(); + attribute.setName(node.get("name").asText()); + return attribute; + } + } + + private ReferenceType getReferenceType(String typeId) { + return Arrays.stream(ReferenceType.ReferenceTypeEnum.values()) + .filter(referenceTypeEnum -> referenceTypeEnum.getJsonName().equals(typeId)) + .findFirst() + .orElse(null); + } + + private Attribute createAttributeFromObject(JsonNode node) { + JsonNode valueNode = node.get("value"); + if (valueNode.has("key") && valueNode.has("label")) { + JsonNode label = valueNode.get("label"); + if (label.getNodeType() == OBJECT) { + return LocalizableEnumAttributeBuilder.of() + .name(node.get("name").asText()) + .value(valueNode.get("key").textValue()) + .build(); + } + return EnumAttributeBuilder.of() + .name(node.get("name").asText()) + .value(valueNode.get("key").textValue()) + .build(); + } + if (valueNode.has("currencyCode")) { + return MoneyAttributeBuilder.of() + .name(node.get("name").asText()) + .value(typedMoneyBuilder -> typedMoneyBuilder.centPrecisionBuilder() + .currencyCode(valueNode.get("currencyCode").asText()) + .centAmount(valueNode.get("centAmount").asLong()) + .fractionDigits(valueNode.get("fractionDigits").asInt())) + .build(); + } + if (valueNode.has("typeId")) { + return ReferenceAttributeBuilder.of() + .name(node.get("name").asText()) + // this is not working because reference contains ID and KeyReference requires ID + // .value((KeyReference) p.getCodec().treeAsTokens(valueNode).readValueAs(getTypeRef(valueNode.get("typeId").asText()))) + .value(createKeyReference(valueNode)) + .build(); + } + return LocalizableTextAttributeBuilder.of().name(node.get("name").asText()).value(localizedStringBuilder -> { + valueNode.fields() + .forEachRemaining(nodeEntry -> localizedStringBuilder.addValue(nodeEntry.getKey(), + nodeEntry.getValue().asText())); + return localizedStringBuilder; + }).build(); + } + + private Attribute createSetAttributeFromObject(JsonNode node) { + JsonNode valueNode = node.get("value"); + JsonNode firstElement = valueNode.get(0); + if (firstElement.has("key") && firstElement.has("label")) { + List keys = new ArrayList<>(); + valueNode.iterator().forEachRemaining(jsonNode -> jsonNode.fields().forEachRemaining(nodeEntry -> { + String key = nodeEntry.getKey(); + if (key.equals("key")) { + keys.add(nodeEntry.getValue().asText()); + } + })); + JsonNode label = firstElement.get("label"); + if (label.getNodeType() == OBJECT) { + return LocalizableEnumSetAttributeBuilder.of().name(node.get("name").asText()).value(keys).build(); + } + return EnumSetAttributeBuilder.of().name(node.get("name").asText()).value(keys).build(); + } + if (firstElement.has("typeId")) { + List keyReferences = new ArrayList<>(); + valueNode.iterator().forEachRemaining(nodeEntry -> { + keyReferences.add(createKeyReference(nodeEntry)); + }); + return ReferenceSetAttributeBuilder.of().name(node.get("name").asText()).value(keyReferences).build(); + } + if (firstElement.has("currencyCode")) { + List values = new ArrayList<>(); + valueNode.iterator().forEachRemaining(nodeEntry -> { + values.add(MoneyBuilder.of() + .currencyCode(nodeEntry.get("currencyCode").asText()) + .centAmount(nodeEntry.get("centAmount").asLong()) + .fractionDigits(nodeEntry.get("fractionDigits").asInt()) + .build()); + }); + return MoneySetAttributeBuilder.of().name(node.get("name").asText()).value(values).build(); + } + + List values = new ArrayList<>(); + valueNode.iterator().forEachRemaining(jsonNode -> { + LocalizedStringBuilder localizedStringBuilder = LocalizedStringBuilder.of(); + jsonNode.fields() + .forEachRemaining(nodeEntry -> localizedStringBuilder.addValue(nodeEntry.getKey(), + nodeEntry.getValue().asText())); + values.add(localizedStringBuilder.build()); + }); + return LocalizableTextSetAttributeBuilder.of().name(node.get("name").asText()).value(values).build(); + } + + private KeyReference createKeyReference(JsonNode node) { + return new KeyReference() { + @Override + public String getKey() { + return node.get("id").asText(); + } + + @Override + public ReferenceType getTypeId() { + return getReferenceType(node.get("typeId").asText()); + } + + @Override + public void setKey(String key) { + } + }; + } +} diff --git a/commercetools/commercetools-sdk-java-importapi/src/main/java/com/commercetools/importapi/json/ImportApiModule.java b/commercetools/commercetools-sdk-java-importapi/src/main/java/com/commercetools/importapi/json/ImportApiModule.java index 0690008154a..4e633b014a9 100644 --- a/commercetools/commercetools-sdk-java-importapi/src/main/java/com/commercetools/importapi/json/ImportApiModule.java +++ b/commercetools/commercetools-sdk-java-importapi/src/main/java/com/commercetools/importapi/json/ImportApiModule.java @@ -1,6 +1,7 @@ package com.commercetools.importapi.json; +import com.commercetools.importapi.models.productvariants.Attribute; import com.commercetools.importapi.models.productvariants.Attributes; import com.fasterxml.jackson.databind.module.SimpleModule; @@ -14,5 +15,6 @@ public class ImportApiModule extends SimpleModule { public ImportApiModule(ModuleOptions options) { setMixInAnnotation(Attributes.class, AttributesMixin.class); + setMixInAnnotation(Attribute.class, AttributeMixin.class); } } diff --git a/commercetools/commercetools-sdk-java-importapi/src/test/java/com/commerctools/importapi/DeserializerTest.java b/commercetools/commercetools-sdk-java-importapi/src/test/java/com/commerctools/importapi/DeserializerTest.java new file mode 100644 index 00000000000..56f70d06804 --- /dev/null +++ b/commercetools/commercetools-sdk-java-importapi/src/test/java/com/commerctools/importapi/DeserializerTest.java @@ -0,0 +1,656 @@ + +package com.commerctools.importapi; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import com.commercetools.importapi.models.common.LocalizedStringBuilder; +import com.commercetools.importapi.models.common.MoneyType; +import com.commercetools.importapi.models.common.ReferenceType; +import com.commercetools.importapi.models.errors.DuplicateAttributeValueError; +import com.commercetools.importapi.models.errors.ErrorResponse; +import com.commercetools.importapi.models.productvariants.*; + +import io.vrap.rmf.base.client.utils.json.JsonUtils; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; + +public class DeserializerTest { + + @Test + public void shouldCorrectlyDeserializeErrorWithLocalizedTextAttribute() { + String t = """ + { + "version": 2, + "importContainerKey": "product-index-all", + "resourceKey": "5098_NZ", + "id": "e3708a0b-18d3-4dd5-ba5d-4d59eaff48de", + "state": "validationFailed", + "errors": [ + { + "code": "DuplicateAttributeValue", + "message": "Attribute can't have the same value in a different variant.", + "attribute": { + "name": "slug", + "value": { + "en-NZ": "en-light-medium", + "de-DE": "de-light-medium" + } + } + } + ], + "createdAt": "2024-10-02T06:39:12.614Z", + "lastModifiedAt": "2024-10-02T06:39:52.840Z", + "expiresAt": "2024-10-04T06:39:12.614Z" + } + """; + ErrorResponse errorResponse = JsonUtils.fromJsonString(t, ErrorResponse.class); + Assertions.assertThat(errorResponse.getErrors()).hasSize(1); + LocalizableTextAttribute value = (LocalizableTextAttribute) ((DuplicateAttributeValueError) errorResponse + .getErrors() + .get(0)).getAttribute(); + Assertions.assertThat(value.getValue().values().get("en-NZ")).isEqualTo("en-light-medium"); + Assertions.assertThat(value.getValue().values().get("de-DE")).isEqualTo("de-light-medium"); + } + + @Test + public void shouldCorrectlyDeserializeErrorWithDateAttribute() { + String t = """ + { + "version": 2, + "importContainerKey": "product-index-all", + "resourceKey": "5098_NZ", + "id": "e3708a0b-18d3-4dd5-ba5d-4d59eaff48de", + "state": "validationFailed", + "errors": [ + { + "code": "DuplicateAttributeValue", + "message": "Attribute can't have the same value in a different variant.", + "attribute": { + "name": "creationDate", + "value": "2016-11-21" + } + } + ], + "createdAt": "2024-10-02T06:39:12.614Z", + "lastModifiedAt": "2024-10-02T06:39:52.840Z", + "expiresAt": "2024-10-04T06:39:12.614Z" + } + """; + ErrorResponse errorResponse = JsonUtils.fromJsonString(t, ErrorResponse.class); + Assertions.assertThat(errorResponse.getErrors()).hasSize(1); + TextAttribute value = (TextAttribute) ((DuplicateAttributeValueError) errorResponse.getErrors().get(0)) + .getAttribute(); + Assertions.assertThat(value.getValue()).isEqualTo("2016-11-21"); + } + + @Test + public void shouldCorrectlyDeserializeErrorWithTextAttribute() { + String t = """ + { + "version": 2, + "importContainerKey": "product-index-all", + "resourceKey": "5098_NZ", + "id": "e3708a0b-18d3-4dd5-ba5d-4d59eaff48de", + "state": "validationFailed", + "errors": [ + { + "code": "DuplicateAttributeValue", + "message": "Attribute can't have the same value in a different variant.", + "attribute": { + "name": "textAttribute", + "value": "text" + } + } + ], + "createdAt": "2024-10-02T06:39:12.614Z", + "lastModifiedAt": "2024-10-02T06:39:52.840Z", + "expiresAt": "2024-10-04T06:39:12.614Z" + } + """; + ErrorResponse errorResponse = JsonUtils.fromJsonString(t, ErrorResponse.class); + Assertions.assertThat(errorResponse.getErrors()).hasSize(1); + TextAttribute value = (TextAttribute) ((DuplicateAttributeValueError) errorResponse.getErrors().get(0)) + .getAttribute(); + Assertions.assertThat(value.getValue()).isEqualTo("text"); + } + + @Test + public void shouldCorrectlyDeserializeErrorWithLTextAttribute() { + String t = """ + { + "version": 2, + "importContainerKey": "product-index-all", + "resourceKey": "5098_NZ", + "id": "e3708a0b-18d3-4dd5-ba5d-4d59eaff48de", + "state": "validationFailed", + "errors": [ + { + "code": "DuplicateAttributeValue", + "message": "Attribute can't have the same value in a different variant.", + "attribute": { + "name": "localized-text", + "value": + { + "en": "en-test", + "de": "de-test" + } + } + } + ], + "createdAt": "2024-10-02T06:39:12.614Z", + "lastModifiedAt": "2024-10-02T06:39:52.840Z", + "expiresAt": "2024-10-04T06:39:12.614Z" + } + """; + ErrorResponse errorResponse = JsonUtils.fromJsonString(t, ErrorResponse.class); + Assertions.assertThat(errorResponse.getErrors()).hasSize(1); + LocalizableTextAttribute value = (LocalizableTextAttribute) ((DuplicateAttributeValueError) errorResponse + .getErrors() + .get(0)).getAttribute(); + Assertions.assertThat(value.getValue()) + .isEqualTo(LocalizedStringBuilder.of().values(Map.of("en", "en-test", "de", "de-test")).build()); + } + + @Test + public void shouldCorrectlyDeserializeErrorWithBooleanAttribute() { + String t = """ + { + "version": 2, + "importContainerKey": "product-index-all", + "resourceKey": "5098_NZ", + "id": "e3708a0b-18d3-4dd5-ba5d-4d59eaff48de", + "state": "validationFailed", + "errors": [ + { + "code": "DuplicateAttributeValue", + "message": "Attribute can't have the same value in a different variant.", + "attribute": { + "name": "booleanAttribute", + "value": false + } + } + ], + "createdAt": "2024-10-02T06:39:12.614Z", + "lastModifiedAt": "2024-10-02T06:39:52.840Z", + "expiresAt": "2024-10-04T06:39:12.614Z" + } + """; + ErrorResponse errorResponse = JsonUtils.fromJsonString(t, ErrorResponse.class); + Assertions.assertThat(errorResponse.getErrors()).hasSize(1); + BooleanAttribute value = (BooleanAttribute) ((DuplicateAttributeValueError) errorResponse.getErrors().get(0)) + .getAttribute(); + Assertions.assertThat(value.getValue()).isEqualTo(false); + } + + @Test + public void shouldCorrectlyDeserializeErrorWithLenumAttribute() { + String t = """ + { + "version": 2, + "importContainerKey": "product-index-all", + "resourceKey": "5098_NZ", + "id": "e3708a0b-18d3-4dd5-ba5d-4d59eaff48de", + "state": "validationFailed", + "errors": [ + { + "code": "DuplicateAttributeValue", + "message": "Attribute can't have the same value in a different variant.", + "attribute": { + "name": "color", + "value": { + "key": "black", + "label": { + "en": "black", + "it": "nero", + "de": "schwarz" + } + } + } + } + ], + "createdAt": "2024-10-02T06:39:12.614Z", + "lastModifiedAt": "2024-10-02T06:39:52.840Z", + "expiresAt": "2024-10-04T06:39:12.614Z" + } + """; + ErrorResponse errorResponse = JsonUtils.fromJsonString(t, ErrorResponse.class); + Assertions.assertThat(errorResponse.getErrors()).hasSize(1); + LocalizableEnumAttribute value = (LocalizableEnumAttribute) ((DuplicateAttributeValueError) errorResponse + .getErrors() + .get(0)).getAttribute(); + Assertions.assertThat(value.getValue()).isEqualTo("black"); + } + + @Test + public void shouldCorrectlyDeserializeErrorWithEnumAttribute() { + String t = """ + { + "version": 2, + "importContainerKey": "product-index-all", + "resourceKey": "5098_NZ", + "id": "e3708a0b-18d3-4dd5-ba5d-4d59eaff48de", + "state": "validationFailed", + "errors": [ + { + "code": "DuplicateAttributeValue", + "message": "Attribute can't have the same value in a different variant.", + "attribute": { + "name": "style", + "value": { + "key": "sporty", + "label": "sporty" + } + } + } + ], + "createdAt": "2024-10-02T06:39:12.614Z", + "lastModifiedAt": "2024-10-02T06:39:52.840Z", + "expiresAt": "2024-10-04T06:39:12.614Z" + } + """; + ErrorResponse errorResponse = JsonUtils.fromJsonString(t, ErrorResponse.class); + Assertions.assertThat(errorResponse.getErrors()).hasSize(1); + EnumAttribute value = (EnumAttribute) ((DuplicateAttributeValueError) errorResponse.getErrors().get(0)) + .getAttribute(); + Assertions.assertThat(value.getValue()).isEqualTo("sporty"); + } + + @Test + public void shouldCorrectlyDeserializeErrorWithSetOfTextAttribute() { + String t = """ + { + "version": 2, + "importContainerKey": "product-index-all", + "resourceKey": "5098_NZ", + "id": "e3708a0b-18d3-4dd5-ba5d-4d59eaff48de", + "state": "validationFailed", + "errors": [ + { + "code": "DuplicateAttributeValue", + "message": "Attribute can't have the same value in a different variant.", + "attribute": { + "name": "completeTheLook", + "value": [ + "072336", + "072337", + "072338", + "072339", + "072340", + "072341" + ] + } + } + ], + "createdAt": "2024-10-02T06:39:12.614Z", + "lastModifiedAt": "2024-10-02T06:39:52.840Z", + "expiresAt": "2024-10-04T06:39:12.614Z" + } + """; + ErrorResponse errorResponse = JsonUtils.fromJsonString(t, ErrorResponse.class); + Assertions.assertThat(errorResponse.getErrors()).hasSize(1); + TextSetAttribute value = (TextSetAttribute) ((DuplicateAttributeValueError) errorResponse.getErrors().get(0)) + .getAttribute(); + Assertions.assertThat(value.getValue()) + .isEqualTo(Arrays.asList("072336", "072337", "072338", "072339", "072340", "072341")); + } + + @Test + public void shouldCorrectlyDeserializeErrorWithSetOfNumberAttribute() { + String t = """ + { + "version": 2, + "importContainerKey": "product-index-all", + "resourceKey": "5098_NZ", + "id": "e3708a0b-18d3-4dd5-ba5d-4d59eaff48de", + "state": "validationFailed", + "errors": [ + { + "code": "DuplicateAttributeValue", + "message": "Attribute can't have the same value in a different variant.", + "attribute": { + "name": "test-set-number", + "value": [ + 11, 12 + ] + } + } + ], + "createdAt": "2024-10-02T06:39:12.614Z", + "lastModifiedAt": "2024-10-02T06:39:52.840Z", + "expiresAt": "2024-10-04T06:39:12.614Z" + } + """; + ErrorResponse errorResponse = JsonUtils.fromJsonString(t, ErrorResponse.class); + Assertions.assertThat(errorResponse.getErrors()).hasSize(1); + NumberSetAttribute value = (NumberSetAttribute) ((DuplicateAttributeValueError) errorResponse.getErrors() + .get(0)).getAttribute(); + Assertions.assertThat(value.getValue()).isEqualTo(Arrays.asList(11.0, 12.0)); + } + + @Test + public void shouldCorrectlyDeserializeErrorWithSetOfBooleanAttribute() { + String t = """ + { + "version": 2, + "importContainerKey": "product-index-all", + "resourceKey": "5098_NZ", + "id": "e3708a0b-18d3-4dd5-ba5d-4d59eaff48de", + "state": "validationFailed", + "errors": [ + { + "code": "DuplicateAttributeValue", + "message": "Attribute can't have the same value in a different variant.", + "attribute": { + "name": "test-set-number", + "value": [ + false, true, false + ] + } + } + ], + "createdAt": "2024-10-02T06:39:12.614Z", + "lastModifiedAt": "2024-10-02T06:39:52.840Z", + "expiresAt": "2024-10-04T06:39:12.614Z" + } + """; + ErrorResponse errorResponse = JsonUtils.fromJsonString(t, ErrorResponse.class); + Assertions.assertThat(errorResponse.getErrors()).hasSize(1); + BooleanSetAttribute value = (BooleanSetAttribute) ((DuplicateAttributeValueError) errorResponse.getErrors() + .get(0)).getAttribute(); + Assertions.assertThat(value.getValue()).isEqualTo(Arrays.asList(false, true, false)); + } + + @Test + public void shouldCorrectlyDeserializeErrorWithSetOfLocalizedTextAttribute() { + String t = """ + { + "version": 2, + "importContainerKey": "product-index-all", + "resourceKey": "5098_NZ", + "id": "e3708a0b-18d3-4dd5-ba5d-4d59eaff48de", + "state": "validationFailed", + "errors": [ + { + "code": "DuplicateAttributeValue", + "message": "Attribute can't have the same value in a different variant.", + "attribute": { + "name": "localized-text-set", + "value": [ + { + "en": "en-test", + "de": "de-test" + } + ] + } + } + ], + "createdAt": "2024-10-02T06:39:12.614Z", + "lastModifiedAt": "2024-10-02T06:39:52.840Z", + "expiresAt": "2024-10-04T06:39:12.614Z" + } + """; + ErrorResponse errorResponse = JsonUtils.fromJsonString(t, ErrorResponse.class); + Assertions.assertThat(errorResponse.getErrors()).hasSize(1); + LocalizableTextSetAttribute value = (LocalizableTextSetAttribute) ((DuplicateAttributeValueError) errorResponse + .getErrors() + .get(0)).getAttribute(); + Assertions.assertThat(value.getValue()) + .isEqualTo( + List.of(LocalizedStringBuilder.of().values(Map.of("en", "en-test", "de", "de-test")).build())); + } + + @Test + public void shouldCorrectlyDeserializeErrorWithSetOfEnumAttribute() { + String t = """ + { + "version": 2, + "importContainerKey": "product-index-all", + "resourceKey": "5098_NZ", + "id": "e3708a0b-18d3-4dd5-ba5d-4d59eaff48de", + "state": "validationFailed", + "errors": [ + { + "code": "DuplicateAttributeValue", + "message": "Attribute can't have the same value in a different variant.", + "attribute": { + "name": "enum-set", + "value": [ + { + "key": "DE", + "label": "DE" + }, + { + "key": "EN", + "label": "EN" + } + ] + } + } + ], + "createdAt": "2024-10-02T06:39:12.614Z", + "lastModifiedAt": "2024-10-02T06:39:52.840Z", + "expiresAt": "2024-10-04T06:39:12.614Z" + } + """; + ErrorResponse errorResponse = JsonUtils.fromJsonString(t, ErrorResponse.class); + Assertions.assertThat(errorResponse.getErrors()).hasSize(1); + EnumSetAttribute value = (EnumSetAttribute) ((DuplicateAttributeValueError) errorResponse.getErrors().get(0)) + .getAttribute(); + Assertions.assertThat(value.getValue()).isEqualTo(Arrays.asList("DE", "EN")); + } + + @Test + public void shouldCorrectlyDeserializeErrorWithSetOfLenumAttribute() { + String t = """ + { + "version": 2, + "importContainerKey": "product-index-all", + "resourceKey": "5098_NZ", + "id": "e3708a0b-18d3-4dd5-ba5d-4d59eaff48de", + "state": "validationFailed", + "errors": [ + { + "code": "DuplicateAttributeValue", + "message": "Attribute can't have the same value in a different variant.", + "attribute": { + "name": "localized-enum-set", + "value": [ + { + "key": "731045", + "label": { + "de-DE": "Titanium" + } + }, + { + "key": "731046", + "label": { + "de-DE": "Load adapted" + } + } + ] + } + } + ], + "createdAt": "2024-10-02T06:39:12.614Z", + "lastModifiedAt": "2024-10-02T06:39:52.840Z", + "expiresAt": "2024-10-04T06:39:12.614Z" + } + """; + ErrorResponse errorResponse = JsonUtils.fromJsonString(t, ErrorResponse.class); + Assertions.assertThat(errorResponse.getErrors()).hasSize(1); + LocalizableEnumSetAttribute value = (LocalizableEnumSetAttribute) ((DuplicateAttributeValueError) errorResponse + .getErrors() + .get(0)).getAttribute(); + Assertions.assertThat(value.getValue()).isEqualTo(Arrays.asList("731045", "731046")); + } + + @Test + public void shouldCorrectlyDeserializeErrorWithSetOfReferenceAttribute() { + String t = """ + { + "version": 2, + "importContainerKey": "product-index-all", + "resourceKey": "5098_NZ", + "id": "e3708a0b-18d3-4dd5-ba5d-4d59eaff48de", + "state": "validationFailed", + "errors": [ + { + "code": "DuplicateAttributeValue", + "message": "Attribute can't have the same value in a different variant.", + "attribute": { + "name": "state-reference-set", + "value": [ + { + "id" : "d3e14b2a-5848-4d86-af8a-8e9a27ca84d8", + "typeId" : "state" + }, + { + "id" : "xxx-123-456", + "typeId" : "state" + } + ] + } + } + ], + "createdAt": "2024-10-02T06:39:12.614Z", + "lastModifiedAt": "2024-10-02T06:39:52.840Z", + "expiresAt": "2024-10-04T06:39:12.614Z" + } + """; + ErrorResponse errorResponse = JsonUtils.fromJsonString(t, ErrorResponse.class); + Assertions.assertThat(errorResponse.getErrors()).hasSize(1); + ReferenceSetAttribute value = (ReferenceSetAttribute) ((DuplicateAttributeValueError) errorResponse.getErrors() + .get(0)).getAttribute(); + Assertions.assertThat(value.getValue().size()).isEqualTo(2); + Assertions.assertThat(value.getValue().get(0).getKey()).isEqualTo("d3e14b2a-5848-4d86-af8a-8e9a27ca84d8"); + Assertions.assertThat(value.getValue().get(0).getTypeId().getJsonName()).isEqualTo("state"); + Assertions.assertThat(value.getValue().get(1).getKey()).isEqualTo("xxx-123-456"); + Assertions.assertThat(value.getValue().get(1).getTypeId().getJsonName()).isEqualTo("state"); + } + + @Test + public void shouldCorrectlyDeserializeErrorWithSetOfMoneyAttribute() { + String t = """ + { + "version": 2, + "importContainerKey": "product-index-all", + "resourceKey": "5098_NZ", + "id": "e3708a0b-18d3-4dd5-ba5d-4d59eaff48de", + "state": "validationFailed", + "errors": [ + { + "code": "DuplicateAttributeValue", + "message": "Attribute can't have the same value in a different variant.", + "attribute": { + "name": "money-set", + "value": [ + { + "type": "centPrecision", + "currencyCode": "EUR", + "centAmount": 6490, + "fractionDigits": 2 + }, + { + "type": "centPrecision", + "currencyCode": "USD", + "centAmount": 123, + "fractionDigits": 2 + } + ] + } + } + ], + "createdAt": "2024-10-02T06:39:12.614Z", + "lastModifiedAt": "2024-10-02T06:39:52.840Z", + "expiresAt": "2024-10-04T06:39:12.614Z" + } + """; + ErrorResponse errorResponse = JsonUtils.fromJsonString(t, ErrorResponse.class); + Assertions.assertThat(errorResponse.getErrors()).hasSize(1); + MoneySetAttribute value = (MoneySetAttribute) ((DuplicateAttributeValueError) errorResponse.getErrors().get(0)) + .getAttribute(); + Assertions.assertThat(value.getValue().size()).isEqualTo(2); + Assertions.assertThat(value.getValue().get(0).getCurrencyCode()).isEqualTo("EUR"); + Assertions.assertThat(value.getValue().get(0).getCentAmount()).isEqualTo(6490); + Assertions.assertThat(value.getValue().get(1).getCurrencyCode()).isEqualTo("USD"); + Assertions.assertThat(value.getValue().get(1).getCentAmount()).isEqualTo(123); + } + + @Test + public void shouldCorrectlyDeserializeErrorWithReferenceAttribute() { + String t = """ + { + "version": 2, + "importContainerKey": "product-index-all", + "resourceKey": "5098_NZ", + "id": "e3708a0b-18d3-4dd5-ba5d-4d59eaff48de", + "state": "validationFailed", + "errors": [ + { + "code": "DuplicateAttributeValue", + "message": "Attribute can't have the same value in a different variant.", + "attribute": { + "name": "state-reference", + "value": { + "typeId": "state", + "id": "3ff4cb59-80a5-4ed2-be53-a9637fb7ffae" + } + } + + } + ], + "createdAt": "2024-10-02T06:39:12.614Z", + "lastModifiedAt": "2024-10-02T06:39:52.840Z", + "expiresAt": "2024-10-04T06:39:12.614Z" + } + """; + ErrorResponse errorResponse = JsonUtils.fromJsonString(t, ErrorResponse.class); + Assertions.assertThat(errorResponse.getErrors()).hasSize(1); + ReferenceAttribute value = (ReferenceAttribute) ((DuplicateAttributeValueError) errorResponse.getErrors() + .get(0)).getAttribute(); + Assertions.assertThat(value.getValue().getKey()).isEqualTo("3ff4cb59-80a5-4ed2-be53-a9637fb7ffae"); + Assertions.assertThat(value.getValue().getTypeId()).isEqualTo(ReferenceType.ReferenceTypeEnum.STATE); + } + + @Test + public void shouldCorrectlyDeserializeErrorWithCentPrecisionMoneyAttribute() { + String t = """ + { + "version": 2, + "importContainerKey": "product-index-all", + "resourceKey": "5098_NZ", + "id": "e3708a0b-18d3-4dd5-ba5d-4d59eaff48de", + "state": "validationFailed", + "errors": [ + { + "code": "DuplicateAttributeValue", + "message": "Attribute can't have the same value in a different variant.", + "attribute": { + "name": "moneyAttribute", + "value": { + "type": "centPrecision", + "currencyCode": "EUR", + "centAmount": 6490, + "fractionDigits": 2 + } + } + } + ], + "createdAt": "2024-10-02T06:39:12.614Z", + "lastModifiedAt": "2024-10-02T06:39:52.840Z", + "expiresAt": "2024-10-04T06:39:12.614Z" + } + """; + ErrorResponse errorResponse = JsonUtils.fromJsonString(t, ErrorResponse.class); + Assertions.assertThat(errorResponse.getErrors()).hasSize(1); + MoneyAttribute value = (MoneyAttribute) ((DuplicateAttributeValueError) errorResponse.getErrors().get(0)) + .getAttribute(); + Assertions.assertThat(value.getValue().getCentAmount()).isEqualTo(6490); + Assertions.assertThat(value.getValue().getCurrencyCode()).isEqualTo("EUR"); + Assertions.assertThat(value.getValue().getFractionDigits()).isEqualTo(2); + Assertions.assertThat(value.getValue().getType()).isEqualTo(MoneyType.CENT_PRECISION); + } +}