reader/android: Refactored the package structure

- introduced db, model subpackages
- renamed PdfFile interface to File
- added more methods to the File interface to match the VDL

Change-Id: I67c631482ebb60deb4f61e90cc92769e5f8067c1
diff --git a/android/app/build.gradle b/android/app/build.gradle
index d387a0b..4f479d9 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -48,6 +48,7 @@
         targetSdkVersion 21
         versionCode 1
         versionName "1.0"
+        multiDexEnabled true
     }
     buildTypes {
         release {
diff --git a/android/app/src/main/java/io/v/android/apps/reader/DB.java b/android/app/src/main/java/io/v/android/apps/reader/DB.java
deleted file mode 100644
index e680a3a..0000000
--- a/android/app/src/main/java/io/v/android/apps/reader/DB.java
+++ /dev/null
@@ -1,108 +0,0 @@
-// Copyright 2015 The Vanadium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package io.v.android.apps.reader;
-
-import android.app.Activity;
-import android.content.Context;
-import android.content.Intent;
-
-/**
- * Borrowed the idea of having a DB interface from syncslides.
- *
- * Provides high-level methods for getting and setting the state of PDF reader.
- * It is an interface instead of a concrete class to make testing easier.
- */
-public interface DB {
-
-    class Singleton {
-
-        private static volatile DB instance;
-
-        public static DB get(Context context) {
-            DB result = instance;
-            if (instance == null) {
-                synchronized (Singleton.class) {
-                    result = instance;
-                    if (result == null) {
-                        // TODO(youngseokyoon): Replace this with a syncbase DB.
-//                        instance = result = new FakeDB(context);
-                        instance = result = new SyncbaseDB(context);
-                    }
-                }
-            }
-
-            return result;
-        }
-    }
-
-    /**
-     * Perform initialization steps.  This method must be called early in the lifetime
-     * of the activity.  As part of the initialization, it might send an intent to
-     * another activity.
-     *
-     * @param activity implements onActivityResult() to call into DB.onActivityResult.
-     */
-    void init(Activity activity);
-
-    /**
-     * If init() sent an intent to another Activity, the result must be forwarded
-     * from our app's activity to this method.
-     *
-     * @return true if the requestCode matches an intent sent by this implementation.
-     */
-    boolean onActivityResult(int requestCode, int resultCode, Intent data);
-
-    /**
-     * Represents a PDF file and its metadata.
-     *
-     * TODO(youngseokyoon): update this interface, once the syncbase DB schema is defined.
-     */
-    interface PdfFile {
-        String getName();
-    }
-
-    /**
-     * Callbacks for when the dataset changes dynamically.
-     *
-     * TODO(youngseokyoon): reorganize the interfaces into sub-packages.
-     */
-    interface Listener {
-        void notifyItemChanged(int position);
-        void notifyItemInserted(int position);
-        void notifyItemRemoved(int position);
-    }
-
-    /**
-     * Provides a list of PDF files via an API that fits well with RecyclerView.Adapter.
-     */
-    interface PdfFileList {
-        /**
-         * Returns the number of available PDF files.
-         */
-        int getItemCount();
-
-        /**
-         * Returns the PDF file object at the given position.
-         */
-        PdfFile getPdfFile(int position);
-
-        /**
-         * Sets the listener for changes to the list.  There can only be one listener.
-         */
-        void setListener(Listener listener);
-
-        /**
-         * Indicates that the list is no longer needed and should stop notifying its listener.
-         */
-        void discard();
-    }
-
-    /**
-     * Gets the list of available PDF files.
-     * @return a list of PDF files.
-     */
-    PdfFileList getPdfFileList();
-
-}
diff --git a/android/app/src/main/java/io/v/android/apps/reader/FakeDB.java b/android/app/src/main/java/io/v/android/apps/reader/FakeDB.java
deleted file mode 100644
index 97e94f4..0000000
--- a/android/app/src/main/java/io/v/android/apps/reader/FakeDB.java
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright 2015 The Vanadium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package io.v.android.apps.reader;
-
-import android.app.Activity;
-import android.content.Context;
-import android.content.Intent;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * A fake implementation of the DB interface for manual testing.
- */
-public class FakeDB implements DB {
-
-    private static final String[] PDF_FILE_NAMES = {
-            "Foo.pdf",
-            "Bar.pdf"
-    };
-
-    private FakePdfFileList mPdfFileList;
-
-    public FakeDB(Context context) {
-        mPdfFileList = new FakePdfFileList();
-    }
-
-    class FakePdfFile implements DB.PdfFile {
-
-        private String mName;
-
-        public FakePdfFile(String name) {
-            mName = name;
-        }
-
-        @Override
-        public String getName() {
-            return mName;
-        }
-    }
-
-    class FakePdfFileList implements DB.PdfFileList {
-
-        private List<FakePdfFile> mPdfFiles;
-        private Listener mListener;
-
-        public FakePdfFileList() {
-            mPdfFiles = new ArrayList<>();
-            for (String fileName : PDF_FILE_NAMES) {
-                mPdfFiles.add(new FakePdfFile(fileName));
-            }
-        }
-
-        @Override
-        public int getItemCount() {
-            return mPdfFiles.size();
-        }
-
-        @Override
-        public FakePdfFile getPdfFile(int position) {
-            return mPdfFiles.get(position);
-        }
-
-        @Override
-        public void setListener(Listener listener) {
-            // This fake list never calls the notify methods.
-            // Just check if the listener is set only once.
-            assert mListener == null;
-            mListener = listener;
-        }
-
-        @Override
-        public void discard() {
-            // Nothing to do.
-        }
-    }
-
-    public void init(Activity activity) {
-        // Nothing to do.
-    }
-
-    @Override
-    public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
-        // Nothing to do.
-        return false;
-    }
-
-    @Override
-    public PdfFileList getPdfFileList() {
-        return mPdfFileList;
-    }
-
-}
diff --git a/android/app/src/main/java/io/v/android/apps/reader/PdfChooserActivity.java b/android/app/src/main/java/io/v/android/apps/reader/PdfChooserActivity.java
index 83c499d..be53c5b 100644
--- a/android/app/src/main/java/io/v/android/apps/reader/PdfChooserActivity.java
+++ b/android/app/src/main/java/io/v/android/apps/reader/PdfChooserActivity.java
@@ -13,6 +13,8 @@
 import android.view.MenuItem;
 import android.view.View;
 
+import io.v.android.apps.reader.db.DB;
+
 /**
  * Activity that displays all the available pdf files in a list.
  *
diff --git a/android/app/src/main/java/io/v/android/apps/reader/PdfListAdapter.java b/android/app/src/main/java/io/v/android/apps/reader/PdfListAdapter.java
index c134fcf..3299752 100644
--- a/android/app/src/main/java/io/v/android/apps/reader/PdfListAdapter.java
+++ b/android/app/src/main/java/io/v/android/apps/reader/PdfListAdapter.java
@@ -12,8 +12,10 @@
 import android.view.ViewGroup;
 import android.widget.TextView;
 
-import io.v.android.apps.reader.DB.Listener;
-import io.v.android.apps.reader.DB.PdfFileList;
+import io.v.android.apps.reader.db.DB;
+import io.v.android.apps.reader.db.DB.DBList;
+import io.v.android.apps.reader.model.Listener;
+import io.v.android.apps.reader.model.File;
 
 /**
  * Adapter that binds the list of pdf files to the corresponding card views.
@@ -22,7 +24,7 @@
         implements Listener {
 
     private OnPdfFileClickListener mClickListener;
-    private PdfFileList mPdfFileList;
+    private DBList<File> mPdfFileList;
 
     public class ViewHolder extends RecyclerView.ViewHolder {
         public CardView mCardView;
@@ -48,7 +50,7 @@
         mClickListener = null;
 
         DB db = DB.Singleton.get(context);
-        mPdfFileList = db.getPdfFileList();
+        mPdfFileList = db.getFileList();
         mPdfFileList.setListener(this);
     }
 
@@ -67,7 +69,7 @@
     }
 
     public String getItem(int position) {
-        return mPdfFileList.getPdfFile(position).getName();
+        return mPdfFileList.getItem(position).getTitle();
     }
 
     @Override
diff --git a/android/app/src/main/java/io/v/android/apps/reader/db/DB.java b/android/app/src/main/java/io/v/android/apps/reader/db/DB.java
new file mode 100644
index 0000000..b04232f
--- /dev/null
+++ b/android/app/src/main/java/io/v/android/apps/reader/db/DB.java
@@ -0,0 +1,91 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package io.v.android.apps.reader.db;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+
+import io.v.android.apps.reader.model.Listener;
+import io.v.android.apps.reader.model.File;
+
+/**
+ * Provides high-level methods for getting and setting the state of PDF reader.
+ * It is an interface instead of a concrete class to make testing easier.
+ */
+public interface DB {
+
+    class Singleton {
+
+        private static volatile DB instance;
+
+        public static DB get(Context context) {
+            DB result = instance;
+            if (instance == null) {
+                synchronized (Singleton.class) {
+                    result = instance;
+                    if (result == null) {
+                        // uncomment either one
+                        instance = result = new FakeDB(context);
+//                        instance = result = new SyncbaseDB(context);
+                    }
+                }
+            }
+
+            return result;
+        }
+    }
+
+    /**
+     * Perform initialization steps.  This method must be called early in the lifetime
+     * of the activity.  As part of the initialization, it might send an intent to
+     * another activity.
+     *
+     * @param activity implements onActivityResult() to call into DB.onActivityResult.
+     */
+    void init(Activity activity);
+
+    /**
+     * If init() sent an intent to another Activity, the result must be forwarded
+     * from our app's activity to this method.
+     *
+     * @return true if the requestCode matches an intent sent by this implementation.
+     */
+    boolean onActivityResult(int requestCode, int resultCode, Intent data);
+
+    /**
+     * Provides a list of elements that fits well with RecyclerView.Adapter.
+     */
+    interface DBList<E> {
+        /**
+         * Returns the number of available elements.
+         */
+        int getItemCount();
+
+        /**
+         * Returns the element at the given position.
+         */
+        E getItem(int position);
+
+        /**
+         * Sets the listener for changes to the list.
+         * There can only be one listener.
+         */
+        void setListener(Listener listener);
+
+        /**
+         * Indicates that the list is no longer needed
+         * and should stop notifying its listener.
+         */
+        void discard();
+    }
+
+    /**
+     * Gets the list of available PDF files.
+     * @return a list of PDF files.
+     */
+    DBList<File> getFileList();
+
+}
diff --git a/android/app/src/main/java/io/v/android/apps/reader/db/FakeDB.java b/android/app/src/main/java/io/v/android/apps/reader/db/FakeDB.java
new file mode 100644
index 0000000..63507f9
--- /dev/null
+++ b/android/app/src/main/java/io/v/android/apps/reader/db/FakeDB.java
@@ -0,0 +1,131 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package io.v.android.apps.reader.db;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import io.v.android.apps.reader.model.Listener;
+import io.v.android.apps.reader.model.File;
+import io.v.v23.services.syncbase.nosql.BlobRef;
+
+/**
+ * A fake implementation of the DB interface for manual testing.
+ */
+public class FakeDB implements DB {
+
+    private static final String[] FILE_NAMES = {
+            "Foo.pdf",
+            "Bar.pdf"
+    };
+
+    private FakeFileList mFileList;
+
+    public FakeDB(Context context) {
+        mFileList = new FakeFileList();
+    }
+
+    class FakeFile implements File {
+
+        private String mId;
+        private BlobRef mRef;
+        private String mTitle;
+        private long mSize;
+        private String mType;
+
+        public FakeFile(String title) {
+            this(null, null, title, 0, null);
+        }
+
+        public FakeFile(String id, BlobRef ref, String title, long size, String type) {
+            mId = id;
+            mRef = ref;
+            mTitle = title;
+            mSize = size;
+            mType = type;
+        }
+
+        @Override
+        public String getId() {
+            return mId;
+        }
+
+        @Override
+        public BlobRef getRef() {
+            return mRef;
+        }
+
+        @Override
+        public String getTitle() {
+            return mTitle;
+        }
+
+        @Override
+        public long getSize() {
+            return mSize;
+        }
+
+        @Override
+        public String getType() {
+            return mType;
+        }
+    }
+
+    class FakeFileList implements DBList<File> {
+
+        private List<FakeFile> mFiles;
+        private Listener mListener;
+
+        public FakeFileList() {
+            mFiles = new ArrayList<>();
+            for (String fileName : FILE_NAMES) {
+                mFiles.add(new FakeFile(fileName));
+            }
+        }
+
+        @Override
+        public int getItemCount() {
+            return mFiles.size();
+        }
+
+        @Override
+        public FakeFile getItem(int position) {
+            return mFiles.get(position);
+        }
+
+        @Override
+        public void setListener(Listener listener) {
+            // This fake list never calls the notify methods.
+            // Just check if the listener is set only once.
+            assert mListener == null;
+            mListener = listener;
+        }
+
+        @Override
+        public void discard() {
+            // Nothing to do.
+        }
+    }
+
+    public void init(Activity activity) {
+        // Nothing to do.
+    }
+
+    @Override
+    public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
+        // Nothing to do.
+        return false;
+    }
+
+    @Override
+    public DBList<File> getFileList() {
+        return mFileList;
+    }
+
+}
diff --git a/android/app/src/main/java/io/v/android/apps/reader/SyncbaseDB.java b/android/app/src/main/java/io/v/android/apps/reader/db/SyncbaseDB.java
similarity index 91%
rename from android/app/src/main/java/io/v/android/apps/reader/SyncbaseDB.java
rename to android/app/src/main/java/io/v/android/apps/reader/db/SyncbaseDB.java
index 281fcba..2ca0bde 100644
--- a/android/app/src/main/java/io/v/android/apps/reader/SyncbaseDB.java
+++ b/android/app/src/main/java/io/v/android/apps/reader/db/SyncbaseDB.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package io.v.android.apps.reader;
+package io.v.android.apps.reader.db;
 
 import android.app.Activity;
 import android.content.Context;
@@ -13,8 +13,8 @@
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 
-import java.io.File;
-
+import io.v.android.apps.reader.model.Listener;
+import io.v.android.apps.reader.model.File;
 import io.v.android.libs.security.BlessingsManager;
 import io.v.android.v23.V;
 import io.v.android.v23.services.blessing.BlessingCreationException;
@@ -146,7 +146,7 @@
 
     private void setupSyncbase(Blessings blessings) {
         // Prepare the syncbase storage directory.
-        File storageDir = new File(mContext.getFilesDir(), "syncbase");
+        java.io.File storageDir = new java.io.File(mContext.getFilesDir(), "syncbase");
         storageDir.mkdirs();
 
         try {
@@ -181,29 +181,20 @@
             if (!mFiles.exists(vContext)) {
                 mFiles.create(vContext, mPermissions);
             }
-
-            // TODO(youngseokyoon): remove this temporary test.
-            testSyncbaseTable();
         } catch (VException e) {
             handleError("Couldn't setup syncbase service: " + e.getMessage());
         }
     }
 
-    private void testSyncbaseTable() throws VException {
-        mFiles.put(vContext, "testKey", "testValue", String.class);
-        String result = (String) mFiles.get(vContext, "testKey", String.class);
-        Log.d(TAG, "TestResult: " + result);
-    }
-
     // TODO(youngseokyoon): Remove once the list is implemented properly.
-    private static class EmptyPdfFileList implements DB.PdfFileList {
+    private static class EmptyFileList implements DBList<File> {
         @Override
         public int getItemCount() {
             return 0;
         }
 
         @Override
-        public PdfFile getPdfFile(int position) {
+        public File getItem(int position) {
             return null;
         }
 
@@ -217,8 +208,8 @@
     }
 
     @Override
-    public PdfFileList getPdfFileList() {
-        return new EmptyPdfFileList();
+    public DBList<File> getFileList() {
+        return new EmptyFileList();
     }
 
     private void handleError(String msg) {
diff --git a/android/app/src/main/java/io/v/android/apps/reader/model/File.java b/android/app/src/main/java/io/v/android/apps/reader/model/File.java
new file mode 100644
index 0000000..6fca3dd
--- /dev/null
+++ b/android/app/src/main/java/io/v/android/apps/reader/model/File.java
@@ -0,0 +1,18 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package io.v.android.apps.reader.model;
+
+import io.v.v23.services.syncbase.nosql.BlobRef;
+
+/**
+ * Represents a PDF file and its metadata.
+ */
+public interface File {
+    String getId();
+    BlobRef getRef();
+    String getTitle();
+    long getSize();
+    String getType();
+}
diff --git a/android/app/src/main/java/io/v/android/apps/reader/model/Listener.java b/android/app/src/main/java/io/v/android/apps/reader/model/Listener.java
new file mode 100644
index 0000000..8ab439e
--- /dev/null
+++ b/android/app/src/main/java/io/v/android/apps/reader/model/Listener.java
@@ -0,0 +1,14 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package io.v.android.apps.reader.model;
+
+/**
+ * Callbacks for when the dataset changes dynamically.
+ */
+public interface Listener {
+    void notifyItemChanged(int position);
+    void notifyItemInserted(int position);
+    void notifyItemRemoved(int position);
+}