Skip to content

Commit 5e973a5

Browse files
authored
Merge pull request #295 from commercetools/286-product-type-attributes-enum-actions-b
#286 product type attributes enum actions
2 parents 3e18555 + 14ea923 commit 5e973a5

17 files changed

Lines changed: 1784 additions & 81 deletions
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.commercetools.sync.commons.exceptions;
2+
3+
import javax.annotation.Nonnull;
4+
5+
/**
6+
* Exception thrown when the attribute type is different between the {@link io.sphere.sdk.producttypes.ProductType} and
7+
* {@link io.sphere.sdk.producttypes.ProductTypeDraft}.
8+
*/
9+
public class DifferentTypeException extends RuntimeException {
10+
public DifferentTypeException(@Nonnull final String message) {
11+
super(message);
12+
}
13+
14+
public DifferentTypeException(@Nonnull final Throwable cause) {
15+
super(cause);
16+
}
17+
18+
public DifferentTypeException(@Nonnull final String message, @Nonnull final Throwable cause) {
19+
super(message, cause);
20+
}
21+
}

src/main/java/com/commercetools/sync/producttypes/utils/AttributeDefinitionUpdateActionUtils.java

Lines changed: 88 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
package com.commercetools.sync.producttypes.utils;
22

3+
import com.commercetools.sync.commons.exceptions.DifferentTypeException;
4+
import com.commercetools.sync.commons.exceptions.DuplicateKeyException;
35
import io.sphere.sdk.commands.UpdateAction;
46
import io.sphere.sdk.models.LocalizedString;
57
import io.sphere.sdk.products.attributes.AttributeDefinition;
68
import io.sphere.sdk.products.attributes.AttributeDefinitionDraft;
9+
import io.sphere.sdk.products.attributes.EnumAttributeType;
10+
import io.sphere.sdk.products.attributes.LocalizedEnumAttributeType;
711
import io.sphere.sdk.producttypes.ProductType;
812
import io.sphere.sdk.producttypes.commands.updateactions.ChangeAttributeDefinitionLabel;
913
import io.sphere.sdk.producttypes.commands.updateactions.SetInputTip;
@@ -17,7 +21,10 @@
1721
import java.util.stream.Stream;
1822

1923
import static com.commercetools.sync.commons.utils.CommonTypeUpdateActionUtils.buildUpdateAction;
24+
import static com.commercetools.sync.producttypes.utils.ProductTypeUpdateLocalizedEnumActionUtils.buildLocalizedEnumValuesUpdateActions;
25+
import static com.commercetools.sync.producttypes.utils.ProductTypeUpdatePlainEnumActionUtils.buildEnumValuesUpdateActions;
2026
import static java.util.stream.Collectors.toList;
27+
import static java.lang.String.format;
2128

2229

2330
public final class AttributeDefinitionUpdateActionUtils {
@@ -29,24 +36,92 @@ public final class AttributeDefinitionUpdateActionUtils {
2936
*
3037
* @param oldAttributeDefinition the attribute definition which should be updated.
3138
* @param newAttributeDefinitionDraft the attribute definition draft where we get the new fields.
39+
*
3240
* @return A list with the update actions or an empty list if the attribute definition fields are identical.
3341
*/
3442
@Nonnull
3543
public static List<UpdateAction<ProductType>> buildActions(
3644
@Nonnull final AttributeDefinition oldAttributeDefinition,
37-
@Nonnull final AttributeDefinitionDraft newAttributeDefinitionDraft) {
38-
39-
return Stream
40-
.of(
41-
buildChangeLabelUpdateAction(oldAttributeDefinition, newAttributeDefinitionDraft),
42-
buildSetInputTipUpdateAction(oldAttributeDefinition, newAttributeDefinitionDraft),
43-
buildChangeIsSearchableUpdateAction(oldAttributeDefinition, newAttributeDefinitionDraft),
44-
buildChangeInputHintUpdateAction(oldAttributeDefinition, newAttributeDefinitionDraft),
45-
buildChangeAttributeConstraintUpdateAction(oldAttributeDefinition, newAttributeDefinitionDraft)
46-
)
47-
.filter(Optional::isPresent)
48-
.map(Optional::get)
49-
.collect(toList());
45+
@Nonnull final AttributeDefinitionDraft newAttributeDefinitionDraft)
46+
throws DuplicateKeyException, DifferentTypeException {
47+
48+
final List<UpdateAction<ProductType>> updateActions;
49+
50+
if (haveSameAttributeType(oldAttributeDefinition, newAttributeDefinitionDraft)) {
51+
updateActions = Stream
52+
.of(
53+
buildChangeLabelUpdateAction(oldAttributeDefinition, newAttributeDefinitionDraft),
54+
buildSetInputTipUpdateAction(oldAttributeDefinition, newAttributeDefinitionDraft),
55+
buildChangeIsSearchableUpdateAction(oldAttributeDefinition, newAttributeDefinitionDraft),
56+
buildChangeInputHintUpdateAction(oldAttributeDefinition, newAttributeDefinitionDraft),
57+
buildChangeAttributeConstraintUpdateAction(oldAttributeDefinition, newAttributeDefinitionDraft)
58+
)
59+
.filter(Optional::isPresent)
60+
.map(Optional::get)
61+
.collect(toList());
62+
63+
if (isPlainEnumAttribute(oldAttributeDefinition)) {
64+
updateActions.addAll(buildEnumValuesUpdateActions(
65+
oldAttributeDefinition.getName(),
66+
((EnumAttributeType) oldAttributeDefinition.getAttributeType()).getValues(),
67+
((EnumAttributeType) newAttributeDefinitionDraft.getAttributeType()).getValues()
68+
));
69+
} else if (isLocalizedEnumAttribute(oldAttributeDefinition)) {
70+
updateActions.addAll(buildLocalizedEnumValuesUpdateActions(
71+
oldAttributeDefinition.getName(),
72+
((LocalizedEnumAttributeType) oldAttributeDefinition.getAttributeType()).getValues(),
73+
((LocalizedEnumAttributeType) newAttributeDefinitionDraft.getAttributeType()).getValues()
74+
));
75+
}
76+
} else {
77+
throw new DifferentTypeException(format("The attribute type of the attribute definitions are different. "
78+
+ "Attribute name: '%s'. Old attribute type: '%s', new attribute type: '%s'. "
79+
+ "Attribute type has to remain the same for the same attribute name.",
80+
oldAttributeDefinition.getName(),
81+
oldAttributeDefinition.getAttributeType().getClass().getName(),
82+
newAttributeDefinitionDraft.getAttributeType().getClass().getName()));
83+
}
84+
85+
86+
return updateActions;
87+
}
88+
89+
/**
90+
* Compares the attribute types of the {@code attributeDefinitionA} and the {@code attributeDefinitionB} and
91+
* returns true if both attribute definitions have the same attribute type, false otherwise.
92+
*
93+
* @param attributeDefinitionA the first attribute definition to compare.
94+
* @param attributeDefinitionB the second attribute definition to compare.
95+
*
96+
* @return true if both attribute definitions have the same attribute type, false otherwise.
97+
*/
98+
private static boolean haveSameAttributeType(
99+
@Nonnull final AttributeDefinition attributeDefinitionA,
100+
@Nonnull final AttributeDefinitionDraft attributeDefinitionB) {
101+
102+
return attributeDefinitionA.getAttributeType().getClass() == attributeDefinitionB.getAttributeType().getClass();
103+
}
104+
105+
/**
106+
* Indicates if the attribute definition is a plain enum value or not.
107+
*
108+
* @param attributeDefiniton the attribute definition.
109+
*
110+
* @return true if the attribute definition is a plain enum value, false otherwise.
111+
*/
112+
private static boolean isPlainEnumAttribute(@Nonnull final AttributeDefinition attributeDefiniton) {
113+
return attributeDefiniton.getAttributeType().getClass() == EnumAttributeType.class;
114+
}
115+
116+
/**
117+
* Indicates if the attribute definition is a localized enum value or not.
118+
*
119+
* @param attributeDefiniton the attribute definition.
120+
*
121+
* @return true if the attribute definition is a localized enum value, false otherwise.
122+
*/
123+
private static boolean isLocalizedEnumAttribute(@Nonnull final AttributeDefinition attributeDefiniton) {
124+
return attributeDefiniton.getAttributeType().getClass() == LocalizedEnumAttributeType.class;
50125
}
51126

52127
/**
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package com.commercetools.sync.producttypes.utils;
2+
3+
import io.sphere.sdk.commands.UpdateAction;
4+
import io.sphere.sdk.models.LocalizedEnumValue;
5+
import io.sphere.sdk.producttypes.ProductType;
6+
import io.sphere.sdk.producttypes.commands.updateactions.ChangeLocalizedEnumValueLabel;
7+
8+
import javax.annotation.Nonnull;
9+
import java.util.List;
10+
import java.util.Optional;
11+
import java.util.stream.Stream;
12+
13+
import static com.commercetools.sync.commons.utils.CommonTypeUpdateActionUtils.buildUpdateAction;
14+
import static java.util.stream.Collectors.toList;
15+
16+
public final class LocalizedEnumUpdateActionsUtils {
17+
/**
18+
* Compares all the fields of an old {@link LocalizedEnumValue} and a new {@link LocalizedEnumValue} and returns a
19+
* list of {@link UpdateAction}&lt;{@link ProductType}&gt; as a result. If both {@link LocalizedEnumValue} have
20+
* identical fields then no update action is needed and hence an empty {@link List} is returned.
21+
*
22+
* @param attributeDefinitionName the attribute definition name whose localized enum values belong to.
23+
* @param oldEnumValue the localized enum value which should be updated.
24+
* @param newEnumValue the localized enum value where we get the new fields.
25+
* @return A list with the update actions or an empty list if the localized enum values are
26+
* identical.
27+
*/
28+
@Nonnull
29+
public static List<UpdateAction<ProductType>> buildActions(
30+
@Nonnull final String attributeDefinitionName,
31+
@Nonnull final LocalizedEnumValue oldEnumValue,
32+
@Nonnull final LocalizedEnumValue newEnumValue) {
33+
34+
return Stream
35+
.of(
36+
buildChangeLabelAction(attributeDefinitionName, oldEnumValue, newEnumValue)
37+
)
38+
.filter(Optional::isPresent)
39+
.map(Optional::get)
40+
.collect(toList());
41+
}
42+
43+
/**
44+
* Compares the {@code label} values of an old {@link LocalizedEnumValue} and a new {@link LocalizedEnumValue}
45+
* and returns an {@link Optional} of update action, which would contain the {@code "changeLabel"}
46+
* {@link UpdateAction}. If both, old and new {@link LocalizedEnumValue} have the same {@code label} values,
47+
* then no update action is needed and empty optional will be returned.
48+
*
49+
* @param attributeDefinitionName the attribute definition name whose localized enum values belong to.
50+
* @param oldEnumValue the old localized enum value.
51+
* @param newEnumValue the new localized enum value which contains the new description.
52+
* @return optional containing update action or empty optional if labels
53+
* are identical.
54+
*/
55+
@Nonnull
56+
public static Optional<UpdateAction<ProductType>> buildChangeLabelAction(
57+
@Nonnull final String attributeDefinitionName,
58+
@Nonnull final LocalizedEnumValue oldEnumValue,
59+
@Nonnull final LocalizedEnumValue newEnumValue) {
60+
61+
return buildUpdateAction(oldEnumValue.getLabel(), newEnumValue.getLabel(),
62+
() -> ChangeLocalizedEnumValueLabel.of(attributeDefinitionName, newEnumValue));
63+
}
64+
65+
private LocalizedEnumUpdateActionsUtils() {
66+
}
67+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package com.commercetools.sync.producttypes.utils;
2+
3+
import io.sphere.sdk.commands.UpdateAction;
4+
import io.sphere.sdk.models.EnumValue;
5+
import io.sphere.sdk.producttypes.ProductType;
6+
import io.sphere.sdk.producttypes.commands.updateactions.ChangePlainEnumValueLabel;
7+
8+
import javax.annotation.Nonnull;
9+
import java.util.List;
10+
import java.util.Optional;
11+
import java.util.stream.Stream;
12+
13+
import static com.commercetools.sync.commons.utils.CommonTypeUpdateActionUtils.buildUpdateAction;
14+
import static java.util.stream.Collectors.toList;
15+
16+
public final class PlainEnumUpdateActionsUtils {
17+
/**
18+
* Compares all the fields of an old {@link EnumValue} and a new {@link EnumValue} and returns a list of
19+
* {@link UpdateAction}&lt;{@link ProductType}&gt; as a result. If both {@link EnumValue} have identical fields,
20+
* then no update action is needed and hence an empty {@link List} is returned.
21+
*
22+
* @param attributeDefinitionName the attribute definition name whose plain enum values belong to.
23+
* @param oldEnumValue the enum value which should be updated.
24+
* @param newEnumValue the enum value where we get the new fields.
25+
* @return A list with the update actions or an empty list if the enum values are
26+
* identical.
27+
*/
28+
@Nonnull
29+
public static List<UpdateAction<ProductType>> buildActions(
30+
@Nonnull final String attributeDefinitionName,
31+
@Nonnull final EnumValue oldEnumValue,
32+
@Nonnull final EnumValue newEnumValue) {
33+
34+
return Stream
35+
.of(
36+
buildChangeLabelAction(attributeDefinitionName, oldEnumValue, newEnumValue)
37+
)
38+
.filter(Optional::isPresent)
39+
.map(Optional::get)
40+
.collect(toList());
41+
}
42+
43+
/**
44+
* Compares the {@code label} values of an old {@link EnumValue} and a new {@link EnumValue}
45+
* and returns an {@link Optional} of update action, which would contain the {@code "changeLabel"}
46+
* {@link UpdateAction}. If both, old and new {@link EnumValue} have the same {@code label} values,
47+
* then no update action is needed and empty optional will be returned.
48+
*
49+
* @param attributeDefinitionName the attribute definition name whose plain enum values belong to.
50+
* @param oldEnumValue the old plain enum value.
51+
* @param newEnumValue the new plain enum value which contains the new description.
52+
* @return optional containing update action or empty optional if labels
53+
* are identical.
54+
*/
55+
@Nonnull
56+
public static Optional<UpdateAction<ProductType>> buildChangeLabelAction(
57+
@Nonnull final String attributeDefinitionName,
58+
@Nonnull final EnumValue oldEnumValue,
59+
@Nonnull final EnumValue newEnumValue) {
60+
61+
return buildUpdateAction(oldEnumValue.getLabel(), newEnumValue.getLabel(),
62+
() -> ChangePlainEnumValueLabel.of(attributeDefinitionName, newEnumValue));
63+
}
64+
65+
private PlainEnumUpdateActionsUtils() {
66+
}
67+
}

src/main/java/com/commercetools/sync/producttypes/utils/ProductTypeUpdateActionUtils.java

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ public final class ProductTypeUpdateActionUtils {
2727
*
2828
* @param oldProductType the product type that should be updated.
2929
* @param newProductType the product type draft which contains the new name.
30-
3130
* @return optional containing update action or empty optional if names are identical.
3231
*/
3332
@Nonnull
@@ -47,7 +46,6 @@ public static Optional<UpdateAction<ProductType>> buildChangeNameAction(
4746
*
4847
* @param oldProductType the product type that should be updated.
4948
* @param newProductType the product type draft which contains the new description.
50-
*
5149
* @return optional containing update action or empty optional if descriptions are identical.
5250
*/
5351
@Nonnull
@@ -66,11 +64,11 @@ public static Optional<UpdateAction<ProductType>> buildChangeDescriptionAction(
6664
* {@link List} is returned. In case, the new product type draft has a list of attributes in which a duplicate name
6765
* exists, the error callback is triggered and an empty list is returned.
6866
*
69-
* @param oldProductType the product type which should be updated.
70-
* @param newProductType the product type draft where we get the key.
71-
* @param syncOptions responsible for supplying the sync options to the sync utility method. It is used for
72-
* triggering the error callback within the utility, in case of errors.
73-
*
67+
* @param oldProductType the product type which should be updated.
68+
* @param newProductType the product type draft where we get the key.
69+
* @param syncOptions responsible for supplying the sync options to the sync utility method.
70+
* It is used for triggering the error callback within the utility, in case of
71+
* errors.
7472
* @return A list with the update actions or an empty list if the attributes are identical.
7573
*/
7674
@Nonnull
@@ -81,8 +79,9 @@ public static List<UpdateAction<ProductType>> buildAttributesUpdateActions(
8179

8280
try {
8381
return buildAttributeDefinitionsUpdateActions(
84-
oldProductType.getAttributes(),
85-
newProductType.getAttributes());
82+
oldProductType.getAttributes(),
83+
newProductType.getAttributes()
84+
);
8685
} catch (final BuildUpdateActionException exception) {
8786
syncOptions.applyErrorCallback(format("Failed to build update actions for the attributes definitions "
8887
+ "of the product type with the key '%s'. Reason: %s", oldProductType.getKey(), exception),
@@ -91,5 +90,6 @@ public static List<UpdateAction<ProductType>> buildAttributesUpdateActions(
9190
}
9291
}
9392

94-
private ProductTypeUpdateActionUtils() { }
93+
private ProductTypeUpdateActionUtils() {
94+
}
9595
}

0 commit comments

Comments
 (0)