Skip to content

Commit d800067

Browse files
authored
[Csl-879] quizzes library support java (#75)
* Add response models * Add request models. * Fix some typos * Add next quiz endpoint * Change a param to take list of list of strings instead of integer * add finalize quiz response * Add tests * Typo, styling * quiz updates * Fix tests * Response tests * lint * Tests * revert pom change * Fix merge * remove test * Remove print * Adjust naming of models, functions * Remove quiz option attribute * update function name * update comments
1 parent 0d3e552 commit d800067

19 files changed

+1098
-15
lines changed

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

Lines changed: 160 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
import io.constructor.client.models.ServerError;
2626
import io.constructor.client.models.AllTasksResponse;
2727
import io.constructor.client.models.Task;
28+
import io.constructor.client.models.QuizQuestionResponse;
29+
import io.constructor.client.models.QuizResultsResponse;
2830
import io.constructor.client.models.VariationsResponse;
2931
import io.constructor.client.models.BrowseFacetOptionsResponse;
3032
import io.constructor.client.models.BrowseFacetsResponse;
@@ -129,9 +131,9 @@ public static OkHttpClient getHttpClient() {
129131
* Creates a constructor.io Client.
130132
*
131133
* @param apiToken API Token, gotten from your <a href="https://constructor.io/dashboard">Constructor.io Dashboard</a>, and kept secret.
132-
* @param apiKey API Key, used publically in your in-site javascript client.
134+
* @param apiKey API Key, used publicly in your in-site javascript client.
133135
* @param isHTTPS true to use HTTPS, false to use HTTP. It is highly recommended that you use HTTPS.
134-
* @param host The host of the autocomplete service that you are using. It is recommended that you let this value be null, in which case the host defaults to the Constructor.io autocomplete servic at ac.cnstrc.com.
136+
* @param host The host of the autocomplete service that you are using. It is recommended that you let this value be null, in which case the host defaults to the Constructor.io autocomplete service at ac.cnstrc.com.
135137
* @param constructorToken The token provided by Constructor to identify your company's traffic if proxying requests for results
136138
*/
137139
public ConstructorIO(String apiToken, String apiKey, boolean isHTTPS, String host, String constructorToken) {
@@ -155,9 +157,9 @@ public ConstructorIO(String apiToken, String apiKey, boolean isHTTPS, String hos
155157
* Creates a constructor.io Client.
156158
*
157159
* @param apiToken API Token, gotten from your <a href="https://constructor.io/dashboard">Constructor.io Dashboard</a>, and kept secret.
158-
* @param apiKey API Key, used publically in your in-site javascript client.
160+
* @param apiKey API Key, used publicly in your in-site javascript client.
159161
* @param isHTTPS true to use HTTPS, false to use HTTP. It is highly recommended that you use HTTPS.
160-
* @param host The host of the autocomplete service that you are using. It is recommended that you let this value be null, in which case the host defaults to the Constructor.io autocomplete servic at ac.cnstrc.com.
162+
* @param host The host of the autocomplete service that you are using. It is recommended that you let this value be null, in which case the host defaults to the Constructor.io autocomplete service at ac.cnstrc.com.
161163
*/
162164
public ConstructorIO(String apiToken, String apiKey, boolean isHTTPS, String host) {
163165
this(apiToken, apiKey, isHTTPS, host, null);
@@ -167,9 +169,9 @@ public ConstructorIO(String apiToken, String apiKey, boolean isHTTPS, String hos
167169
* Creates a constructor.io Client.
168170
*
169171
* @param apiToken API Token, gotten from your <a href="https://constructor.io/dashboard">Constructor.io Dashboard</a>, and kept secret.
170-
* @param apiKey API Key, used publically in your in-site javascript client.
172+
* @param apiKey API Key, used publicly in your in-site javascript client.
171173
* @param isHTTPS true to use HTTPS, false to use HTTP. It is highly recommended that you use HTTPS.
172-
* @param host The host of the autocomplete service that you are using. It is recommended that you let this value be null, in which case the host defaults to the Constructor.io autocomplete servic at ac.cnstrc.com.
174+
* @param host The host of the autocomplete service that you are using. It is recommended that you let this value be null, in which case the host defaults to the Constructor.io autocomplete service at ac.cnstrc.com.
173175
* @param port The port to connect to
174176
*/
175177
public ConstructorIO(String apiToken, String apiKey, boolean isHTTPS, String host, int port) {
@@ -1603,7 +1605,7 @@ public String recommendationsAsJSON(RecommendationsRequest req, UserInfo userInf
16031605
/**
16041606
* Makes a URL to issue the requests to. Note that the URL will automagically have the apiKey embedded.
16051607
*
1606-
* @param path endpoint of the autocomplete service.
1608+
* @param paths endpoint of the autocomplete service.
16071609
* @return the created URL. Now you can use it to issue requests and things!
16081610
*/
16091611
protected HttpUrl makeUrl(List<String> paths) throws UnsupportedEncodingException {
@@ -1632,7 +1634,7 @@ protected HttpUrl makeUrl(List<String> paths) throws UnsupportedEncodingExceptio
16321634
/**
16331635
* Makes a URL to issue the requests to. Note that the URL will automagically have the apiKey embedded.
16341636
*
1635-
* @param path endpoint of the autocomplete service.
1637+
* @param paths endpoint of the autocomplete service.
16361638
* @return the created URL. Now you can use it to issue requests and things!
16371639
*/
16381640
protected HttpUrl makeUrl(List<String> paths, UserInfo info) throws UnsupportedEncodingException {
@@ -1751,7 +1753,7 @@ protected String getVersion() {
17511753

17521754
/**
17531755
* Transforms a JSON string to a new JSON string for easy Gson parsing into an autocomplete response.
1754-
* Using JSON objects to acheive this is considerably less error prone than attempting to do it in
1756+
* Using JSON objects to achieve this is considerably less error prone than attempting to do it in
17551757
* a Gson Type Adapter.
17561758
*/
17571759
protected static AutocompleteResponse createAutocompleteResponse(String string) {
@@ -1768,7 +1770,7 @@ protected static AutocompleteResponse createAutocompleteResponse(String string)
17681770

17691771
/**
17701772
* Transforms a JSON string to a new JSON string for easy Gson parsing into an search response.
1771-
* Using JSON objects to acheive this is considerably less error prone than attempting to do it in
1773+
* Using JSON objects to achieve this is considerably less error prone than attempting to do it in
17721774
* a Gson Type Adapter.
17731775
*/
17741776
protected static SearchResponse createSearchResponse(String string) {
@@ -1787,7 +1789,7 @@ protected static SearchResponse createSearchResponse(String string) {
17871789

17881790
/**
17891791
* Transforms a JSON string to a new JSON string for easy Gson parsing into an browse response.
1790-
* Using JSON objects to acheive this is considerably less error prone than attempting to do it in
1792+
* Using JSON objects to achieve this is considerably less error prone than attempting to do it in
17911793
* a Gson Type Adapter.
17921794
*/
17931795
protected static BrowseResponse createBrowseResponse(String string) {
@@ -1823,7 +1825,7 @@ protected static BrowseFacetOptionsResponse createBrowseFacetOptionsResponse(Str
18231825

18241826
/**
18251827
* Transforms a JSON string to a new JSON string for easy Gson parsing into an recommendations response.
1826-
* Using JSON objects to acheive this is considerably less error prone than attempting to do it in
1828+
* Using JSON objects to achieve this is considerably less error prone than attempting to do it in
18271829
* a Gson Type Adapter.
18281830
*/
18291831
protected static RecommendationsResponse createRecommendationsResponse(String string) {
@@ -1837,7 +1839,7 @@ protected static RecommendationsResponse createRecommendationsResponse(String st
18371839

18381840
/**
18391841
* Transforms a JSON string to a new JSON string for easy Gson parsing into an All Tasks response.
1840-
* Using JSON objects to acheive this is considerably less error prone than attempting to do it in
1842+
* Using JSON objects to achieve this is considerably less error prone than attempting to do it in
18411843
* a Gson Type Adapter.
18421844
*/
18431845
protected static AllTasksResponse createAllTasksResponse(String string) {
@@ -1848,7 +1850,7 @@ protected static AllTasksResponse createAllTasksResponse(String string) {
18481850

18491851
/**
18501852
* Transforms a JSON string to a new JSON string for easy Gson parsing into a Task response.
1851-
* Using JSON objects to acheive this is considerably less error prone than attempting to do it in
1853+
* Using JSON objects to achieve this is considerably less error prone than attempting to do it in
18521854
* a Gson Type Adapter.
18531855
*/
18541856
protected static Task createTaskResponse(String string) {
@@ -1857,6 +1859,28 @@ protected static Task createTaskResponse(String string) {
18571859
return new Gson().fromJson(transformed, Task.class);
18581860
}
18591861

1862+
/**
1863+
* Transforms a JSON string to a new JSON string for easy Gson parsing into a Quiz Question response.
1864+
* Using JSON objects to achieve this is considerably less error prone than attempting to do it in
1865+
* a Gson Type Adapter.
1866+
*/
1867+
protected static QuizQuestionResponse createQuizQuestionResponse(String string) {
1868+
JSONObject json = new JSONObject(string);
1869+
String transformed = json.toString();
1870+
return new Gson().fromJson(transformed, QuizQuestionResponse.class);
1871+
}
1872+
1873+
/**
1874+
* Transforms a JSON string to a new JSON string for easy Gson parsing into a Quiz results response.
1875+
* Using JSON objects to achieve this is considerably less error prone than attempting to do it in
1876+
* a Gson Type Adapter.
1877+
*/
1878+
protected static QuizResultsResponse createQuizResultsResponse(String string) {
1879+
JSONObject json = new JSONObject(string);
1880+
String transformed = json.toString();
1881+
return new Gson().fromJson(transformed, QuizResultsResponse.class);
1882+
}
1883+
18601884
/**
18611885
* Transforms a JSON string to a new JSON string for easy Gson parsing into an Items response.
18621886
* Using JSON objects to acheive this is considerably less error prone than attempting to do it in
@@ -1898,7 +1922,7 @@ protected static void moveMetadataOutOfResultData(JSONArray results) {
18981922
JSONObject resultData = result.getJSONObject("data");
18991923
JSONObject metadata = new JSONObject();
19001924

1901-
// Recursive call to move unspecified properties in result variations to it's metadata object
1925+
// Recursive call to move unspecified properties in result variations to its metadata object
19021926
if (!result.isNull("variations")) {
19031927
JSONArray variations = result.getJSONArray("variations");
19041928
moveMetadataOutOfResultData(variations);
@@ -2276,4 +2300,125 @@ public String taskAsJson(TaskRequest req) throws ConstructorException {
22762300
throw new ConstructorException(exception);
22772301
}
22782302
}
2303+
2304+
/**
2305+
* Creates a Quiz OkHttp request
2306+
*
2307+
* @param req the Quiz request
2308+
* @param type the type of quiz request (next/finalize)
2309+
* @return a Task OkHttp request
2310+
* @throws ConstructorException
2311+
*/
2312+
protected Request createQuizRequest(QuizRequest req, String type, UserInfo userInfo) throws ConstructorException {
2313+
try {
2314+
if (!type.equals("next") && !type.equals("finalize"))
2315+
throw new IllegalArgumentException("type must be either 'next' or 'finalize'");
2316+
2317+
List<String> paths = Arrays.asList("v1", "quizzes", req.getId(), type);
2318+
HttpUrl url = this.makeUrl(paths);
2319+
2320+
if (req.getSection() != null) {
2321+
url = url.newBuilder()
2322+
.addQueryParameter("section", req.getSection())
2323+
.build();
2324+
}
2325+
2326+
if (req.getVersionId() != null) {
2327+
url = url.newBuilder()
2328+
.addQueryParameter("version_id", req.getVersionId())
2329+
.build();
2330+
}
2331+
2332+
if (req.getAnswers().size() > 0) {
2333+
for (List<String> questionAnswers : req.getAnswers())
2334+
{
2335+
String answerParam = String.join(",", questionAnswers);
2336+
url = url.newBuilder().addQueryParameter("a", answerParam).build();
2337+
}
2338+
} else {
2339+
if (type.equals("finalize")) {
2340+
throw new IllegalArgumentException("answers is a required parameter for a finalize request");
2341+
}
2342+
}
2343+
2344+
Request request = this.makeUserRequestBuilder(userInfo)
2345+
.url(url)
2346+
.get()
2347+
.build();
2348+
2349+
return request;
2350+
} catch (Exception exception) {
2351+
throw new ConstructorException(exception);
2352+
}
2353+
}
2354+
2355+
/**
2356+
* Queries the quiz service for a quiz question
2357+
*
2358+
* @param req the Quiz request
2359+
* @return a Quiz Question Response
2360+
* @throws ConstructorException if the request is invalid.
2361+
*/
2362+
public QuizQuestionResponse quizNextQuestion(QuizRequest req, UserInfo userInfo) throws ConstructorException {
2363+
try {
2364+
Request request = createQuizRequest(req, "next", userInfo);
2365+
Response response = clientWithRetry.newCall(request).execute();
2366+
String json = getResponseBody(response);
2367+
return createQuizQuestionResponse(json);
2368+
} catch (Exception exception) {
2369+
throw new ConstructorException(exception);
2370+
}
2371+
}
2372+
2373+
/**
2374+
* Queries the quiz service for the a quiz question
2375+
*
2376+
* @param req the Quiz request
2377+
* @return a string of JSON
2378+
* @throws ConstructorException if the request is invalid.
2379+
*/
2380+
public String quizNextQuestionAsJson(QuizRequest req, UserInfo userInfo) throws ConstructorException {
2381+
try {
2382+
Request request = createQuizRequest(req, "next", userInfo);
2383+
Response response = clientWithRetry.newCall(request).execute();
2384+
return getResponseBody(response);
2385+
} catch (Exception exception) {
2386+
throw new ConstructorException(exception);
2387+
}
2388+
}
2389+
2390+
/**
2391+
* Queries the quiz service for the quiz results
2392+
*
2393+
* @param req the Quiz request
2394+
* @return a Quiz Results Response
2395+
* @throws ConstructorException if the request is invalid.
2396+
*/
2397+
public QuizResultsResponse quizResults(QuizRequest req, UserInfo userInfo) throws ConstructorException {
2398+
try {
2399+
Request request = createQuizRequest(req, "finalize", userInfo);
2400+
Response response = clientWithRetry.newCall(request).execute();
2401+
String json = getResponseBody(response);
2402+
return createQuizResultsResponse(json);
2403+
} catch (Exception exception) {
2404+
throw new ConstructorException(exception);
2405+
}
2406+
}
2407+
2408+
/**
2409+
* Queries the quiz service for the quiz results
2410+
*
2411+
* @param req the Quiz request
2412+
* @return a string of JSON
2413+
* @throws ConstructorException if the request is invalid.
2414+
*/
2415+
public String quizResultsAsJson(QuizRequest req, UserInfo userInfo) throws ConstructorException {
2416+
try {
2417+
Request request = createQuizRequest(req, "finalize", userInfo);
2418+
Response response = clientWithRetry.newCall(request).execute();
2419+
return getResponseBody(response);
2420+
} catch (Exception exception) {
2421+
throw new ConstructorException(exception);
2422+
}
2423+
}
22792424
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package io.constructor.client;
2+
3+
import java.util.ArrayList;
4+
import java.util.List;
5+
6+
/**
7+
* Constructor.io Next Quiz and Finalize Quiz request
8+
*/
9+
public class QuizRequest {
10+
private String id;
11+
private String indexKey;
12+
private String section;
13+
private List<List<String>> answers;
14+
private String versionId;
15+
16+
/**
17+
* Creates a Next Quiz/Finalize Quiz request
18+
*
19+
* @param id the id of the quiz to request
20+
*/
21+
public QuizRequest(String id) {
22+
if (id == null)
23+
throw new IllegalArgumentException("id is a required parameter of type String");
24+
25+
this.id = id;
26+
this.section = null;
27+
this.answers = new ArrayList<>();
28+
this.versionId = null;
29+
}
30+
31+
/**
32+
* @param id the id of the quiz to request
33+
*/
34+
public void setId(String id) {
35+
this.id = id;
36+
}
37+
38+
/**
39+
* @return the id of the quiz to request
40+
*/
41+
public String getId() { return id; }
42+
43+
/**
44+
* @param section the section of the product catalog
45+
*/
46+
public void setSection(String section) {
47+
this.section = section;
48+
}
49+
50+
/**
51+
* @return the section of the product catalog
52+
*/
53+
public String getSection() {
54+
return section;
55+
}
56+
57+
/**
58+
* @param answers the list of answers in the format [ [1,2], [3,4] ] where [1,2] are the selected answers
59+
* for the first question and [3,4] are the selected answers for the second question
60+
*/
61+
public void setAnswers(List<List<String>> answers) {
62+
this.answers = answers;
63+
}
64+
65+
/**
66+
* @return the list of answers for the quiz
67+
*/
68+
public List<List<String>> getAnswers() { return answers; }
69+
70+
/**
71+
* @param versionId the specific version id for the quiz
72+
*/
73+
public void setVersionId(String versionId) { this.versionId = versionId;}
74+
75+
/**
76+
* @return the specific version id for the quiz
77+
*/
78+
public String getVersionId() { return versionId; }
79+
}

0 commit comments

Comments
 (0)