summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--AndroidManifest.xml5
-rw-r--r--res/drawable/ic_menu_close_clear_cancel.pngbin0 -> 5306 bytes
-rw-r--r--res/drawable/ic_menu_preferences.pngbin0 -> 2144 bytes
-rw-r--r--res/drawable/ic_menu_refresh.pngbin0 -> 2450 bytes
-rw-r--r--res/menu/menu.xml7
-rw-r--r--res/menu/settings.xml14
-rw-r--r--res/values/arrays.xml9
-rw-r--r--res/values/id.xml5
-rw-r--r--src/de/animux/android/andmal/AnimeListActivity.java112
-rw-r--r--src/de/animux/android/andmal/ListActivity.java215
-rw-r--r--src/de/animux/android/andmal/Settings.java13
-rw-r--r--src/de/animux/android/andmal/api/MalList.java79
-rw-r--r--src/de/animux/android/andmal/api/MalListParser.java40
-rw-r--r--src/de/animux/android/andmal/api/MalObject.java7
-rw-r--r--src/de/animux/android/andmal/api/MalObjectStore.java5
-rw-r--r--src/de/animux/android/andmal/api/MalState.java5
-rw-r--r--src/de/animux/android/andmal/api/anime/Anime.java22
-rw-r--r--src/de/animux/android/andmal/api/anime/AnimeList.java141
-rw-r--r--src/de/animux/android/andmal/api/anime/AnimeListParser.java45
-rw-r--r--src/de/animux/android/andmal/api/anime/State.java4
-rw-r--r--src/de/animux/android/andmal/api/manga/Manga.java209
-rw-r--r--src/de/animux/android/andmal/api/manga/MangaList.java86
-rw-r--r--src/de/animux/android/andmal/api/manga/MangaListParser.java50
-rw-r--r--src/de/animux/android/andmal/api/manga/State.java38
24 files changed, 907 insertions, 204 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index a1db31e..0b92c22 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -4,14 +4,15 @@
android:versionCode="1"
android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
- <activity android:label="@string/app_name" android:name=".AnimeListActivity">
+ <activity android:label="@string/app_name" android:name=".ListActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
- </application>
+ <activity android:name="Settings"></activity>
+</application>
<uses-sdk android:minSdkVersion="3" />
diff --git a/res/drawable/ic_menu_close_clear_cancel.png b/res/drawable/ic_menu_close_clear_cancel.png
new file mode 100644
index 0000000..78222ea
--- /dev/null
+++ b/res/drawable/ic_menu_close_clear_cancel.png
Binary files differ
diff --git a/res/drawable/ic_menu_preferences.png b/res/drawable/ic_menu_preferences.png
new file mode 100644
index 0000000..b8e7141
--- /dev/null
+++ b/res/drawable/ic_menu_preferences.png
Binary files differ
diff --git a/res/drawable/ic_menu_refresh.png b/res/drawable/ic_menu_refresh.png
new file mode 100644
index 0000000..77d70dd
--- /dev/null
+++ b/res/drawable/ic_menu_refresh.png
Binary files differ
diff --git a/res/menu/menu.xml b/res/menu/menu.xml
new file mode 100644
index 0000000..5dd2311
--- /dev/null
+++ b/res/menu/menu.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android"><item android:title="Refresh" android:id="@+id/menu_refresh" android:icon="@drawable/ic_menu_refresh"></item><item android:visible="false" android:enabled="true" android:id="@+id/menu_switch_anime" android:title="Animes">
+</item>
+<item android:visible="true" android:enabled="true" android:title="Mangas" android:id="@+id/menu_switch_manga"></item>
+<item android:visible="true" android:enabled="true" android:icon="@drawable/ic_menu_preferences" android:alphabeticShortcut="S" android:title="Settings..." android:id="@+id/menu_settings"></item>
+<item android:visible="true" android:enabled="true" android:icon="@drawable/ic_menu_close_clear_cancel" android:alphabeticShortcut="E" android:title="Exit" android:id="@+id/menu_exit"></item>
+</menu>
diff --git a/res/menu/settings.xml b/res/menu/settings.xml
new file mode 100644
index 0000000..8c646a7
--- /dev/null
+++ b/res/menu/settings.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
+
+<PreferenceCategory android:title="myanimelist.net Account">
+ <EditTextPreference android:title="Username" android:key="MAL_USERNAME" android:summary="Please enter your myanimelist.net Username.">
+ </EditTextPreference>
+ <EditTextPreference android:title="Password" android:key="MAL_PASSWORD" android:password="true" android:summary="Please enter your myanimelist.net Password.">
+ </EditTextPreference>
+</PreferenceCategory>
+<!-- <PreferenceCategory android:title="Application">
+ <ListPreference android:title="Startscreen" android:key="STARTSCREEN" android:entries="@array/screen_names" android:entryValues="@array/screen_values" android:defaultValue="@raw/screen_anime">
+ </ListPreference>
+</PreferenceCategory>-->
+</PreferenceScreen>
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
new file mode 100644
index 0000000..d4e8db0
--- /dev/null
+++ b/res/values/arrays.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources><string-array name="screen_names"><item>Anime</item>
+<item>Manga</item>
+</string-array>
+
+<integer-array name="screen_values"><item>@raw/screen_anime</item>
+<item>@raw/screen_manga</item>
+</integer-array>
+</resources>
diff --git a/res/values/id.xml b/res/values/id.xml
new file mode 100644
index 0000000..065a6fb
--- /dev/null
+++ b/res/values/id.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources>
+<item name="screen_anime" type="raw" format="integer">0</item>
+<item name="screen_manga" type="raw" format="integer">1</item>
+</resources>
diff --git a/src/de/animux/android/andmal/AnimeListActivity.java b/src/de/animux/android/andmal/AnimeListActivity.java
deleted file mode 100644
index 566fa1d..0000000
--- a/src/de/animux/android/andmal/AnimeListActivity.java
+++ /dev/null
@@ -1,112 +0,0 @@
-package de.animux.android.andmal;
-
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-
-import de.animux.android.andmal.api.anime.Anime;
-import de.animux.android.andmal.api.anime.AnimeList;
-import de.animux.android.andmal.api.anime.State;
-import de.animux.android.andmal.util.SeparatedListAdapter;
-
-import android.app.Activity;
-import android.app.Dialog;
-import android.app.ProgressDialog;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
-import android.widget.ListView;
-import android.widget.SimpleAdapter;
-
-public class AnimeListActivity extends Activity {
-
- public final static String ITEM_TITLE = "title";
- public final static String ITEM_CAPTION = "caption";
-
- public final static int INITIAL_SYNC = 0;
-
- private AnimeList animeList;
-
- private UpdateUIHandler updateUIHandler = new UpdateUIHandler();
-
- public Map<String, ?> createItem(String title, String caption) {
- Map<String, String> item = new HashMap<String, String>();
- item.put(ITEM_TITLE, title);
- item.put(ITEM_CAPTION, caption);
- return item;
- }
-
- private class UpdateUIHandler extends Handler {
- @Override
- public void handleMessage(Message msg) {
- SeparatedListAdapter adapter = new SeparatedListAdapter(
- AnimeListActivity.this);
- Map<de.animux.android.andmal.api.anime.State, List<Anime>> animes = animeList
- .getAnimes();
-
- for (State s : State.values())
- addAnimes(adapter, animes.get(s), s.toString());
-
- ListView list = new ListView(AnimeListActivity.this);
- list.setAdapter(adapter);
-
- dismissDialog(INITIAL_SYNC);
-
- AnimeListActivity.this.setContentView(list);
- }
- }
-
- /** Called when the activity is first created. */
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- showDialog(INITIAL_SYNC);
-
- new Thread() {
- public void run() {
- try {
- animeList = new AnimeList("AlexanderS");
- } catch (Exception e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
-
- updateUIHandler.sendEmptyMessage(0);
- }
- }.start();
- }
-
- private void addAnimes(SeparatedListAdapter adapter,
- Collection<Anime> animes, String sectionName) {
- if (animes != null && animes.size() > 0) {
- java.util.List<Map<String, ?>> listSection = new LinkedList<Map<String, ?>>();
-
- for (Anime a : animes) {
- listSection.add(createItem(a.getTitle(), a.getWatchedEpisodes()
- + "/" + a.getEpisodes()));
- }
-
- adapter.addSection(sectionName, new SimpleAdapter(this,
- listSection, R.layout.list_item, new String[] { ITEM_TITLE,
- ITEM_CAPTION }, new int[] { R.id.list_item_title,
- R.id.list_item_other }));
- }
- }
-
- @Override
- protected Dialog onCreateDialog(int id) {
- switch (id) {
- case INITIAL_SYNC:
- ProgressDialog dialog = ProgressDialog.show(this, "",
- "Loading list. Please wait...", true);
- dialog.show();
- return dialog;
- default:
- return super.onCreateDialog(id);
- }
- }
-
-} \ No newline at end of file
diff --git a/src/de/animux/android/andmal/ListActivity.java b/src/de/animux/android/andmal/ListActivity.java
new file mode 100644
index 0000000..ec21f41
--- /dev/null
+++ b/src/de/animux/android/andmal/ListActivity.java
@@ -0,0 +1,215 @@
+package de.animux.android.andmal;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.Map;
+
+import de.animux.android.andmal.api.MalList;
+import de.animux.android.andmal.api.MalObject;
+import de.animux.android.andmal.api.MalState;
+import de.animux.android.andmal.api.anime.AnimeList;
+import de.animux.android.andmal.api.manga.MangaList;
+import de.animux.android.andmal.util.SeparatedListAdapter;
+
+import android.app.Activity;
+import android.app.Dialog;
+import android.app.ProgressDialog;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.preference.PreferenceManager;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.widget.ListView;
+import android.widget.SimpleAdapter;
+
+public class ListActivity extends Activity {
+
+ public final static String ITEM_TITLE = "title";
+ public final static String ITEM_CAPTION = "caption";
+
+ public final static int SYNCING = 0;
+
+ private MalList currentList;
+
+ private UpdateUIHandler updateUIHandler = new UpdateUIHandler();
+ private SharedPreferences prefs;
+
+ public ListActivity() {
+ super();
+ this.currentList = null;
+ this.prefs = null;
+ }
+
+ public Map<String, ?> createItem(String title, String caption) {
+ Map<String, String> item = new HashMap<String, String>();
+ item.put(ITEM_TITLE, title);
+ item.put(ITEM_CAPTION, caption);
+ return item;
+ }
+
+ private class UpdateUIHandler extends Handler {
+ @Override
+ public void handleMessage(Message msg) {
+ SeparatedListAdapter adapter = new SeparatedListAdapter(
+ ListActivity.this);
+
+ if (currentList != null) {
+ Map<MalState, Collection<MalObject>> malObjects = currentList
+ .getObjects();
+
+ if (malObjects != null) {
+ for (MalState s : malObjects.keySet())
+ addMalObjects(adapter, malObjects.get(s), s.toString());
+
+ ListView list = new ListView(ListActivity.this);
+ list.setAdapter(adapter);
+ ListActivity.this.setContentView(list);
+ }
+ }
+
+ dismissDialog(SYNCING);
+ }
+ }
+
+ /** Called when the activity is first created. */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ PreferenceManager.setDefaultValues(this, R.menu.settings, false);
+
+ prefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
+
+ if (prefs.getString("MAL_USERNAME", null) == null) {
+ startActivity(new Intent(this, Settings.class));
+ return;
+ }
+
+ currentList = new AnimeList(prefs.getString("MAL_USERNAME", null),
+ prefs.getString("MAL_PASSWORD", null));
+ refreshDisplay();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+
+ if (currentList == null) {
+ if (prefs.getString("USERNAME", null) != null) {
+ currentList = new AnimeList(prefs.getString("MAL_USERNAME",
+ null), prefs.getString("MAL_PASSWORD", null));
+ }
+ } else {
+ currentList.setUsername(prefs.getString("MAL_USERNAME", null));
+ currentList.setPassword(prefs.getString("MAL_PASSWORD", null));
+ }
+
+ refreshDisplay();
+ }
+
+ private synchronized void refreshDisplay() {
+ if (currentList != null) {
+ if (currentList.needsRefresh()) {
+ showDialog(SYNCING);
+
+ new Thread() {
+ public void run() {
+ try {
+ currentList.refresh();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ updateUIHandler.sendEmptyMessage(0);
+ }
+ }.start();
+ } else {
+ updateUIHandler.sendEmptyMessage(0);
+ }
+ }
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ super.onCreateOptionsMenu(menu);
+ MenuInflater inflater = getMenuInflater();
+ inflater.inflate(R.menu.menu, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onPrepareOptionsMenu(Menu menu) {
+ super.onPrepareOptionsMenu(menu);
+ MenuItem item;
+
+ item = menu.findItem(R.id.menu_switch_anime);
+ item.setVisible(currentList instanceof MangaList);
+
+ item = menu.findItem(R.id.menu_switch_manga);
+ item.setVisible(currentList instanceof AnimeList);
+
+ return true;
+ }
+
+ private void addMalObjects(SeparatedListAdapter adapter,
+ Collection<MalObject> malObjects, String sectionName) {
+ if (malObjects != null && malObjects.size() > 0) {
+ java.util.List<Map<String, ?>> listSection = new LinkedList<Map<String, ?>>();
+
+ for (MalObject m : malObjects) {
+ listSection.add(createItem(m.getTitle(), m.getProgress()));
+ }
+
+ adapter.addSection(sectionName, new SimpleAdapter(this,
+ listSection, R.layout.list_item, new String[] { ITEM_TITLE,
+ ITEM_CAPTION }, new int[] { R.id.list_item_title,
+ R.id.list_item_other }));
+ }
+ }
+
+ @Override
+ protected Dialog onCreateDialog(int id) {
+ switch (id) {
+ case SYNCING:
+ ProgressDialog dialog = ProgressDialog.show(this, "",
+ "Loading list. Please wait...", true);
+ dialog.show();
+ return dialog;
+ default:
+ return super.onCreateDialog(id);
+ }
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case R.id.menu_settings:
+ startActivity(new Intent(this, Settings.class));
+ return true;
+ case R.id.menu_switch_manga:
+ currentList = new MangaList();
+ break;
+ case R.id.menu_switch_anime:
+ currentList = new AnimeList();
+ break;
+ case R.id.menu_refresh:
+ if (currentList != null)
+ currentList.setNeedsRefresh(true);
+
+ break;
+ case R.id.menu_exit:
+ System.exit(0);
+ break;
+ default:
+ return false;
+ }
+
+ refreshDisplay();
+ return true;
+ }
+
+} \ No newline at end of file
diff --git a/src/de/animux/android/andmal/Settings.java b/src/de/animux/android/andmal/Settings.java
new file mode 100644
index 0000000..b13e083
--- /dev/null
+++ b/src/de/animux/android/andmal/Settings.java
@@ -0,0 +1,13 @@
+package de.animux.android.andmal;
+
+import android.os.Bundle;
+import android.preference.PreferenceActivity;
+
+public class Settings extends PreferenceActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ addPreferencesFromResource(R.menu.settings);
+ }
+}
diff --git a/src/de/animux/android/andmal/api/MalList.java b/src/de/animux/android/andmal/api/MalList.java
new file mode 100644
index 0000000..79a37b6
--- /dev/null
+++ b/src/de/animux/android/andmal/api/MalList.java
@@ -0,0 +1,79 @@
+package de.animux.android.andmal.api;
+
+import java.util.Collection;
+import java.util.Map;
+
+public abstract class MalList {
+
+ private String username;
+
+ private String password;
+
+ protected boolean needsRefresh;
+
+ private static MalList cache;
+
+ public MalList(String username, String password) {
+ this.username = username;
+ this.password = password;
+ cache = this;
+ setNeedsRefresh(true);
+ }
+
+ public MalList() {
+ if (cache != null) {
+ this.username = cache.getUsername();
+ this.password = cache.getPassword();
+ setNeedsRefresh(false);
+ }
+ }
+
+ public String getUsername() {
+ return this.username;
+ }
+
+ public void setUsername(String username) {
+ if (this.username != null && this.username.equals(username))
+ return;
+
+ this.username = username;
+ this.needsRefresh = true;
+
+ if (cache != this
+ && (cache.getUsername() == null || !cache.getUsername().equals(
+ username))) {
+ cache.setUsername(username);
+ }
+ }
+
+ protected String getPassword() {
+ return this.password;
+ }
+
+ public void setPassword(String password) {
+ if (this.password != null && this.password.equals(password))
+ return;
+
+ this.password = password;
+ this.needsRefresh = true;
+
+ if (cache != this
+ && (cache.getPassword() == null || !cache.getPassword().equals(
+ password))) {
+ cache.setPassword(password);
+ }
+ }
+
+ public void setNeedsRefresh(boolean needsRefresh) {
+ this.needsRefresh = needsRefresh;
+ }
+
+ public boolean needsRefresh() {
+ return needsRefresh;
+ }
+
+ abstract public void refresh();
+
+ abstract public Map<MalState, Collection<MalObject>> getObjects();
+
+} \ No newline at end of file
diff --git a/src/de/animux/android/andmal/api/MalListParser.java b/src/de/animux/android/andmal/api/MalListParser.java
new file mode 100644
index 0000000..014b718
--- /dev/null
+++ b/src/de/animux/android/andmal/api/MalListParser.java
@@ -0,0 +1,40 @@
+package de.animux.android.andmal.api;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+public abstract class MalListParser<T extends MalObject> extends DefaultHandler {
+ private StringBuffer currentValue;
+
+ protected MalObjectStore<T> objectStore;
+
+ public MalListParser(MalObjectStore<T> objectStore) {
+ super();
+
+ this.objectStore = objectStore;
+ currentValue = new StringBuffer();
+ }
+
+ @Override
+ public void characters(char[] ch, int start, int length)
+ throws SAXException {
+ currentValue.append(new String(ch).substring(start, length - start)
+ .replaceAll("&amp;", "&"));
+ }
+
+ @Override
+ public void endElement(String uri, String localName, String qName)
+ throws SAXException {
+ addElement(localName, currentValue.toString());
+ currentValue.setLength(0);
+ }
+
+ @Override
+ public void startElement(String uri, String localName, String qName,
+ Attributes attributes) throws SAXException {
+ currentValue.setLength(0);
+ }
+
+ abstract public void addElement(String name, String value);
+}
diff --git a/src/de/animux/android/andmal/api/MalObject.java b/src/de/animux/android/andmal/api/MalObject.java
new file mode 100644
index 0000000..9ccf279
--- /dev/null
+++ b/src/de/animux/android/andmal/api/MalObject.java
@@ -0,0 +1,7 @@
+package de.animux.android.andmal.api;
+
+public abstract class MalObject implements Comparable<MalObject> {
+
+ public abstract String getTitle();
+ public abstract String getProgress();
+}
diff --git a/src/de/animux/android/andmal/api/MalObjectStore.java b/src/de/animux/android/andmal/api/MalObjectStore.java
new file mode 100644
index 0000000..937ac2e
--- /dev/null
+++ b/src/de/animux/android/andmal/api/MalObjectStore.java
@@ -0,0 +1,5 @@
+package de.animux.android.andmal.api;
+
+public interface MalObjectStore<T extends MalObject> {
+ public void add(T object);
+}
diff --git a/src/de/animux/android/andmal/api/MalState.java b/src/de/animux/android/andmal/api/MalState.java
new file mode 100644
index 0000000..ed76bc6
--- /dev/null
+++ b/src/de/animux/android/andmal/api/MalState.java
@@ -0,0 +1,5 @@
+package de.animux.android.andmal.api;
+
+public interface MalState {
+ public String toString();
+}
diff --git a/src/de/animux/android/andmal/api/anime/Anime.java b/src/de/animux/android/andmal/api/anime/Anime.java
index d4f542f..dc4b34e 100644
--- a/src/de/animux/android/andmal/api/anime/Anime.java
+++ b/src/de/animux/android/andmal/api/anime/Anime.java
@@ -1,6 +1,8 @@
package de.animux.android.andmal.api.anime;
-public class Anime implements Comparable<Anime> {
+import de.animux.android.andmal.api.MalObject;
+
+public class Anime extends MalObject {
private int id;
private String title;
@@ -180,18 +182,28 @@ public class Anime implements Comparable<Anime> {
}
@Override
- public int compareTo(Anime arg0) {
- int compareTitle = arg0.getTitle().compareTo(getTitle());
+ public int compareTo(MalObject arg0) {
+ if ( !(arg0 instanceof Anime)) {
+ throw new IllegalArgumentException();
+ }
+
+ Anime a = (Anime)arg0;
+ int compareTitle = a.getTitle().compareTo(getTitle());
if (compareTitle != 0) {
return compareTitle;
}
else {
- if (arg0.getId() != getId()) {
- return getId() - arg0.getId();
+ if (a.getId() != getId()) {
+ return getId() - a.getId();
}
}
return 0;
}
+ @Override
+ public String getProgress() {
+ return getWatchedEpisodes() + "/" + getEpisodes();
+ }
+
}
diff --git a/src/de/animux/android/andmal/api/anime/AnimeList.java b/src/de/animux/android/andmal/api/anime/AnimeList.java
index 78a1e09..0fbb4ea 100644
--- a/src/de/animux/android/andmal/api/anime/AnimeList.java
+++ b/src/de/animux/android/andmal/api/anime/AnimeList.java
@@ -1,117 +1,90 @@
package de.animux.android.andmal.api.anime;
-import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
+import java.util.Collection;
import java.util.HashMap;
-import java.util.List;
import java.util.Map;
-import javax.xml.parsers.FactoryConfigurationError;
-import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
-import org.xml.sax.Attributes;
-import org.xml.sax.SAXException;
-import org.xml.sax.helpers.DefaultHandler;
-
+import de.animux.android.andmal.api.MalList;
+import de.animux.android.andmal.api.MalObject;
+import de.animux.android.andmal.api.MalObjectStore;
+import de.animux.android.andmal.api.MalState;
import de.animux.android.andmal.api.anime.State;
import de.animux.android.andmal.util.SortedLinkedList;
-public class AnimeList extends DefaultHandler {
+public class AnimeList extends MalList implements MalObjectStore<Anime> {
- private Anime currentAnime;
- private StringBuffer currentValue;
+ // cache last instance of this class to restore if a new one is created with
+ // the same username and password
+ private static AnimeList cache;
- private HashMap<State,List<Anime>> animes;
+ private Map<MalState, Collection<MalObject>> animes;
- public AnimeList(String user) throws IOException,
- ParserConfigurationException, SAXException,
- FactoryConfigurationError {
- currentAnime = null;
- currentValue = new StringBuffer();
-
- animes = new HashMap<State, List<Anime>>();
- animes.put(State.WATCHING, new SortedLinkedList<Anime>());
- animes.put(State.COMPLETED, new SortedLinkedList<Anime>());
- animes.put(State.ONHOLD, new SortedLinkedList<Anime>());
- animes.put(State.DROPPED, new SortedLinkedList<Anime>());
- animes.put(State.PLANTOWATCH, new SortedLinkedList<Anime>());
-
- URL url = new URL("http://myanimelist.net/malappinfo.php?status=all&type=anime&u=" + user);
- InputStream stream = url.openStream();
-
- SAXParser sax = SAXParserFactory.newInstance().newSAXParser();
- sax.parse(stream, this);
- }
+ public AnimeList(String username, String password) {
+ super(username, password);
- public Anime getCurrentAnime() {
- return currentAnime;
+ if (((cache != null) && cache.getUsername().equals(username))
+ && cache.getPassword().equals(username)) {
+ animes = cache.getObjects();
+ } else {
+ cache = this;
+ needsRefresh = true;
+ }
}
- public StringBuffer getCurrentValue() {
- return currentValue;
- }
+ public AnimeList() {
+ super();
- public Map<State, List<Anime>> getAnimes() {
- return animes;
+ if (cache != null && cache.getUsername() != null
+ && cache.getUsername().equals(this.getUsername())) {
+ animes = cache.getObjects();
+ }
+ else {
+ cache = this;
+ needsRefresh = true;
+ }
}
@Override
- public void characters(char[] ch, int start, int length)
- throws SAXException {
- currentValue.append(new String(ch).substring(start, length - start)
- .replaceAll("&amp;", "&"));
+ public void refresh() {
+ if (this.getUsername() == null)
+ return;
+
+ animes = new HashMap<MalState, Collection<MalObject>>();
+ animes.put(State.WATCHING, new SortedLinkedList<MalObject>());
+ animes.put(State.COMPLETED, new SortedLinkedList<MalObject>());
+ animes.put(State.ONHOLD, new SortedLinkedList<MalObject>());
+ animes.put(State.DROPPED, new SortedLinkedList<MalObject>());
+ animes.put(State.PLANTOWATCH, new SortedLinkedList<MalObject>());
+
+ try {
+ URL url = new URL(
+ "http://myanimelist.net/malappinfo.php?status=all&type=anime&u="
+ + this.getUsername());
+ InputStream stream = url.openStream();
+
+ SAXParser sax = SAXParserFactory.newInstance().newSAXParser();
+ sax.parse(stream, new AnimeListParser(this));
+ needsRefresh = false;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
}
@Override
- public void endElement(String uri, String localName, String qName)
- throws SAXException {
-
- if (localName.equals("anime")) {
- if (animes.containsKey(State.valueOf(currentAnime.getMyStatus()))) {
- animes.get(State.valueOf(currentAnime.getMyStatus())).add(currentAnime);
- }
-
- } else if (localName.equals("series_animedb_id")) {
- currentAnime.setId(Integer.valueOf(currentValue.toString()));
- } else if (localName.equals("series_title")) {
- currentAnime.setTitle(currentValue.toString());
- } else if (localName.equals("series_synonyms")) {
- currentAnime.setSynonyms(currentValue.toString());
- } else if (localName.equals("series_type")) {
- currentAnime.setType(Integer.valueOf(currentValue.toString()));
- } else if (localName.equals("series_episodes")) {
- currentAnime.setEpisodes(Integer.valueOf(currentValue.toString()));
- } else if (localName.equals("series_status")) {
- currentAnime.setStatus(Integer.valueOf(currentValue.toString()));
- } else if (localName.equals("series_start")) {
- currentAnime.setStart(currentValue.toString());
- } else if (localName.equals("series_end")) {
- currentAnime.setEnd(currentValue.toString());
- } else if (localName.equals("series_image")) {
- currentAnime.setImage(currentValue.toString());
- } else if (localName.equals("my_id")) {
- currentAnime.setMyId(Integer.valueOf(currentValue.toString()));
- } else if (localName.equals("my_watched_episodes")) {
- currentAnime.setWatchedEpisodes(Integer.valueOf(currentValue
- .toString()));
- } else if (localName.equals("my_status")) {
- currentAnime.setMyStatus(Integer.valueOf(currentValue.toString()));
+ public void add(Anime object) {
+ if (animes.containsKey(State.valueOf(object.getMyStatus()))) {
+ animes.get(State.valueOf(object.getMyStatus())).add(object);
}
-
- currentValue.setLength(0);
}
@Override
- public void startElement(String uri, String localName, String qName,
- Attributes attributes) throws SAXException {
-
- currentValue.setLength(0);
- if (localName.equals("anime")) {
- currentAnime = new Anime();
- }
+ public Map<MalState, Collection<MalObject>> getObjects() {
+ return animes;
}
}
diff --git a/src/de/animux/android/andmal/api/anime/AnimeListParser.java b/src/de/animux/android/andmal/api/anime/AnimeListParser.java
new file mode 100644
index 0000000..e7545dd
--- /dev/null
+++ b/src/de/animux/android/andmal/api/anime/AnimeListParser.java
@@ -0,0 +1,45 @@
+package de.animux.android.andmal.api.anime;
+
+import de.animux.android.andmal.api.MalListParser;
+import de.animux.android.andmal.api.MalObjectStore;
+
+public class AnimeListParser extends MalListParser<Anime> {
+
+ private Anime currentAnime;
+
+ public AnimeListParser(MalObjectStore<Anime> objectStore) {
+ super(objectStore);
+ currentAnime = new Anime();
+ }
+
+ public void addElement(String name, String value) {
+ if (name.equals("anime")) {
+ objectStore.add(currentAnime);
+ currentAnime = new Anime();
+ } else if (name.equals("series_animedb_id")) {
+ currentAnime.setId(Integer.valueOf(value));
+ } else if (name.equals("series_title")) {
+ currentAnime.setTitle(value);
+ } else if (name.equals("series_synonyms")) {
+ currentAnime.setSynonyms(value);
+ } else if (name.equals("series_type")) {
+ currentAnime.setType(Integer.valueOf(value));
+ } else if (name.equals("series_episodes")) {
+ currentAnime.setEpisodes(Integer.valueOf(value));
+ } else if (name.equals("series_status")) {
+ currentAnime.setStatus(Integer.valueOf(value));
+ } else if (name.equals("series_start")) {
+ currentAnime.setStart(value);
+ } else if (name.equals("series_end")) {
+ currentAnime.setEnd(value);
+ } else if (name.equals("series_image")) {
+ currentAnime.setImage(value);
+ } else if (name.equals("my_id")) {
+ currentAnime.setMyId(Integer.valueOf(value));
+ } else if (name.equals("my_watched_episodes")) {
+ currentAnime.setWatchedEpisodes(Integer.valueOf(value));
+ } else if (name.equals("my_status")) {
+ currentAnime.setMyStatus(Integer.valueOf(value));
+ }
+ }
+}
diff --git a/src/de/animux/android/andmal/api/anime/State.java b/src/de/animux/android/andmal/api/anime/State.java
index 639b761..9ba4769 100644
--- a/src/de/animux/android/andmal/api/anime/State.java
+++ b/src/de/animux/android/andmal/api/anime/State.java
@@ -1,6 +1,8 @@
package de.animux.android.andmal.api.anime;
-public enum State {
+import de.animux.android.andmal.api.MalState;
+
+public enum State implements MalState {
WATCHING (1, "Watching"),
COMPLETED (2, "Completed"),
ONHOLD (3, "On Hold"),
diff --git a/src/de/animux/android/andmal/api/manga/Manga.java b/src/de/animux/android/andmal/api/manga/Manga.java
new file mode 100644
index 0000000..25670df
--- /dev/null
+++ b/src/de/animux/android/andmal/api/manga/Manga.java
@@ -0,0 +1,209 @@
+package de.animux.android.andmal.api.manga;
+
+import de.animux.android.andmal.api.MalObject;
+
+public class Manga extends MalObject {
+
+ private int id;
+ private String title;
+ private String synonyms;
+ private int type;
+ private int chapters;
+ private int volumes;
+ private int status;
+ private String start;
+ private String end;
+ private String image;
+
+ private int personalId;
+ private int personalReadChapters;
+ private int personalReadVolumes;
+ private String personalStart;
+ private String personalEnd;
+ private int personalScore;
+ private int personalStatus;
+ private int personalRereading;
+ private int personalRereadingChapters;
+ private int personalLastUpdated;
+ private String personalTags;
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public String getSynonyms() {
+ return synonyms;
+ }
+
+ public void setSynonyms(String synonyms) {
+ this.synonyms = synonyms;
+ }
+
+ public int getType() {
+ return type;
+ }
+
+ public void setType(int type) {
+ this.type = type;
+ }
+
+ public int getChapters() {
+ return chapters;
+ }
+
+ public void setChapters(int chapters) {
+ this.chapters = chapters;
+ }
+
+ public int getVolumes() {
+ return volumes;
+ }
+
+ public void setVolumes(int volumes) {
+ this.volumes = volumes;
+ }
+
+ public int getStatus() {
+ return status;
+ }
+
+ public void setStatus(int status) {
+ this.status = status;
+ }
+
+ public String getStart() {
+ return start;
+ }
+
+ public void setStart(String start) {
+ this.start = start;
+ }
+
+ public String getEnd() {
+ return end;
+ }
+
+ public void setEnd(String end) {
+ this.end = end;
+ }
+
+ public String getImage() {
+ return image;
+ }
+
+ public void setImage(String image) {
+ this.image = image;
+ }
+
+ public int getPersonalId() {
+ return personalId;
+ }
+
+ public void setPersonalId(int personalId) {
+ this.personalId = personalId;
+ }
+
+ public int getPersonalReadChapters() {
+ return personalReadChapters;
+ }
+
+ public void setPersonalReadChapters(int personalReadChapters) {
+ this.personalReadChapters = personalReadChapters;
+ }
+
+ public int getPersonalReadVolumes() {
+ return personalReadVolumes;
+ }
+
+ public void setPersonalReadVolumes(int personalReadVolumes) {
+ this.personalReadVolumes = personalReadVolumes;
+ }
+
+ public String getPersonalStart() {
+ return personalStart;
+ }
+
+ public void setPersonalStart(String personalStart) {
+ this.personalStart = personalStart;
+ }
+
+ public String getPersonalEnd() {
+ return personalEnd;
+ }
+
+ public void setPersonalEnd(String personalEnd) {
+ this.personalEnd = personalEnd;
+ }
+
+ public int getPersonalScore() {
+ return personalScore;
+ }
+
+ public void setPersonalScore(int personalScore) {
+ this.personalScore = personalScore;
+ }
+
+ public int getPersonalStatus() {
+ return personalStatus;
+ }
+
+ public void setPersonalStatus(int personalStatus) {
+ this.personalStatus = personalStatus;
+ }
+
+ public int getPersonalRereading() {
+ return personalRereading;
+ }
+
+ public void setPersonalRereading(int personalRereading) {
+ this.personalRereading = personalRereading;
+ }
+
+ public int getPersonalRereadingChapters() {
+ return personalRereadingChapters;
+ }
+
+ public void setPersonalRereadingChapters(int personalRereadingChapters) {
+ this.personalRereadingChapters = personalRereadingChapters;
+ }
+
+ public int getPersonalLastUpdated() {
+ return personalLastUpdated;
+ }
+
+ public void setPersonalLastUpdated(int personalLastUpdated) {
+ this.personalLastUpdated = personalLastUpdated;
+ }
+
+ public String getPersonalTags() {
+ return personalTags;
+ }
+
+ public void setPersonalTags(String personalTags) {
+ this.personalTags = personalTags;
+ }
+
+ @Override
+ public String getTitle() {
+ return this.title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ @Override
+ public int compareTo(MalObject arg0) {
+ return 0;
+ }
+
+ @Override
+ public String getProgress() {
+ return getPersonalReadChapters() + "/" + getChapters() + " ("
+ + getPersonalReadVolumes() + "/" + getVolumes() + ")";
+ }
+}
diff --git a/src/de/animux/android/andmal/api/manga/MangaList.java b/src/de/animux/android/andmal/api/manga/MangaList.java
new file mode 100644
index 0000000..00a89e4
--- /dev/null
+++ b/src/de/animux/android/andmal/api/manga/MangaList.java
@@ -0,0 +1,86 @@
+package de.animux.android.andmal.api.manga;
+
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import de.animux.android.andmal.api.MalList;
+import de.animux.android.andmal.api.MalObject;
+import de.animux.android.andmal.api.MalObjectStore;
+import de.animux.android.andmal.api.MalState;
+import de.animux.android.andmal.util.SortedLinkedList;
+
+public class MangaList extends MalList implements MalObjectStore<Manga> {
+
+ // cache last instance of this class to restore if a new one is created with
+ // the same username and password
+ private static MangaList cache;
+ private Map<MalState, Collection<MalObject>> mangas;
+
+ public MangaList(String username, String password) {
+ super(username, password);
+
+ if (((cache != null) && cache.getUsername().equals(username))
+ && cache.getPassword().equals(username)) {
+ mangas = cache.getObjects();
+ } else {
+ cache = this;
+ needsRefresh = true;
+ }
+ }
+
+ public MangaList() {
+ super();
+
+ if (cache != null && cache.getUsername() != null
+ && cache.getUsername().equals(this.getUsername())) {
+ mangas = cache.getObjects();
+ } else {
+ cache = this;
+ needsRefresh = true;
+ }
+ }
+
+ @Override
+ public void refresh() {
+ if (this.getUsername() == null)
+ return;
+
+ mangas = new HashMap<MalState, Collection<MalObject>>();
+ mangas.put(State.READING, new SortedLinkedList<MalObject>());
+ mangas.put(State.COMPLETED, new SortedLinkedList<MalObject>());
+ mangas.put(State.ONHOLD, new SortedLinkedList<MalObject>());
+ mangas.put(State.DROPPED, new SortedLinkedList<MalObject>());
+ mangas.put(State.PLANTOREAD, new SortedLinkedList<MalObject>());
+
+ try {
+ URL url = new URL(
+ "http://myanimelist.net/malappinfo.php?status=all&type=manga&u="
+ + this.getUsername());
+ InputStream stream = url.openStream();
+
+ SAXParser sax = SAXParserFactory.newInstance().newSAXParser();
+ sax.parse(stream, new MangaListParser(this));
+ needsRefresh = false;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void add(Manga object) {
+ if (mangas.containsKey(State.valueOf(object.getPersonalStatus()))) {
+ mangas.get(State.valueOf(object.getPersonalStatus())).add(object);
+ }
+ }
+
+ @Override
+ public Map<MalState, Collection<MalObject>> getObjects() {
+ return mangas;
+ }
+}
diff --git a/src/de/animux/android/andmal/api/manga/MangaListParser.java b/src/de/animux/android/andmal/api/manga/MangaListParser.java
new file mode 100644
index 0000000..7e0ec4b
--- /dev/null
+++ b/src/de/animux/android/andmal/api/manga/MangaListParser.java
@@ -0,0 +1,50 @@
+package de.animux.android.andmal.api.manga;
+
+import de.animux.android.andmal.api.MalListParser;
+import de.animux.android.andmal.api.MalObjectStore;
+
+public class MangaListParser extends MalListParser<Manga> {
+
+ private Manga currentManga;
+
+ public MangaListParser(MalObjectStore<Manga> objectStore) {
+ super(objectStore);
+ currentManga = new Manga();
+ }
+
+ @Override
+ public void addElement(String name, String value) {
+ if (name.equals("manga")) {
+ objectStore.add(currentManga);
+ currentManga = new Manga();
+ } else if (name.equals("series_mangadb_id")) {
+ currentManga.setId(Integer.valueOf(value));
+ } else if (name.equals("series_title")) {
+ currentManga.setTitle(value);
+ } else if (name.equals("series_synonyms")) {
+ currentManga.setSynonyms(value);
+ } else if (name.equals("series_type")) {
+ currentManga.setType(Integer.valueOf(value));
+ } else if (name.equals("series_chapters")) {
+ currentManga.setChapters(Integer.valueOf(value));
+ } else if (name.equals("volumes")) {
+ currentManga.setVolumes(Integer.valueOf(value));
+ } else if (name.equals("series_status")) {
+ currentManga.setStatus(Integer.valueOf(value));
+ } else if (name.equals("series_start")) {
+ currentManga.setStart(value);
+ } else if (name.equals("series_end")) {
+ currentManga.setEnd(value);
+ } else if (name.equals("series_image")) {
+ currentManga.setImage(value);
+ } else if (name.equals("my_id")) {
+ currentManga.setPersonalId(Integer.valueOf(value));
+ } else if (name.equals("my_read_chapters")) {
+ currentManga.setPersonalReadChapters(Integer.valueOf(value));
+ } else if (name.equals("my_read_volumes")) {
+ currentManga.setPersonalReadVolumes(Integer.valueOf(value));
+ } else if (name.equals("my_status")) {
+ currentManga.setPersonalStatus(Integer.valueOf(value));
+ }
+ }
+}
diff --git a/src/de/animux/android/andmal/api/manga/State.java b/src/de/animux/android/andmal/api/manga/State.java
new file mode 100644
index 0000000..a39fe78
--- /dev/null
+++ b/src/de/animux/android/andmal/api/manga/State.java
@@ -0,0 +1,38 @@
+package de.animux.android.andmal.api.manga;
+
+import de.animux.android.andmal.api.MalState;
+
+public enum State implements MalState {
+ READING (1, "Reading"),
+ COMPLETED (2, "Completed"),
+ ONHOLD (3, "On Hold"),
+ DROPPED (4, "Dropped"),
+ PLANTOREAD (6, "Plan to read");
+
+ private final int id;
+ private final String name;
+
+ State(int id, String name) {
+ this.id = id;
+ this.name = name;
+ }
+
+ @Override
+ public String toString() {
+ return name;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ static State valueOf(int id) {
+ for (State s : State.values()) {
+ if (s.getId() == id) {
+ return s;
+ }
+ }
+
+ return null;
+ }
+} \ No newline at end of file