Skip to content

Commit 8a37a8e

Browse files
committed
Merge branch 'master' into cdx-428-java-sdk-support-passing-multiple-emails-in
2 parents 635c72d + e03d7d0 commit 8a37a8e

234 files changed

Lines changed: 7275 additions & 3667 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/CODEOWNERS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
# Define which individuals or teams that are responsible for code in a repository
22

3-
* @Mudaafi @esezen
3+
* @Constructor-io/integrations-static-lib-java-admins

constructorio-client/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<groupId>io.constructor.client</groupId>
55
<artifactId>constructorio-client</artifactId>
66
<packaging>jar</packaging>
7-
<version>7.2.0</version>
7+
<version>7.4.1</version>
88
<name>constructorio-client</name>
99
<url>https://github.com/Constructor-io/constructorio-java</url>
1010
<dependencies>

constructorio-client/src/main/java/io/constructor/client/ConstructorIO.java

Lines changed: 89 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@
1010
import java.util.Arrays;
1111
import java.util.Base64;
1212
import java.util.HashMap;
13+
import java.util.LinkedHashSet;
1314
import java.util.List;
1415
import java.util.Map;
16+
import java.util.Set;
1517
import java.util.concurrent.TimeUnit;
1618
import okhttp3.Call;
1719
import okhttp3.Callback;
@@ -33,6 +35,10 @@
3335
/** Constructor.io Client */
3436
public class ConstructorIO {
3537

38+
/** Valid file extensions for catalog uploads */
39+
private static final Set<String> VALID_CATALOG_EXTENSIONS =
40+
new LinkedHashSet<>(Arrays.asList(".csv", ".json", ".jsonl"));
41+
3642
/** the HTTP client used by all instances */
3743
private static OkHttpClient client =
3844
new OkHttpClient.Builder()
@@ -1854,6 +1860,17 @@ public String recommendationsAsJSON(RecommendationsRequest req, UserInfo userInf
18541860
}
18551861
}
18561862

1863+
if (StringUtils.isNotBlank(req.getVariationId())) {
1864+
if (req.getItemIds() == null || req.getItemIds().size() != 1) {
1865+
throw new IllegalArgumentException(
1866+
"variationId requires exactly one itemId to be specified");
1867+
}
1868+
url =
1869+
url.newBuilder()
1870+
.addQueryParameter("variation_id", req.getVariationId())
1871+
.build();
1872+
}
1873+
18571874
if (StringUtils.isNotBlank(req.getTerm())) {
18581875
url = url.newBuilder().addQueryParameter("term", req.getTerm()).build();
18591876
}
@@ -2090,13 +2107,60 @@ protected static String getResponseBody(Response response) throws ConstructorExc
20902107
throw new ConstructorException(errorMessage, errorCode);
20912108
}
20922109

2110+
/**
2111+
* Validates and extracts the file extension from a File object for catalog uploads.
2112+
*
2113+
* @param file the File object containing the actual file
2114+
* @param fileName the logical file name (items, variations, item_groups)
2115+
* @return the validated file extension (including the dot, e.g., ".csv", ".json", or ".jsonl")
2116+
* @throws ConstructorException if the file extension is not in VALID_CATALOG_EXTENSIONS
2117+
*/
2118+
private static String getValidatedFileExtension(File file, String fileName)
2119+
throws ConstructorException {
2120+
if (file == null) {
2121+
throw new ConstructorException(
2122+
"Invalid file for '" + fileName + "': file cannot be null.");
2123+
}
2124+
2125+
String actualFileName = file.getName();
2126+
if (actualFileName == null || actualFileName.isEmpty()) {
2127+
throw new ConstructorException(
2128+
"Invalid file for '" + fileName + "': file name cannot be empty.");
2129+
}
2130+
2131+
int lastDotIndex = actualFileName.lastIndexOf('.');
2132+
if (lastDotIndex == -1 || lastDotIndex == actualFileName.length() - 1) {
2133+
throw new ConstructorException(
2134+
"Invalid file for '"
2135+
+ fileName
2136+
+ "': file must have "
2137+
+ VALID_CATALOG_EXTENSIONS
2138+
+ " extension. Found: "
2139+
+ actualFileName);
2140+
}
2141+
2142+
String extension = actualFileName.substring(lastDotIndex).toLowerCase();
2143+
2144+
if (!VALID_CATALOG_EXTENSIONS.contains(extension)) {
2145+
throw new ConstructorException(
2146+
"Invalid file type for '"
2147+
+ fileName
2148+
+ "': file must have "
2149+
+ VALID_CATALOG_EXTENSIONS
2150+
+ " extension. Found: "
2151+
+ actualFileName);
2152+
}
2153+
2154+
return extension;
2155+
}
2156+
20932157
/**
20942158
* Grabs the version number (hard coded ATM)
20952159
*
20962160
* @return version number
20972161
*/
20982162
protected String getVersion() {
2099-
return "ciojava-7.2.0";
2163+
return "ciojava-7.4.1";
21002164
}
21012165

21022166
/**
@@ -2369,9 +2433,12 @@ protected static JSONArray transformItemsAPIV2Response(JSONArray results) {
23692433
/**
23702434
* Send a full catalog to replace the current one (sync)
23712435
*
2372-
* @param req the catalog request
2373-
* @return a string of JSON
2374-
* @throws ConstructorException if the request is invalid.
2436+
* <p>Supports CSV, JSON, and JSONL file formats. The file type is automatically detected from
2437+
* the file extension (.csv, .json, or .jsonl).
2438+
*
2439+
* @param req the catalog request containing files with .csv, .json, or .jsonl extensions
2440+
* @return a string of JSON containing task information
2441+
* @throws ConstructorException if the request is invalid or file extensions are not supported
23752442
*/
23762443
public String replaceCatalog(CatalogRequest req) throws ConstructorException {
23772444
try {
@@ -2399,10 +2466,11 @@ public String replaceCatalog(CatalogRequest req) throws ConstructorException {
23992466
for (Map.Entry<String, File> entry : files.entrySet()) {
24002467
String fileName = entry.getKey();
24012468
File file = entry.getValue();
2469+
String fileExtension = getValidatedFileExtension(file, fileName);
24022470

24032471
multipartBuilder.addFormDataPart(
24042472
fileName,
2405-
fileName + ".csv",
2473+
fileName + fileExtension,
24062474
RequestBody.create(MediaType.parse("application/octet-stream"), file));
24072475
}
24082476
}
@@ -2428,9 +2496,12 @@ public String replaceCatalog(CatalogRequest req) throws ConstructorException {
24282496
/**
24292497
* Send a partial catalog to update specific items (delta)
24302498
*
2431-
* @param req the catalog request
2432-
* @return a string of JSON
2433-
* @throws ConstructorException if the request is invalid.
2499+
* <p>Supports CSV, JSON, and JSONL file formats. The file type is automatically detected from
2500+
* the file extension (.csv, .json, or .jsonl).
2501+
*
2502+
* @param req the catalog request containing files with .csv, .json, or .jsonl extensions
2503+
* @return a string of JSON containing task information
2504+
* @throws ConstructorException if the request is invalid or file extensions are not supported
24342505
*/
24352506
public String updateCatalog(CatalogRequest req) throws ConstructorException {
24362507
try {
@@ -2458,10 +2529,11 @@ public String updateCatalog(CatalogRequest req) throws ConstructorException {
24582529
for (Map.Entry<String, File> entry : files.entrySet()) {
24592530
String fileName = entry.getKey();
24602531
File file = entry.getValue();
2532+
String fileExtension = getValidatedFileExtension(file, fileName);
24612533

24622534
multipartBuilder.addFormDataPart(
24632535
fileName,
2464-
fileName + ".csv",
2536+
fileName + fileExtension,
24652537
RequestBody.create(MediaType.parse("application/octet-stream"), file));
24662538
}
24672539
}
@@ -2488,9 +2560,12 @@ public String updateCatalog(CatalogRequest req) throws ConstructorException {
24882560
/**
24892561
* Send a patch delta catalog to update specific items (delta)
24902562
*
2491-
* @param req the catalog request
2492-
* @return a string of JSON
2493-
* @throws ConstructorException if the request is invalid.
2563+
* <p>Supports CSV, JSON, and JSONL file formats. The file type is automatically detected from
2564+
* the file extension (.csv, .json, or .jsonl).
2565+
*
2566+
* @param req the catalog request containing files with .csv, .json, or .jsonl extensions
2567+
* @return a string of JSON containing task information
2568+
* @throws ConstructorException if the request is invalid or file extensions are not supported
24942569
*/
24952570
public String patchCatalog(CatalogRequest req) throws ConstructorException {
24962571
try {
@@ -2523,10 +2598,11 @@ public String patchCatalog(CatalogRequest req) throws ConstructorException {
25232598
for (Map.Entry<String, File> entry : files.entrySet()) {
25242599
String fileName = entry.getKey();
25252600
File file = entry.getValue();
2601+
String fileExtension = getValidatedFileExtension(file, fileName);
25262602

25272603
multipartBuilder.addFormDataPart(
25282604
fileName,
2529-
fileName + ".csv",
2605+
fileName + fileExtension,
25302606
RequestBody.create(MediaType.parse("application/octet-stream"), file));
25312607
}
25322608
}

constructorio-client/src/main/java/io/constructor/client/RecommendationsRequest.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ public class RecommendationsRequest {
1212
private String term;
1313
private int numResults;
1414
private List<String> itemIds;
15+
private String variationId;
1516
private Map<String, List<String>> facets;
1617
private String section;
1718
private String preFilterExpression;
@@ -32,6 +33,7 @@ public RecommendationsRequest(String podId) throws IllegalArgumentException {
3233
this.podId = podId;
3334
this.numResults = 10;
3435
this.itemIds = null;
36+
this.variationId = null;
3537
this.term = null;
3638
this.section = "Products";
3739
this.variationsMap = null;
@@ -97,6 +99,22 @@ public List<String> getItemIds() {
9799
return itemIds;
98100
}
99101

102+
/**
103+
* @param variationId the variation id to set. Can be used with exactly one item_id specified in
104+
* the request. Applicable for alternative_items, complementary_items, and bundles pod
105+
* types.
106+
*/
107+
public void setVariationId(String variationId) {
108+
this.variationId = variationId;
109+
}
110+
111+
/**
112+
* @return the variation id
113+
*/
114+
public String getVariationId() {
115+
return variationId;
116+
}
117+
100118
/**
101119
* @param section the section to set
102120
*/
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package io.constructor.client.models;
2+
3+
import com.google.gson.annotations.SerializedName;
4+
5+
/** Constructor.io Related Browse Page - uses Gson/Reflection to load data in */
6+
public class RelatedBrowsePage {
7+
8+
@SerializedName("filter_name")
9+
private String filterName;
10+
11+
@SerializedName("filter_value")
12+
private String filterValue;
13+
14+
@SerializedName("display_name")
15+
private String displayName;
16+
17+
@SerializedName("image_url")
18+
private String imageUrl;
19+
20+
/**
21+
* @return the filter name
22+
*/
23+
public String getFilterName() {
24+
return filterName;
25+
}
26+
27+
/**
28+
* @return the filter value
29+
*/
30+
public String getFilterValue() {
31+
return filterValue;
32+
}
33+
34+
/**
35+
* @return the display name
36+
*/
37+
public String getDisplayName() {
38+
return displayName;
39+
}
40+
41+
/**
42+
* @return the image URL
43+
*/
44+
public String getImageUrl() {
45+
return imageUrl;
46+
}
47+
48+
/**
49+
* @param filterName the filter name to set
50+
*/
51+
public void setFilterName(String filterName) {
52+
this.filterName = filterName;
53+
}
54+
55+
/**
56+
* @param filterValue the filter value to set
57+
*/
58+
public void setFilterValue(String filterValue) {
59+
this.filterValue = filterValue;
60+
}
61+
62+
/**
63+
* @param displayName the display name to set
64+
*/
65+
public void setDisplayName(String displayName) {
66+
this.displayName = displayName;
67+
}
68+
69+
/**
70+
* @param imageUrl the image URL to set
71+
*/
72+
public void setImageUrl(String imageUrl) {
73+
this.imageUrl = imageUrl;
74+
}
75+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package io.constructor.client.models;
2+
3+
import com.google.gson.annotations.SerializedName;
4+
5+
/** Constructor.io Related Search - uses Gson/Reflection to load data in */
6+
public class RelatedSearch {
7+
8+
@SerializedName("query")
9+
private String query;
10+
11+
/**
12+
* @return the related search query
13+
*/
14+
public String getQuery() {
15+
return query;
16+
}
17+
18+
/**
19+
* @param query the related search query to set
20+
*/
21+
public void setQuery(String query) {
22+
this.query = query;
23+
}
24+
}

constructorio-client/src/main/java/io/constructor/client/models/SearchResponseInner.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@ public class SearchResponseInner extends BaseResultsResponse {
1515
@SerializedName("features")
1616
private List<Feature> features;
1717

18+
@SerializedName("related_searches")
19+
private List<RelatedSearch> relatedSearches;
20+
21+
@SerializedName("related_browse_pages")
22+
private List<RelatedBrowsePage> relatedBrowsePages;
23+
1824
/**
1925
* @return redirect data
2026
*/
@@ -47,4 +53,32 @@ public void setRefinedContent(List<RefinedContent> refinedContent) {
4753
public void setFeatures(List<Feature> features) {
4854
this.features = features;
4955
}
56+
57+
/**
58+
* @return list of related searches
59+
*/
60+
public List<RelatedSearch> getRelatedSearches() {
61+
return relatedSearches;
62+
}
63+
64+
/**
65+
* @return list of related browse pages
66+
*/
67+
public List<RelatedBrowsePage> getRelatedBrowsePages() {
68+
return relatedBrowsePages;
69+
}
70+
71+
/**
72+
* @param relatedSearches list of related searches to set
73+
*/
74+
public void setRelatedSearches(List<RelatedSearch> relatedSearches) {
75+
this.relatedSearches = relatedSearches;
76+
}
77+
78+
/**
79+
* @param relatedBrowsePages list of related browse pages to set
80+
*/
81+
public void setRelatedBrowsePages(List<RelatedBrowsePage> relatedBrowsePages) {
82+
this.relatedBrowsePages = relatedBrowsePages;
83+
}
5084
}

0 commit comments

Comments
 (0)