Yuvipanda has uploaded a new change for review.
https://gerrit.wikimedia.org/r/93015
Change subject: Add code to fetch and parse a Page
......................................................................
Add code to fetch and parse a Page
Tests connect to english wikipedia directly, can be considered to
be slightly flaky.
Dependent on Iafdcc85d8c8ac030873bfe4e7f3675e8c868c45f
Change-Id: I83b393d6b37f5e47e05913f111d04e8cdb750f85
---
A
wikipedia-it/src/main/java/org/wikimedia/wikipedia/test/PageFetchTaskTests.java
A wikipedia/src/main/java/org/wikimedia/wikipedia/Page.java
A wikipedia/src/main/java/org/wikimedia/wikipedia/PageFetchTask.java
A wikipedia/src/main/java/org/wikimedia/wikipedia/PageTitle.java
A wikipedia/src/main/java/org/wikimedia/wikipedia/Section.java
A
wikipedia/src/main/java/org/wikimedia/wikipedia/concurrency/ExecutorService.java
6 files changed, 267 insertions(+), 0 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/apps/android/wikipedia
refs/changes/15/93015/1
diff --git
a/wikipedia-it/src/main/java/org/wikimedia/wikipedia/test/PageFetchTaskTests.java
b/wikipedia-it/src/main/java/org/wikimedia/wikipedia/test/PageFetchTaskTests.java
new file mode 100644
index 0000000..e5f149d
--- /dev/null
+++
b/wikipedia-it/src/main/java/org/wikimedia/wikipedia/test/PageFetchTaskTests.java
@@ -0,0 +1,49 @@
+package org.wikimedia.wikipedia.test;
+
+import android.content.Intent;
+import android.test.ActivityUnitTestCase;
+import android.util.Log;
+import org.mediawiki.api.json.Api;
+import org.wikimedia.wikipedia.Page;
+import org.wikimedia.wikipedia.PageFetchTask;
+import org.wikimedia.wikipedia.PageTitle;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+public class PageFetchTaskTests extends
ActivityUnitTestCase<TestDummyActivity> {
+ private static final int TASK_COMPLETION_TIMEOUT = 20000;
+
+ private Api enwiki;
+
+ public PageFetchTaskTests() {
+ super(TestDummyActivity.class);
+ }
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ enwiki = new Api("en.wikipedia.org");
+ startActivity(new Intent(), null, null);
+ }
+
+ public void testPageFetch() throws Throwable {
+ final CountDownLatch completionLatch = new CountDownLatch(1);
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ new PageFetchTask(enwiki, new PageTitle(null, "India")) {
+ @Override
+ public void onFinish(Page result) {
+ assertNotNull(result);
+ // FIXME: SUPER FLAKY TEST BELOW! 15 is count of first
level sections + 1 in en:India article!
+ assertEquals(15, result.getSections().size());
+ assertEquals(4,
result.getSections().get(2).getSubSections().size());
+ completionLatch.countDown();
+ }
+ }.execute();
+ }
+ });
+ assertTrue(completionLatch.await(TASK_COMPLETION_TIMEOUT,
TimeUnit.MILLISECONDS));
+ }
+}
diff --git a/wikipedia/src/main/java/org/wikimedia/wikipedia/Page.java
b/wikipedia/src/main/java/org/wikimedia/wikipedia/Page.java
new file mode 100644
index 0000000..b072fef
--- /dev/null
+++ b/wikipedia/src/main/java/org/wikimedia/wikipedia/Page.java
@@ -0,0 +1,33 @@
+package org.wikimedia.wikipedia;
+
+import java.util.ArrayList;
+
+/**
+ * Represents a particular page along with its full contents.
+ */
+public class Page {
+ private final PageTitle title;
+ private final ArrayList<Section> sections;
+
+ public Page(PageTitle title, ArrayList<Section> sections) {
+ this.title = title;
+ this.sections = sections;
+ }
+
+ public PageTitle getTitle() {
+ return title;
+ }
+
+ public ArrayList<Section> getSections() {
+ return sections;
+ }
+
+ public String getHTML() {
+ String html = "";
+ for (Section s : sections) {
+ html += s.toHTML();
+ }
+ return html;
+ }
+
+}
diff --git a/wikipedia/src/main/java/org/wikimedia/wikipedia/PageFetchTask.java
b/wikipedia/src/main/java/org/wikimedia/wikipedia/PageFetchTask.java
new file mode 100644
index 0000000..0930a8c
--- /dev/null
+++ b/wikipedia/src/main/java/org/wikimedia/wikipedia/PageFetchTask.java
@@ -0,0 +1,54 @@
+package org.wikimedia.wikipedia;
+
+import android.content.Context;
+import org.json.JSONArray;
+import org.json.JSONObject;
+import org.mediawiki.api.json.Api;
+import org.mediawiki.api.json.ApiResult;
+import org.wikimedia.wikipedia.concurrency.ExecutorService;
+import org.wikimedia.wikipedia.concurrency.SaneAsyncTask;
+
+import java.util.ArrayList;
+
+public class PageFetchTask extends SaneAsyncTask<Page> {
+ PageTitle title;
+ Api api;
+
+ public PageFetchTask(Api api, PageTitle title) {
+ super(ExecutorService.getSingleton().getExecutor(PageFetchTask.class));
+ this.title = title;
+ this.api = api;
+ }
+
+ @Override
+ public Page performTask() throws Throwable {
+ ApiResult result = api.action("mobileview")
+ .param("page", title.getTitle()) //TODO: Support non main NS!
+ .param("sections", "all")
+ .param("sectionprop", "toclevel|line|anchor")
+ .param("noheadings", "true")
+ .get();
+ JSONArray sectionsJSON =
result.asObject().optJSONObject("mobileview").optJSONArray("sections");
+
+ ArrayList<Section> sections = new ArrayList<Section>();
+ Section curSection = null;
+
+ for (int i=0; i < sectionsJSON.length(); i++) {
+ JSONObject sectionJSON = sectionsJSON.getJSONObject(i);
+ Section newSection = new Section(sectionJSON.optInt("id"),
+ sectionJSON.optInt("toclevel", 1), // Assume all sections
are 1st level if they don't have that info
+ sectionJSON.optString("line", null),
+ sectionJSON.optString("anchor", null),
+ sectionJSON.optString("text")
+ );
+ if (curSection == null || newSection.getLevel() <=
curSection.getLevel()) {
+ curSection = newSection;
+ sections.add(newSection);
+ } else {
+ curSection.insertSection(newSection);
+ }
+ }
+
+ return new Page(title, sections);
+ }
+}
diff --git a/wikipedia/src/main/java/org/wikimedia/wikipedia/PageTitle.java
b/wikipedia/src/main/java/org/wikimedia/wikipedia/PageTitle.java
new file mode 100644
index 0000000..0ec9ca1
--- /dev/null
+++ b/wikipedia/src/main/java/org/wikimedia/wikipedia/PageTitle.java
@@ -0,0 +1,25 @@
+package org.wikimedia.wikipedia;
+
+/**
+ * Value object representing the title of a page.
+ *
+ * Points to a specific page in a specific namespace on a specific site.
+ * Is immutable.
+ */
+public class PageTitle {
+ private final String namespace;
+ private final String title;
+
+ public PageTitle(final String namesapce, final String title) {
+ this.namespace = namesapce;
+ this.title = title; //FIXME: Actually normalize this!
+ }
+
+ public String getNamespace() {
+ return namespace;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+}
diff --git a/wikipedia/src/main/java/org/wikimedia/wikipedia/Section.java
b/wikipedia/src/main/java/org/wikimedia/wikipedia/Section.java
new file mode 100644
index 0000000..ee481d8
--- /dev/null
+++ b/wikipedia/src/main/java/org/wikimedia/wikipedia/Section.java
@@ -0,0 +1,74 @@
+package org.wikimedia.wikipedia;
+
+import java.util.ArrayList;
+
+/**
+ * Represents a particular section of an article.
+ */
+public class Section {
+ private int id;
+ private int level;
+ private String heading;
+ private String anchor;
+ private String content;
+
+ private ArrayList<Section> subSections = new ArrayList<Section>();
+
+ public Section(int id, int level, String heading, String anchor, String
content) {
+ this.id = id;
+ this.level = level;
+ this.heading = heading;
+ this.anchor = anchor;
+ this.content = content;
+ }
+
+ public boolean isLead() {
+ return level == 0;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public int getLevel() {
+ return level;
+ }
+
+ public String getHeading() {
+ return heading;
+ }
+
+ public String getAnchor() {
+ return anchor;
+ }
+
+ public String getContent() {
+ return content;
+ }
+
+ public void insertSection(Section subSection) {
+ subSections.add(subSection);
+ }
+
+ public ArrayList<Section> getSubSections() {
+ return subSections;
+ }
+
+ public String toHTML() {
+ String html = "";
+
+ if (!isLead()) {
+ int headingLevel = getLevel() + 1;
+ html = "<h" + headingLevel + ">" + getHeading() + "</h" +
headingLevel + ">";
+ }
+
+ html += "<div>";
+ html += getContent();
+ for (Section s : subSections) {
+ html += s.toHTML();
+ }
+ html += "</div>";
+
+ return html;
+ }
+}
diff --git
a/wikipedia/src/main/java/org/wikimedia/wikipedia/concurrency/ExecutorService.java
b/wikipedia/src/main/java/org/wikimedia/wikipedia/concurrency/ExecutorService.java
new file mode 100644
index 0000000..f1ea571
--- /dev/null
+++
b/wikipedia/src/main/java/org/wikimedia/wikipedia/concurrency/ExecutorService.java
@@ -0,0 +1,32 @@
+package org.wikimedia.wikipedia.concurrency;
+
+import java.util.HashMap;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+
+/**
+ * Service registry for providing Executors for various purposes.
+ *
+ * TODO: Make number of threads per executor configurable.
+ */
+public class ExecutorService {
+ private static final ExecutorService singleton = new ExecutorService();
+
+ public static ExecutorService getSingleton() {
+ return singleton;
+ }
+
+ private final HashMap<Class, Executor> executors;
+
+ public ExecutorService() {
+ executors = new HashMap<Class, Executor>();
+ }
+
+ public Executor getExecutor(Class cls) {
+ if (!executors.containsKey(cls)) {
+ // TODO: Custom number of threads for services
+ executors.put(cls, new ScheduledThreadPoolExecutor(1));
+ }
+ return executors.get(cls);
+ }
+}
--
To view, visit https://gerrit.wikimedia.org/r/93015
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I83b393d6b37f5e47e05913f111d04e8cdb750f85
Gerrit-PatchSet: 1
Gerrit-Project: apps/android/wikipedia
Gerrit-Branch: master
Gerrit-Owner: Yuvipanda <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits