1+ package com.contentstack.cms.stack;
2+ import java.util.Arrays;
3+ import java.util.HashMap;
4+ import java.util.List;
5+ import java.util.Map;
6+
7+ import org.jetbrains.annotations.NotNull;
8+ import org.json.simple.JSONArray;
9+ import org.json.simple.JSONObject;
10+
11+ import com.contentstack.cms.BaseImplementation;
12+
13+ import okhttp3.ResponseBody;
14+ import retrofit2.Call;
15+ import retrofit2.Retrofit;
16+
17+ /**
18+ * The VariantGroup class provides functionality to manage variant groups in Contentstack.
19+ * Variant groups allow you to manage different versions of your content for various use cases,
20+ * such as A/B testing, localization, or personalization.
21+ */
22+ public class VariantGroup implements BaseImplementation<VariantGroup> {
23+ protected final VariantsService service;
24+ protected final Map<String, Object> headers;
25+ protected Map<String, Object> params;
26+ private final Retrofit instance;
27+ private String variantGroupUid;
28+ private List<String> branches;
29+
30+ /**
31+ * Creates a new VariantGroup instance without a specific variant group UID.
32+ * This constructor is used when creating new variant groups.
33+ *
34+ * @param instance The Retrofit instance for making API calls
35+ * @param headers The headers to be included in API requests
36+ */
37+ protected VariantGroup(Retrofit instance, Map<String, Object> headers) {
38+ this.headers = new HashMap<>();
39+ this.headers.putAll(headers);
40+ this.params = new HashMap<>();
41+ this.instance = instance;
42+ this.service = instance.create(VariantsService.class);
43+ this.branches = Arrays.asList("main"); // Default to main branch
44+ }
45+
46+ /**
47+ * Creates a new VariantGroup instance with a specific variant group UID.
48+ * This constructor is used when working with existing variant groups.
49+ *
50+ * @param instance The Retrofit instance for making API calls
51+ * @param headers The headers to be included in API requests
52+ * @param variantGroupUid The unique identifier of the variant group
53+ */
54+ protected VariantGroup(Retrofit instance, Map<String, Object> headers, String variantGroupUid) {
55+ this.headers = new HashMap<>();
56+ this.headers.putAll(headers);
57+ this.params = new HashMap<>();
58+ this.instance = instance;
59+ this.variantGroupUid = variantGroupUid;
60+ this.service = instance.create(VariantsService.class);
61+ this.branches = Arrays.asList("main"); // Default to main branch
62+ }
63+
64+ /**
65+ * Validates that the variant group UID is not null or empty.
66+ * This method is called before operations that require a valid variant group UID.
67+ *
68+ * @throws IllegalAccessError if the variant group UID is null or empty
69+ */
70+ void validate() {
71+ if (this.variantGroupUid == null || this.variantGroupUid.isEmpty())
72+ throw new IllegalAccessError("Variant group uid can not be null or empty");
73+ }
74+
75+ /**
76+ * Sets the branches for the variant group using a List of branch names.
77+ * These branches will be used when linking or unlinking content types to the variant group.
78+ *
79+ * @param branches A List of String values representing the branch names
80+ * @return The current VariantGroup instance for method chaining
81+ */
82+ public VariantGroup setBranches(List<String> branches) {
83+ this.branches = branches;
84+ return this;
85+ }
86+
87+ /**
88+ * Sets the branches for the variant group using varargs (variable number of arguments).
89+ * This is a convenience method that allows passing branch names directly as arguments.
90+ * These branches will be used when linking or unlinking content types to the variant group.
91+ *
92+ * @param branches Variable number of String arguments representing branch names
93+ * @return The current VariantGroup instance for method chaining
94+ */
95+ public VariantGroup setBranches(String... branches) {
96+ this.branches = Arrays.asList(branches);
97+ return this;
98+ }
99+
100+ /**
101+ * @param key A string representing the key of the parameter. It cannot be
102+ * null and must be
103+ * provided as a non-null value.
104+ * @param value The "value" parameter is of type Object, which means it can
105+ * accept any type of
106+ * object as its value.
107+ * @return instance of VariantGroup
108+ */
109+ @Override
110+ public VariantGroup addParam(@NotNull String key, @NotNull Object value) {
111+ this.params.put(key, value);
112+ return this;
113+ }
114+
115+ /**
116+ * @param key The key parameter is a string that represents the name or
117+ * identifier of the header.
118+ * It is used to specify the type of information being sent in the
119+ * header.
120+ * @param value The value parameter is a string that represents the value of the
121+ * header.
122+ * @return instance of VariantGroup
123+ */
124+ @Override
125+ public VariantGroup addHeader(@NotNull String key, @NotNull String value) {
126+ this.headers.put(key, value);
127+ return this;
128+ }
129+
130+ /**
131+ * @param headers A HashMap containing key-value pairs of headers, where the key
132+ * is a String
133+ * representing the header name and the value is a String
134+ * representing the header value.
135+ * @return instance of VariantGroup
136+ */
137+ @Override
138+ public VariantGroup addHeaders(@NotNull HashMap<String, String> headers) {
139+ this.headers.putAll(headers);
140+ return this;
141+ }
142+
143+
144+ /**
145+ * @param headers The "params" parameter is a HashMap that maps String keys to
146+ * Object values. It is
147+ * annotated with @NotNull, indicating that it cannot be null.
148+ * @return instance of VariantGroup
149+ */
150+ @Override
151+ public VariantGroup addParams(@NotNull HashMap<String, Object> headers) {
152+ this.params.putAll(headers);
153+ return this;
154+ }
155+
156+
157+ /**
158+ * clears all params in the request
159+ */
160+ protected void clearParams() {
161+ this.params.clear();
162+ }
163+
164+ /**
165+ * Retrieves a list of all variant groups.
166+ * This method does not require a variant group UID to be set.
167+ *
168+ * @return A Call object that can be executed to perform the API request to fetch all variant groups
169+ */
170+ public Call<ResponseBody> find() {
171+ return this.service.fetchVariantGroups(this.headers, this.params);
172+ }
173+
174+ /**
175+ * Links content types to the variant group.
176+ *
177+ * @param contentTypeUids Array of content type UIDs to link to the variant group
178+ * @return A Call object that can be executed to perform the API request
179+ * @throws IllegalAccessError if the variant group UID is not set
180+ * @throws IllegalArgumentException if contentTypeUids is empty
181+ */
182+ public Call<ResponseBody> linkContentTypes(@NotNull String... contentTypeUids) {
183+ if (contentTypeUids.length == 0) {
184+ throw new IllegalArgumentException("Content type UIDs cannot be empty");
185+ }
186+ return updateContentTypeLinks(contentTypeUids, true);
187+ }
188+
189+ /**
190+ * Unlinks content types from the variant group.
191+ *
192+ * @param contentTypeUids Array of content type UIDs to unlink from the variant group
193+ * @return A Call object that can be executed to perform the API request
194+ * @throws IllegalAccessError if the variant group UID is not set
195+ * @throws IllegalArgumentException if contentTypeUids is empty
196+ */
197+ public Call<ResponseBody> unlinkContentTypes(@NotNull String... contentTypeUids) {
198+ if (contentTypeUids.length == 0) {
199+ throw new IllegalArgumentException("Content type UIDs cannot be empty");
200+ }
201+ return updateContentTypeLinks(contentTypeUids, false);
202+ }
203+
204+ /**
205+ * Updates the linking status of content types to a variant group.
206+ * This private method handles both linking and unlinking operations.
207+ *
208+ * @param contentTypeUids Array of content type UIDs to update
209+ * @param isLink true to link content types, false to unlink
210+ * @return A Call object that can be executed to perform the API request
211+ * @throws IllegalAccessError if the variant group UID is not set
212+ */
213+ @SuppressWarnings("unchecked")
214+ private Call<ResponseBody> updateContentTypeLinks(String[] contentTypeUids, boolean isLink) {
215+ validate();
216+
217+ // Construct the request body
218+ JSONObject requestBody = new JSONObject();
219+ JSONArray contentTypes = new JSONArray();
220+ JSONArray branches = new JSONArray();
221+ for (String branch : this.branches) {
222+ branches.add(branch);
223+ }
224+
225+ for (String uid : contentTypeUids) {
226+ JSONObject contentType = new JSONObject();
227+ contentType.put("uid", uid);
228+ contentType.put("status", isLink ? "linked" : "unlinked");
229+ contentTypes.add(contentType);
230+ }
231+ requestBody.put("uid", this.variantGroupUid);
232+ requestBody.put("branches", branches);
233+ requestBody.put("content_types", contentTypes);
234+ return this.service.updateVariantGroupContentTypes(this.headers, this.variantGroupUid, this.params, requestBody);
235+ }
236+ }
0 commit comments