diff --git a/.idea/encodings.xml b/.idea/encodings.xml
new file mode 100644
index 0000000000..97626ba454
--- /dev/null
+++ b/.idea/encodings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
new file mode 100644
index 0000000000..8d2df476e5
--- /dev/null
+++ b/.idea/gradle.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/appcompat_v7_23_1_1.xml b/.idea/libraries/appcompat_v7_23_1_1.xml
new file mode 100644
index 0000000000..ba79709059
--- /dev/null
+++ b/.idea/libraries/appcompat_v7_23_1_1.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/design_23_1_1.xml b/.idea/libraries/design_23_1_1.xml
new file mode 100644
index 0000000000..da1aaa46da
--- /dev/null
+++ b/.idea/libraries/design_23_1_1.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/recyclerview_v7_23_1_1.xml b/.idea/libraries/recyclerview_v7_23_1_1.xml
new file mode 100644
index 0000000000..dabc8b7b84
--- /dev/null
+++ b/.idea/libraries/recyclerview_v7_23_1_1.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/support_annotations_23_1_1.xml b/.idea/libraries/support_annotations_23_1_1.xml
new file mode 100644
index 0000000000..00e0e70313
--- /dev/null
+++ b/.idea/libraries/support_annotations_23_1_1.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/support_v4_23_1_1.xml b/.idea/libraries/support_v4_23_1_1.xml
new file mode 100644
index 0000000000..3eee20cfc7
--- /dev/null
+++ b/.idea/libraries/support_v4_23_1_1.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/README.md b/README.md
index ebf306d1d7..efcd8bfa9a 100644
--- a/README.md
+++ b/README.md
@@ -41,7 +41,7 @@ You can make improvements to the project as you require. However this project is
* [`AccountDAO`](/app/src/main/java/lk/ac/mrt/cse/dbs/simpleexpensemanager/data/AccountDAO.java)
* [`TransactionDAO`](/app/src/main/java/lk/ac/mrt/cse/dbs/simpleexpensemanager/data/TransactionDAO.java)
4. Extend and implement the `setup()` method of the abstract class [`ExpenseManager`](/app/src/main/java/lk/ac/mrt/cse/dbs/simpleexpensemanager/control/ExpenseManager.java).
-5. Change current implementation to your implementation in the [`MainActivity`](/app/src/main/java/lk/ac/mrt/cse/dbs/simpleexpensemanager/ui/MainActivity.java) ui class.
+5. Change current implementation to your implementation in the [`MainActivity`](/app/src/main/java/lk/ac/mrt/cse/dbs/simpleexpensemanager/ui/MainActivity.java) UI class.
Current implementation
```Java
diff --git a/SimpleExpenseManager.iml b/SimpleExpenseManager.iml
new file mode 100644
index 0000000000..79b88c864d
--- /dev/null
+++ b/SimpleExpenseManager.iml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 7a80be4194..a019d8d57c 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -19,6 +19,7 @@
package="lk.ac.mrt.cse.dbs.simpleexpensemanager">
getAccountNumbersList() {
+
+ //Open the database connection
+ DBHandler handler = DBHandler.getInstance(context);
+ if( handler == null){
+ System.out.print("Damn");
+ }
+ SQLiteDatabase db = handler.getReadableDatabase();
+
+ //Query to select all account numbers from the account table
+ String query = "SELECT "+ Fields.COLUMN_ACCOUNT_NO+" FROM " + Fields.TABLE_ACCOUNT+" ORDER BY " + Fields.COLUMN_ACCOUNT_NO + " ASC";
+
+ Cursor cursor = db.rawQuery(query, null);
+
+ ArrayList resultSet = new ArrayList<>();
+
+ //Add account numbers to a list
+ while (cursor.moveToNext())
+ {
+ resultSet.add(cursor.getString(cursor.getColumnIndex(Fields.COLUMN_ACCOUNT_NO)));
+ }
+
+ cursor.close();
+
+ //Return the list of account numbers
+ return resultSet;
+
+ }
+
+ @Override
+ public List getAccountsList() {
+
+ DBHandler handler = DBHandler.getInstance(context);
+ SQLiteDatabase db = handler.getReadableDatabase();
+
+ //Query to select all the details about all the accounts in the account table
+ String query = "SELECT * FROM " + Fields.TABLE_ACCOUNT+" ORDER BY "+Fields.COLUMN_ACCOUNT_NO+" ASC";
+
+ Cursor cursor = db.rawQuery(query, null);
+
+ ArrayList resultSet = new ArrayList<>();
+
+ //Add account details to a list
+ while (cursor.moveToNext())
+ {
+ Account account = new Account(cursor.getString(cursor.getColumnIndex(Fields.COLUMN_ACCOUNT_NO)),
+ cursor.getString(cursor.getColumnIndex(Fields.COLUMN_BANK_NAME)),
+ cursor.getString(cursor.getColumnIndex(Fields.COLUMN_ACCOUNT_HOLDER_NAME)),
+ cursor.getDouble(cursor.getColumnIndex(Fields.COLUMN_BALANCE)));
+
+ resultSet.add(account);
+ }
+
+ cursor.close();
+
+ //Return list of account objects
+ return resultSet;
+
+ }
+
+ @Override
+ public Account getAccount(String accountNo) throws InvalidAccountException {
+
+ DBHandler handler = DBHandler.getInstance(context);
+ SQLiteDatabase db = handler.getReadableDatabase();
+
+ //Query to get details of the account specifiec by the account number
+ String query = "SELECT * FROM " + Fields.TABLE_ACCOUNT + " WHERE " + Fields.COLUMN_ACCOUNT_NO + " = '" + accountNo + "'";
+
+ Cursor cursor = db.rawQuery(query, null);
+
+ Account account = null;
+
+ //add the details to an account object
+ if (cursor.moveToFirst()) {
+ account = new Account(cursor.getString(cursor.getColumnIndex(Fields.COLUMN_ACCOUNT_NO)),
+ cursor.getString(cursor.getColumnIndex(Fields.COLUMN_BANK_NAME)),
+ cursor.getString(cursor.getColumnIndex(Fields.COLUMN_ACCOUNT_HOLDER_NAME)),
+ cursor.getDouble(cursor.getColumnIndex(Fields.COLUMN_BALANCE)));
+ }
+ //If account is not found throw an exception
+ else {
+ throw new InvalidAccountException("You have selected an invalid account number...!");
+ }
+
+ cursor.close();
+
+ //Return the account object
+ return account;
+ }
+
+ @Override
+ public void addAccount(Account account) {
+
+ DBHandler handler = DBHandler.getInstance(context);
+ SQLiteDatabase db = handler.getWritableDatabase();
+
+ //Save account details to the account table
+ ContentValues values = new ContentValues();
+ values.put(Fields.COLUMN_ACCOUNT_NO, account.getAccountNo());
+ values.put(Fields.COLUMN_BANK_NAME, account.getBankName());
+ values.put(Fields.COLUMN_ACCOUNT_HOLDER_NAME, account.getAccountHolderName());
+ values.put(Fields.COLUMN_BALANCE, account.getBalance());
+
+ db.insert(Fields.TABLE_ACCOUNT, null, values);
+
+ }
+
+ @Override
+ public void removeAccount(String accountNo) throws InvalidAccountException {
+
+ DBHandler handler = DBHandler.getInstance(context);
+ SQLiteDatabase db = handler.getWritableDatabase();
+
+ //Query to delete a particular account from the account table
+ String query = "SELECT * FROM " + Fields.TABLE_ACCOUNT + " WHERE " + Fields.COLUMN_ACCOUNT_NO + " = '" + accountNo + "'";
+
+ Cursor cursor = db.rawQuery(query, null);
+
+ Account account = null;
+
+ //Delete the account if found in the table
+ if (cursor.moveToFirst()) {
+ account = new Account(cursor.getString(cursor.getColumnIndex(Fields.COLUMN_ACCOUNT_NO)),
+ cursor.getString(cursor.getColumnIndex(Fields.COLUMN_BANK_NAME)),
+ cursor.getString(cursor.getColumnIndex(Fields.COLUMN_ACCOUNT_HOLDER_NAME)),
+ cursor.getFloat(cursor.getColumnIndex(Fields.COLUMN_BALANCE)));
+ db.delete(Fields.TABLE_ACCOUNT, Fields.COLUMN_ACCOUNT_NO + " = ?", new String[] { accountNo });
+ cursor.close();
+
+ }
+ //If account is not found throw an exception
+ else {
+ throw new InvalidAccountException("No such account found...!");
+ }
+
+ }
+
+ @Override
+ public void updateBalance(String accountNo, ExpenseType expenseType, double amount) throws InvalidAccountException {
+
+ DBHandler handler = DBHandler.getInstance(context);
+ SQLiteDatabase db = handler.getWritableDatabase();
+
+ ContentValues values = new ContentValues();
+
+ //Retrieve the account details of the selected account
+ Account account = getAccount(accountNo);
+
+ //Update the balance if the account is found in the table
+ if (account!=null) {
+
+ double new_amount=0;
+
+ //Deduct the amount is it is an expense
+ if (expenseType.equals(ExpenseType.EXPENSE)) {
+ new_amount = account.getBalance() - amount;
+ }
+ //Add the amount if it is an income
+ else if (expenseType.equals(ExpenseType.INCOME)) {
+ new_amount = account.getBalance() + amount;
+ }
+
+ //Query to update balance in the account table
+ String strSQL = "UPDATE "+Fields.TABLE_ACCOUNT+" SET "+Fields.COLUMN_BALANCE+" = "+new_amount+" WHERE "+Fields.COLUMN_ACCOUNT_NO+" = '"+ accountNo+"'";
+
+ db.execSQL(strSQL);
+
+ }
+ //If account is not found throw an exception
+ else {
+ throw new InvalidAccountException("No such account found...!");
+ }
+
+ }
+}
diff --git a/app/src/main/java/lk/ac/mrt/cse/dbs/simpleexpensemanager/data/impl/PersistentTransactionDAO.java b/app/src/main/java/lk/ac/mrt/cse/dbs/simpleexpensemanager/data/impl/PersistentTransactionDAO.java
new file mode 100644
index 0000000000..f87c62f901
--- /dev/null
+++ b/app/src/main/java/lk/ac/mrt/cse/dbs/simpleexpensemanager/data/impl/PersistentTransactionDAO.java
@@ -0,0 +1,118 @@
+package lk.ac.mrt.cse.dbs.simpleexpensemanager.data.impl;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import lk.ac.mrt.cse.dbs.simpleexpensemanager.data.TransactionDAO;
+import lk.ac.mrt.cse.dbs.simpleexpensemanager.data.model.ExpenseType;
+import lk.ac.mrt.cse.dbs.simpleexpensemanager.data.model.Transaction;
+import lk.ac.mrt.cse.dbs.simpleexpensemanager.database.DBHandler;
+import lk.ac.mrt.cse.dbs.simpleexpensemanager.database.Fields;
+
+/**
+ * Created by Eranga on 12/6/2015.
+ */
+public class PersistentTransactionDAO implements TransactionDAO {
+
+ private Context context;
+
+ //Constructor
+ public PersistentTransactionDAO(Context context) {
+ this.context = context;
+ }
+
+ @Override
+ public void logTransaction(Date date, String accountNo, ExpenseType expenseType, double amount) {
+
+ DBHandler handler = DBHandler.getInstance(context);
+ SQLiteDatabase db = handler.getReadableDatabase();
+
+ //Save transaction details to the transaction_log table
+ ContentValues values = new ContentValues();
+ values.put(Fields.COLUMN_ACCOUNT_NO, accountNo);
+ values.put(Fields.COLUMN_TRANSACTION_DATE, convertDateToString(date));
+ values.put(Fields.COLUMN_TRANSACTION_AMOUNT, amount);
+ values.put(Fields.COLUMN_EXPENSE_TYPE, expenseType.toString());
+
+ db.insert(Fields.TABLE_TRANSACTION_LOG,null,values);
+ }
+
+ @Override
+ public List getAllTransactionLogs() {
+ return getPaginatedTransactionLogs(0);
+ }
+
+ @Override
+ public List getPaginatedTransactionLogs(int limit) {
+
+ DBHandler handler = DBHandler.getInstance(context);
+ SQLiteDatabase db = handler.getReadableDatabase();
+
+ //Query to get details of all the transactions
+ String query = "SELECT "+ Fields.COLUMN_ACCOUNT_NO + ", " +
+ Fields.COLUMN_TRANSACTION_DATE + ", " +
+ Fields.COLUMN_EXPENSE_TYPE+", " +
+ Fields.COLUMN_TRANSACTION_AMOUNT +
+ " FROM " + Fields.TABLE_TRANSACTION_LOG + " ORDER BY " + Fields.COLUMN_TRANSACTION_ID + " DESC";
+
+ Cursor cursor = db.rawQuery(query, null);
+
+ ArrayList transactionLogs = new ArrayList<>();
+
+ //Add the transaction details to a list
+ while (cursor.moveToNext())
+ {
+ try {
+
+ ExpenseType expenseType = null;
+ if (cursor.getString(cursor.getColumnIndex(Fields.COLUMN_EXPENSE_TYPE)).equals(ExpenseType.INCOME.toString())) {
+ expenseType = ExpenseType.INCOME;
+ }
+ else{
+ expenseType = ExpenseType.EXPENSE;
+ }
+
+ String dateString = cursor.getString(cursor.getColumnIndex(Fields.COLUMN_TRANSACTION_DATE));
+ Date date = convertStringToDate(dateString);
+
+ Transaction tans = new Transaction(
+ date,
+ cursor.getString(cursor.getColumnIndex(Fields.COLUMN_ACCOUNT_NO)),
+ expenseType,
+ cursor.getDouble(cursor.getColumnIndex(Fields.COLUMN_TRANSACTION_AMOUNT)));
+
+ transactionLogs.add(tans);
+
+ } catch (ParseException e) {
+ e.printStackTrace();
+ }
+
+ }
+
+ //Return the list of transactions
+ return transactionLogs;
+ }
+
+ //Method to convert a date object to a string
+ public static String convertDateToString(Date date){
+ SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy");
+ String dateString = dateFormat.format(date);
+ return dateString;
+
+ }
+
+ //Method to convert a string to a date object
+ public static Date convertStringToDate(String date) throws ParseException {
+ SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy");
+ Date strDate = dateFormat.parse(date);
+ return strDate;
+ }
+}
diff --git a/app/src/main/java/lk/ac/mrt/cse/dbs/simpleexpensemanager/database/DBHandler.java b/app/src/main/java/lk/ac/mrt/cse/dbs/simpleexpensemanager/database/DBHandler.java
new file mode 100644
index 0000000000..d63478e3f5
--- /dev/null
+++ b/app/src/main/java/lk/ac/mrt/cse/dbs/simpleexpensemanager/database/DBHandler.java
@@ -0,0 +1,64 @@
+package lk.ac.mrt.cse.dbs.simpleexpensemanager.database;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+
+/**
+ * Created by Eranga on 12/6/2015.
+ */
+public class DBHandler extends SQLiteOpenHelper {
+ private static DBHandler handler = null;
+
+ //private static final
+ private static final String DATABASE_NAME = "130401J.db";
+ private static final int DATABASE_VERSION = 1;
+
+
+ public DBHandler(Context context) {
+ super(context,DATABASE_NAME,null,DATABASE_VERSION);
+ }
+
+ public static DBHandler getInstance(Context context)
+ {
+ if(handler == null)
+ handler = new DBHandler(context);
+ return handler;
+ }
+
+ //private static final
+
+ @Override
+ public void onCreate(SQLiteDatabase sqLiteDatabase) {
+
+ String accountTable = "CREATE TABLE " +
+ Fields.TABLE_ACCOUNT + "("
+ + Fields.COLUMN_ACCOUNT_NO + " VARCHAR(20) NOT NULL PRIMARY KEY,"
+ + Fields.COLUMN_BANK_NAME + " VARCHAR(100) NULL,"
+ + Fields.COLUMN_ACCOUNT_HOLDER_NAME + " VARCHAR(100) NULL,"
+ + Fields.COLUMN_BALANCE + " DECIMAL(10,2) NULL )";
+
+ String transactionTable = "CREATE TABLE " +
+ Fields.TABLE_TRANSACTION_LOG + "("
+ + Fields.COLUMN_TRANSACTION_ID + " INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,"
+ + Fields.COLUMN_ACCOUNT_NO + " VARCHAR(100) NOT NULL,"
+ + Fields.COLUMN_TRANSACTION_DATE + " DATE NULL,"
+ + Fields.COLUMN_TRANSACTION_AMOUNT + " DECIMAL(10,2) NULL,"
+ + Fields.COLUMN_EXPENSE_TYPE + " VARCHAR(100) NULL, " +
+ "FOREIGN KEY("+Fields.COLUMN_ACCOUNT_NO+") REFERENCES "+Fields.TABLE_ACCOUNT+"("+Fields.COLUMN_ACCOUNT_NO+"))";
+
+ sqLiteDatabase.execSQL(accountTable);
+ sqLiteDatabase.execSQL(transactionTable);
+
+ }
+
+ @Override
+ public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int j) {
+
+ sqLiteDatabase.execSQL("DROP TABLE IF EXISTS " + Fields.TABLE_ACCOUNT);
+ sqLiteDatabase.execSQL("DROP TABLE IF EXISTS " + Fields.TABLE_TRANSACTION_LOG);
+ onCreate(sqLiteDatabase);
+
+ }
+}
diff --git a/app/src/main/java/lk/ac/mrt/cse/dbs/simpleexpensemanager/database/Fields.java b/app/src/main/java/lk/ac/mrt/cse/dbs/simpleexpensemanager/database/Fields.java
new file mode 100644
index 0000000000..fd989b415f
--- /dev/null
+++ b/app/src/main/java/lk/ac/mrt/cse/dbs/simpleexpensemanager/database/Fields.java
@@ -0,0 +1,22 @@
+package lk.ac.mrt.cse.dbs.simpleexpensemanager.database;
+
+/**
+ * Created by Eranga on 12/6/2015.
+ */
+public class Fields {
+
+ //account table
+ public static final String TABLE_ACCOUNT = "account";
+ public static final String COLUMN_ACCOUNT_NO = "accountNo";
+ public static final String COLUMN_BANK_NAME = "bankName";
+ public static final String COLUMN_ACCOUNT_HOLDER_NAME = "accountHolderName";
+ public static final String COLUMN_BALANCE = "balance";
+
+ //transaction_log table
+ public static final String TABLE_TRANSACTION_LOG = "transaction_log";
+ public static final String COLUMN_TRANSACTION_ID = "transaction_id";
+ public static final String COLUMN_TRANSACTION_AMOUNT = "amount";
+ public static final String COLUMN_TRANSACTION_DATE = "date";
+ public static final String COLUMN_EXPENSE_TYPE = "expense_type";
+
+}
diff --git a/app/src/main/java/lk/ac/mrt/cse/dbs/simpleexpensemanager/ui/MainActivity.java b/app/src/main/java/lk/ac/mrt/cse/dbs/simpleexpensemanager/ui/MainActivity.java
index 46c5f78299..c6fa3267ee 100644
--- a/app/src/main/java/lk/ac/mrt/cse/dbs/simpleexpensemanager/ui/MainActivity.java
+++ b/app/src/main/java/lk/ac/mrt/cse/dbs/simpleexpensemanager/ui/MainActivity.java
@@ -16,6 +16,7 @@
package lk.ac.mrt.cse.dbs.simpleexpensemanager.ui;
+import android.content.Context;
import android.os.Bundle;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
@@ -25,9 +26,10 @@
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
+import lk.ac.mrt.cse.dbs.simpleexpensemanager.AppContext;
import lk.ac.mrt.cse.dbs.simpleexpensemanager.R;
import lk.ac.mrt.cse.dbs.simpleexpensemanager.control.ExpenseManager;
-import lk.ac.mrt.cse.dbs.simpleexpensemanager.control.InMemoryDemoExpenseManager;
+import lk.ac.mrt.cse.dbs.simpleexpensemanager.control.PersistentExpenseManager;
public class MainActivity extends AppCompatActivity {
private ExpenseManager expenseManager;
@@ -45,6 +47,7 @@ public class MainActivity extends AppCompatActivity {
* The {@link ViewPager} that will host the section contents.
*/
private ViewPager mViewPager;
+ private Context context;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -65,7 +68,8 @@ protected void onCreate(Bundle savedInstanceState) {
tabLayout.setupWithViewPager(mViewPager);
/*** Begin generating dummy data for In-Memory implementation ***/
- expenseManager = new InMemoryDemoExpenseManager();
+ context = AppContext.getContext();
+ expenseManager = new PersistentExpenseManager(context);
/*** END ***/
}