Panagiotis Triantafyllou

questionnaire part3

......@@ -72,7 +72,7 @@ public class User implements Parcelable, Serializable {
private String msisdn;
private String profileMetadata;
private Questionnaire questionnaire;
private JSONObject questionnaireAnswers;
private ArrayList<QuestionnaireAnswer> questionnaireAnswers;
private JSONObject userAnswers;
private String userId;
private JSONArray userSegments;
......@@ -128,7 +128,18 @@ public class User implements Parcelable, Serializable {
this.msisdn = optNullableString(json, MSISDN);
this.profileMetadata = optNullableString(json, PROFILE_METADATA);
this.questionnaire = json.isNull(QUESTIONNAIRE) ? null : new Questionnaire(json.optJSONObject(QUESTIONNAIRE));
this.questionnaireAnswers = json.optJSONObject(QUESTIONNAIRE_ANSWERS);
JSONArray answersArr = json.optJSONArray(QUESTIONNAIRE_ANSWERS);
if (answersArr != null) {
this.questionnaireAnswers = new ArrayList<>();
for (int i = 0; i < answersArr.length(); i++) {
JSONObject answerJson = answersArr.optJSONObject(i);
if (answerJson != null) {
this.questionnaireAnswers.add(new QuestionnaireAnswer(answerJson));
}
}
} else {
this.questionnaireAnswers = null;
}
this.userAnswers = json.optJSONObject(USER_ANSWERS);
this.userId = optNullableString(json, USER_ID);
this.userSegments = json.optJSONArray(USER_SEGMENTS);
......@@ -164,7 +175,18 @@ public class User implements Parcelable, Serializable {
}
try {
String questionnaireAnswersStr = source.readString();
this.questionnaireAnswers = questionnaireAnswersStr != null ? new JSONObject(questionnaireAnswersStr) : null;
if (questionnaireAnswersStr != null) {
this.questionnaireAnswers = new ArrayList<>();
JSONArray answersArr = new JSONArray(questionnaireAnswersStr);
for (int i = 0; i < answersArr.length(); i++) {
JSONObject answerJson = answersArr.optJSONObject(i);
if (answerJson != null) {
this.questionnaireAnswers.add(new QuestionnaireAnswer(answerJson));
}
}
} else {
this.questionnaireAnswers = null;
}
} catch (JSONException e) {
this.questionnaireAnswers = null;
}
......@@ -194,7 +216,15 @@ public class User implements Parcelable, Serializable {
dest.writeString(this.consumerMetadata != null ? this.consumerMetadata.toString() : null);
dest.writeString(this.favoriteCouponsets != null ? this.favoriteCouponsets.toString() : null);
dest.writeString(this.questionnaire != null ? this.questionnaire.toString() : null);
dest.writeString(this.questionnaireAnswers != null ? this.questionnaireAnswers.toString() : null);
if (this.questionnaireAnswers != null) {
JSONArray answersArr = new JSONArray();
for (QuestionnaireAnswer qa : this.questionnaireAnswers) {
answersArr.put(qa.toJSONObject());
}
dest.writeString(answersArr.toString());
} else {
dest.writeString(null);
}
dest.writeString(this.userAnswers != null ? this.userAnswers.toString() : null);
dest.writeString(this.userSegments != null ? this.userSegments.toString() : null);
}
......@@ -215,7 +245,15 @@ public class User implements Parcelable, Serializable {
jObj.put(MSISDN, this.msisdn != null ? this.msisdn : JSONObject.NULL);
jObj.put(PROFILE_METADATA, this.profileMetadata != null ? this.profileMetadata : JSONObject.NULL);
jObj.put(QUESTIONNAIRE, this.questionnaire != null ? this.questionnaire.toJSONObject() : JSONObject.NULL);
jObj.put(QUESTIONNAIRE_ANSWERS, this.questionnaireAnswers != null ? this.questionnaireAnswers : JSONObject.NULL);
if (this.questionnaireAnswers != null) {
JSONArray answersArr = new JSONArray();
for (QuestionnaireAnswer qa : this.questionnaireAnswers) {
answersArr.put(qa.toJSONObject());
}
jObj.put(QUESTIONNAIRE_ANSWERS, answersArr);
} else {
jObj.put(QUESTIONNAIRE_ANSWERS, JSONObject.NULL);
}
jObj.put(USER_ANSWERS, this.userAnswers != null ? this.userAnswers : JSONObject.NULL);
jObj.put(USER_ID, this.userId != null ? this.userId : JSONObject.NULL);
jObj.put(USER_SEGMENTS, this.userSegments != null ? this.userSegments : JSONObject.NULL);
......@@ -312,7 +350,7 @@ public class User implements Parcelable, Serializable {
return questionnaire;
}
public JSONObject getQuestionnaireAnswers() {
public ArrayList<QuestionnaireAnswer> getQuestionnaireAnswers() {
return questionnaireAnswers;
}
......@@ -372,7 +410,7 @@ public class User implements Parcelable, Serializable {
this.questionnaire = questionnaire;
}
public void setQuestionnaireAnswers(JSONObject questionnaireAnswers) {
public void setQuestionnaireAnswers(ArrayList<QuestionnaireAnswer> questionnaireAnswers) {
this.questionnaireAnswers = questionnaireAnswers;
}
......@@ -417,6 +455,108 @@ public class User implements Parcelable, Serializable {
return listData;
}
public static class QuestionnaireAnswer implements Parcelable, Serializable {
private int questionId;
private JSONArray answer; // Stored as JSONArray internally for uniformity
private int version;
private boolean isSingleAnswer; // Tracks original format for serialization
public QuestionnaireAnswer() {}
public QuestionnaireAnswer(JSONObject json) {
if (json != null) {
this.questionId = json.optInt("question_id", -1);
this.version = json.optInt("version", 0);
Object rawAnswer = json.opt("answer");
if (rawAnswer instanceof JSONArray) {
this.answer = (JSONArray) rawAnswer;
this.isSingleAnswer = false;
} else {
// Single string answer — wrap into JSONArray for uniformity
this.answer = new JSONArray();
this.answer.put(rawAnswer != null ? rawAnswer.toString() : "");
this.isSingleAnswer = true;
}
}
}
protected QuestionnaireAnswer(Parcel in) {
questionId = in.readInt();
version = in.readInt();
isSingleAnswer = in.readByte() != 0;
try {
String answerStr = in.readString();
answer = answerStr != null ? new JSONArray(answerStr) : null;
} catch (JSONException e) {
answer = null;
}
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(questionId);
dest.writeInt(version);
dest.writeByte((byte) (isSingleAnswer ? 1 : 0));
dest.writeString(answer != null ? answer.toString() : null);
}
@Override
public int describeContents() {
return 0;
}
public static final Creator<QuestionnaireAnswer> CREATOR = new Creator<QuestionnaireAnswer>() {
@Override
public QuestionnaireAnswer createFromParcel(Parcel in) {
return new QuestionnaireAnswer(in);
}
@Override
public QuestionnaireAnswer[] newArray(int size) {
return new QuestionnaireAnswer[size];
}
};
public JSONObject toJSONObject() {
JSONObject jObj = new JSONObject();
try {
jObj.put("question_id", this.questionId);
jObj.put("version", this.version);
// Serialize back to original format
if (this.isSingleAnswer && this.answer != null && this.answer.length() > 0) {
jObj.put("answer", this.answer.optString(0));
} else {
jObj.put("answer", this.answer != null ? this.answer : JSONObject.NULL);
}
} catch (JSONException e) {
if (WarpConstants.DEBUG) e.printStackTrace();
}
return jObj;
}
public int getQuestionId() { return questionId; }
public void setQuestionId(int questionId) { this.questionId = questionId; }
public JSONArray getAnswer() { return answer; }
public void setAnswer(JSONArray answer) { this.answer = answer; }
public boolean isSingleAnswer() { return isSingleAnswer; }
public void setSingleAnswer(boolean singleAnswer) { isSingleAnswer = singleAnswer; }
public int getVersion() { return version; }
public void setVersion(int version) { this.version = version; }
/**
* Convenience method to get the answer as a list of strings.
*/
public ArrayList<String> getAnswerList() {
ArrayList<String> list = new ArrayList<>();
if (answer != null) {
for (int i = 0; i < answer.length(); i++) {
list.add(answer.optString(i));
}
}
return list;
}
}
public static class Questionnaire implements Parcelable, Serializable {
private String questionnaireId;
private ArrayList<Question> questions;
......
......@@ -204,6 +204,18 @@ public interface ApiService {
@Header(WarpConstants.HEADER_SIGNATURE) String signature,
@Header(WarpConstants.HEADER_AUTHORIZATION) String bearer);
@Headers("Content-Type: application/json")
@POST("/oauth/{appUuid}/context")
Call<ResponseBody> saveQuestionnaire(@Path("appUuid") String appUuid,
@Body RequestBody request,
@Header(WarpConstants.HEADER_DATE) String timeStamp,
@Header(WarpConstants.HEADER_LOYALTY_BUNDLE_ID) String bundleId,
@Header(WarpConstants.HEADER_UNIQUE_DEVICE_ID) String deviceId,
@Header(WarpConstants.HEADER_CHANNEL) String channel,
@Header(WarpConstants.HEADER_WEB_ID) String webId,
@Header(WarpConstants.HEADER_SIGNATURE) String signature,
@Header(WarpConstants.HEADER_AUTHORIZATION) String bearer);
// ===========================================================
// Getter & Setter
// ===========================================================
......
......@@ -1549,4 +1549,112 @@ public class WarplyManager {
});
return future;
}
public static void saveQuestionnaire(ArrayList<User.QuestionnaireAnswer> answers, String questionnaireId, final CallbackReceiver<JSONObject> receiver) {
WarpUtils.log("************* WARPLY Questionnaire Request ********************");
WarpUtils.log("[WARP Trace] WARPLY Questionnaire Request is active");
WarpUtils.log("**************************************************");
ApiService service = ApiClient.getRetrofitInstance().create(ApiService.class);
ListeningExecutorService executorService = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(1));
ListenableFuture<JSONObject> futureFilters = saveQuestionnaireRetro(answers, questionnaireId, service);
ListenableFuture<List<Object>> allResultsFuture = Futures.allAsList(futureFilters);
ListenableFuture<JSONObject> mergedResultFuture = Futures.transformAsync(allResultsFuture, results -> {
JSONObject resultFilters = (JSONObject) results.get(0);
return executorService.submit(() -> resultFilters);
}, executorService);
Futures.addCallback(mergedResultFuture, new FutureCallback<JSONObject>() {
@Override
public void onSuccess(JSONObject mergedResult) {
executorService.shutdownNow();
new Handler(Looper.getMainLooper()).post(() -> receiver.onSuccess(mergedResult));
}
@Override
public void onFailure(Throwable throwable) {
executorService.shutdownNow();
new Handler(Looper.getMainLooper()).post(() -> receiver.onFailure(2));
}
}, executorService);
}
private static ListenableFuture<JSONObject> saveQuestionnaireRetro(ArrayList<User.QuestionnaireAnswer> answers, String questionnaireId, ApiService service) {
SettableFuture<JSONObject> future = SettableFuture.create();
String timeStamp = DateFormat.format("yyyy-MM-dd hh:mm:ss", System.currentTimeMillis()).toString();
String apiKey = WarpUtils.getApiKey(Warply.getWarplyContext());
String webId = WarpUtils.getWebId(Warply.getWarplyContext());
// Serialize answers list to JSONArray using toJSONObject() on each element
JSONArray answersJsonArray = new JSONArray();
for (User.QuestionnaireAnswer answer : answers) {
answersJsonArray.put(answer.toJSONObject());
}
Map<String, Object> jsonParamsDetails = new ArrayMap<>();
Map<String, Object> jsonParams = new ArrayMap<>();
jsonParams.put("action", "handle_user_details");
jsonParams.put("process", "questionnaire");
jsonParams.put("del_empty", false);
Map<String, Object> jsonParamsQuestionnaireAnswers = new ArrayMap<>();
jsonParamsQuestionnaireAnswers.put("questionnaire_answers", answersJsonArray);
jsonParamsQuestionnaireAnswers.put("questionnaire_id", questionnaireId);
jsonParamsQuestionnaireAnswers.put("first_write", false);
jsonParams.put("data", jsonParamsQuestionnaireAnswers);
jsonParamsDetails.put("consumer_data", jsonParams);
RequestBody detailsRequest = RequestBody.create(MediaType.get("application/json; charset=utf-8"), (new JSONObject(jsonParamsDetails)).toString());
Call<ResponseBody> detailsCall = service.saveQuestionnaire(
WarplyProperty.getAppUuid(Warply.getWarplyContext()),
detailsRequest,
timeStamp,
"android:" + Warply.getWarplyContext().getPackageName(),
new WarplyDeviceInfoCollector(Warply.getWarplyContext()).getUniqueDeviceId(),
"mobile",
webId,
WarpUtils.produceSignature(apiKey + timeStamp),
"Bearer " + WarplyDBHelper.getInstance(Warply.getWarplyContext()).getAuthValue("access_token")
);
detailsCall.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(@NonNull Call<ResponseBody> call, @NonNull Response<ResponseBody> response) {
if (response.code() == 200 && response.body() != null) {
JSONObject jobjDetailsResponse = null;
try {
jobjDetailsResponse = new JSONObject(response.body().string());
} catch (Exception e) {
e.printStackTrace();
}
if (jobjDetailsResponse != null && jobjDetailsResponse.has("status") && jobjDetailsResponse.optString("status", "2").equals("1")) {
JSONObject newResult = new JSONObject();
try {
newResult.putOpt("status", 1);
newResult.putOpt("message", "Success");
future.set(newResult);
} catch (JSONException e) {
e.printStackTrace();
future.set(new JSONObject());
}
} else {
future.set(new JSONObject());
}
} else if (String.valueOf(response.code()).startsWith("5")) {
future.set(new JSONObject());
} else {
// future.set(new CouponsetsList());
future.setException(new Throwable());
}
}
@Override
public void onFailure(@NonNull Call<ResponseBody> call, @NonNull Throwable t) {
// future.set(new CouponsetsList());
future.setException(new Throwable());
}
});
return future;
}
}
......