diff --git a/app/build.gradle b/app/build.gradle index 5b521a10..668cf4df 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -39,6 +39,7 @@ dependencies { compile 'com.android.support:recyclerview-v7:25.3.1' compile 'com.squareup.picasso:picasso:2.5.2' compile 'org.apache.commons:commons-lang3:3.6' + compile 'org.apache.commons:commons-collections4:4.1' testCompile 'junit:junit:4.12' testCompile 'org.powermock:powermock-api-mockito:1.6.1' diff --git a/app/src/main/java/io/github/wulkanowy/activity/dashboard/marks/MarksFragment.java b/app/src/main/java/io/github/wulkanowy/activity/dashboard/marks/MarksFragment.java index 0b782e23..5f206580 100644 --- a/app/src/main/java/io/github/wulkanowy/activity/dashboard/marks/MarksFragment.java +++ b/app/src/main/java/io/github/wulkanowy/activity/dashboard/marks/MarksFragment.java @@ -6,7 +6,6 @@ import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.RecyclerView; -import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -20,16 +19,17 @@ import java.util.Map; import io.github.wulkanowy.R; import io.github.wulkanowy.api.Cookies; import io.github.wulkanowy.api.StudentAndParent; -import io.github.wulkanowy.api.grades.Grade; import io.github.wulkanowy.api.grades.GradesList; import io.github.wulkanowy.api.grades.Subject; import io.github.wulkanowy.api.grades.SubjectsList; -import io.github.wulkanowy.database.accounts.AccountData; -import io.github.wulkanowy.database.accounts.DatabaseAccount; +import io.github.wulkanowy.database.accounts.Account; +import io.github.wulkanowy.database.accounts.AccountsDatabase; +import io.github.wulkanowy.database.grades.GradesDatabase; +import io.github.wulkanowy.database.subjects.SubjectsDatabase; public class MarksFragment extends Fragment { - private ArrayList subject = new ArrayList<>(); + private ArrayList subjectsName = new ArrayList<>(); private View view; @@ -38,13 +38,13 @@ public class MarksFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { + Bundle savedInstanceState) { view = inflater.inflate(R.layout.fragment_marks, container, false); - if (subject.size() == 0) { + if (subjectsName.size() == 0) { new MarksTask(container.getContext()).execute(); - } else if (subject.size() > 1) { + } else if (subjectsName.size() > 1) { createGrid(); view.findViewById(R.id.loadingPanel).setVisibility(View.GONE); } @@ -59,7 +59,7 @@ public class MarksFragment extends Fragment { RecyclerView.LayoutManager layoutManager = new GridLayoutManager(view.getContext(), 2); recyclerView.setLayoutManager(layoutManager); - ImageAdapter adapter = new ImageAdapter(view.getContext(), subject); + ImageAdapter adapter = new ImageAdapter(view.getContext(), subjectsName); recyclerView.setAdapter(adapter); } @@ -86,22 +86,31 @@ public class MarksFragment extends Fragment { try { Cookies cookies = new Cookies(); cookies.setItems(loginCookies); - DatabaseAccount databaseAccount = new DatabaseAccount(mContext); - databaseAccount.open(); - AccountData accountData = databaseAccount.getAccount(1); - databaseAccount.close(); - StudentAndParent snp = new StudentAndParent(cookies, accountData.getCounty()).setUp(); + + AccountsDatabase accountsDatabase = new AccountsDatabase(mContext); + accountsDatabase.open(); + Account account = accountsDatabase.getAccount(mContext.getSharedPreferences("LoginData", mContext.MODE_PRIVATE).getLong("isLogin", 0)); + accountsDatabase.close(); + + StudentAndParent snp = new StudentAndParent(cookies, account.getCounty()).setUp(); SubjectsList subjectsList = new SubjectsList(snp.getCookiesObject(), snp); - List subjects = subjectsList.getAll(); - for (Subject item : subjects) { - subject.add(item.getName()); + + SubjectsDatabase subjectsDatabase = new SubjectsDatabase(mContext); + subjectsDatabase.open(); + subjectsDatabase.put(subjectsList.getAll()); + List subjects = subjectsDatabase.getAllSubjectsNames(); + subjectsDatabase.close(); + + for (Subject subject : subjects) { + subjectsName.add(subject.getName()); } GradesList gradesList = new GradesList(snp.getCookiesObject(), snp); - List grades = gradesList.getAll(); - for (Grade item : grades) { - Log.d("MarksFragment", item.getSubject() + ": " + item.getValue()); - } + GradesDatabase gradesDatabase = new GradesDatabase(mContext); + gradesDatabase.open(); + gradesDatabase.put(gradesList.getAll()); + gradesDatabase.close(); + } catch (Exception e) { e.printStackTrace(); } diff --git a/app/src/main/java/io/github/wulkanowy/activity/main/LoginTask.java b/app/src/main/java/io/github/wulkanowy/activity/main/LoginTask.java index 243b7b26..88940784 100644 --- a/app/src/main/java/io/github/wulkanowy/activity/main/LoginTask.java +++ b/app/src/main/java/io/github/wulkanowy/activity/main/LoginTask.java @@ -3,6 +3,7 @@ package io.github.wulkanowy.activity.main; import android.app.Activity; import android.app.ProgressDialog; import android.content.Intent; +import android.content.SharedPreferences; import android.database.SQLException; import android.os.AsyncTask; import android.widget.Toast; @@ -22,8 +23,8 @@ import io.github.wulkanowy.api.login.LoginErrorException; import io.github.wulkanowy.api.user.BasicInformation; import io.github.wulkanowy.api.user.PersonalData; import io.github.wulkanowy.api.user.User; -import io.github.wulkanowy.database.accounts.AccountData; -import io.github.wulkanowy.database.accounts.DatabaseAccount; +import io.github.wulkanowy.database.accounts.Account; +import io.github.wulkanowy.database.accounts.AccountsDatabase; import io.github.wulkanowy.security.CryptoException; import io.github.wulkanowy.security.Safety; @@ -87,17 +88,23 @@ public class LoginTask extends AsyncTask { Safety safety = new Safety(activity); - AccountData accountData = new AccountData() + Account account = new Account() .setName(firstAndLastName) .setEmail(credentials[0]) .setPassword(safety.encrypt(credentials[0], credentials[1])) .setCounty(credentials[2]); - DatabaseAccount databaseAccount = new DatabaseAccount(activity); + AccountsDatabase accountsDatabase = new AccountsDatabase(activity); + + accountsDatabase.open(); + long idUser = accountsDatabase.put(account); + accountsDatabase.close(); + + SharedPreferences sharedPreferences = activity.getSharedPreferences("LoginData", activity.MODE_PRIVATE); + SharedPreferences.Editor editor = sharedPreferences.edit(); + editor.putLong("isLogin", idUser); + editor.apply(); - databaseAccount.open(); - databaseAccount.put(accountData); - databaseAccount.close(); } catch (SQLException e) { return R.string.SQLite_ioError_text; } catch (IOException | LoginErrorException e) { diff --git a/app/src/main/java/io/github/wulkanowy/activity/started/LoadingTask.java b/app/src/main/java/io/github/wulkanowy/activity/started/LoadingTask.java index 27147f7a..5003f8b2 100644 --- a/app/src/main/java/io/github/wulkanowy/activity/started/LoadingTask.java +++ b/app/src/main/java/io/github/wulkanowy/activity/started/LoadingTask.java @@ -14,8 +14,8 @@ import java.net.SocketAddress; import io.github.wulkanowy.R; import io.github.wulkanowy.activity.main.LoginTask; import io.github.wulkanowy.activity.main.MainActivity; -import io.github.wulkanowy.database.accounts.AccountData; -import io.github.wulkanowy.database.accounts.DatabaseAccount; +import io.github.wulkanowy.database.accounts.Account; +import io.github.wulkanowy.database.accounts.AccountsDatabase; import io.github.wulkanowy.security.CryptoException; import io.github.wulkanowy.security.Safety; @@ -73,21 +73,22 @@ public class LoadingTask extends AsyncTask { private boolean signIn() { if (SAVE_DATA) { - DatabaseAccount databaseAccount = new DatabaseAccount(activity); + AccountsDatabase accountsDatabase = new AccountsDatabase(activity); + accountsDatabase.open(); - if (databaseAccount.checkExist()) { + if (accountsDatabase.checkExist("accounts", null, null)) { try { - AccountData accountData = databaseAccount.getAccount(1); - databaseAccount.close(); + Account account = accountsDatabase.getAccount(activity.getSharedPreferences("LoginData", activity.MODE_PRIVATE).getLong("isLogin", 0)); + accountsDatabase.close(); - if (accountData != null) { + if (account != null) { Safety safety = new Safety(activity); new LoginTask(activity, false).execute( - accountData.getEmail(), - safety.decrypt(accountData.getEmail(), accountData.getPassword()), - accountData.getCounty() + account.getEmail(), + safety.decrypt(account.getEmail(), account.getPassword()), + account.getCounty() ); return true; @@ -99,6 +100,7 @@ public class LoadingTask extends AsyncTask { Toast.makeText(activity, R.string.decrypt_failed, Toast.LENGTH_LONG).show(); } } + accountsDatabase.close(); } Intent intent = new Intent(activity, MainActivity.class); diff --git a/app/src/main/java/io/github/wulkanowy/api/grades/Grade.java b/app/src/main/java/io/github/wulkanowy/api/grades/Grade.java index 8acbaf7c..b362da8c 100644 --- a/app/src/main/java/io/github/wulkanowy/api/grades/Grade.java +++ b/app/src/main/java/io/github/wulkanowy/api/grades/Grade.java @@ -1,6 +1,14 @@ package io.github.wulkanowy.api.grades; +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; + public class Grade { + private int id; + + private int userID; + + private int subjectID; private String subject; @@ -8,6 +16,8 @@ public class Grade { private String color; + private String symbol; + private String description; private String weight; @@ -16,6 +26,40 @@ public class Grade { private String teacher; + private String semester; + + private boolean isNew; + + public int getId() { + return id; + } + + public Grade setId(int id) { + this.id = id; + + return this; + } + + public int getUserID() { + return userID; + } + + public Grade setUserID(int userID) { + this.userID = userID; + + return this; + } + + public int getSubjectID() { + return subjectID; + } + + public Grade setSubjectID(int subjectID) { + this.subjectID = subjectID; + + return this; + } + public String getSubject() { return subject; } @@ -46,6 +90,16 @@ public class Grade { return this; } + public String getSymbol() { + return symbol; + } + + public Grade setSymbol(String symbol) { + this.symbol = symbol; + + return this; + } + public String getDescription() { return description; } @@ -85,4 +139,59 @@ public class Grade { return this; } + + public String getSemester() { + return semester; + } + + public Grade setSemester(String semester) { + this.semester = semester; + + return this; + } + + public boolean isNew() { + return isNew; + } + + public Grade setIsNew(boolean isNew) { + this.isNew = isNew; + return this; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + + if (o == null || getClass() != o.getClass()) return false; + + Grade grade = (Grade) o; + + return new EqualsBuilder() + .append(subject, grade.subject) + .append(value, grade.value) + .append(color, grade.color) + .append(symbol, grade.symbol) + .append(description, grade.description) + .append(weight, grade.weight) + .append(date, grade.date) + .append(teacher, grade.teacher) + .append(semester, grade.semester) + .isEquals(); + } + + @Override + public int hashCode() { + return new HashCodeBuilder(17, 37) + .append(subject) + .append(value) + .append(color) + .append(symbol) + .append(description) + .append(weight) + .append(date) + .append(teacher) + .append(semester) + .toHashCode(); + } } diff --git a/app/src/main/java/io/github/wulkanowy/api/grades/Subject.java b/app/src/main/java/io/github/wulkanowy/api/grades/Subject.java index 99da55d9..06eda2a2 100644 --- a/app/src/main/java/io/github/wulkanowy/api/grades/Subject.java +++ b/app/src/main/java/io/github/wulkanowy/api/grades/Subject.java @@ -2,10 +2,24 @@ package io.github.wulkanowy.api.grades; public class Subject { + private int id; + private String name; + private String predictedRating; + private String finalRating; + public int getId(){ + return id; + } + + public Subject setId(int id){ + this.id = id; + + return this; + } + public String getName() { return name; } diff --git a/app/src/main/java/io/github/wulkanowy/database/DatabaseAdapter.java b/app/src/main/java/io/github/wulkanowy/database/DatabaseAdapter.java new file mode 100644 index 00000000..41e3b080 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/database/DatabaseAdapter.java @@ -0,0 +1,82 @@ +package io.github.wulkanowy.database; + +import android.content.Context; +import android.database.Cursor; +import android.database.SQLException; +import android.database.sqlite.SQLiteDatabase; +import android.util.Log; + +public class DatabaseAdapter { + + private final String DATABASE_NAME = "accountdatabase.db"; + private final int DATABASE_VERSION = 2; + public static SQLiteDatabase database; + private DatabaseHelper databaseHelper; + public Context context; + + public DatabaseAdapter(Context context) { + this.context = context; + } + + public DatabaseAdapter open() { + + databaseHelper = new DatabaseHelper(context, DATABASE_NAME, null, DATABASE_VERSION); + + try { + database = databaseHelper.getWritableDatabase(); + } catch (SQLException e) { + database = databaseHelper.getReadableDatabase(); + Log.w(DatabaseHelper.DEBUG_TAG, "Database in read-only"); + } + + Log.d(DatabaseHelper.DEBUG_TAG, "Open database"); + + return this; + } + + public void close() { + databaseHelper.close(); + + Log.d(DatabaseHelper.DEBUG_TAG, "Close database"); + } + + public boolean checkExist(String tableName, String dbfield, String fieldValue) { + + Cursor cursor; + + if (dbfield == null && fieldValue == null && tableName != null) { + cursor = database.rawQuery("SELECT COUNT(*) FROM " + tableName, null); + Log.d(DatabaseHelper.DEBUG_TAG, "Check exist " + tableName + " table"); + } else if (dbfield != null && fieldValue != null && tableName != null) { + cursor = database.rawQuery("SELECT COUNT(*) FROM " + tableName + " WHERE " + dbfield + "=?", new String[]{fieldValue}); + Log.d(DatabaseHelper.DEBUG_TAG, "Check exist " + fieldValue + " row"); + } else { + cursor = null; + } + + if (cursor != null) { + cursor.moveToFirst(); + + int count = cursor.getInt(0); + + if (count > 0) { + return true; + } + + cursor.close(); + } + + return false; + } + + public void deleteAndCreate(String tableName) { + + database.execSQL(databaseHelper.DROP_TABLE + tableName); + database.execSQL(databaseHelper.SUBJECT_TABLE); + database.execSQL(databaseHelper.ACCOUNT_TABLE); + database.execSQL(databaseHelper.GRADE_TABLE); + + Log.d(DatabaseHelper.DEBUG_TAG, "Recreate table " + tableName); + + } +} diff --git a/app/src/main/java/io/github/wulkanowy/database/DatabaseComparer.java b/app/src/main/java/io/github/wulkanowy/database/DatabaseComparer.java new file mode 100644 index 00000000..294176d5 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/database/DatabaseComparer.java @@ -0,0 +1,25 @@ +package io.github.wulkanowy.database; + + +import org.apache.commons.collections4.CollectionUtils; + +import java.util.ArrayList; +import java.util.List; + +import io.github.wulkanowy.api.grades.Grade; + +public class DatabaseComparer { + + public static List compareGradesLists(List newList, List oldList) { + + List addedOrUpdatedGradesList = new ArrayList<>(CollectionUtils.removeAll(newList, oldList)); + List updatedList = new ArrayList<>(CollectionUtils.removeAll(newList, addedOrUpdatedGradesList)); + + for (Grade grade : addedOrUpdatedGradesList) { + grade.setIsNew(true); + updatedList.add(grade); + } + + return updatedList; + } +} diff --git a/app/src/main/java/io/github/wulkanowy/database/DatabaseHelper.java b/app/src/main/java/io/github/wulkanowy/database/DatabaseHelper.java new file mode 100644 index 00000000..494bad2d --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/database/DatabaseHelper.java @@ -0,0 +1,62 @@ +package io.github.wulkanowy.database; + +import android.content.Context; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteDatabase.CursorFactory; +import android.database.sqlite.SQLiteOpenHelper; +import android.util.Log; + +public class DatabaseHelper extends SQLiteOpenHelper { + + public final static String DEBUG_TAG = "SQLiteWulkanowyDatabase"; + public final String ACCOUNT_TABLE = "CREATE TABLE IF NOT EXISTS accounts( " + + "id INTEGER PRIMARY KEY AUTOINCREMENT, " + + "name TEXT, " + + "email TEXT," + + "password TEXT, " + + "county TEXT );"; + public final String SUBJECT_TABLE = "CREATE TABLE IF NOT EXISTS subjects( " + + "id INTEGER PRIMARY KEY AUTOINCREMENT, " + + "name TEXT, " + + "predictedRating1 TEXT, " + + "finalRating1 TEXT, " + + "predictedRating2 TEXT, " + + "finalRating2 TEXT );"; + public final String GRADE_TABLE = "CREATE TABLE IF NOT EXISTS grades( " + + "id INTEGER PRIMARY KEY AUTOINCREMENT, " + + "userID INTEGER, " + + "subjectID INTEGER, " + + "subject TEXT, " + + "value TEXT, " + + "color TEXT, " + + "symbol TEXT, " + + "description TEXT, " + + "weight TEXT, " + + "date TEXT, " + + "teacher TEXT, " + + "semester INTEGER, " + + "isNew INTEGER );"; + + public final String DROP_TABLE = "DROP TABLE IF EXISTS "; + + public DatabaseHelper(Context context, String name, CursorFactory factory, int version) { + super(context, name, factory, version); + } + + @Override + public void onCreate(SQLiteDatabase db) { + db.execSQL(ACCOUNT_TABLE); + db.execSQL(SUBJECT_TABLE); + db.execSQL(GRADE_TABLE); + Log.d(DEBUG_TAG, "Create database"); + } + + @Override + public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { + db.execSQL(DROP_TABLE + "accounts"); + db.execSQL(DROP_TABLE + "subjects"); + db.execSQL(DROP_TABLE + "grades"); + onCreate(db); + Log.d(DEBUG_TAG, "Database upgrade from ver." + oldVersion + " to ver." + newVersion); + } +} diff --git a/app/src/main/java/io/github/wulkanowy/database/accounts/AccountData.java b/app/src/main/java/io/github/wulkanowy/database/accounts/Account.java similarity index 74% rename from app/src/main/java/io/github/wulkanowy/database/accounts/AccountData.java rename to app/src/main/java/io/github/wulkanowy/database/accounts/Account.java index 5c91301b..ba130e33 100644 --- a/app/src/main/java/io/github/wulkanowy/database/accounts/AccountData.java +++ b/app/src/main/java/io/github/wulkanowy/database/accounts/Account.java @@ -1,7 +1,7 @@ package io.github.wulkanowy.database.accounts; -public class AccountData { +public class Account { private int id; @@ -17,7 +17,7 @@ public class AccountData { return id; } - public AccountData setId(int id) { + public Account setId(int id) { this.id = id; return this; } @@ -26,7 +26,7 @@ public class AccountData { return name; } - public AccountData setName(String name) { + public Account setName(String name) { this.name = name; return this; } @@ -35,7 +35,7 @@ public class AccountData { return email; } - public AccountData setEmail(String email) { + public Account setEmail(String email) { this.email = email; return this; } @@ -44,7 +44,7 @@ public class AccountData { return password; } - public AccountData setPassword(String password) { + public Account setPassword(String password) { this.password = password; return this; } @@ -53,7 +53,7 @@ public class AccountData { return county; } - public AccountData setCounty(String county) { + public Account setCounty(String county) { this.county = county; return this; } diff --git a/app/src/main/java/io/github/wulkanowy/database/accounts/AccountAdapter.java b/app/src/main/java/io/github/wulkanowy/database/accounts/AccountAdapter.java deleted file mode 100644 index 5365cdd2..00000000 --- a/app/src/main/java/io/github/wulkanowy/database/accounts/AccountAdapter.java +++ /dev/null @@ -1,66 +0,0 @@ -package io.github.wulkanowy.database.accounts; - -import android.content.Context; -import android.database.Cursor; -import android.database.SQLException; -import android.database.sqlite.SQLiteDatabase; -import android.util.Log; - -public class AccountAdapter { - - private final String DATABASE_NAME = "accountdatabase.db"; - private final int DATABASE_VERSION = 1; - public SQLiteDatabase database; - private DatabaseHelper databaseHelper; - private Context context; - - AccountAdapter(Context context) { - this.context = context; - } - - public AccountAdapter open() { - - databaseHelper = new DatabaseHelper(context, DATABASE_NAME, null, DATABASE_VERSION); - - try { - database = databaseHelper.getWritableDatabase(); - } catch (SQLException e) { - database = databaseHelper.getReadableDatabase(); - Log.w(DatabaseHelper.DEBUG_TAG, "Database in read-only"); - } - - Log.d(DatabaseHelper.DEBUG_TAG, "Open database"); - - return this; - } - - public void close() { - databaseHelper.close(); - - Log.d(DatabaseHelper.DEBUG_TAG, "Close database"); - } - - public boolean checkExist() { - - open(); - - Log.d(DatabaseHelper.DEBUG_TAG, "Check exist table"); - - Cursor cursor = database.rawQuery("SELECT COUNT(*) FROM accounts", null); - - if (cursor != null) { - cursor.moveToFirst(); - - int count = cursor.getInt(0); - - if (count > 0) { - return true; - } - - cursor.close(); - close(); - } - - return false; - } -} diff --git a/app/src/main/java/io/github/wulkanowy/database/accounts/AccountsDatabase.java b/app/src/main/java/io/github/wulkanowy/database/accounts/AccountsDatabase.java new file mode 100644 index 00000000..adf2a550 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/database/accounts/AccountsDatabase.java @@ -0,0 +1,95 @@ +package io.github.wulkanowy.database.accounts; + +import android.content.ContentValues; +import android.content.Context; +import android.database.Cursor; +import android.database.CursorIndexOutOfBoundsException; +import android.database.SQLException; +import android.util.Log; + +import io.github.wulkanowy.database.DatabaseAdapter; +import io.github.wulkanowy.database.DatabaseHelper; + +public class AccountsDatabase extends DatabaseAdapter { + + private String name = "name"; + private String email = "email"; + private String password = "password"; + private String county = "county"; + private String idText = "id"; + private String accounts = "accounts"; + + public AccountsDatabase(Context context) { + super(context); + } + + public long put(Account account) throws SQLException { + + ContentValues newAccount = new ContentValues(); + newAccount.put(name, account.getName()); + newAccount.put(email, account.getEmail()); + newAccount.put(password, account.getPassword()); + newAccount.put(county, account.getCounty()); + + if (!database.isReadOnly()) { + long newId = database.insertOrThrow(accounts, null, newAccount); + Log.d(DatabaseHelper.DEBUG_TAG, "Put account " + newId + " into database"); + return newId; + } + + Log.e(DatabaseHelper.DEBUG_TAG, "Attempt to write on read-only database"); + throw new SQLException("Attempt to write on read-only database"); + } + + public long update(Account account) throws SQLException { + + ContentValues updateAccount = new ContentValues(); + updateAccount.put(name, account.getName()); + updateAccount.put(email, account.getEmail()); + updateAccount.put(password, account.getPassword()); + updateAccount.put(county, account.getCounty()); + String args[] = {account.getId() + ""}; + + if (!database.isReadOnly()) { + long updateId = database.update(accounts, updateAccount, "id=?", args); + Log.d(DatabaseHelper.DEBUG_TAG, "Update account " + updateId + " into database"); + return updateId; + } + + Log.e(DatabaseHelper.DEBUG_TAG, "Attempt to write on read-only database"); + throw new SQLException("Attempt to write on read-only database"); + } + + public Account getAccount(long id) throws SQLException { + + Account account = new Account(); + + String[] columns = {idText, name, email, password, county}; + String args[] = {id + ""}; + + try { + Cursor cursor = database.query(accounts, columns, "id=?", args, null, null, null, null); + if (cursor != null) { + cursor.moveToFirst(); + account.setId(cursor.getInt(0)); + account.setName(cursor.getString(1)); + account.setEmail(cursor.getString(2)); + account.setPassword(cursor.getString(3)); + account.setCounty(cursor.getString(4)); + cursor.close(); + } + } catch (SQLException e) { + + Log.e(DatabaseHelper.DEBUG_TAG, e.getMessage()); + throw e; + } catch (CursorIndexOutOfBoundsException e) { + + Log.e(DatabaseHelper.DEBUG_TAG, e.getMessage()); + throw new SQLException(e.getMessage()); + } + + Log.d(DatabaseHelper.DEBUG_TAG, "Extract account " + id + " from database"); + + return account; + } +} diff --git a/app/src/main/java/io/github/wulkanowy/database/accounts/DatabaseAccount.java b/app/src/main/java/io/github/wulkanowy/database/accounts/DatabaseAccount.java deleted file mode 100644 index f41808d7..00000000 --- a/app/src/main/java/io/github/wulkanowy/database/accounts/DatabaseAccount.java +++ /dev/null @@ -1,80 +0,0 @@ -package io.github.wulkanowy.database.accounts; - -import android.content.ContentValues; -import android.content.Context; -import android.database.Cursor; -import android.database.SQLException; -import android.util.Log; - -public class DatabaseAccount extends AccountAdapter { - - private String name = "name"; - private String email = "email"; - private String password = "password"; - private String county = "county"; - private String idText = "id"; - private String accounts = "accounts"; - - public DatabaseAccount(Context context) { - super(context); - } - - public void put(AccountData accountData) throws SQLException { - - ContentValues newAccount = new ContentValues(); - newAccount.put(name, accountData.getName()); - newAccount.put(email, accountData.getEmail()); - newAccount.put(password, accountData.getPassword()); - newAccount.put(county, accountData.getCounty()); - - Log.d(DatabaseHelper.DEBUG_TAG, "Put account into database"); - - if (!database.isReadOnly()) { - database.insertOrThrow(accounts, null, newAccount); - } - } - - public long update(AccountData accountData) { - - ContentValues updateAccount = new ContentValues(); - - updateAccount.put(name, accountData.getName()); - updateAccount.put(email, accountData.getEmail()); - updateAccount.put(password, accountData.getPassword()); - updateAccount.put(county, accountData.getCounty()); - String args[] = {accountData.getId() + ""}; - - Log.d(DatabaseHelper.DEBUG_TAG, "Update account into database"); - - return database.update(accounts, updateAccount, "id=?", args); - } - - public AccountData getAccount(int id) throws SQLException { - - AccountData accountData = new AccountData(); - - String[] columns = {idText, name, email, password, county}; - String args[] = {id + ""}; - - try { - Cursor cursor = database.query(accounts, columns, "id=?", args, null, null, null, null); - if (cursor != null) { - cursor.moveToFirst(); - accountData.setId(cursor.getInt(0)); - accountData.setName(cursor.getString(1)); - accountData.setEmail(cursor.getString(2)); - accountData.setPassword(cursor.getString(3)); - accountData.setCounty(cursor.getString(4)); - cursor.close(); - } - } catch (SQLException e) { - - Log.e(DatabaseHelper.DEBUG_TAG, e.getMessage()); - throw e; - } - - Log.d(DatabaseHelper.DEBUG_TAG, "Extract account from base"); - - return accountData; - } -} diff --git a/app/src/main/java/io/github/wulkanowy/database/accounts/DatabaseHelper.java b/app/src/main/java/io/github/wulkanowy/database/accounts/DatabaseHelper.java deleted file mode 100644 index 6baf712c..00000000 --- a/app/src/main/java/io/github/wulkanowy/database/accounts/DatabaseHelper.java +++ /dev/null @@ -1,36 +0,0 @@ -package io.github.wulkanowy.database.accounts; - -import android.content.Context; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteDatabase.CursorFactory; -import android.database.sqlite.SQLiteOpenHelper; -import android.util.Log; - -public class DatabaseHelper extends SQLiteOpenHelper { - - public final static String DEBUG_TAG = "SQLiteAccountsDatabase"; - private final String ACCOUNT_TABLE = "CREATE TABLE accounts( " + - "id INTEGER PRIMARY KEY AUTOINCREMENT, " + - "name TEXT, " + - "email TEXT," + - "password TEXT, " + - "county TEXT );"; - private final String DROP_ACCOUNT_TABLE = "DROP TABLE IF EXISTS accounts"; - - public DatabaseHelper(Context context, String name, CursorFactory factory, int version) { - super(context, name, factory, version); - } - - @Override - public void onCreate(SQLiteDatabase db) { - db.execSQL(ACCOUNT_TABLE); - Log.d(DEBUG_TAG, "Create database"); - } - - @Override - public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { - db.execSQL(DROP_ACCOUNT_TABLE); - onCreate(db); - Log.d(DEBUG_TAG, "Upgrade database"); - } -} diff --git a/app/src/main/java/io/github/wulkanowy/database/grades/GradesDatabase.java b/app/src/main/java/io/github/wulkanowy/database/grades/GradesDatabase.java new file mode 100644 index 00000000..27257169 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/database/grades/GradesDatabase.java @@ -0,0 +1,211 @@ +package io.github.wulkanowy.database.grades; + + +import android.content.ContentValues; +import android.content.Context; +import android.database.Cursor; +import android.database.CursorIndexOutOfBoundsException; +import android.database.SQLException; +import android.util.Log; + +import java.util.ArrayList; +import java.util.List; + +import io.github.wulkanowy.api.grades.Grade; +import io.github.wulkanowy.database.DatabaseAdapter; +import io.github.wulkanowy.database.DatabaseComparer; +import io.github.wulkanowy.database.DatabaseHelper; +import io.github.wulkanowy.database.subjects.SubjectsDatabase; + +public class GradesDatabase extends DatabaseAdapter { + + private String idText = "id"; + private String userIdText = "userID"; + private String subjectIdText = "subjectID"; + private String subject = "subject"; + private String value = "value"; + private String color = "color"; + private String symbol = "symbol"; + private String description = "description"; + private String weight = "weight"; + private String date = "date"; + private String teacher = "teacher"; + private String isNew = "isNew"; + private String semester = "semester"; + private String grades = "grades"; + + public GradesDatabase(Context context) { + super(context); + } + + public long put(Grade grade) throws SQLException { + + ContentValues newGrade = new ContentValues(); + newGrade.put(userIdText, context.getSharedPreferences("LoginData", context.MODE_PRIVATE).getLong("isLogin", 0)); + newGrade.put(subjectIdText, SubjectsDatabase.getSubjectId(grade.getSubject())); + newGrade.put(subject, grade.getSubject()); + newGrade.put(value, grade.getValue()); + newGrade.put(color, grade.getColor()); + newGrade.put(symbol, grade.getSymbol()); + newGrade.put(description, grade.getDescription()); + newGrade.put(weight, grade.getWeight()); + newGrade.put(date, grade.getDate()); + newGrade.put(teacher, grade.getTeacher()); + newGrade.put(semester, grade.getSemester()); + newGrade.put(isNew, grade.isNew() ? 1 : 0); + + if (!database.isReadOnly()) { + long newId = database.insertOrThrow(grades, null, newGrade); + Log.d(DatabaseHelper.DEBUG_TAG, "Put grade " + newId + " into database"); + return newId; + } + + Log.e(DatabaseHelper.DEBUG_TAG, "Attempt to write on read-only database"); + throw new SQLException("Attempt to write on read-only database"); + } + + public List put(List gradeList) throws SQLException { + + List newIdList = new ArrayList<>(); + List preparedList; + + if (checkExist(grades, null, null)) { + preparedList = DatabaseComparer.compareGradesLists(gradeList, getAllUserGrades()); + deleteAndCreate(grades); + } else { + preparedList = gradeList; + } + + for (Grade grade : preparedList) { + + newIdList.add(put(grade)); + } + return newIdList; + } + + public long update(Grade grade) throws SQLException { + + ContentValues updateGrade = new ContentValues(); + updateGrade.put(userIdText, grade.getUserID()); + updateGrade.put(subjectIdText, grade.getSubjectID()); + updateGrade.put(subject, grade.getSubject()); + updateGrade.put(value, grade.getValue()); + updateGrade.put(color, grade.getColor()); + updateGrade.put(symbol, grade.getSymbol()); + updateGrade.put(description, grade.getDescription()); + updateGrade.put(weight, grade.getWeight()); + updateGrade.put(date, grade.getDate()); + updateGrade.put(teacher, grade.getTeacher()); + updateGrade.put(semester, grade.getSemester()); + updateGrade.put(isNew, grade.isNew() ? 1 : 0); + String args[] = {grade.getId() + ""}; + + if (!database.isReadOnly()) { + long updateId = database.update(grades, updateGrade, "id=?", args); + Log.d(DatabaseHelper.DEBUG_TAG, "Update grade " + updateId + " into database"); + return updateId; + } + + Log.e(DatabaseHelper.DEBUG_TAG, "Attempt to write on read-only database"); + throw new SQLException("Attempt to write on read-only database"); + + } + + public Grade getGrade(long id) throws SQLException { + + Grade grade = new Grade(); + + String[] columns = {idText, userIdText, subjectIdText, value, color, description, weight, date, teacher}; + String args[] = {id + ""}; + + try { + Cursor cursor = database.query(grades, columns, "id=?", args, null, null, null, null); + if (cursor != null) { + cursor.moveToFirst(); + grade.setId(cursor.getInt(0)); + grade.setUserID(cursor.getInt(1)); + grade.setSubjectID(cursor.getInt(2)); + grade.setSubject(cursor.getString(3)); + grade.setValue(cursor.getString(4)); + grade.setColor(cursor.getString(5)); + grade.setSymbol(cursor.getString(6)); + grade.setDescription(cursor.getString(7)); + grade.setWeight(cursor.getString(8)); + grade.setDate(cursor.getString(9)); + grade.setTeacher(cursor.getString(10)); + grade.setSemester(cursor.getString(11)); + grade.setIsNew(cursor.getInt(12) != 0); + cursor.close(); + } + } catch (SQLException e) { + + Log.e(DatabaseHelper.DEBUG_TAG, e.getMessage()); + throw e; + } catch (CursorIndexOutOfBoundsException e) { + + Log.e(DatabaseHelper.DEBUG_TAG, e.getMessage()); + throw new SQLException(e.getMessage()); + } + + Log.d(DatabaseHelper.DEBUG_TAG, "Extract grade " + id + " from database"); + + return grade; + } + + public List getSubjectGrades(long userId, long subjectId) throws SQLException { + + String whereExec = "SELECT * FROM " + grades + " WHERE " + userIdText + "=? AND " + subjectIdText + "=?"; + + List gradesList = new ArrayList<>(); + + Cursor cursor = database.rawQuery(whereExec, new String[]{String.valueOf(userId), String.valueOf(subjectId)}); + + while (cursor.moveToNext()) { + Grade grade = new Grade(); + grade.setId(cursor.getInt(0)); + grade.setUserID(cursor.getInt(1)); + grade.setSubjectID(cursor.getInt(2)); + grade.setSubject(cursor.getString(3)); + grade.setValue(cursor.getString(4)); + grade.setColor(cursor.getString(5)); + grade.setSymbol(cursor.getString(6)); + grade.setDescription(cursor.getString(7)); + grade.setWeight(cursor.getString(8)); + grade.setDate(cursor.getString(9)); + grade.setTeacher(cursor.getString(10)); + grade.setSemester(cursor.getString(11)); + grade.setIsNew(cursor.getInt(12) != 0); + gradesList.add(grade); + } + + cursor.close(); + return gradesList; + } + + public List getAllUserGrades() { + + List gradesList = new ArrayList<>(); + + String exec = "SELECT * FROM " + grades + " WHERE " + userIdText + "=?"; + + Cursor cursor = database.rawQuery(exec, new String[]{String.valueOf(context.getSharedPreferences("LoginData", context.MODE_PRIVATE).getLong("isLogin", 0))}); + + while (cursor.moveToNext()) { + Grade grade = new Grade(); + grade.setSubject(cursor.getString(3)); + grade.setValue(cursor.getString(4)); + grade.setColor(cursor.getString(5)); + grade.setSymbol(cursor.getString(6)); + grade.setDescription(cursor.getString(7)); + grade.setWeight(cursor.getString(8)); + grade.setDate(cursor.getString(9)); + grade.setTeacher(cursor.getString(10)); + grade.setSemester(cursor.getString(11)); + grade.setIsNew(cursor.getInt(12) != 0); + gradesList.add(grade); + } + cursor.close(); + return gradesList; + } +} + diff --git a/app/src/main/java/io/github/wulkanowy/database/subjects/SubjectsDatabase.java b/app/src/main/java/io/github/wulkanowy/database/subjects/SubjectsDatabase.java new file mode 100644 index 00000000..4b8d99ae --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/database/subjects/SubjectsDatabase.java @@ -0,0 +1,138 @@ +package io.github.wulkanowy.database.subjects; + + +import android.content.ContentValues; +import android.content.Context; +import android.database.Cursor; +import android.database.CursorIndexOutOfBoundsException; +import android.database.SQLException; +import android.util.Log; + +import java.util.ArrayList; +import java.util.List; + +import io.github.wulkanowy.api.grades.Subject; +import io.github.wulkanowy.database.DatabaseAdapter; +import io.github.wulkanowy.database.DatabaseHelper; + +public class SubjectsDatabase extends DatabaseAdapter { + + private static String idText = "id"; + private static String name = "name"; + private static String predictedRating1 = "predictedRating1"; + private static String finalRating1 = "finalRating1"; + private static String predictedRating2 = "predictedRating2"; + private static String finalRating2 = "finalRating2"; + private static String subjects = "subjects"; + + public SubjectsDatabase(Context context) { + super(context); + } + + public long put(Subject subject) throws SQLException { + + ContentValues newSubject = new ContentValues(); + newSubject.put(name, subject.getName()); + newSubject.put(predictedRating1, subject.getPredictedRating()); + newSubject.put(finalRating1, subject.getFinalRating()); + + if (!database.isReadOnly()) { + long newId = database.insertOrThrow(subjects, null, newSubject); + Log.d(DatabaseHelper.DEBUG_TAG, "Put subject " + newId + " into database"); + return newId; + } + + Log.e(DatabaseHelper.DEBUG_TAG, "Attempt to write on read-only database"); + throw new SQLException("Attempt to write on read-only database"); + } + + public List put(List subjectList) throws SQLException { + + List newIdList = new ArrayList<>(); + + for (Subject subject : subjectList) { + if (!checkExist(subjects, name, subject.getName())) { + newIdList.add(put(subject)); + } + } + return newIdList; + } + + public long update(Subject subject) throws SQLException { + + ContentValues updateSubject = new ContentValues(); + updateSubject.put(name, subject.getName()); + updateSubject.put(predictedRating1, subject.getPredictedRating()); + updateSubject.put(finalRating1, subject.getFinalRating()); + String args[] = {subject.getId() + ""}; + + if (!database.isReadOnly()) { + long updateId = database.update(subjects, updateSubject, "id=?", args); + Log.d(DatabaseHelper.DEBUG_TAG, "Update subject " + updateId + " into database"); + return updateId; + } + + Log.e(DatabaseHelper.DEBUG_TAG, "Attempt to write on read-only database"); + throw new SQLException("Attempt to write on read-only database"); + } + + public Subject getSubject(long id) throws SQLException { + + Subject subject = new Subject(); + + String[] columns = {idText, name, predictedRating1, finalRating1, predictedRating2, finalRating2}; + String args[] = {id + ""}; + + try { + Cursor cursor = database.query(subjects, columns, "id=?", args, null, null, null, null); + if (cursor != null) { + cursor.moveToFirst(); + subject.setId(cursor.getInt(0)); + subject.setName(cursor.getString(1)); + subject.setPredictedRating(cursor.getString(2)); + subject.setFinalRating(cursor.getString(3)); + cursor.close(); + } + } catch (SQLException e) { + + Log.e(DatabaseHelper.DEBUG_TAG, e.getMessage()); + throw e; + } catch (CursorIndexOutOfBoundsException e) { + + Log.e(DatabaseHelper.DEBUG_TAG, e.getMessage()); + throw new SQLException(e.getMessage()); + } + + Log.d(DatabaseHelper.DEBUG_TAG, "Extract subject " + id + " from database"); + + return subject; + } + + public List getAllSubjectsNames() { + + List subjectsList = new ArrayList<>(); + + String exec = "SELECT " + name + " FROM " + subjects; + + Cursor cursor = database.rawQuery(exec, null); + + while (cursor.moveToNext()) { + Subject subject = new Subject(); + subject.setName(cursor.getString(0)); + subjectsList.add(subject); + } + cursor.close(); + return subjectsList; + } + + public static long getSubjectId(String nameSubject) throws SQLException { + + String whereExec = "SELECT " + idText + " FROM " + subjects + " WHERE " + name + " =?"; + + Cursor cursor = database.rawQuery(whereExec, new String[]{nameSubject}); + cursor.moveToFirst(); + int idSubject = cursor.getInt(0); + cursor.close(); + return idSubject; + } +} diff --git a/app/src/main/java/io/github/wulkanowy/security/Safety.java b/app/src/main/java/io/github/wulkanowy/security/Safety.java index 6c4823b3..5326687e 100644 --- a/app/src/main/java/io/github/wulkanowy/security/Safety.java +++ b/app/src/main/java/io/github/wulkanowy/security/Safety.java @@ -3,6 +3,7 @@ package io.github.wulkanowy.security; import android.content.Context; import android.os.Build; import android.util.Base64; +import android.util.Log; import io.github.wulkanowy.utilities.RootUtilities; @@ -24,6 +25,7 @@ public class Safety extends Scrambler { if (!RootUtilities.isRooted()) { return new String(Base64.encode(plainText.getBytes(), Base64.DEFAULT)); } else { + Log.e(Scrambler.DEBUG_TAG, "Password store in this devices isn't safe because is rooted"); throw new UnsupportedOperationException("Password store in this devices isn't safe because is rooted"); } } diff --git a/app/src/main/java/io/github/wulkanowy/security/Scrambler.java b/app/src/main/java/io/github/wulkanowy/security/Scrambler.java index 70819e06..33df50b4 100644 --- a/app/src/main/java/io/github/wulkanowy/security/Scrambler.java +++ b/app/src/main/java/io/github/wulkanowy/security/Scrambler.java @@ -45,6 +45,7 @@ public class Scrambler { keyStore = KeyStore.getInstance(ANDROID_KEYSTORE); keyStore.load(null); } catch (Exception e) { + Log.e(DEBUG_TAG, e.getMessage()); throw new CryptoException(e.getMessage()); } @@ -59,6 +60,7 @@ public class Scrambler { keyAliases.add(aliases.nextElement()); } } catch (Exception e) { + Log.e(DEBUG_TAG, e.getMessage()); throw new CryptoException(e.getMessage()); } @@ -104,9 +106,11 @@ public class Scrambler { Log.w(DEBUG_TAG, "GenerateNewKey - " + alias + " is exist"); } } catch (Exception e) { + Log.e(DEBUG_TAG, e.getMessage()); throw new CryptoException(e.getMessage()); } } else { + Log.e(DEBUG_TAG, "GenerateNewKey - String is empty"); throw new CryptoException("GenerateNewKey - String is empty"); } @@ -125,6 +129,7 @@ public class Scrambler { Log.e(DEBUG_TAG, e.getMessage()); } } else { + Log.e(DEBUG_TAG, "DeleteKey - String is empty"); throw new CryptoException("DeleteKey - String is empty"); } } @@ -154,9 +159,11 @@ public class Scrambler { return encryptedText; } catch (Exception e) { + Log.e(DEBUG_TAG, e.getMessage()); throw new CryptoException(e.getMessage()); } } else { + Log.e(DEBUG_TAG, "EncryptString - String is empty"); throw new CryptoException("EncryptString - String is empty"); } } @@ -188,9 +195,11 @@ public class Scrambler { return new String(ArrayUtils.toPrimitive(bytes), 0, bytes.length, "UTF-8"); } catch (Exception e) { + Log.e(DEBUG_TAG, e.getMessage()); throw new CryptoException(e.getMessage()); } } else { + Log.e(DEBUG_TAG, "EncryptString - String is empty"); throw new CryptoException("EncryptString - String is empty"); }