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

Reply via email to