jenkins-bot has submitted this change and it was merged.
Change subject: Add user option data client
......................................................................
Add user option data client
No functional changes intended at this time. This code is exercised by a
subsequent patch.
Change-Id: I7a3f3663dcd9c383d84bf2ca16eafb8a1469e491
---
A app/src/main/java/org/wikipedia/dataclient/mwapi/MwQueryResponse.java
M app/src/main/java/org/wikipedia/editing/EditTokenStorage.java
A app/src/main/java/org/wikipedia/useroption/UserOption.java
A
app/src/main/java/org/wikipedia/useroption/dataclient/DefaultUserOptionDataClient.java
A app/src/main/java/org/wikipedia/useroption/dataclient/UserInfo.java
A
app/src/main/java/org/wikipedia/useroption/dataclient/UserOptionDataClient.java
A
app/src/main/java/org/wikipedia/useroption/dataclient/UserOptionDataClientSingleton.java
7 files changed, 273 insertions(+), 3 deletions(-)
Approvals:
BearND: Looks good to me, approved
jenkins-bot: Verified
diff --git
a/app/src/main/java/org/wikipedia/dataclient/mwapi/MwQueryResponse.java
b/app/src/main/java/org/wikipedia/dataclient/mwapi/MwQueryResponse.java
new file mode 100644
index 0000000..1982a82
--- /dev/null
+++ b/app/src/main/java/org/wikipedia/dataclient/mwapi/MwQueryResponse.java
@@ -0,0 +1,17 @@
+package org.wikipedia.dataclient.mwapi;
+
+import com.google.gson.annotations.SerializedName;
+
+public class MwQueryResponse<T> {
+ @SerializedName("batchcomplete")
+ private boolean batchComplete;
+ private T query;
+
+ public boolean batchComplete() {
+ return batchComplete;
+ }
+
+ public T query() {
+ return query;
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/wikipedia/editing/EditTokenStorage.java
b/app/src/main/java/org/wikipedia/editing/EditTokenStorage.java
index faac4cc..25ed992 100644
--- a/app/src/main/java/org/wikipedia/editing/EditTokenStorage.java
+++ b/app/src/main/java/org/wikipedia/editing/EditTokenStorage.java
@@ -2,6 +2,8 @@
import android.content.Context;
import android.os.Looper;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
import org.wikipedia.Site;
import org.wikipedia.settings.Prefs;
@@ -30,11 +32,19 @@
}
}
- public void get(final Site site, final TokenRetrievedCallback callback) {
+ @Nullable public String token(@NonNull Site site) {
+ return tokenJar.get(site.getDomain());
+ }
+
+ public void token(@NonNull Site site, String token) {
+ updatePrefs(site.getDomain(), token);
+ }
+
+ public void get(@NonNull final Site site, final TokenRetrievedCallback
callback) {
// This might run an AsyncTask, and hence must be called from main
thread
ensureMainThread();
- String curToken = tokenJar.get(site.getDomain());
+ String curToken = token(site);
if (curToken != null) {
callback.onTokenRetrieved(curToken);
return;
@@ -43,7 +53,7 @@
new FetchEditTokenTask(context, site) {
@Override
public void onFinish(String result) {
- updatePrefs(site.getDomain(), result);
+ token(site, result);
callback.onTokenRetrieved(result);
}
diff --git a/app/src/main/java/org/wikipedia/useroption/UserOption.java
b/app/src/main/java/org/wikipedia/useroption/UserOption.java
new file mode 100644
index 0000000..91434ff
--- /dev/null
+++ b/app/src/main/java/org/wikipedia/useroption/UserOption.java
@@ -0,0 +1,30 @@
+package org.wikipedia.useroption;
+
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+
+public class UserOption {
+ @NonNull private final String key;
+ @Nullable private final String val;
+
+ public UserOption(@NonNull String key) {
+ this(key, null);
+ }
+
+ public UserOption(@NonNull UserOption option) {
+ this(option.key(), option.val());
+ }
+
+ public UserOption(@NonNull String key, @Nullable String val) {
+ this.key = key;
+ this.val = val;
+ }
+
+ @NonNull public String key() {
+ return key;
+ }
+
+ @Nullable public String val() {
+ return val;
+ }
+}
\ No newline at end of file
diff --git
a/app/src/main/java/org/wikipedia/useroption/dataclient/DefaultUserOptionDataClient.java
b/app/src/main/java/org/wikipedia/useroption/dataclient/DefaultUserOptionDataClient.java
new file mode 100644
index 0000000..b575b7e
--- /dev/null
+++
b/app/src/main/java/org/wikipedia/useroption/dataclient/DefaultUserOptionDataClient.java
@@ -0,0 +1,132 @@
+package org.wikipedia.useroption.dataclient;
+
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+
+import com.google.gson.annotations.SerializedName;
+
+import org.wikipedia.Site;
+import org.wikipedia.WikipediaApp;
+import org.wikipedia.dataclient.RestAdapterFactory;
+import org.wikipedia.dataclient.mwapi.MwQueryResponse;
+import org.wikipedia.editing.FetchEditTokenTask;
+import org.wikipedia.useroption.UserOption;
+
+import java.util.concurrent.Executor;
+
+import retrofit.RetrofitError;
+import retrofit.http.Field;
+import retrofit.http.FormUrlEncoded;
+import retrofit.http.GET;
+import retrofit.http.POST;
+import retrofit.http.Query;
+
+public class DefaultUserOptionDataClient implements UserOptionDataClient {
+ @NonNull private final Site site;
+ @NonNull private final Client client;
+
+ public DefaultUserOptionDataClient(@NonNull Site site) {
+ this.site = site;
+ client = RestAdapterFactory.newInstance(site).create(Client.class);
+ }
+
+ @NonNull
+ @Override
+ public UserInfo get() {
+ return client.get().query().userInfo();
+ }
+
+ @Override
+ public void post(@NonNull UserOption option) {
+ client.post(getToken(), option.key(), option.val()).check();
+ }
+
+ @Override
+ public void delete(@NonNull UserOption option) {
+ client.delete(getToken(), option.key()).check();
+ }
+
+ @NonNull private String getToken() {
+ if (app().getEditTokenStorage().token(site) == null) {
+ requestToken();
+ }
+
+ String token = app().getEditTokenStorage().token(site);
+ if (token == null) {
+ throw RetrofitError.unexpectedError(site.getDomain(), new
RuntimeException("No token"));
+ }
+ return token;
+ }
+
+ private void requestToken() {
+ new FetchEditTokenTask(app(), site) {
+ @Override
+ public void onFinish(String result) {
+ app().getEditTokenStorage().token(site, result);
+ }
+
+ @Override
+ public void execute() {
+ super.executeOnExecutor(new SynchronousExecutor());
+ }
+ }.execute();
+ }
+
+ private WikipediaApp app() {
+ return WikipediaApp.getInstance();
+ }
+
+ private static class SynchronousExecutor implements Executor {
+ @Override
+ public void execute(@NonNull Runnable runnable) {
+ runnable.run();
+ }
+ }
+
+ private interface Client {
+ String ACTION = "/w/api.php?format=json&formatversion=2&action=";
+
+ @GET(ACTION + "query&meta=userinfo&uiprop=options")
+ @NonNull MwQueryResponse<QueryUserInfo> get();
+
+ @FormUrlEncoded
+ @POST(ACTION + "options")
+ @NonNull PostResponse post(@Field("token") @NonNull String token,
+ @Query("optionname") @NonNull String key,
+ @Query("optionvalue") @Nullable String
value);
+
+ @FormUrlEncoded
+ @POST(ACTION + "options")
+ @NonNull PostResponse delete(@Field("token") @NonNull String token,
+ @Query("change") @NonNull String key);
+ }
+
+ private static class PostResponse {
+ private String options;
+
+ public boolean success() {
+ return "success".equals(options);
+ }
+
+ public String result() {
+ return options;
+ }
+
+ public void check() {
+ if (!success()) {
+ // TODO: pass actual URL (here and elsewhere). This class is
populated by Retrofit and
+ // doesn't seem to be able to hold references to the
outter class' instance members.
+ throw RetrofitError.unexpectedError("", new
RuntimeException("Bad response=" + result()));
+ }
+ }
+ }
+
+ private static class QueryUserInfo {
+ @SerializedName("userinfo")
+ private UserInfo userInfo;
+
+ public UserInfo userInfo() {
+ return userInfo;
+ }
+ }
+}
diff --git
a/app/src/main/java/org/wikipedia/useroption/dataclient/UserInfo.java
b/app/src/main/java/org/wikipedia/useroption/dataclient/UserInfo.java
new file mode 100644
index 0000000..9e01b25
--- /dev/null
+++ b/app/src/main/java/org/wikipedia/useroption/dataclient/UserInfo.java
@@ -0,0 +1,50 @@
+package org.wikipedia.useroption.dataclient;
+
+import android.support.annotation.NonNull;
+
+import com.google.gson.annotations.SerializedName;
+
+import org.wikipedia.useroption.UserOption;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Map;
+
+public class UserInfo {
+ @SerializedName("name")
+ private String username;
+ private int id;
+
+ // Object type is any JSON type.
+ @NonNull private Map<String, ?> options;
+
+ public int id() {
+ return id;
+ }
+
+ @NonNull
+ public String username() {
+ return username;
+ }
+
+ @NonNull
+ public Collection<UserOption> userjsOptions() {
+ Collection<UserOption> ret = new ArrayList<>();
+ for (Map.Entry<String, ?> entry : options.entrySet()) {
+ if (entry.getKey().startsWith("userjs-")) {
+ ret.add(new UserOption(entry.getKey(), (String)
entry.getValue()));
+ }
+ }
+ return ret;
+ }
+
+ // Auto-generated
+ @Override
+ public String toString() {
+ return "UserInfo{"
+ + "username='" + username + '\''
+ + ", id=" + id
+ + ", options=" + options
+ + '}';
+ }
+}
\ No newline at end of file
diff --git
a/app/src/main/java/org/wikipedia/useroption/dataclient/UserOptionDataClient.java
b/app/src/main/java/org/wikipedia/useroption/dataclient/UserOptionDataClient.java
new file mode 100644
index 0000000..6e8d13d
--- /dev/null
+++
b/app/src/main/java/org/wikipedia/useroption/dataclient/UserOptionDataClient.java
@@ -0,0 +1,11 @@
+package org.wikipedia.useroption.dataclient;
+
+import android.support.annotation.NonNull;
+
+import org.wikipedia.useroption.UserOption;
+
+public interface UserOptionDataClient {
+ @NonNull UserInfo get();
+ void post(@NonNull UserOption option);
+ void delete(@NonNull UserOption option);
+}
\ No newline at end of file
diff --git
a/app/src/main/java/org/wikipedia/useroption/dataclient/UserOptionDataClientSingleton.java
b/app/src/main/java/org/wikipedia/useroption/dataclient/UserOptionDataClientSingleton.java
new file mode 100644
index 0000000..abd76f8
--- /dev/null
+++
b/app/src/main/java/org/wikipedia/useroption/dataclient/UserOptionDataClientSingleton.java
@@ -0,0 +1,20 @@
+package org.wikipedia.useroption.dataclient;
+
+import org.wikipedia.Site;
+
+public final class UserOptionDataClientSingleton {
+ public static UserOptionDataClient instance() {
+ return LazyHolder.INSTANCE;
+ }
+
+ private UserOptionDataClientSingleton() { }
+
+ private static class LazyHolder {
+ private static final UserOptionDataClient INSTANCE = instance();
+
+ private static UserOptionDataClient instance() {
+ Site site = new Site("meta.wikimedia.org");
+ return new DefaultUserOptionDataClient(site);
+ }
+ }
+}
\ No newline at end of file
--
To view, visit https://gerrit.wikimedia.org/r/270246
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I7a3f3663dcd9c383d84bf2ca16eafb8a1469e491
Gerrit-PatchSet: 6
Gerrit-Project: apps/android/wikipedia
Gerrit-Branch: master
Gerrit-Owner: Niedzielski <[email protected]>
Gerrit-Reviewer: BearND <[email protected]>
Gerrit-Reviewer: Brion VIBBER <[email protected]>
Gerrit-Reviewer: Dbrant <[email protected]>
Gerrit-Reviewer: Mholloway <[email protected]>
Gerrit-Reviewer: Niedzielski <[email protected]>
Gerrit-Reviewer: jenkins-bot <>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits