1717
1818import io .constructor .client .models .AutocompleteResponse ;
1919import io .constructor .client .models .SearchResponse ;
20+ import io .constructor .client .models .RecommendationsResponse ;
2021import io .constructor .client .models .ServerError ;
2122import okhttp3 .HttpUrl ;
2223import okhttp3 .MediaType ;
@@ -97,7 +98,7 @@ public ConstructorIO(String apiToken, String apiKey, boolean isHTTPS, String hos
9798
9899 /**
99100 * Creates a constructor.io Client.
100- *
101+ *
101102 * @param apiToken API Token, gotten from your <a href="https://constructor.io/dashboard">Constructor.io Dashboard</a>, and kept secret.
102103 * @param apiKey API Key, used publically in your in-site javascript client.
103104 * @param isHTTPS true to use HTTPS, false to use HTTP. It is highly recommended that you use HTTPS.
@@ -349,7 +350,7 @@ public boolean modifyItem(ConstructorItem item, String autocompleteSection, Stri
349350 /**
350351 * Queries the autocomplete service.
351352 *
352- * Note that if you're making an autocomplete service on a website, you should definitely use our javascript client instead of doing it server-side!
353+ * Note that if you're making an autocomplete request for a website, you should definitely use our javascript client instead of doing it server-side!
353354 * That's important. That will be a solid latency difference.
354355 *
355356 * @param req the autocomplete request
@@ -369,7 +370,7 @@ public AutocompleteResponse autocomplete(AutocompleteRequest req, UserInfo userI
369370 /**
370371 * Queries the autocomplete service.
371372 *
372- * Note that if you're making an autocomplete service on a website, you should definitely use our javascript client instead of doing it server-side!
373+ * Note that if you're making an autocomplete request for a website, you should definitely use our javascript client instead of doing it server-side!
373374 * That's important. That will be a solid latency difference.
374375 *
375376 * @param req the autocomplete request
@@ -405,7 +406,7 @@ public String autocompleteAsJSON(AutocompleteRequest req, UserInfo userInfo) thr
405406 /**
406407 * Queries the search service.
407408 *
408- * Note that if you're making an search service on a website, you should definitely use our javascript client instead of doing it server-side!
409+ * Note that if you're making a search request for a website, you should definitely use our javascript client instead of doing it server-side!
409410 * That's important. That will be a solid latency difference.
410411 *
411412 * @param req the search request
@@ -425,7 +426,7 @@ public SearchResponse search(SearchRequest req, UserInfo userInfo) throws Constr
425426 /**
426427 * Queries the search service.
427428 *
428- * Note that if you're making an search service on a website, you should definitely use our javascript client instead of doing it server-side!
429+ * Note that if you're making a search request for a website, you should definitely use our javascript client instead of doing it server-side!
429430 * That's important. That will be a solid latency difference.
430431 *
431432 * @param req the search request
@@ -479,7 +480,7 @@ public String searchAsJSON(SearchRequest req, UserInfo userInfo) throws Construc
479480 /**
480481 * Queries the search service with natural language processing.
481482 *
482- * Note that if you're making a search service on a website, you should definitely use our javascript client instead of doing it server-side!
483+ * Note that if you're making a search request for a website, you should definitely use our javascript client instead of doing it server-side!
483484 * That's important. That will be a solid latency difference.
484485 *
485486 * @param req the natural language search request
@@ -499,7 +500,7 @@ public SearchResponse naturalLanguageSearch(NaturalLanguageSearchRequest req, Us
499500 /**
500501 * Queries the search service with natural language processing.
501502 *
502- * Note that if you're making a search service on a website, you should definitely use our javascript client instead of doing it server-side!
503+ * Note that if you're making a search request for a website, you should definitely use our javascript client instead of doing it server-side!
503504 * That's important. That will be a solid latency difference.
504505 *
505506 * @param req the natural language search request
@@ -530,6 +531,66 @@ public String naturalLanguageSearchAsJSON(NaturalLanguageSearchRequest req, User
530531 }
531532 }
532533
534+ /**
535+ * Queries the recommendations service to retrieve results.
536+ *
537+ * Note that if you're making a recommendations request for a website, you should definitely use our javascript client instead of doing it server-side!
538+ * That's important. That will be a solid latency difference.
539+ *
540+ * @param req the recommendations request
541+ * @param userInfo optional information about the user
542+ * @return a recommendations response
543+ * @throws ConstructorException if the request is invalid.
544+ */
545+ public RecommendationsResponse recommendations (RecommendationsRequest req , UserInfo userInfo ) throws ConstructorException {
546+ try {
547+ String json = recommendationsAsJSON (req , userInfo );
548+ return createRecommendationsResponse (json );
549+ } catch (Exception exception ) {
550+ throw new ConstructorException (exception );
551+ }
552+ }
553+
554+ /**
555+ * Queries the recommendations service to retrieve results.
556+ *
557+ * Note that if you're making an recommendations request for a website, you should definitely use our javascript client instead of doing it server-side!
558+ * That's important. That will be a solid latency difference.
559+ *
560+ * @param req the recommendations request
561+ * @param userInfo optional information about the user
562+ * @return a string of JSON
563+ * @throws ConstructorException if the request is invalid.
564+ */
565+ public String recommendationsAsJSON (RecommendationsRequest req , UserInfo userInfo ) throws ConstructorException {
566+ try {
567+ String path = "recommendations/v1/pods/" + req .getPodId ();
568+ HttpUrl url = (userInfo == null ) ? this .makeUrl (path ) : this .makeUrl (path , userInfo );
569+ url = url .newBuilder ()
570+ .addQueryParameter ("num_results" , String .valueOf (req .getNumResults ()))
571+ .addQueryParameter ("section" , req .getSection ())
572+ .build ();
573+
574+ if (req .getItemIds () != null ) {
575+ for (String itemId : req .getItemIds ()) {
576+ url = url .newBuilder ()
577+ .addQueryParameter ("item_id" , itemId )
578+ .build ();
579+ }
580+ }
581+
582+ Request request = this .makeUserRequestBuilder (userInfo )
583+ .url (url )
584+ .get ()
585+ .build ();
586+
587+ Response response = clientWithRetry .newCall (request ).execute ();
588+ return getResponseBody (response );
589+ } catch (Exception exception ) {
590+ throw new ConstructorException (exception );
591+ }
592+ }
593+
533594 /**
534595 * Makes a URL to issue the requests to. Note that the URL will automagically have the apiKey embedded.
535596 *
@@ -544,7 +605,7 @@ protected HttpUrl makeUrl(String path) throws UnsupportedEncodingException {
544605 .addQueryParameter ("c" , this .version )
545606 .host (this .host )
546607 .build ();
547-
608+
548609 return url ;
549610 }
550611
@@ -568,7 +629,7 @@ protected HttpUrl makeUrl(String path, UserInfo info) throws UnsupportedEncoding
568629 if (info .getUserId () != null ) {
569630 url = url .newBuilder ()
570631 .addQueryParameter ("ui" , String .valueOf (info .getUserId ()))
571- .build ();
632+ .build ();
572633 }
573634
574635 if (info .getUserSegments () != null ) {
@@ -584,7 +645,7 @@ protected HttpUrl makeUrl(String path, UserInfo info) throws UnsupportedEncoding
584645
585646 /**
586647 * Creates a builder for an authorized request
587- *
648+ *
588649 * @return Request Builder
589650 */
590651 protected Builder makeAuthorizedRequestBuilder () {
@@ -595,7 +656,7 @@ protected Builder makeAuthorizedRequestBuilder() {
595656
596657 /**
597658 * Creates a builder for an end user request
598- *
659+ *
599660 * @param info user information if available
600661 * @return Request Builder
601662 */
@@ -612,7 +673,7 @@ protected Builder makeUserRequestBuilder(UserInfo info) {
612673
613674 /**
614675 * Checks the response from an endpoint and throws an exception if an error occurred
615- *
676+ *
616677 * @return whether the request was successful
617678 */
618679 protected static String getResponseBody (Response response ) throws ConstructorException {
@@ -681,7 +742,21 @@ protected static SearchResponse createSearchResponse(String string) {
681742 }
682743
683744 /**
684- * Moves metadata out of the result data for an array of results
745+ * Transforms a JSON string to a new JSON string for easy Gson parsing into an recommendations response.
746+ * Using JSON objects to acheive this is considerably less error prone than attempting to do it in
747+ * a Gson Type Adapter.
748+ */
749+ protected static RecommendationsResponse createRecommendationsResponse (String string ) {
750+ JSONObject json = new JSONObject (string );
751+ JSONObject response = json .getJSONObject ("response" );
752+ JSONArray results = response .getJSONArray ("results" );
753+ moveMetadataOutOfResultData (results );
754+ String transformed = json .toString ();
755+ return new Gson ().fromJson (transformed , RecommendationsResponse .class );
756+ }
757+
758+ /**
759+ * Moves metadata out of the result data for an array of results
685760 * @param results A JSON array of results
686761 */
687762 protected static void moveMetadataOutOfResultData (JSONArray results ) {
@@ -690,7 +765,7 @@ protected static void moveMetadataOutOfResultData(JSONArray results) {
690765 JSONObject result = results .getJSONObject (i );
691766 JSONObject resultData = result .getJSONObject ("data" );
692767 JSONObject metadata = new JSONObject ();
693-
768+
694769 // Move unspecified properties in result data object to metadata object
695770 for (Object propertyKey : resultData .keySet ()) {
696771 String propertyName = (String )propertyKey ;
@@ -709,4 +784,4 @@ protected static void moveMetadataOutOfResultData(JSONArray results) {
709784 resultData .put ("metadata" , metadata );
710785 }
711786 }
712- }
787+ }
0 commit comments