Commit cfe6ddec authored by Yusuke Iwaki's avatar Yusuke Iwaki

fix DDP result handling (JSONObject/JSONArray)

parent 35a2c42c
...@@ -68,7 +68,7 @@ dependencies { ...@@ -68,7 +68,7 @@ dependencies {
compile 'com.facebook.stetho:stetho-okhttp3:1.4.1' compile 'com.facebook.stetho:stetho-okhttp3:1.4.1'
compile 'com.uphyca:stetho_realm:2.0.0' compile 'com.uphyca:stetho_realm:2.0.0'
compile 'chat.rocket:android-ddp:0.0.7' compile 'chat.rocket:android-ddp:0.0.8'
compile 'com.jakewharton.timber:timber:4.3.1' compile 'com.jakewharton.timber:timber:4.3.1'
compile 'com.jakewharton.rxbinding:rxbinding:0.4.0' compile 'com.jakewharton.rxbinding:rxbinding:0.4.0'
......
...@@ -34,7 +34,7 @@ public class MethodCallHelper { ...@@ -34,7 +34,7 @@ public class MethodCallHelper {
this.api = api; this.api = api;
} }
private Task<JSONObject> executeMethodCall(String methodName, String param, long timeout) { private Task<String> executeMethodCall(String methodName, String param, long timeout) {
if (api != null) { if (api != null) {
return api.rpc(UUID.randomUUID().toString(), methodName, param, timeout) return api.rpc(UUID.randomUUID().toString(), methodName, param, timeout)
.onSuccessTask(task -> Task.forResult(task.getResult().result)); .onSuccessTask(task -> Task.forResult(task.getResult().result));
...@@ -43,7 +43,7 @@ public class MethodCallHelper { ...@@ -43,7 +43,7 @@ public class MethodCallHelper {
} }
} }
private Task<JSONObject> injectErrorHandler(Task<JSONObject> task) { private Task<String> injectErrorHandler(Task<String> task) {
return task.continueWithTask(_task -> { return task.continueWithTask(_task -> {
if (_task.isFaulted()) { if (_task.isFaulted()) {
Exception exception = _task.getError(); Exception exception = _task.getError();
...@@ -62,40 +62,39 @@ public class MethodCallHelper { ...@@ -62,40 +62,39 @@ public class MethodCallHelper {
} }
private interface ParamBuilder { private interface ParamBuilder {
void buildParam(JSONArray params) throws JSONException; JSONArray buildParam() throws JSONException;
} }
private <T> Task<T> call(String methodName, long timeout, private Task<String> call(String methodName, long timeout) {
Continuation<JSONObject, Task<T>> onSuccess) { return injectErrorHandler(executeMethodCall(methodName, null, timeout));
return injectErrorHandler(executeMethodCall(methodName, null, timeout))
.onSuccessTask(onSuccess);
} }
private <T> Task<T> call(String methodName, long timeout, ParamBuilder paramBuilder, private Task<String> call(String methodName, long timeout, ParamBuilder paramBuilder) {
Continuation<JSONObject, Task<T>> onSuccess) {
JSONArray params = new JSONArray();
try { try {
paramBuilder.buildParam(params); final JSONArray params = paramBuilder.buildParam();
return injectErrorHandler(executeMethodCall(methodName,
params != null ? params.toString() : null, timeout));
} catch (JSONException exception) { } catch (JSONException exception) {
return Task.forError(exception); return Task.forError(exception);
} }
return injectErrorHandler(executeMethodCall(methodName, params.toString(), timeout))
.onSuccessTask(onSuccess);
} }
private static final Continuation<String, Task<JSONObject>> CONVERT_TO_JSON_OBJECT =
task -> Task.forResult(new JSONObject(task.getResult()));
private static final Continuation<String, Task<JSONArray>> CONVERT_TO_JSON_ARRAY =
task -> Task.forResult(new JSONArray(task.getResult()));
/** /**
* Register User. * Register User.
*/ */
public Task<Void> registerUser(final String name, final String email, public Task<String> registerUser(final String name, final String email,
final String password, final String confirmPassword) { final String password, final String confirmPassword) {
return call("registerUser", TIMEOUT_MS, params -> params.put(new JSONObject() return call("registerUser", TIMEOUT_MS, () -> new JSONArray().put(new JSONObject()
.put("name", name) .put("name", name)
.put("email", email) .put("email", email)
.put("pass", password) .put("pass", password)
.put("confirm-pass", confirmPassword)), .put("confirm-pass", confirmPassword))); // nothing to do.
task -> Task.forResult(null)); // nothing to do.
} }
private Task<Void> saveToken(Task<String> task) { private Task<Void> saveToken(Task<String> task) {
...@@ -110,7 +109,7 @@ public class MethodCallHelper { ...@@ -110,7 +109,7 @@ public class MethodCallHelper {
* Login with username/email and password. * Login with username/email and password.
*/ */
public Task<Void> loginWithEmail(final String usernameOrEmail, final String password) { public Task<Void> loginWithEmail(final String usernameOrEmail, final String password) {
return call("login", TIMEOUT_MS, params -> { return call("login", TIMEOUT_MS, () -> {
JSONObject param = new JSONObject(); JSONObject param = new JSONObject();
if (Patterns.EMAIL_ADDRESS.matcher(usernameOrEmail).matches()) { if (Patterns.EMAIL_ADDRESS.matcher(usernameOrEmail).matches()) {
param.put("user", new JSONObject().put("email", usernameOrEmail)); param.put("user", new JSONObject().put("email", usernameOrEmail));
...@@ -120,8 +119,10 @@ public class MethodCallHelper { ...@@ -120,8 +119,10 @@ public class MethodCallHelper {
param.put("password", new JSONObject() param.put("password", new JSONObject()
.put("digest", CheckSum.sha256(password)) .put("digest", CheckSum.sha256(password))
.put("algorithm", "sha-256")); .put("algorithm", "sha-256"));
params.put(param); return new JSONArray().put(param);
}, task -> Task.forResult(task.getResult().getString("token"))).onSuccessTask(this::saveToken); }).onSuccessTask(CONVERT_TO_JSON_OBJECT)
.onSuccessTask(task -> Task.forResult(task.getResult().getString("token")))
.onSuccessTask(this::saveToken);
} }
/** /**
...@@ -129,92 +130,50 @@ public class MethodCallHelper { ...@@ -129,92 +130,50 @@ public class MethodCallHelper {
*/ */
public Task<Void> loginWithGitHub(final String credentialToken, public Task<Void> loginWithGitHub(final String credentialToken,
final String credentialSecret) { final String credentialSecret) {
return call("login", TIMEOUT_MS, params -> params.put(new JSONObject() return call("login", TIMEOUT_MS, () -> new JSONArray().put(new JSONObject()
.put("oauth", new JSONObject() .put("oauth", new JSONObject()
.put("credentialToken", credentialToken) .put("credentialToken", credentialToken)
.put("credentialSecret", credentialSecret)) .put("credentialSecret", credentialSecret))
), task -> Task.forResult(task.getResult().getString("token"))).onSuccessTask(this::saveToken); )).onSuccessTask(CONVERT_TO_JSON_OBJECT)
.onSuccessTask(task -> Task.forResult(task.getResult().getString("token")))
.onSuccessTask(this::saveToken);
} }
/** /**
* Login with token. * Login with token.
*/ */
public Task<Void> loginWithToken(final String token) { public Task<Void> loginWithToken(final String token) {
return call("login", TIMEOUT_MS, params -> params.put(new JSONObject().put("resume", token)), return call("login", TIMEOUT_MS, () -> new JSONArray().put(new JSONObject()
task -> Task.forResult(task.getResult().getString("token"))).onSuccessTask(this::saveToken); .put("resume", token)
)).onSuccessTask(CONVERT_TO_JSON_OBJECT)
.onSuccessTask(task -> Task.forResult(task.getResult().getString("token")))
.onSuccessTask(this::saveToken);
} }
/** /**
* Logout. * Logout.
*/ */
public Task<Void> logout() { public Task<String> logout() {
return call("logout", TIMEOUT_MS, task -> Task.forResult(null)); return call("logout", TIMEOUT_MS);
} }
/** /**
* request "subscriptions/get" and "rooms/get". * request "subscriptions/get".
*/ */
public Task<Void> getRooms() { public Task<Void> getRooms() {
return getRoomSubscriptionRecursive(0) return call("subscriptions/get", TIMEOUT_MS).onSuccessTask(CONVERT_TO_JSON_ARRAY)
.onSuccessTask(task -> getRoomRecursive(0)) .onSuccessTask(task -> {
.onSuccessTask(task -> Task.forResult(null)); final JSONArray result = task.getResult();
}
private Task<Long> getRoomSubscriptionRecursive(long timestamp) {
return getObjectRecursive("subscriptions", updatedRooms -> {
for (int i = 0; i < updatedRooms.length(); i++) {
updatedRooms.getJSONObject(i).put("serverConfigId", serverConfigId);
}
}, timestamp);
}
private Task<Long> getRoomRecursive(long timestamp) {
return getObjectRecursive("rooms", updatedRooms -> {
for (int i = 0; i < updatedRooms.length(); i++) {
JSONObject roomJson = updatedRooms.getJSONObject(i);
String rid = roomJson.getString("_id");
roomJson.put("rid", rid)
.put("serverConfigId", serverConfigId)
.remove("_id");
}
}, timestamp);
}
private interface Customizer {
void customizeResult(JSONArray updatedRooms) throws JSONException;
}
private Task<Long> getObjectRecursive(String objName, Customizer customizer, long timestamp) {
return call(objName + "/get", TIMEOUT_MS,
params -> params.put(new JSONObject().put("$date", timestamp)),
task -> {
JSONObject result = task.getResult();
long nextTimestamp = 0;
try {
nextTimestamp = result.getJSONArray("remove")
.getJSONObject(0).getJSONObject("_deletedAt").getLong("$date");
} catch (JSONException exception) {
// keep nextTimestamp = 0
}
try { try {
JSONArray updatedRooms = result.getJSONArray("update"); for (int i = 0; i < result.length(); i++) {
customizer.customizeResult(updatedRooms); result.getJSONObject(i).put("serverConfigId", serverConfigId);
}
Task<Void> saveToDB = RealmHelperBolts.executeTransaction(realm -> { return RealmHelperBolts.executeTransaction(realm -> {
realm.createOrUpdateAllFromJson( realm.createOrUpdateAllFromJson(
RoomSubscription.class, result.getJSONArray("update")); RoomSubscription.class, result);
return null; return null;
}); });
if (nextTimestamp > 0 && (timestamp == 0 || nextTimestamp < timestamp)) {
final long _next = nextTimestamp;
return saveToDB.onSuccessTask(_task ->
getObjectRecursive(objName, customizer, _next));
} else {
return saveToDB.onSuccessTask(_task -> Task.forResult(0L));
}
} catch (JSONException exception) { } catch (JSONException exception) {
return Task.forError(exception); return Task.forError(exception);
} }
...@@ -226,12 +185,13 @@ public class MethodCallHelper { ...@@ -226,12 +185,13 @@ public class MethodCallHelper {
*/ */
public Task<Void> loadHistory(final String roomId, final long timestamp, public Task<Void> loadHistory(final String roomId, final long timestamp,
final int count, final long lastSeen) { final int count, final long lastSeen) {
return call("loadHistory", TIMEOUT_MS, params -> params return call("loadHistory", TIMEOUT_MS, () -> new JSONArray()
.put(roomId) .put(roomId)
.put(timestamp > 0 ? new JSONObject().put("$date", timestamp) : JSONObject.NULL) .put(timestamp > 0 ? new JSONObject().put("$date", timestamp) : JSONObject.NULL)
.put(count) .put(count)
.put(lastSeen > 0 ? new JSONObject().put("$date", lastSeen) : JSONObject.NULL), .put(lastSeen > 0 ? new JSONObject().put("$date", lastSeen) : JSONObject.NULL)
task -> { ).onSuccessTask(CONVERT_TO_JSON_OBJECT)
.onSuccessTask(task -> {
JSONObject result = task.getResult(); JSONObject result = task.getResult();
final JSONArray messages = result.getJSONArray("messages"); final JSONArray messages = result.getJSONArray("messages");
for (int i = 0; i < messages.length(); i++) { for (int i = 0; i < messages.length(); i++) {
......
...@@ -11,7 +11,6 @@ import io.realm.annotations.PrimaryKey; ...@@ -11,7 +11,6 @@ import io.realm.annotations.PrimaryKey;
import java.util.UUID; import java.util.UUID;
import jp.co.crowdworks.realm_java_helpers.RealmObjectObserver; import jp.co.crowdworks.realm_java_helpers.RealmObjectObserver;
import jp.co.crowdworks.realm_java_helpers_bolts.RealmHelperBolts; import jp.co.crowdworks.realm_java_helpers_bolts.RealmHelperBolts;
import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
public class MethodCall extends RealmObject { public class MethodCall extends RealmObject {
...@@ -99,10 +98,10 @@ public class MethodCall extends RealmObject { ...@@ -99,10 +98,10 @@ public class MethodCall extends RealmObject {
/** /**
* insert a new record to request a method call. * insert a new record to request a method call.
*/ */
public static Task<JSONObject> execute(String serverConfigId, String name, String paramsJson, public static Task<String> execute(String serverConfigId, String name, String paramsJson,
long timeout) { long timeout) {
final String newId = UUID.randomUUID().toString(); final String newId = UUID.randomUUID().toString();
TaskCompletionSource<JSONObject> task = new TaskCompletionSource<>(); TaskCompletionSource<String> task = new TaskCompletionSource<>();
RealmHelperBolts.executeTransaction(realm -> { RealmHelperBolts.executeTransaction(realm -> {
MethodCall call = realm.createObjectFromJson(MethodCall.class, new JSONObject() MethodCall call = realm.createObjectFromJson(MethodCall.class, new JSONObject()
.put("methodCallId", newId) .put("methodCallId", newId)
...@@ -124,12 +123,11 @@ public class MethodCall extends RealmObject { ...@@ -124,12 +123,11 @@ public class MethodCall extends RealmObject {
@Override protected void onChange(MethodCall methodCall) { @Override protected void onChange(MethodCall methodCall) {
int syncstate = methodCall.getSyncstate(); int syncstate = methodCall.getSyncstate();
if (syncstate == SyncState.SYNCED) { if (syncstate == SyncState.SYNCED) {
try { String resultJson = methodCall.getResultJson();
String resultJson = methodCall.getResultJson(); if (TextUtils.isEmpty(resultJson)) {
task.setResult(TextUtils.isEmpty(resultJson) ? null : new JSONObject(resultJson)); task.setResult(null);
} catch (JSONException exception) {
task.setError(new Error(exception));
} }
task.setResult(resultJson);
exit(methodCall.getMethodCallId()); exit(methodCall.getMethodCallId());
} else if (syncstate == SyncState.FAILED) { } else if (syncstate == SyncState.FAILED) {
task.setError(new Error(methodCall.getResultJson())); task.setError(new Error(methodCall.getResultJson()));
......
...@@ -69,11 +69,11 @@ public class MethodCallObserver extends AbstractModelObserver<MethodCall> { ...@@ -69,11 +69,11 @@ public class MethodCallObserver extends AbstractModelObserver<MethodCall> {
).onSuccessTask(task -> ).onSuccessTask(task ->
webSocketAPI.rpc(methodCallId, methodName, params, timeout) webSocketAPI.rpc(methodCallId, methodName, params, timeout)
.onSuccessTask(_task -> RealmHelperBolts.executeTransaction(realm -> { .onSuccessTask(_task -> RealmHelperBolts.executeTransaction(realm -> {
JSONObject result = _task.getResult().result; String json = _task.getResult().result;
return realm.createOrUpdateObjectFromJson(MethodCall.class, new JSONObject() return realm.createOrUpdateObjectFromJson(MethodCall.class, new JSONObject()
.put("methodCallId", methodCallId) .put("methodCallId", methodCallId)
.put("syncstate", SyncState.SYNCED) .put("syncstate", SyncState.SYNCED)
.put("resultJson", result == null ? null : result.toString())); .put("resultJson", json));
}) })
) )
).continueWithTask(task -> { ).continueWithTask(task -> {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment