Refactor login module (#151)

This commit is contained in:
Rafał Borcz 2018-08-22 22:31:17 +02:00 committed by Mikołaj Pich
parent 64b0919b7f
commit a90d5cb9c3
208 changed files with 2101 additions and 11998 deletions

View File

@ -139,6 +139,7 @@ jobs:
- run:
name: Collect logs from emulator
command: adb logcat -d > ./app/build/reports/logcat_emulator.txt
when: always
- run:
name: Upload code covarage to codecov
command: bash <(curl -s https://codecov.io/bash) -F instrumented

View File

@ -13,6 +13,7 @@ import java.util.Map;
import java.util.concurrent.TimeUnit;
import io.github.wulkanowy.api.generic.School;
import io.github.wulkanowy.api.login.AccountPermissionException;
import io.github.wulkanowy.api.login.Login;
public class Client {
@ -31,6 +32,8 @@ public class Client {
private List<School> schools;
private List<String> symbols;
private Date lastSuccessRequest;
private Cookies cookies = new Cookies();
@ -117,6 +120,20 @@ public class Client {
return schools;
}
public void setSymbols(List<String> symbols) {
this.symbols = symbols;
}
public List<String> getSymbols() throws IOException, VulcanException {
try {
login();
} catch (AccountPermissionException e) {
// logger.error(e.getMessage(), e);
}
return symbols;
}
public String getSchoolId() throws IOException, VulcanException {
return schoolId != null ? schoolId : getSchools().get(0).getId();
}

View File

@ -72,6 +72,10 @@ public class Vulcan {
return getClient().getSchools();
}
public List<String> getSymbols() throws VulcanException, IOException {
return getClient().getSymbols();
}
public SnP getStudentAndParent() throws VulcanException, IOException {
if (null != this.snp) {
return this.snp;
@ -83,6 +87,11 @@ public class Vulcan {
return this.snp;
}
public void logout() {
client = null;
snp = null;
}
public List<AttendanceLesson> getAttendance(String dateStart) throws VulcanException, IOException {
return new Attendance(getStudentAndParent()).getAttendance(dateStart);
}

View File

@ -1,5 +1,6 @@
package io.github.wulkanowy.api.login;
import org.apache.commons.lang3.StringUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
@ -9,6 +10,8 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import io.github.wulkanowy.api.Client;
import io.github.wulkanowy.api.NotLoggedInErrorException;
@ -121,26 +124,39 @@ public class Login {
}
private String findSymbol(String symbol, String certificate) throws AccountPermissionException {
List<String> symbols = getSymbolsFromCertificate(certificate);
client.setSymbols(symbols);
if ("Default".equals(symbol)) {
return findSymbolInCertificate(certificate);
return getLastSymbol(symbols);
}
return symbol;
}
String findSymbolInCertificate(String certificate) throws AccountPermissionException {
List<String> getSymbolsFromCertificate(String certificate) {
Elements instances = Jsoup
.parse(certificate.replaceAll(":", ""), "", Parser.xmlParser())
.select("[AttributeName=\"UserInstance\"] samlAttributeValue");
if (instances.isEmpty()) { // on adfs login
List<String> symbols = new ArrayList<>();
for (Element e : instances) {
symbols.add(e.text());
}
return symbols;
}
String getLastSymbol(List<String> symbols) throws AccountPermissionException {
if (symbols.isEmpty()) { // on adfs login
return "";
}
if (instances.size() < 2) { // 1st index is always `Default`
if (symbols.size() < 2) { // 1st index is always `Default`
throw new AccountPermissionException("First login detected, specify symbol");
}
return instances.get(1).text();
return StringUtils.stripAccents(symbols.get(1).replaceAll("\\s", ""));
}
}

View File

@ -6,6 +6,8 @@ import org.junit.Assert;
import org.junit.Test;
import org.mockito.Mockito;
import java.util.List;
import io.github.wulkanowy.api.Client;
import io.github.wulkanowy.api.FixtureHelper;
@ -118,14 +120,17 @@ public class LoginTest {
Login login = new Login(getClient("Logowanie-certyfikat.html"));
String certificate = getFixtureAsString("cert-stock.xml");
List<String> symbols = login.getSymbolsFromCertificate(certificate);
Assert.assertEquals("demo12345", login.findSymbolInCertificate(certificate));
Assert.assertEquals("demo12345", login.getLastSymbol(symbols));
}
@Test(expected = AccountPermissionException.class)
public void findSymbolInCertificateWithoutSecondInstanceTest() throws Exception {
Login login = new Login(getClient("Logowanie-certyfikat.html"));
login.findSymbolInCertificate(getFixtureAsString("cert-no-symbols.xml"));
List<String> symbols = login.getSymbolsFromCertificate(getFixtureAsString("cert-no-symbols.xml"));
login.getLastSymbol(symbols);
}
}

View File

@ -1,7 +1,7 @@
apply plugin: 'org.greenrobot.greendao'
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'// sync warning probably caused by bug https://issuetracker.google.com/issues/74537216
apply plugin: 'kotlin-android-extensions'
apply plugin: 'io.fabric'
apply from: 'jacoco.gradle'
apply from: 'android-sonarqube.gradle'
@ -16,7 +16,6 @@ buildscript {
}
dependencies {
classpath "org.greenrobot:greendao-gradle-plugin:$greenDaoGradle"
classpath "io.fabric.tools:gradle:$fabricGradle"
classpath "com.google.gms:oss-licenses:0.9.2"
classpath "com.github.triplet.gradle:play-publisher:$playPublisher"
@ -45,6 +44,7 @@ android {
targetSdkVersion 27
versionCode 16
versionName "0.5.2"
multiDexEnabled true
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
vectorDrawables.useSupportLibrary = true
playAccountConfig = playAccountConfigs.defaultAccountConfig
@ -73,6 +73,7 @@ android {
versionNameSuffix "-dev"
testCoverageEnabled = true
ext.enableCrashlytics = false
multiDexKeepProguard file('proguard-multidex-rules.pro')
}
}
@ -87,34 +88,31 @@ android {
}
}
androidExtensions {
experimental = true
}
play {
track = 'alpha'
uploadImages = true
}
greendao {
schemaVersion 29
generateTests = true
}
configurations.all {
resolutionStrategy.force "com.android.support:support-annotations:$supportVersion"
}
dependencies {
implementation project(':api')
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation "com.android.support:support-v4:$supportVersion"
implementation "com.android.support:design:$supportVersion"
implementation "com.android.support:cardview-v7:$supportVersion"
implementation "com.android.support:customtabs:$supportVersion"
implementation "com.android.support:preference-v14:$supportVersion"
implementation "com.firebase:firebase-jobdispatcher:$firebaseJob"
implementation "org.apache.commons:commons-lang3:$apacheLang"
implementation "org.apache.commons:commons-collections4:$apacheCollections"
implementation "eu.davidea:flexible-adapter:$flexibleAdapter"
implementation "eu.davidea:flexible-adapter-ui:$flexibleUi"
implementation "org.greenrobot:greendao:$greenDao"
implementation "com.jakewharton:butterknife:$butterknife"
implementation "com.google.dagger:dagger-android-support:$dagger2"
implementation "com.aurelhubert:ahbottomnavigation:$ahbottom"
@ -122,6 +120,12 @@ dependencies {
implementation "com.google.android.gms:play-services-oss-licenses:$ossLicenses"
implementation "com.jakewharton.timber:timber:$timber"
implementation "at.favre.lib:slf4j-timber:$slf4jTimber"
implementation "android.arch.persistence.room:runtime:1.1.1"
implementation 'io.reactivex.rxjava2:rxandroid:2.0.2'
implementation "io.reactivex.rxjava2:rxjava:2.2.0"
implementation 'com.android.support:multidex:1.0.3'
implementation "android.arch.persistence.room:rxjava2:1.1.1"
implementation 'com.github.pwittchen:reactivenetwork-rx2:2.1.0'
implementation("com.crashlytics.sdk.android:crashlytics:$crashlyticsSdk@aar") {
transitive = true
@ -133,11 +137,13 @@ dependencies {
kapt "com.google.dagger:dagger-compiler:$dagger2"
kapt "com.google.dagger:dagger-android-processor:$dagger2"
kapt "com.jakewharton:butterknife-compiler:$butterknife"
kapt "android.arch.persistence.room:compiler:1.1.1"
debugImplementation "com.amitshekhar.android:debug-db:$debugDb"
testImplementation "junit:junit:$junit"
testImplementation "org.mockito:mockito-core:$mockito"
testImplementation "org.mockito:mockito-inline:$mockito"
testImplementation "org.jsoup:jsoup:$jsoup"
androidTestImplementation "com.android.support.test:runner:$testRunner"
androidTestImplementation "org.mockito:mockito-android:$mockito"

View File

@ -0,0 +1,3 @@
-keep class android.support.test.internal** { *; }
-keep class org.junit.** { *; }
-keep public class io.github.wulkanowy** { *; }

View File

@ -1,18 +0,0 @@
package io.github.wulkanowy.data.db.dao.entities;
import org.greenrobot.greendao.test.AbstractDaoTestLongPk;
public class AccountTest extends AbstractDaoTestLongPk<AccountDao, Account> {
public AccountTest() {
super(AccountDao.class);
}
@Override
protected Account createEntity(Long key) {
Account entity = new Account();
entity.setId(key);
return entity;
}
}

View File

@ -1,25 +0,0 @@
package io.github.wulkanowy.data.db.dao.entities;
import org.greenrobot.greendao.test.AbstractDaoTestLongPk;
public class AttendanceLessonTest extends AbstractDaoTestLongPk<AttendanceLessonDao, AttendanceLesson> {
public AttendanceLessonTest() {
super(AttendanceLessonDao.class);
}
@Override
protected AttendanceLesson createEntity(Long key) {
AttendanceLesson entity = new AttendanceLesson();
entity.setId(key);
entity.setPresence(false);
entity.setAbsenceUnexcused(false);
entity.setAbsenceExcused(false);
entity.setUnexcusedLateness(false);
entity.setAbsenceForSchoolReasons(false);
entity.setExcusedLateness(false);
entity.setExemption(false);
return entity;
}
}

View File

@ -1,19 +0,0 @@
package io.github.wulkanowy.data.db.dao.entities;
import org.greenrobot.greendao.test.AbstractDaoTestLongPk;
public class DayTest extends AbstractDaoTestLongPk<DayDao, Day> {
public DayTest() {
super(DayDao.class);
}
@Override
protected Day createEntity(Long key) {
Day entity = new Day();
entity.setId(key);
entity.setFreeDay(false);
return entity;
}
}

View File

@ -1,19 +0,0 @@
package io.github.wulkanowy.data.db.dao.entities;
import org.greenrobot.greendao.test.AbstractDaoTestLongPk;
public class DiaryTest extends AbstractDaoTestLongPk<DiaryDao, Diary> {
public DiaryTest() {
super(DiaryDao.class);
}
@Override
protected Diary createEntity(Long key) {
Diary entity = new Diary();
entity.setId(key);
entity.setCurrent(false);
return entity;
}
}

View File

@ -1,18 +0,0 @@
package io.github.wulkanowy.data.db.dao.entities;
import org.greenrobot.greendao.test.AbstractDaoTestLongPk;
public class ExamTest extends AbstractDaoTestLongPk<ExamDao, Exam> {
public ExamTest() {
super(ExamDao.class);
}
@Override
protected Exam createEntity(Long key) {
Exam entity = new Exam();
entity.setId(key);
return entity;
}
}

View File

@ -1,20 +0,0 @@
package io.github.wulkanowy.data.db.dao.entities;
import org.greenrobot.greendao.test.AbstractDaoTestLongPk;
public class GradeTest extends AbstractDaoTestLongPk<GradeDao, Grade> {
public GradeTest() {
super(GradeDao.class);
}
@Override
protected Grade createEntity(Long key) {
Grade entity = new Grade();
entity.setId(key);
entity.setIsNew(false);
entity.setRead(false);
return entity;
}
}

View File

@ -1,22 +0,0 @@
package io.github.wulkanowy.data.db.dao.entities;
import org.greenrobot.greendao.test.AbstractDaoTestLongPk;
import io.github.wulkanowy.data.db.dao.entities.School;
import io.github.wulkanowy.data.db.dao.entities.SchoolDao;
public class SchoolTest extends AbstractDaoTestLongPk<SchoolDao, School> {
public SchoolTest() {
super(SchoolDao.class);
}
@Override
protected School createEntity(Long key) {
School entity = new School();
entity.setId(key);
entity.setCurrent(false);
return entity;
}
}

View File

@ -1,21 +0,0 @@
package io.github.wulkanowy.data.db.dao.entities;
import org.greenrobot.greendao.test.AbstractDaoTestLongPk;
import io.github.wulkanowy.data.db.dao.entities.Semester;
import io.github.wulkanowy.data.db.dao.entities.SemesterDao;
public class SemesterTest extends AbstractDaoTestLongPk<SemesterDao, Semester> {
public SemesterTest() {
super(SemesterDao.class);
}
@Override
protected Semester createEntity(Long key) {
Semester entity = new Semester();
entity.setId(key);
return entity;
}
}

View File

@ -1,21 +0,0 @@
package io.github.wulkanowy.data.db.dao.entities;
import org.greenrobot.greendao.test.AbstractDaoTestLongPk;
import io.github.wulkanowy.data.db.dao.entities.Student;
import io.github.wulkanowy.data.db.dao.entities.StudentDao;
public class StudentTest extends AbstractDaoTestLongPk<StudentDao, Student> {
public StudentTest() {
super(StudentDao.class);
}
@Override
protected Student createEntity(Long key) {
Student entity = new Student();
entity.setId(key);
return entity;
}
}

View File

@ -1,18 +0,0 @@
package io.github.wulkanowy.data.db.dao.entities;
import org.greenrobot.greendao.test.AbstractDaoTestLongPk;
public class SubjectTest extends AbstractDaoTestLongPk<SubjectDao, Subject> {
public SubjectTest() {
super(SubjectDao.class);
}
@Override
protected Subject createEntity(Long key) {
Subject entity = new Subject();
entity.setId(key);
return entity;
}
}

View File

@ -1,21 +0,0 @@
package io.github.wulkanowy.data.db.dao.entities;
import org.greenrobot.greendao.test.AbstractDaoTestLongPk;
import io.github.wulkanowy.data.db.dao.entities.Symbol;
import io.github.wulkanowy.data.db.dao.entities.SymbolDao;
public class SymbolTest extends AbstractDaoTestLongPk<SymbolDao, Symbol> {
public SymbolTest() {
super(SymbolDao.class);
}
@Override
protected Symbol createEntity(Long key) {
Symbol entity = new Symbol();
entity.setId(key);
return entity;
}
}

View File

@ -1,24 +0,0 @@
package io.github.wulkanowy.data.db.dao.entities;
import org.greenrobot.greendao.test.AbstractDaoTestLongPk;
public class TimetableLessonTest extends AbstractDaoTestLongPk<TimetableLessonDao, TimetableLesson> {
public TimetableLessonTest() {
super(TimetableLessonDao.class);
}
@Override
protected TimetableLesson createEntity(Long key) {
TimetableLesson entity = new TimetableLesson();
entity.setId(key);
entity.setEmpty(false);
entity.setDivisionIntoGroups(false);
entity.setPlanning(false);
entity.setRealized(false);
entity.setMovedOrCanceled(false);
entity.setNewMovedInOrChanged(false);
return entity;
}
}

View File

@ -1,18 +0,0 @@
package io.github.wulkanowy.data.db.dao.entities;
import org.greenrobot.greendao.test.AbstractDaoTestLongPk;
public class WeekTest extends AbstractDaoTestLongPk<WeekDao, Week> {
public WeekTest() {
super(WeekDao.class);
}
@Override
protected Week createEntity(Long key) {
Week entity = new Week();
entity.setId(key);
return entity;
}
}

View File

@ -0,0 +1,49 @@
package io.github.wulkanowy.data.repositories.local
import android.arch.persistence.room.Room
import android.content.Context
import android.support.test.InstrumentationRegistry
import android.support.test.runner.AndroidJUnit4
import io.github.wulkanowy.data.db.AppDatabase
import io.github.wulkanowy.data.db.SharedPrefHelper
import io.github.wulkanowy.data.db.entities.Student
import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import kotlin.test.assertEquals
@RunWith(AndroidJUnit4::class)
class StudentLocalTest {
private lateinit var studentLocal: StudentLocal
private lateinit var testDb: AppDatabase
private lateinit var sharedHelper: SharedPrefHelper
@Before
fun createDb() {
val context = InstrumentationRegistry.getContext()
testDb = Room.inMemoryDatabaseBuilder(context, AppDatabase::class.java)
.build()
sharedHelper = SharedPrefHelper(context.getSharedPreferences("TEST", Context.MODE_PRIVATE))
studentLocal = StudentLocal(testDb.studentDao(), sharedHelper, context)
}
@After
fun closeDb() {
testDb.close()
}
@Test
fun saveAndReadTest() {
studentLocal.save(Student(email = "test", password = "test123", schoolId = "23"))
assert(sharedHelper.getLong(StudentLocal.CURRENT_USER_KEY, 0) == 1L)
assert(studentLocal.isStudentLoggedIn)
val student = studentLocal.getCurrentStudent().blockingGet()
assertEquals("23", student.schoolId)
}
}

View File

@ -28,7 +28,7 @@
<activity
android:name=".ui.login.LoginActivity"
android:configChanges="orientation|screenSize"
android:label="@string/title_activity_login"
android:label="@string/login_options_header"
android:theme="@style/WulkanowyTheme.DarkActionBar"
android:windowSoftInputMode="adjustResize" />
<activity

View File

@ -1,5 +1,7 @@
package io.github.wulkanowy
import android.content.Context
import android.support.multidex.MultiDex
import com.crashlytics.android.Crashlytics
import com.crashlytics.android.answers.Answers
import com.crashlytics.android.core.CrashlyticsCore
@ -8,19 +10,16 @@ import dagger.android.AndroidInjector
import dagger.android.support.DaggerApplication
import eu.davidea.flexibleadapter.FlexibleAdapter
import io.fabric.sdk.android.Fabric
import io.github.wulkanowy.data.RepositoryContract
import io.github.wulkanowy.di.DaggerAppComponent
import io.github.wulkanowy.utils.FabricUtils
import io.github.wulkanowy.utils.LoggerUtils
import io.github.wulkanowy.utils.security.ScramblerException
import org.greenrobot.greendao.query.QueryBuilder
import timber.log.Timber
import javax.inject.Inject
class WulkanowyApp : DaggerApplication() {
@Inject
internal lateinit var repository: RepositoryContract
override fun attachBaseContext(base: Context?) {
super.attachBaseContext(base)
MultiDex.install(this)
}
override fun onCreate() {
super.onCreate()
@ -30,28 +29,9 @@ class WulkanowyApp : DaggerApplication() {
enableDebugLog()
}
initializeFabric()
initializeUserSession()
}
private fun initializeUserSession() {
if (repository.sharedRepo.isUserLoggedIn) {
try {
repository.syncRepo.initLastUser()
FabricUtils.logLogin("Open app", true)
} catch (e: Exception) {
FabricUtils.logLogin("Open app", false)
Timber.e(e, "An error occurred when the application was started")
} catch (e: ScramblerException) {
FabricUtils.logLogin("Open app", false)
Timber.e(e, "A security error has occurred")
repository.cleanAllData()
}
}
}
private fun enableDebugLog() {
QueryBuilder.LOG_VALUES = true
FlexibleAdapter.enableLogs(eu.davidea.flexibleadapter.utils.Log.Level.DEBUG)
Timber.plant(LoggerUtils.DebugLogTree())
}

View File

@ -0,0 +1,31 @@
package io.github.wulkanowy.data
import android.content.res.Resources
import io.github.wulkanowy.R
import io.github.wulkanowy.api.NotLoggedInErrorException
import timber.log.Timber
import java.io.IOException
import java.net.SocketTimeoutException
import java.net.UnknownHostException
import javax.inject.Inject
open class ErrorHandler @Inject constructor(private val resources: Resources) {
var showErrorMessage: (String) -> Unit = {}
open fun proceed(error: Throwable) {
Timber.i(error, "An exception occurred while the Wulkanowy was running")
showErrorMessage((when (error) {
is UnknownHostException -> resources.getString(R.string.noInternet_text)
is SocketTimeoutException -> resources.getString(R.string.generic_timeout_error)
is NotLoggedInErrorException, is IOException -> resources.getString(R.string.login_failed_text)
else -> error.localizedMessage
}))
}
open fun clear() {
showErrorMessage = {}
}
}

View File

@ -1,56 +0,0 @@
package io.github.wulkanowy.data;
import javax.inject.Inject;
import javax.inject.Singleton;
import io.github.wulkanowy.data.db.dao.DbContract;
import io.github.wulkanowy.data.db.resources.ResourcesContract;
import io.github.wulkanowy.data.db.shared.SharedPrefContract;
import io.github.wulkanowy.data.sync.SyncContract;
@Singleton
public class Repository implements RepositoryContract {
private final DbContract database;
private final ResourcesContract resources;
private final SharedPrefContract sharedPref;
private final SyncContract synchronization;
@Inject
Repository(DbContract database, ResourcesContract resources, SharedPrefContract sharedPref,
SyncContract synchronization) {
this.database = database;
this.resources = resources;
this.sharedPref = sharedPref;
this.synchronization = synchronization;
}
@Override
public SharedPrefContract getSharedRepo() {
return sharedPref;
}
@Override
public ResourcesContract getResRepo() {
return resources;
}
@Override
public DbContract getDbRepo() {
return database;
}
@Override
public SyncContract getSyncRepo() {
return synchronization;
}
@Override
public void cleanAllData() {
sharedPref.cleanSharedPref();
database.recreateDatabase();
}
}

View File

@ -1,22 +0,0 @@
package io.github.wulkanowy.data;
import javax.inject.Singleton;
import io.github.wulkanowy.data.db.dao.DbContract;
import io.github.wulkanowy.data.db.resources.ResourcesContract;
import io.github.wulkanowy.data.db.shared.SharedPrefContract;
import io.github.wulkanowy.data.sync.SyncContract;
@Singleton
public interface RepositoryContract {
SharedPrefContract getSharedRepo();
ResourcesContract getResRepo();
DbContract getDbRepo();
SyncContract getSyncRepo();
void cleanAllData();
}

View File

@ -0,0 +1,44 @@
package io.github.wulkanowy.data
import android.arch.persistence.room.Room
import android.content.Context
import android.content.SharedPreferences
import android.support.v7.preference.PreferenceManager
import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings
import dagger.Module
import dagger.Provides
import io.github.wulkanowy.api.Vulcan
import io.github.wulkanowy.data.db.AppDatabase
import io.github.wulkanowy.utils.DATABASE_NAME
import javax.inject.Singleton
@Module
internal class RepositoryModule {
@Singleton
@Provides
fun provideInternetObservingSettings(): InternetObservingSettings {
return InternetObservingSettings.create()
}
@Singleton
@Provides
fun provideVulcanApi() = Vulcan()
@Singleton
@Provides
fun provideDatabase(context: Context): AppDatabase {
return Room.databaseBuilder(context, AppDatabase::class.java, DATABASE_NAME)
.build()
}
@Singleton
@Provides
fun provideSharedPref(context: Context): SharedPreferences {
return PreferenceManager.getDefaultSharedPreferences(context)
}
@Singleton
@Provides
fun provideStudentDao(database: AppDatabase) = database.studentDao()
}

View File

@ -0,0 +1,18 @@
package io.github.wulkanowy.data.db
import android.arch.persistence.room.Database
import android.arch.persistence.room.RoomDatabase
import io.github.wulkanowy.data.db.dao.StudentDao
import io.github.wulkanowy.data.db.entities.Student
import javax.inject.Singleton
@Singleton
@Database(
entities = [Student::class],
version = 1,
exportSchema = false
)
abstract class AppDatabase : RoomDatabase() {
abstract fun studentDao(): StudentDao
}

View File

@ -0,0 +1,17 @@
package io.github.wulkanowy.data.db
import android.content.SharedPreferences
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class SharedPrefHelper @Inject constructor(private val sharedPref: SharedPreferences) {
fun putLong(key: String, value: Long) {
sharedPref.edit().putLong(key, value).apply()
}
fun getLong(key: String, defaultValue: Long): Long {
return sharedPref.getLong(key, defaultValue)
}
}

View File

@ -1,37 +0,0 @@
package io.github.wulkanowy.data.db.dao;
import java.util.List;
import io.github.wulkanowy.data.db.dao.entities.Grade;
import io.github.wulkanowy.data.db.dao.entities.Subject;
import io.github.wulkanowy.data.db.dao.entities.Symbol;
import io.github.wulkanowy.data.db.dao.entities.Week;
public interface DbContract {
Week getWeek(String date);
Week getWeek(long diaryId, String date);
List<Subject> getSubjectList(int semesterName);
List<Grade> getNewGrades(int semesterName);
long getCurrentSchoolId();
long getCurrentStudentId();
long getCurrentSymbolId();
Symbol getCurrentSymbol();
long getCurrentDiaryId();
long getSemesterId(int name);
long getCurrentSemesterId();
int getCurrentSemesterName();
void recreateDatabase();
}

View File

@ -1,102 +0,0 @@
package io.github.wulkanowy.data.db.dao;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import org.greenrobot.greendao.database.Database;
import org.greenrobot.greendao.database.StandardDatabase;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import io.github.wulkanowy.api.Vulcan;
import io.github.wulkanowy.data.db.dao.entities.DaoMaster;
import io.github.wulkanowy.data.db.dao.migrations.Migration23;
import io.github.wulkanowy.data.db.dao.migrations.Migration26;
import io.github.wulkanowy.data.db.dao.migrations.Migration27;
import io.github.wulkanowy.data.db.dao.migrations.Migration28;
import io.github.wulkanowy.data.db.dao.migrations.Migration29;
import io.github.wulkanowy.data.db.shared.SharedPrefContract;
import timber.log.Timber;
@Singleton
public class DbHelper extends DaoMaster.OpenHelper {
private final SharedPrefContract sharedPref;
private final Vulcan vulcan;
@Inject
DbHelper(Context context, @Named("dbName") String dbName,
SharedPrefContract sharedPref, Vulcan vulcan) {
super(context, dbName);
this.sharedPref = sharedPref;
this.vulcan = vulcan;
}
@Override
public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Timber.i("Cleaning user data oldVersion=%s newVersion=%s", oldVersion, newVersion);
Database database = new StandardDatabase(db);
recreateDatabase(database);
}
@Override
public void onUpgrade(Database db, int oldVersion, int newVersion) {
List<Migration> migrations = getMigrations();
// Only run migrations past the old version
for (Migration migration : migrations) {
if (oldVersion < migration.getVersion()) {
try {
Timber.i("Applying migration to db schema v%s...", migration.getVersion());
migration.runMigration(db, sharedPref, vulcan);
Timber.i("Migration %s complete", migration.getVersion());
} catch (Exception e) {
Timber.e(e, "Failed to apply migration");
recreateDatabase(db);
break;
}
}
}
}
private void recreateDatabase(Database db) {
Timber.i("Database is recreating...");
sharedPref.setCurrentUserId(0);
DaoMaster.dropAllTables(db, true);
onCreate(db);
}
private List<Migration> getMigrations() {
List<Migration> migrations = new ArrayList<>();
migrations.add(new Migration23());
migrations.add(new Migration26());
migrations.add(new Migration27());
migrations.add(new Migration28());
migrations.add(new Migration29());
// Sorting just to be safe, in case other people add migrations in the wrong order.
Comparator<Migration> migrationComparator = new Comparator<Migration>() {
@Override
public int compare(Migration m1, Migration m2) {
return m1.getVersion().compareTo(m2.getVersion());
}
};
Collections.sort(migrations, migrationComparator);
return migrations;
}
public interface Migration {
Integer getVersion();
void runMigration(Database db, SharedPrefContract sharedPref, Vulcan vulcan) throws Exception;
}
}

View File

@ -1,132 +0,0 @@
package io.github.wulkanowy.data.db.dao;
import org.greenrobot.greendao.database.Database;
import java.util.List;
import javax.inject.Inject;
import io.github.wulkanowy.data.db.dao.entities.DaoMaster;
import io.github.wulkanowy.data.db.dao.entities.DaoSession;
import io.github.wulkanowy.data.db.dao.entities.DiaryDao;
import io.github.wulkanowy.data.db.dao.entities.Grade;
import io.github.wulkanowy.data.db.dao.entities.GradeDao;
import io.github.wulkanowy.data.db.dao.entities.SchoolDao;
import io.github.wulkanowy.data.db.dao.entities.Semester;
import io.github.wulkanowy.data.db.dao.entities.SemesterDao;
import io.github.wulkanowy.data.db.dao.entities.StudentDao;
import io.github.wulkanowy.data.db.dao.entities.Subject;
import io.github.wulkanowy.data.db.dao.entities.Symbol;
import io.github.wulkanowy.data.db.dao.entities.SymbolDao;
import io.github.wulkanowy.data.db.dao.entities.Week;
import io.github.wulkanowy.data.db.dao.entities.WeekDao;
import io.github.wulkanowy.data.db.shared.SharedPrefContract;
public class DbRepository implements DbContract {
private final DaoSession daoSession;
private final SharedPrefContract sharedPref;
@Inject
DbRepository(DaoSession daoSession, SharedPrefContract sharedPrefContract) {
this.daoSession = daoSession;
this.sharedPref = sharedPrefContract;
}
@Override
public Week getWeek(String date) {
return getWeek(getCurrentDiaryId(), date);
}
@Override
public Week getWeek(long diaryId, String date) {
return daoSession.getWeekDao().queryBuilder().where(
WeekDao.Properties.StartDayDate.eq(date),
WeekDao.Properties.DiaryId.eq(diaryId)
).unique();
}
@Override
public List<Subject> getSubjectList(int semesterName) {
return daoSession.getSemesterDao().load(getSemesterId(semesterName)).getSubjectList();
}
@Override
public List<Grade> getNewGrades(int semesterName) {
return daoSession.getGradeDao().queryBuilder().where(
GradeDao.Properties.IsNew.eq(1),
GradeDao.Properties.SemesterId.eq(getSemesterId(semesterName))
).list();
}
@Override
public Symbol getCurrentSymbol() {
return daoSession.getSymbolDao().queryBuilder().where(
SymbolDao.Properties.UserId.eq(sharedPref.getCurrentUserId())
).unique();
}
@Override
public long getCurrentSymbolId() {
return getCurrentSymbol().getId();
}
@Override
public long getCurrentSchoolId() {
return daoSession.getSchoolDao().queryBuilder().where(
SchoolDao.Properties.SymbolId.eq(getCurrentSymbolId()),
SchoolDao.Properties.Current.eq(true)
).unique().getId();
}
@Override
public long getCurrentStudentId() {
return daoSession.getStudentDao().queryBuilder().where(
StudentDao.Properties.SchoolId.eq(getCurrentSchoolId()),
StudentDao.Properties.Current.eq(true)
).unique().getId();
}
@Override
public long getCurrentDiaryId() {
return daoSession.getDiaryDao().queryBuilder().where(
DiaryDao.Properties.StudentId.eq(getCurrentStudentId()),
DiaryDao.Properties.Current.eq(true)
).unique().getId();
}
@Override
public long getSemesterId(int name) {
return daoSession.getSemesterDao().queryBuilder().where(
SemesterDao.Properties.DiaryId.eq(getCurrentDiaryId()),
SemesterDao.Properties.Name.eq(String.valueOf(name))
).unique().getId();
}
@Override
public long getCurrentSemesterId() {
return getCurrentSemester().getId();
}
@Override
public int getCurrentSemesterName() {
return Integer.valueOf(getCurrentSemester().getName());
}
private Semester getCurrentSemester() {
return daoSession.getSemesterDao().queryBuilder().where(
SemesterDao.Properties.DiaryId.eq(getCurrentDiaryId()),
SemesterDao.Properties.Current.eq(true)
).unique();
}
@Override
public void recreateDatabase() {
Database database = daoSession.getDatabase();
DaoMaster.dropAllTables(database, true);
DaoMaster.createAllTables(database, true);
}
}

View File

@ -0,0 +1,18 @@
package io.github.wulkanowy.data.db.dao
import android.arch.persistence.room.Dao
import android.arch.persistence.room.Insert
import android.arch.persistence.room.OnConflictStrategy.REPLACE
import android.arch.persistence.room.Query
import io.github.wulkanowy.data.db.entities.Student
import io.reactivex.Single
@Dao
interface StudentDao {
@Insert(onConflict = REPLACE)
fun insert(student: Student): Long
@Query("SELECT * FROM Students WHERE id = :id")
fun load(id: Long): Single<Student>
}

View File

@ -1,153 +0,0 @@
package io.github.wulkanowy.data.db.dao.entities;
import org.greenrobot.greendao.DaoException;
import org.greenrobot.greendao.annotation.Entity;
import org.greenrobot.greendao.annotation.Generated;
import org.greenrobot.greendao.annotation.Id;
import org.greenrobot.greendao.annotation.Property;
import org.greenrobot.greendao.annotation.ToMany;
import org.greenrobot.greendao.annotation.Unique;
import java.util.List;
@Entity(
nameInDb = "Accounts",
active = true
)
public class Account {
@Id(autoincrement = true)
private Long id;
@Unique
@Property(nameInDb = "email")
private String email;
@Property(nameInDb = "password")
private String password;
@ToMany(referencedJoinProperty = "userId")
private List<Symbol> symbolList;
/**
* Used to resolve relations
*/
@Generated(hash = 2040040024)
private transient DaoSession daoSession;
/**
* Used for active entity operations.
*/
@Generated(hash = 335469827)
private transient AccountDao myDao;
@Generated(hash = 1104194311)
public Account(Long id, String email, String password) {
this.id = id;
this.email = email;
this.password = password;
}
@Generated(hash = 882125521)
public Account() {
}
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
public String getEmail() {
return this.email;
}
public Account setEmail(String email) {
this.email = email;
return this;
}
public String getPassword() {
return this.password;
}
public Account setPassword(String password) {
this.password = password;
return this;
}
/**
* To-many relationship, resolved on first access (and after reset).
* Changes to to-many relations are not persisted, make changes to the target entity.
*/
@Generated(hash = 822972496)
public List<Symbol> getSymbolList() {
if (symbolList == null) {
final DaoSession daoSession = this.daoSession;
if (daoSession == null) {
throw new DaoException("Entity is detached from DAO context");
}
SymbolDao targetDao = daoSession.getSymbolDao();
List<Symbol> symbolListNew = targetDao._queryAccount_SymbolList(id);
synchronized (this) {
if (symbolList == null) {
symbolList = symbolListNew;
}
}
}
return symbolList;
}
/**
* Resets a to-many relationship, making the next get call to query for a fresh result.
*/
@Generated(hash = 1716801695)
public synchronized void resetSymbolList() {
symbolList = null;
}
/**
* Convenient call for {@link org.greenrobot.greendao.AbstractDao#delete(Object)}.
* Entity must attached to an entity context.
*/
@Generated(hash = 128553479)
public void delete() {
if (myDao == null) {
throw new DaoException("Entity is detached from DAO context");
}
myDao.delete(this);
}
/**
* Convenient call for {@link org.greenrobot.greendao.AbstractDao#refresh(Object)}.
* Entity must attached to an entity context.
*/
@Generated(hash = 1942392019)
public void refresh() {
if (myDao == null) {
throw new DaoException("Entity is detached from DAO context");
}
myDao.refresh(this);
}
/**
* Convenient call for {@link org.greenrobot.greendao.AbstractDao#update(Object)}.
* Entity must attached to an entity context.
*/
@Generated(hash = 713229351)
public void update() {
if (myDao == null) {
throw new DaoException("Entity is detached from DAO context");
}
myDao.update(this);
}
/** called by internal mechanisms, do not call yourself. */
@Generated(hash = 1812283172)
public void __setDaoSession(DaoSession daoSession) {
this.daoSession = daoSession;
myDao = daoSession != null ? daoSession.getAccountDao() : null;
}
}

View File

@ -1,254 +0,0 @@
package io.github.wulkanowy.data.db.dao.entities;
import org.greenrobot.greendao.DaoException;
import org.greenrobot.greendao.annotation.Entity;
import org.greenrobot.greendao.annotation.Generated;
import org.greenrobot.greendao.annotation.Id;
import org.greenrobot.greendao.annotation.Index;
import org.greenrobot.greendao.annotation.Property;
import org.greenrobot.greendao.annotation.Transient;
import java.io.Serializable;
@Entity(
nameInDb = "AttendanceLessons",
active = true,
indexes = {@Index(value = "dayId,date,number", unique = true)}
)
public class AttendanceLesson implements Serializable {
@Id(autoincrement = true)
private Long id;
@Property(nameInDb = "day_id")
private Long dayId;
@Property(nameInDb = "date")
private String date = "";
@Property(nameInDb = "number_of_lesson")
private int number = 0;
@Property(nameInDb = "subject")
private String subject = "";
@Property(nameInDb = "presence")
private boolean presence = false;
@Property(nameInDb = "absence_unexcused")
private boolean absenceUnexcused = false;
@Property(nameInDb = "absence_excused")
private boolean absenceExcused = false;
@Property(nameInDb = "unexcused_lateness")
private boolean unexcusedLateness = false;
@Property(nameInDb = "absence_for_school_reasons")
private boolean absenceForSchoolReasons = false;
@Property(nameInDb = "excused_lateness")
private boolean excusedLateness = false;
@Property(nameInDb = "exemption")
private boolean exemption = false;
@Transient
private String description = "";
private static final long serialVersionUID = 42L;
/**
* Used to resolve relations
*/
@Generated(hash = 2040040024)
private transient DaoSession daoSession;
/**
* Used for active entity operations.
*/
@Generated(hash = 1936953859)
private transient AttendanceLessonDao myDao;
@Generated(hash = 1741231228)
public AttendanceLesson(Long id, Long dayId, String date, int number,
String subject, boolean presence, boolean absenceUnexcused,
boolean absenceExcused, boolean unexcusedLateness,
boolean absenceForSchoolReasons, boolean excusedLateness,
boolean exemption) {
this.id = id;
this.dayId = dayId;
this.date = date;
this.number = number;
this.subject = subject;
this.presence = presence;
this.absenceUnexcused = absenceUnexcused;
this.absenceExcused = absenceExcused;
this.unexcusedLateness = unexcusedLateness;
this.absenceForSchoolReasons = absenceForSchoolReasons;
this.excusedLateness = excusedLateness;
this.exemption = exemption;
}
@Generated(hash = 921806575)
public AttendanceLesson() {
}
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
public Long getDayId() {
return this.dayId;
}
public void setDayId(Long dayId) {
this.dayId = dayId;
}
public String getDate() {
return this.date;
}
public AttendanceLesson setDate(String date) {
this.date = date;
return this;
}
public int getNumber() {
return this.number;
}
public AttendanceLesson setNumber(int number) {
this.number = number;
return this;
}
public String getSubject() {
return this.subject;
}
public AttendanceLesson setSubject(String subject) {
this.subject = subject;
return this;
}
public boolean getPresence() {
return this.presence;
}
public AttendanceLesson setPresence(boolean presence) {
this.presence = presence;
return this;
}
public boolean getAbsenceUnexcused() {
return this.absenceUnexcused;
}
public AttendanceLesson setAbsenceUnexcused(boolean absenceUnexcused) {
this.absenceUnexcused = absenceUnexcused;
return this;
}
public boolean getAbsenceExcused() {
return this.absenceExcused;
}
public AttendanceLesson setAbsenceExcused(boolean absenceExcused) {
this.absenceExcused = absenceExcused;
return this;
}
public boolean getUnexcusedLateness() {
return this.unexcusedLateness;
}
public AttendanceLesson setUnexcusedLateness(boolean unexcusedLateness) {
this.unexcusedLateness = unexcusedLateness;
return this;
}
public boolean getAbsenceForSchoolReasons() {
return this.absenceForSchoolReasons;
}
public AttendanceLesson setAbsenceForSchoolReasons(boolean absenceForSchoolReasons) {
this.absenceForSchoolReasons = absenceForSchoolReasons;
return this;
}
public boolean getExcusedLateness() {
return this.excusedLateness;
}
public AttendanceLesson setExcusedLateness(boolean excusedLateness) {
this.excusedLateness = excusedLateness;
return this;
}
public boolean getExemption() {
return this.exemption;
}
public AttendanceLesson setExemption(boolean exemption) {
this.exemption = exemption;
return this;
}
public String getDescription() {
return description;
}
public AttendanceLesson setDescription(String description) {
this.description = description;
return this;
}
/**
* Convenient call for {@link org.greenrobot.greendao.AbstractDao#delete(Object)}.
* Entity must attached to an entity context.
*/
@Generated(hash = 128553479)
public void delete() {
if (myDao == null) {
throw new DaoException("Entity is detached from DAO context");
}
myDao.delete(this);
}
/**
* Convenient call for {@link org.greenrobot.greendao.AbstractDao#refresh(Object)}.
* Entity must attached to an entity context.
*/
@Generated(hash = 1942392019)
public void refresh() {
if (myDao == null) {
throw new DaoException("Entity is detached from DAO context");
}
myDao.refresh(this);
}
/**
* Convenient call for {@link org.greenrobot.greendao.AbstractDao#update(Object)}.
* Entity must attached to an entity context.
*/
@Generated(hash = 713229351)
public void update() {
if (myDao == null) {
throw new DaoException("Entity is detached from DAO context");
}
myDao.update(this);
}
/** called by internal mechanisms, do not call yourself. */
@Generated(hash = 1157101112)
public void __setDaoSession(DaoSession daoSession) {
this.daoSession = daoSession;
myDao = daoSession != null ? daoSession.getAttendanceLessonDao() : null;
}
}

View File

@ -1,263 +0,0 @@
package io.github.wulkanowy.data.db.dao.entities;
import org.greenrobot.greendao.DaoException;
import org.greenrobot.greendao.annotation.Entity;
import org.greenrobot.greendao.annotation.Generated;
import org.greenrobot.greendao.annotation.Id;
import org.greenrobot.greendao.annotation.Index;
import org.greenrobot.greendao.annotation.OrderBy;
import org.greenrobot.greendao.annotation.Property;
import org.greenrobot.greendao.annotation.ToMany;
import java.util.List;
@Entity(
nameInDb = "Days",
active = true,
indexes = {@Index(value = "weekId,date", unique = true)}
)
public class Day {
@Id(autoincrement = true)
private Long id;
@Property(nameInDb = "week_id")
private Long weekId;
@Property(nameInDb = "date")
private String date = "";
@Property(nameInDb = "day_name")
private String dayName = "";
@Property(nameInDb = "free_day")
private boolean freeDay = false;
@Property(nameInDb = "free_day_name")
private String freeDayName = "";
@OrderBy("number ASC")
@ToMany(referencedJoinProperty = "dayId")
private List<TimetableLesson> timetableLessons;
@OrderBy("number ASC")
@ToMany(referencedJoinProperty = "dayId")
private List<AttendanceLesson> attendanceLessons;
@ToMany(referencedJoinProperty = "dayId")
private List<Exam> exams;
/**
* Used to resolve relations
*/
@Generated(hash = 2040040024)
private transient DaoSession daoSession;
/** Used for active entity operations. */
@Generated(hash = 312167767)
private transient DayDao myDao;
@Generated(hash = 523139020)
public Day(Long id, Long weekId, String date, String dayName, boolean freeDay,
String freeDayName) {
this.id = id;
this.weekId = weekId;
this.date = date;
this.dayName = dayName;
this.freeDay = freeDay;
this.freeDayName = freeDayName;
}
@Generated(hash = 866989762)
public Day() {
}
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
public Long getWeekId() {
return this.weekId;
}
public void setWeekId(Long weekId) {
this.weekId = weekId;
}
public String getDate() {
return this.date;
}
public Day setDate(String date) {
this.date = date;
return this;
}
public String getDayName() {
return this.dayName;
}
public Day setDayName(String dayName) {
this.dayName = dayName;
return this;
}
public boolean getFreeDay() {
return this.freeDay;
}
public Day setFreeDay(boolean freeDay) {
this.freeDay = freeDay;
return this;
}
public String getFreeDayName() {
return this.freeDayName;
}
public Day setFreeDayName(String freeDayName) {
this.freeDayName = freeDayName;
return this;
}
/**
* To-many relationship, resolved on first access (and after reset).
* Changes to to-many relations are not persisted, make changes to the target entity.
*/
@Generated(hash = 218588195)
public List<TimetableLesson> getTimetableLessons() {
if (timetableLessons == null) {
final DaoSession daoSession = this.daoSession;
if (daoSession == null) {
throw new DaoException("Entity is detached from DAO context");
}
TimetableLessonDao targetDao = daoSession.getTimetableLessonDao();
List<TimetableLesson> timetableLessonsNew = targetDao
._queryDay_TimetableLessons(id);
synchronized (this) {
if (timetableLessons == null) {
timetableLessons = timetableLessonsNew;
}
}
}
return timetableLessons;
}
/**
* Resets a to-many relationship, making the next get call to query for a fresh result.
*/
@Generated(hash = 1687683740)
public synchronized void resetTimetableLessons() {
timetableLessons = null;
}
/**
* To-many relationship, resolved on first access (and after reset).
* Changes to to-many relations are not persisted, make changes to the target entity.
*/
@Generated(hash = 1166820581)
public List<AttendanceLesson> getAttendanceLessons() {
if (attendanceLessons == null) {
final DaoSession daoSession = this.daoSession;
if (daoSession == null) {
throw new DaoException("Entity is detached from DAO context");
}
AttendanceLessonDao targetDao = daoSession.getAttendanceLessonDao();
List<AttendanceLesson> attendanceLessonsNew = targetDao
._queryDay_AttendanceLessons(id);
synchronized (this) {
if (attendanceLessons == null) {
attendanceLessons = attendanceLessonsNew;
}
}
}
return attendanceLessons;
}
/**
* Resets a to-many relationship, making the next get call to query for a fresh result.
*/
@Generated(hash = 1343075564)
public synchronized void resetAttendanceLessons() {
attendanceLessons = null;
}
/**
* To-many relationship, resolved on first access (and after reset).
* Changes to to-many relations are not persisted, make changes to the target entity.
*/
@Generated(hash = 1231531946)
public List<Exam> getExams() {
if (exams == null) {
final DaoSession daoSession = this.daoSession;
if (daoSession == null) {
throw new DaoException("Entity is detached from DAO context");
}
ExamDao targetDao = daoSession.getExamDao();
List<Exam> examsNew = targetDao._queryDay_Exams(id);
synchronized (this) {
if (exams == null) {
exams = examsNew;
}
}
}
return exams;
}
/**
* Resets a to-many relationship, making the next get call to query for a fresh result.
*/
@Generated(hash = 841969952)
public synchronized void resetExams() {
exams = null;
}
/**
* Convenient call for {@link org.greenrobot.greendao.AbstractDao#delete(Object)}.
* Entity must attached to an entity context.
*/
@Generated(hash = 128553479)
public void delete() {
if (myDao == null) {
throw new DaoException("Entity is detached from DAO context");
}
myDao.delete(this);
}
/**
* Convenient call for {@link org.greenrobot.greendao.AbstractDao#refresh(Object)}.
* Entity must attached to an entity context.
*/
@Generated(hash = 1942392019)
public void refresh() {
if (myDao == null) {
throw new DaoException("Entity is detached from DAO context");
}
myDao.refresh(this);
}
/**
* Convenient call for {@link org.greenrobot.greendao.AbstractDao#update(Object)}.
* Entity must attached to an entity context.
*/
@Generated(hash = 713229351)
public void update() {
if (myDao == null) {
throw new DaoException("Entity is detached from DAO context");
}
myDao.update(this);
}
/** called by internal mechanisms, do not call yourself. */
@Generated(hash = 1409317752)
public void __setDaoSession(DaoSession daoSession) {
this.daoSession = daoSession;
myDao = daoSession != null ? daoSession.getDayDao() : null;
}
}

View File

@ -1,177 +0,0 @@
package io.github.wulkanowy.data.db.dao.entities;
import org.greenrobot.greendao.DaoException;
import org.greenrobot.greendao.annotation.Entity;
import org.greenrobot.greendao.annotation.Generated;
import org.greenrobot.greendao.annotation.Id;
import org.greenrobot.greendao.annotation.Property;
import org.greenrobot.greendao.annotation.ToMany;
import java.util.List;
@Entity(
nameInDb = "Diaries",
active = true
)
public class Diary {
@Id(autoincrement = true)
private Long id;
@Property(nameInDb = "student_id")
private Long studentId;
@Property(nameInDb = "current")
private boolean current;
@Property(nameInDb = "name")
private String name;
@Property(nameInDb = "value")
private String value;
@ToMany(referencedJoinProperty = "diaryId")
private List<Semester> semesterList;
/**
* Used to resolve relations
*/
@Generated(hash = 2040040024)
private transient DaoSession daoSession;
/**
* Used for active entity operations.
*/
@Generated(hash = 21166549)
private transient DiaryDao myDao;
@Generated(hash = 277096196)
public Diary(Long id, Long studentId, boolean current, String name, String value) {
this.id = id;
this.studentId = studentId;
this.current = current;
this.name = name;
this.value = value;
}
@Generated(hash = 112123061)
public Diary() {
}
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
public Long getStudentId() {
return this.studentId;
}
public Diary setStudentId(Long studentId) {
this.studentId = studentId;
return this;
}
public String getName() {
return this.name;
}
public Diary setName(String name) {
this.name = name;
return this;
}
public String getValue() {
return this.value;
}
public Diary setValue(String value) {
this.value = value;
return this;
}
public boolean getCurrent() {
return this.current;
}
public Diary setCurrent(boolean current) {
this.current = current;
return this;
}
/**
* To-many relationship, resolved on first access (and after reset).
* Changes to to-many relations are not persisted, make changes to the target entity.
*/
@Generated(hash = 1738383053)
public List<Semester> getSemesterList() {
if (semesterList == null) {
final DaoSession daoSession = this.daoSession;
if (daoSession == null) {
throw new DaoException("Entity is detached from DAO context");
}
SemesterDao targetDao = daoSession.getSemesterDao();
List<Semester> semesterListNew = targetDao._queryDiary_SemesterList(id);
synchronized (this) {
if (semesterList == null) {
semesterList = semesterListNew;
}
}
}
return semesterList;
}
/**
* Resets a to-many relationship, making the next get call to query for a fresh result.
*/
@Generated(hash = 995060657)
public synchronized void resetSemesterList() {
semesterList = null;
}
/**
* Convenient call for {@link org.greenrobot.greendao.AbstractDao#delete(Object)}.
* Entity must attached to an entity context.
*/
@Generated(hash = 128553479)
public void delete() {
if (myDao == null) {
throw new DaoException("Entity is detached from DAO context");
}
myDao.delete(this);
}
/**
* Convenient call for {@link org.greenrobot.greendao.AbstractDao#refresh(Object)}.
* Entity must attached to an entity context.
*/
@Generated(hash = 1942392019)
public void refresh() {
if (myDao == null) {
throw new DaoException("Entity is detached from DAO context");
}
myDao.refresh(this);
}
/**
* Convenient call for {@link org.greenrobot.greendao.AbstractDao#update(Object)}.
* Entity must attached to an entity context.
*/
@Generated(hash = 713229351)
public void update() {
if (myDao == null) {
throw new DaoException("Entity is detached from DAO context");
}
myDao.update(this);
}
/** called by internal mechanisms, do not call yourself. */
@Generated(hash = 629297785)
public void __setDaoSession(DaoSession daoSession) {
this.daoSession = daoSession;
myDao = daoSession != null ? daoSession.getDiaryDao() : null;
}
}

View File

@ -1,177 +0,0 @@
package io.github.wulkanowy.data.db.dao.entities;
import org.greenrobot.greendao.DaoException;
import org.greenrobot.greendao.annotation.Entity;
import org.greenrobot.greendao.annotation.Generated;
import org.greenrobot.greendao.annotation.Id;
import org.greenrobot.greendao.annotation.Index;
import org.greenrobot.greendao.annotation.Property;
import java.io.Serializable;
@Entity(
nameInDb = "Exams",
active = true,
indexes = {@Index(value = "dayId,entryDate,subjectAndGroup,type,teacher", unique = true)}
)
public class Exam implements Serializable {
@Id(autoincrement = true)
private Long id;
@Property(nameInDb = "day_id")
private Long dayId;
@Property(nameInDb = "subject_and_group")
private String subjectAndGroup = "";
@Property(nameInDb = "type")
private String type = "";
@Property(nameInDb = "description")
private String description = "";
@Property(nameInDb = "teacher")
private String teacher = "";
@Property(nameInDb = "entry_date")
private String entryDate = "";
private static final long serialVersionUID = 42L;
/**
* Used to resolve relations
*/
@Generated(hash = 2040040024)
private transient DaoSession daoSession;
/**
* Used for active entity operations.
*/
@Generated(hash = 973692038)
private transient ExamDao myDao;
@Generated(hash = 998653360)
public Exam(Long id, Long dayId, String subjectAndGroup, String type, String description,
String teacher, String entryDate) {
this.id = id;
this.dayId = dayId;
this.subjectAndGroup = subjectAndGroup;
this.type = type;
this.description = description;
this.teacher = teacher;
this.entryDate = entryDate;
}
@Generated(hash = 945526930)
public Exam() {
}
public Long getId() {
return id;
}
public Exam setId(Long id) {
this.id = id;
return this;
}
public Long getDayId() {
return this.dayId;
}
public Exam setDayId(Long dayId) {
this.dayId = dayId;
return this;
}
public String getSubjectAndGroup() {
return subjectAndGroup;
}
public Exam setSubjectAndGroup(String subjectAndGroup) {
this.subjectAndGroup = subjectAndGroup;
return this;
}
public String getType() {
return type;
}
public Exam setType(String type) {
this.type = type;
return this;
}
public String getDescription() {
return description;
}
public Exam setDescription(String description) {
this.description = description;
return this;
}
public String getTeacher() {
return teacher;
}
public Exam setTeacher(String teacher) {
this.teacher = teacher;
return this;
}
public String getEntryDate() {
return entryDate;
}
public Exam setEntryDate(String entryDate) {
this.entryDate = entryDate;
return this;
}
/**
* Convenient call for {@link org.greenrobot.greendao.AbstractDao#delete(Object)}.
* Entity must attached to an entity context.
*/
@Generated(hash = 128553479)
public void delete() {
if (myDao == null) {
throw new DaoException("Entity is detached from DAO context");
}
myDao.delete(this);
}
/**
* Convenient call for {@link org.greenrobot.greendao.AbstractDao#refresh(Object)}.
* Entity must attached to an entity context.
*/
@Generated(hash = 1942392019)
public void refresh() {
if (myDao == null) {
throw new DaoException("Entity is detached from DAO context");
}
myDao.refresh(this);
}
/**
* Convenient call for {@link org.greenrobot.greendao.AbstractDao#update(Object)}.
* Entity must attached to an entity context.
*/
@Generated(hash = 713229351)
public void update() {
if (myDao == null) {
throw new DaoException("Entity is detached from DAO context");
}
myDao.update(this);
}
/** called by internal mechanisms, do not call yourself. */
@Generated(hash = 1730563422)
public void __setDaoSession(DaoSession daoSession) {
this.daoSession = daoSession;
myDao = daoSession != null ? daoSession.getExamDao() : null;
}
}

View File

@ -1,293 +0,0 @@
package io.github.wulkanowy.data.db.dao.entities;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.greenrobot.greendao.DaoException;
import org.greenrobot.greendao.annotation.Entity;
import org.greenrobot.greendao.annotation.Generated;
import org.greenrobot.greendao.annotation.Id;
import org.greenrobot.greendao.annotation.Property;
import java.io.Serializable;
@Entity(
nameInDb = "Grades",
active = true
)
public class Grade implements Serializable {
@Id(autoincrement = true)
protected Long id;
@Property(nameInDb = "semester_id")
private Long semesterId;
@Property(nameInDb = "subject_id")
private Long subjectId;
@Property(nameInDb = "subject")
private String subject = "";
@Property(nameInDb = "value")
protected String value = "";
@Property(nameInDb = "weight")
private String weight = "";
@Property(nameInDb = "date")
private String date = "";
@Property(nameInDb = "symbol")
private String symbol = "";
@Property(nameInDb = "color")
private String color = "";
@Property(nameInDb = "description")
private String description = "";
@Property(nameInDb = "teacher")
private String teacher = "";
@Property(nameInDb = "is_new")
private boolean isNew = false;
@Property(nameInDb = "read")
private boolean read = true;
private static final long serialVersionUID = 42L;
/**
* Used to resolve relations
*/
@Generated(hash = 2040040024)
private transient DaoSession daoSession;
/**
* Used for active entity operations.
*/
@Generated(hash = 681281562)
private transient GradeDao myDao;
@Generated(hash = 2042976393)
public Grade() {
}
@Generated(hash = 619853992)
public Grade(Long id, Long semesterId, Long subjectId, String subject, String value,
String weight, String date, String symbol, String color, String description,
String teacher, boolean isNew, boolean read) {
this.id = id;
this.semesterId = semesterId;
this.subjectId = subjectId;
this.subject = subject;
this.value = value;
this.weight = weight;
this.date = date;
this.symbol = symbol;
this.color = color;
this.description = description;
this.teacher = teacher;
this.isNew = isNew;
this.read = read;
}
@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(semesterId, grade.semesterId)
.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)
.isEquals();
}
@Override
public int hashCode() {
return new HashCodeBuilder(17, 37)
.append(semesterId)
.append(subject)
.append(value)
.append(color)
.append(symbol)
.append(description)
.append(weight)
.append(date)
.append(teacher)
.toHashCode();
}
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
public String getValue() {
return this.value;
}
public Grade setValue(String value) {
this.value = value;
return this;
}
public Long getSemesterId() {
return this.semesterId;
}
public Grade setSemesterId(Long semesterId) {
this.semesterId = semesterId;
return this;
}
public String getSubject() {
return this.subject;
}
public Grade setSubject(String subject) {
this.subject = subject;
return this;
}
public String getColor() {
return this.color;
}
public Grade setColor(String color) {
this.color = color;
return this;
}
public String getSymbol() {
return this.symbol;
}
public Grade setSymbol(String symbol) {
this.symbol = symbol;
return this;
}
public String getDescription() {
return this.description;
}
public Grade setDescription(String description) {
this.description = description;
return this;
}
public String getWeight() {
return this.weight;
}
public Grade setWeight(String weight) {
this.weight = weight;
return this;
}
public String getDate() {
return this.date;
}
public Grade setDate(String date) {
this.date = date;
return this;
}
public String getTeacher() {
return this.teacher;
}
public Grade setTeacher(String teacher) {
this.teacher = teacher;
return this;
}
public boolean getIsNew() {
return this.isNew;
}
public void setIsNew(boolean isNew) {
this.isNew = isNew;
}
public boolean getRead() {
return this.read;
}
public Grade setRead(boolean read) {
this.read = read;
return this;
}
public Long getSubjectId() {
return this.subjectId;
}
public void setSubjectId(Long subjectId) {
this.subjectId = subjectId;
}
/**
* Convenient call for {@link org.greenrobot.greendao.AbstractDao#delete(Object)}.
* Entity must attached to an entity context.
*/
@Generated(hash = 128553479)
public void delete() {
if (myDao == null) {
throw new DaoException("Entity is detached from DAO context");
}
myDao.delete(this);
}
/**
* Convenient call for {@link org.greenrobot.greendao.AbstractDao#refresh(Object)}.
* Entity must attached to an entity context.
*/
@Generated(hash = 1942392019)
public void refresh() {
if (myDao == null) {
throw new DaoException("Entity is detached from DAO context");
}
myDao.refresh(this);
}
/**
* Convenient call for {@link org.greenrobot.greendao.AbstractDao#update(Object)}.
* Entity must attached to an entity context.
*/
@Generated(hash = 713229351)
public void update() {
if (myDao == null) {
throw new DaoException("Entity is detached from DAO context");
}
myDao.update(this);
}
/** called by internal mechanisms, do not call yourself. */
@Generated(hash = 1187286414)
public void __setDaoSession(DaoSession daoSession) {
this.daoSession = daoSession;
myDao = daoSession != null ? daoSession.getGradeDao() : null;
}
}

View File

@ -1,179 +0,0 @@
package io.github.wulkanowy.data.db.dao.entities;
import org.greenrobot.greendao.DaoException;
import org.greenrobot.greendao.annotation.Entity;
import org.greenrobot.greendao.annotation.Generated;
import org.greenrobot.greendao.annotation.Id;
import org.greenrobot.greendao.annotation.Property;
import org.greenrobot.greendao.annotation.ToMany;
import java.util.List;
@Entity(
nameInDb = "Schools",
active = true
)
public class School {
@Id(autoincrement = true)
private Long id;
@Property(nameInDb = "symbol_id")
private Long symbolId;
@Property(nameInDb = "current")
private boolean current;
@Property(nameInDb = "real_id")
private String realId;
@Property(nameInDb = "name")
private String name;
@ToMany(referencedJoinProperty = "schoolId")
private List<Student> studentList;
/**
* Used to resolve relations
*/
@Generated(hash = 2040040024)
private transient DaoSession daoSession;
/**
* Used for active entity operations.
*/
@Generated(hash = 1796006707)
private transient SchoolDao myDao;
@Generated(hash = 975562398)
public School(Long id, Long symbolId, boolean current, String realId,
String name) {
this.id = id;
this.symbolId = symbolId;
this.current = current;
this.realId = realId;
this.name = name;
}
@Generated(hash = 1579966795)
public School() {
}
public Long getId() {
return this.id;
}
public School setId(Long id) {
this.id = id;
return this;
}
public Long getSymbolId() {
return this.symbolId;
}
public School setSymbolId(Long symbolId) {
this.symbolId = symbolId;
return this;
}
public boolean getCurrent() {
return this.current;
}
public School setCurrent(boolean current) {
this.current = current;
return this;
}
public String getRealId() {
return this.realId;
}
public School setRealId(String realId) {
this.realId = realId;
return this;
}
public String getName() {
return this.name;
}
public School setName(String name) {
this.name = name;
return this;
}
/**
* To-many relationship, resolved on first access (and after reset).
* Changes to to-many relations are not persisted, make changes to the target entity.
*/
@Generated(hash = 180118651)
public List<Student> getStudentList() {
if (studentList == null) {
final DaoSession daoSession = this.daoSession;
if (daoSession == null) {
throw new DaoException("Entity is detached from DAO context");
}
StudentDao targetDao = daoSession.getStudentDao();
List<Student> studentListNew = targetDao._querySchool_StudentList(id);
synchronized (this) {
if (studentList == null) {
studentList = studentListNew;
}
}
}
return studentList;
}
/**
* Resets a to-many relationship, making the next get call to query for a fresh result.
*/
@Generated(hash = 1628625923)
public synchronized void resetStudentList() {
studentList = null;
}
/**
* Convenient call for {@link org.greenrobot.greendao.AbstractDao#delete(Object)}.
* Entity must attached to an entity context.
*/
@Generated(hash = 128553479)
public void delete() {
if (myDao == null) {
throw new DaoException("Entity is detached from DAO context");
}
myDao.delete(this);
}
/**
* Convenient call for {@link org.greenrobot.greendao.AbstractDao#refresh(Object)}.
* Entity must attached to an entity context.
*/
@Generated(hash = 1942392019)
public void refresh() {
if (myDao == null) {
throw new DaoException("Entity is detached from DAO context");
}
myDao.refresh(this);
}
/**
* Convenient call for {@link org.greenrobot.greendao.AbstractDao#update(Object)}.
* Entity must attached to an entity context.
*/
@Generated(hash = 713229351)
public void update() {
if (myDao == null) {
throw new DaoException("Entity is detached from DAO context");
}
myDao.update(this);
}
/** called by internal mechanisms, do not call yourself. */
@Generated(hash = 234091322)
public void __setDaoSession(DaoSession daoSession) {
this.daoSession = daoSession;
myDao = daoSession != null ? daoSession.getSchoolDao() : null;
}
}

View File

@ -1,208 +0,0 @@
package io.github.wulkanowy.data.db.dao.entities;
import org.greenrobot.greendao.DaoException;
import org.greenrobot.greendao.annotation.Entity;
import org.greenrobot.greendao.annotation.Generated;
import org.greenrobot.greendao.annotation.Id;
import org.greenrobot.greendao.annotation.Property;
import org.greenrobot.greendao.annotation.ToMany;
import java.util.List;
@Entity(
nameInDb = "Semesters",
active = true
)
public class Semester {
@Id(autoincrement = true)
private Long id;
@Property(nameInDb = "diary_id")
private Long diaryId;
@Property(nameInDb = "current")
private boolean current;
@Property(nameInDb = "name")
private String name;
@Property(nameInDb = "value")
private String value;
@ToMany(referencedJoinProperty = "semesterId")
private List<Subject> subjectList;
@ToMany(referencedJoinProperty = "semesterId")
private List<Grade> gradeList;
/**
* Used to resolve relations
*/
@Generated(hash = 2040040024)
private transient DaoSession daoSession;
/**
* Used for active entity operations.
*/
@Generated(hash = 282930393)
private transient SemesterDao myDao;
@Generated(hash = 1661077309)
public Semester(Long id, Long diaryId, boolean current, String name, String value) {
this.id = id;
this.diaryId = diaryId;
this.current = current;
this.name = name;
this.value = value;
}
@Generated(hash = 58335877)
public Semester() {
}
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
public Long getDiaryId() {
return this.diaryId;
}
public Semester setDiaryId(Long diaryId) {
this.diaryId = diaryId;
return this;
}
public String getName() {
return this.name;
}
public Semester setName(String name) {
this.name = name;
return this;
}
public String getValue() {
return this.value;
}
public Semester setValue(String value) {
this.value = value;
return this;
}
public boolean getCurrent() {
return this.current;
}
public Semester setCurrent(boolean current) {
this.current = current;
return this;
}
/**
* To-many relationship, resolved on first access (and after reset).
* Changes to to-many relations are not persisted, make changes to the target entity.
*/
@Generated(hash = 723353662)
public List<Subject> getSubjectList() {
if (subjectList == null) {
final DaoSession daoSession = this.daoSession;
if (daoSession == null) {
throw new DaoException("Entity is detached from DAO context");
}
SubjectDao targetDao = daoSession.getSubjectDao();
List<Subject> subjectListNew = targetDao._querySemester_SubjectList(id);
synchronized (this) {
if (subjectList == null) {
subjectList = subjectListNew;
}
}
}
return subjectList;
}
/**
* Resets a to-many relationship, making the next get call to query for a fresh result.
*/
@Generated(hash = 594294258)
public synchronized void resetSubjectList() {
subjectList = null;
}
/**
* Convenient call for {@link org.greenrobot.greendao.AbstractDao#delete(Object)}.
* Entity must attached to an entity context.
*/
@Generated(hash = 128553479)
public void delete() {
if (myDao == null) {
throw new DaoException("Entity is detached from DAO context");
}
myDao.delete(this);
}
/**
* Convenient call for {@link org.greenrobot.greendao.AbstractDao#refresh(Object)}.
* Entity must attached to an entity context.
*/
@Generated(hash = 1942392019)
public void refresh() {
if (myDao == null) {
throw new DaoException("Entity is detached from DAO context");
}
myDao.refresh(this);
}
/**
* Convenient call for {@link org.greenrobot.greendao.AbstractDao#update(Object)}.
* Entity must attached to an entity context.
*/
@Generated(hash = 713229351)
public void update() {
if (myDao == null) {
throw new DaoException("Entity is detached from DAO context");
}
myDao.update(this);
}
/**
* To-many relationship, resolved on first access (and after reset).
* Changes to to-many relations are not persisted, make changes to the target entity.
*/
@Generated(hash = 390330007)
public List<Grade> getGradeList() {
if (gradeList == null) {
final DaoSession daoSession = this.daoSession;
if (daoSession == null) {
throw new DaoException("Entity is detached from DAO context");
}
GradeDao targetDao = daoSession.getGradeDao();
List<Grade> gradeListNew = targetDao._querySemester_GradeList(id);
synchronized (this) {
if (gradeList == null) {
gradeList = gradeListNew;
}
}
}
return gradeList;
}
/** Resets a to-many relationship, making the next get call to query for a fresh result. */
@Generated(hash = 1939990047)
public synchronized void resetGradeList() {
gradeList = null;
}
/** called by internal mechanisms, do not call yourself. */
@Generated(hash = 676204164)
public void __setDaoSession(DaoSession daoSession) {
this.daoSession = daoSession;
myDao = daoSession != null ? daoSession.getSemesterDao() : null;
}
}

View File

@ -1,178 +0,0 @@
package io.github.wulkanowy.data.db.dao.entities;
import org.greenrobot.greendao.DaoException;
import org.greenrobot.greendao.annotation.Entity;
import org.greenrobot.greendao.annotation.Generated;
import org.greenrobot.greendao.annotation.Id;
import org.greenrobot.greendao.annotation.Property;
import org.greenrobot.greendao.annotation.ToMany;
import java.util.List;
@Entity(
nameInDb = "Students",
active = true
)
public class Student {
@Id(autoincrement = true)
private Long id;
@Property(nameInDb = "school_id")
private Long schoolId;
@Property(nameInDb = "current")
private boolean current;
@Property(nameInDb = "real_id")
private String realId;
@Property(nameInDb = "name")
private String name;
@ToMany(referencedJoinProperty = "studentId")
private List<Diary> diaryList;
/**
* Used to resolve relations
*/
@Generated(hash = 2040040024)
private transient DaoSession daoSession;
/**
* Used for active entity operations.
*/
@Generated(hash = 1943931642)
private transient StudentDao myDao;
@Generated(hash = 470181623)
public Student(Long id, Long schoolId, boolean current, String realId, String name) {
this.id = id;
this.schoolId = schoolId;
this.current = current;
this.realId = realId;
this.name = name;
}
@Generated(hash = 1556870573)
public Student() {
}
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
public Long getSchoolId() {
return this.schoolId;
}
public Student setSchoolId(Long schoolId) {
this.schoolId = schoolId;
return this;
}
public String getRealId() {
return this.realId;
}
public Student setRealId(String realId) {
this.realId = realId;
return this;
}
public String getName() {
return this.name;
}
public Student setName(String name) {
this.name = name;
return this;
}
public boolean getCurrent() {
return this.current;
}
public Student setCurrent(boolean current) {
this.current = current;
return this;
}
/**
* To-many relationship, resolved on first access (and after reset).
* Changes to to-many relations are not persisted, make changes to the target entity.
*/
@Generated(hash = 508305571)
public List<Diary> getDiaryList() {
if (diaryList == null) {
final DaoSession daoSession = this.daoSession;
if (daoSession == null) {
throw new DaoException("Entity is detached from DAO context");
}
DiaryDao targetDao = daoSession.getDiaryDao();
List<Diary> diaryListNew = targetDao._queryStudent_DiaryList(id);
synchronized (this) {
if (diaryList == null) {
diaryList = diaryListNew;
}
}
}
return diaryList;
}
/**
* Resets a to-many relationship, making the next get call to query for a fresh result.
*/
@Generated(hash = 1078514341)
public synchronized void resetDiaryList() {
diaryList = null;
}
/**
* Convenient call for {@link org.greenrobot.greendao.AbstractDao#delete(Object)}.
* Entity must attached to an entity context.
*/
@Generated(hash = 128553479)
public void delete() {
if (myDao == null) {
throw new DaoException("Entity is detached from DAO context");
}
myDao.delete(this);
}
/**
* Convenient call for {@link org.greenrobot.greendao.AbstractDao#refresh(Object)}.
* Entity must attached to an entity context.
*/
@Generated(hash = 1942392019)
public void refresh() {
if (myDao == null) {
throw new DaoException("Entity is detached from DAO context");
}
myDao.refresh(this);
}
/**
* Convenient call for {@link org.greenrobot.greendao.AbstractDao#update(Object)}.
* Entity must attached to an entity context.
*/
@Generated(hash = 713229351)
public void update() {
if (myDao == null) {
throw new DaoException("Entity is detached from DAO context");
}
myDao.update(this);
}
/** called by internal mechanisms, do not call yourself. */
@Generated(hash = 1701634981)
public void __setDaoSession(DaoSession daoSession) {
this.daoSession = daoSession;
myDao = daoSession != null ? daoSession.getStudentDao() : null;
}
}

View File

@ -1,176 +0,0 @@
package io.github.wulkanowy.data.db.dao.entities;
import org.greenrobot.greendao.DaoException;
import org.greenrobot.greendao.annotation.Entity;
import org.greenrobot.greendao.annotation.Generated;
import org.greenrobot.greendao.annotation.Id;
import org.greenrobot.greendao.annotation.Property;
import org.greenrobot.greendao.annotation.ToMany;
import java.util.List;
@Entity(
nameInDb = "Subjects",
active = true
)
public class Subject {
@Id(autoincrement = true)
private Long id;
@Property(nameInDb = "semester_id")
private Long semesterId;
@Property(nameInDb = "name")
private String name;
@Property(nameInDb = "predicted_rating")
private String predictedRating;
@Property(nameInDb = "final_rating")
private String finalRating;
@ToMany(referencedJoinProperty = "subjectId")
private List<Grade> gradeList;
/**
* Used to resolve relations
*/
@Generated(hash = 2040040024)
private transient DaoSession daoSession;
/**
* Used for active entity operations.
*/
@Generated(hash = 1644932788)
private transient SubjectDao myDao;
@Generated(hash = 1817932538)
public Subject(Long id, Long semesterId, String name, String predictedRating,
String finalRating) {
this.id = id;
this.semesterId = semesterId;
this.name = name;
this.predictedRating = predictedRating;
this.finalRating = finalRating;
}
@Generated(hash = 1617906264)
public Subject() {
}
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
public Long getSemesterId() {
return this.semesterId;
}
public Subject setSemesterId(Long semesterId) {
this.semesterId = semesterId;
return this;
}
public String getName() {
return this.name;
}
public Subject setName(String name) {
this.name = name;
return this;
}
public String getPredictedRating() {
return this.predictedRating;
}
public Subject setPredictedRating(String predictedRating) {
this.predictedRating = predictedRating;
return this;
}
public String getFinalRating() {
return this.finalRating;
}
public Subject setFinalRating(String finalRating) {
this.finalRating = finalRating;
return this;
}
/**
* Convenient call for {@link org.greenrobot.greendao.AbstractDao#delete(Object)}.
* Entity must attached to an entity context.
*/
@Generated(hash = 128553479)
public void delete() {
if (myDao == null) {
throw new DaoException("Entity is detached from DAO context");
}
myDao.delete(this);
}
/**
* Convenient call for {@link org.greenrobot.greendao.AbstractDao#refresh(Object)}.
* Entity must attached to an entity context.
*/
@Generated(hash = 1942392019)
public void refresh() {
if (myDao == null) {
throw new DaoException("Entity is detached from DAO context");
}
myDao.refresh(this);
}
/**
* Convenient call for {@link org.greenrobot.greendao.AbstractDao#update(Object)}.
* Entity must attached to an entity context.
*/
@Generated(hash = 713229351)
public void update() {
if (myDao == null) {
throw new DaoException("Entity is detached from DAO context");
}
myDao.update(this);
}
/**
* To-many relationship, resolved on first access (and after reset).
* Changes to to-many relations are not persisted, make changes to the target entity.
*/
@Generated(hash = 1358847893)
public List<Grade> getGradeList() {
if (gradeList == null) {
final DaoSession daoSession = this.daoSession;
if (daoSession == null) {
throw new DaoException("Entity is detached from DAO context");
}
GradeDao targetDao = daoSession.getGradeDao();
List<Grade> gradeListNew = targetDao._querySubject_GradeList(id);
synchronized (this) {
if (gradeList == null) {
gradeList = gradeListNew;
}
}
}
return gradeList;
}
/** Resets a to-many relationship, making the next get call to query for a fresh result. */
@Generated(hash = 1939990047)
public synchronized void resetGradeList() {
gradeList = null;
}
/** called by internal mechanisms, do not call yourself. */
@Generated(hash = 937984622)
public void __setDaoSession(DaoSession daoSession) {
this.daoSession = daoSession;
myDao = daoSession != null ? daoSession.getSubjectDao() : null;
}
}

View File

@ -1,175 +0,0 @@
package io.github.wulkanowy.data.db.dao.entities;
import org.greenrobot.greendao.DaoException;
import org.greenrobot.greendao.annotation.Entity;
import org.greenrobot.greendao.annotation.Generated;
import org.greenrobot.greendao.annotation.Id;
import org.greenrobot.greendao.annotation.Property;
import org.greenrobot.greendao.annotation.ToMany;
import java.util.List;
@Entity(
nameInDb = "Symbols",
active = true
)
public class Symbol {
@Id(autoincrement = true)
private Long id;
@Property(nameInDb = "user_id")
private Long userId;
@Property(nameInDb = "host")
private String host;
@Property(nameInDb = "symbol")
private String symbol;
@Property(nameInDb = "type")
private String type;
@ToMany(referencedJoinProperty = "symbolId")
private List<School> schoolList;
/**
* Used to resolve relations
*/
@Generated(hash = 2040040024)
private transient DaoSession daoSession;
/**
* Used for active entity operations.
*/
@Generated(hash = 684907977)
private transient SymbolDao myDao;
@Generated(hash = 1034469460)
public Symbol(Long id, Long userId, String host, String symbol, String type) {
this.id = id;
this.userId = userId;
this.host = host;
this.symbol = symbol;
this.type = type;
}
@Generated(hash = 460475327)
public Symbol() {
}
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
public Long getUserId() {
return this.userId;
}
public Symbol setUserId(Long userId) {
this.userId = userId;
return this;
}
public String getHost() {
return this.host;
}
public Symbol setHost(String host) {
this.host = host;
return this;
}
public String getSymbol() {
return this.symbol;
}
public Symbol setSymbol(String symbol) {
this.symbol = symbol;
return this;
}
public String getType() {
return this.type;
}
public Symbol setType(String type) {
this.type = type;
return this;
}
/**
* To-many relationship, resolved on first access (and after reset).
* Changes to to-many relations are not persisted, make changes to the target entity.
*/
@Generated(hash = 1733082867)
public List<School> getSchoolList() {
if (schoolList == null) {
final DaoSession daoSession = this.daoSession;
if (daoSession == null) {
throw new DaoException("Entity is detached from DAO context");
}
SchoolDao targetDao = daoSession.getSchoolDao();
List<School> schoolListNew = targetDao._querySymbol_SchoolList(id);
synchronized (this) {
if (schoolList == null) {
schoolList = schoolListNew;
}
}
}
return schoolList;
}
/** Resets a to-many relationship, making the next get call to query for a fresh result. */
@Generated(hash = 1757777300)
public synchronized void resetSchoolList() {
schoolList = null;
}
/**
* Convenient call for {@link org.greenrobot.greendao.AbstractDao#delete(Object)}.
* Entity must attached to an entity context.
*/
@Generated(hash = 128553479)
public void delete() {
if (myDao == null) {
throw new DaoException("Entity is detached from DAO context");
}
myDao.delete(this);
}
/**
* Convenient call for {@link org.greenrobot.greendao.AbstractDao#refresh(Object)}.
* Entity must attached to an entity context.
*/
@Generated(hash = 1942392019)
public void refresh() {
if (myDao == null) {
throw new DaoException("Entity is detached from DAO context");
}
myDao.refresh(this);
}
/**
* Convenient call for {@link org.greenrobot.greendao.AbstractDao#update(Object)}.
* Entity must attached to an entity context.
*/
@Generated(hash = 713229351)
public void update() {
if (myDao == null) {
throw new DaoException("Entity is detached from DAO context");
}
myDao.update(this);
}
/** called by internal mechanisms, do not call yourself. */
@Generated(hash = 632145708)
public void __setDaoSession(DaoSession daoSession) {
this.daoSession = daoSession;
myDao = daoSession != null ? daoSession.getSymbolDao() : null;
}
}

View File

@ -1,332 +0,0 @@
package io.github.wulkanowy.data.db.dao.entities;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.greenrobot.greendao.DaoException;
import org.greenrobot.greendao.annotation.Entity;
import org.greenrobot.greendao.annotation.Generated;
import org.greenrobot.greendao.annotation.Id;
import org.greenrobot.greendao.annotation.Index;
import org.greenrobot.greendao.annotation.Property;
import java.io.Serializable;
@Entity(
nameInDb = "TimetableLessons",
active = true,
indexes = {@Index(value = "dayId,date,number,startTime,endTime", unique = true)}
)
public class TimetableLesson implements Serializable {
private static final long serialVersionUID = 42L;
@Id(autoincrement = true)
private Long id;
@Property(nameInDb = "day_id")
private Long dayId;
@Property(nameInDb = "number")
private int number = 0;
@Property(nameInDb = "subject")
private String subject = "";
@Property(nameInDb = "teacher")
private String teacher = "";
@Property(nameInDb = "room")
private String room = "";
@Property(nameInDb = "description")
private String description = "";
@Property(nameInDb = "group")
private String group = "";
@Property(nameInDb = "start_time")
private String startTime = "";
@Property(nameInDb = "end_time")
private String endTime = "";
@Property(nameInDb = "date")
private String date = "";
@Property(nameInDb = "empty")
private boolean empty = false;
@Property(nameInDb = "division_into_groups")
private boolean divisionIntoGroups = false;
@Property(nameInDb = "planning")
private boolean planning = false;
@Property(nameInDb = "realized")
private boolean realized = false;
@Property(nameInDb = "moved_canceled")
private boolean movedOrCanceled = false;
@Property(nameInDb = "new_moved_in_canceled")
private boolean newMovedInOrChanged = false;
/**
* Used to resolve relations
*/
@Generated(hash = 2040040024)
private transient DaoSession daoSession;
/** Used for active entity operations. */
@Generated(hash = 1119360138)
private transient TimetableLessonDao myDao;
@Generated(hash = 1665905034)
public TimetableLesson(Long id, Long dayId, int number, String subject, String teacher,
String room, String description, String group, String startTime, String endTime,
String date, boolean empty, boolean divisionIntoGroups, boolean planning,
boolean realized, boolean movedOrCanceled, boolean newMovedInOrChanged) {
this.id = id;
this.dayId = dayId;
this.number = number;
this.subject = subject;
this.teacher = teacher;
this.room = room;
this.description = description;
this.group = group;
this.startTime = startTime;
this.endTime = endTime;
this.date = date;
this.empty = empty;
this.divisionIntoGroups = divisionIntoGroups;
this.planning = planning;
this.realized = realized;
this.movedOrCanceled = movedOrCanceled;
this.newMovedInOrChanged = newMovedInOrChanged;
}
@Generated(hash = 1878030142)
public TimetableLesson() {
}
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
public Long getDayId() {
return this.dayId;
}
public TimetableLesson setDayId(Long dayId) {
this.dayId = dayId;
return this;
}
public int getNumber() {
return this.number;
}
public TimetableLesson setNumber(int number) {
this.number = number;
return this;
}
public String getSubject() {
return this.subject;
}
public TimetableLesson setSubject(String subject) {
this.subject = subject;
return this;
}
public String getTeacher() {
return this.teacher;
}
public TimetableLesson setTeacher(String teacher) {
this.teacher = teacher;
return this;
}
public String getRoom() {
return this.room;
}
public TimetableLesson setRoom(String room) {
this.room = room;
return this;
}
public String getDescription() {
return this.description;
}
public TimetableLesson setDescription(String description) {
this.description = description;
return this;
}
public String getGroup() {
return this.group;
}
public TimetableLesson setGroup(String group) {
this.group = group;
return this;
}
public String getStartTime() {
return this.startTime;
}
public TimetableLesson setStartTime(String startTime) {
this.startTime = startTime;
return this;
}
public String getEndTime() {
return this.endTime;
}
public TimetableLesson setEndTime(String endTime) {
this.endTime = endTime;
return this;
}
public String getDate() {
return this.date;
}
public TimetableLesson setDate(String date) {
this.date = date;
return this;
}
public boolean getEmpty() {
return this.empty;
}
public TimetableLesson setEmpty(boolean empty) {
this.empty = empty;
return this;
}
public boolean getDivisionIntoGroups() {
return this.divisionIntoGroups;
}
public TimetableLesson setDivisionIntoGroups(boolean divisionIntoGroups) {
this.divisionIntoGroups = divisionIntoGroups;
return this;
}
public boolean getPlanning() {
return this.planning;
}
public TimetableLesson setPlanning(boolean planning) {
this.planning = planning;
return this;
}
public boolean getRealized() {
return this.realized;
}
public TimetableLesson setRealized(boolean realized) {
this.realized = realized;
return this;
}
public boolean getMovedOrCanceled() {
return this.movedOrCanceled;
}
public TimetableLesson setMovedOrCanceled(boolean movedOrCanceled) {
this.movedOrCanceled = movedOrCanceled;
return this;
}
public boolean getNewMovedInOrChanged() {
return this.newMovedInOrChanged;
}
public TimetableLesson setNewMovedInOrChanged(boolean newMovedInOrChanged) {
this.newMovedInOrChanged = newMovedInOrChanged;
return this;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
TimetableLesson lesson = (TimetableLesson) o;
return new EqualsBuilder()
.append(number, lesson.number)
.append(startTime, lesson.startTime)
.append(endTime, lesson.endTime)
.append(date, lesson.date)
.isEquals();
}
@Override
public int hashCode() {
return new HashCodeBuilder(17, 37)
.append(number)
.append(startTime)
.append(endTime)
.append(date)
.toHashCode();
}
/**
* Convenient call for {@link org.greenrobot.greendao.AbstractDao#delete(Object)}.
* Entity must attached to an entity context.
*/
@Generated(hash = 128553479)
public void delete() {
if (myDao == null) {
throw new DaoException("Entity is detached from DAO context");
}
myDao.delete(this);
}
/**
* Convenient call for {@link org.greenrobot.greendao.AbstractDao#refresh(Object)}.
* Entity must attached to an entity context.
*/
@Generated(hash = 1942392019)
public void refresh() {
if (myDao == null) {
throw new DaoException("Entity is detached from DAO context");
}
myDao.refresh(this);
}
/**
* Convenient call for {@link org.greenrobot.greendao.AbstractDao#update(Object)}.
* Entity must attached to an entity context.
*/
@Generated(hash = 713229351)
public void update() {
if (myDao == null) {
throw new DaoException("Entity is detached from DAO context");
}
myDao.update(this);
}
/** called by internal mechanisms, do not call yourself. */
@Generated(hash = 1885258429)
public void __setDaoSession(DaoSession daoSession) {
this.daoSession = daoSession;
myDao = daoSession != null ? daoSession.getTimetableLessonDao() : null;
}
}

View File

@ -1,194 +0,0 @@
package io.github.wulkanowy.data.db.dao.entities;
import org.greenrobot.greendao.DaoException;
import org.greenrobot.greendao.annotation.Entity;
import org.greenrobot.greendao.annotation.Generated;
import org.greenrobot.greendao.annotation.Id;
import org.greenrobot.greendao.annotation.Index;
import org.greenrobot.greendao.annotation.Property;
import org.greenrobot.greendao.annotation.ToMany;
import java.util.List;
@Entity(
nameInDb = "Weeks",
active = true,
indexes = {@Index(value = "diaryId,startDayDate", unique = true)}
)
public class Week {
@Id(autoincrement = true)
private Long id;
@Property(nameInDb = "diary_id")
private Long diaryId;
@Property(nameInDb = "start_day_date")
private String startDayDate = "";
@Property(nameInDb = "attendance_synced")
private boolean attendanceSynced = false;
@Property(nameInDb = "timetable_synced")
private boolean timetableSynced = false;
@Property(nameInDb = "exams_synced")
private boolean examsSynced = false;
@ToMany(referencedJoinProperty = "weekId")
private List<Day> dayList;
/**
* Used to resolve relations
*/
@Generated(hash = 2040040024)
private transient DaoSession daoSession;
/**
* Used for active entity operations.
*/
@Generated(hash = 1019310398)
private transient WeekDao myDao;
@Generated(hash = 23357599)
public Week(Long id, Long diaryId, String startDayDate, boolean attendanceSynced,
boolean timetableSynced, boolean examsSynced) {
this.id = id;
this.diaryId = diaryId;
this.startDayDate = startDayDate;
this.attendanceSynced = attendanceSynced;
this.timetableSynced = timetableSynced;
this.examsSynced = examsSynced;
}
@Generated(hash = 2135529658)
public Week() {
}
public Long getId() {
return id;
}
public Week setId(Long id) {
this.id = id;
return this;
}
public Long getDiaryId() {
return diaryId;
}
public Week setDiaryId(Long diaryId) {
this.diaryId = diaryId;
return this;
}
public String getStartDayDate() {
return startDayDate;
}
public Week setStartDayDate(String startDayDate) {
this.startDayDate = startDayDate;
return this;
}
public boolean getAttendanceSynced() {
return this.attendanceSynced;
}
public Week setAttendanceSynced(boolean attendanceSynced) {
this.attendanceSynced = attendanceSynced;
return this;
}
public boolean getTimetableSynced() {
return this.timetableSynced;
}
public Week setTimetableSynced(boolean timetableSynced) {
this.timetableSynced = timetableSynced;
return this;
}
public Week setExamsSynced(boolean examsSynced) {
this.examsSynced = examsSynced;
return this;
}
public boolean getExamsSynced() {
return examsSynced;
}
/**
* To-many relationship, resolved on first access (and after reset).
* Changes to to-many relations are not persisted, make changes to the target entity.
*/
@Generated(hash = 1562119145)
public List<Day> getDayList() {
if (dayList == null) {
final DaoSession daoSession = this.daoSession;
if (daoSession == null) {
throw new DaoException("Entity is detached from DAO context");
}
DayDao targetDao = daoSession.getDayDao();
List<Day> dayListNew = targetDao._queryWeek_DayList(id);
synchronized (this) {
if (dayList == null) {
dayList = dayListNew;
}
}
}
return dayList;
}
/**
* Resets a to-many relationship, making the next get call to query for a fresh result.
*/
@Generated(hash = 1010399236)
public synchronized void resetDayList() {
dayList = null;
}
/**
* Convenient call for {@link org.greenrobot.greendao.AbstractDao#delete(Object)}.
* Entity must attached to an entity context.
*/
@Generated(hash = 128553479)
public void delete() {
if (myDao == null) {
throw new DaoException("Entity is detached from DAO context");
}
myDao.delete(this);
}
/**
* Convenient call for {@link org.greenrobot.greendao.AbstractDao#refresh(Object)}.
* Entity must attached to an entity context.
*/
@Generated(hash = 1942392019)
public void refresh() {
if (myDao == null) {
throw new DaoException("Entity is detached from DAO context");
}
myDao.refresh(this);
}
/**
* Convenient call for {@link org.greenrobot.greendao.AbstractDao#update(Object)}.
* Entity must attached to an entity context.
*/
@Generated(hash = 713229351)
public void update() {
if (myDao == null) {
throw new DaoException("Entity is detached from DAO context");
}
myDao.update(this);
}
/** called by internal mechanisms, do not call yourself. */
@Generated(hash = 665278367)
public void __setDaoSession(DaoSession daoSession) {
this.daoSession = daoSession;
myDao = daoSession != null ? daoSession.getWeekDao() : null;
}
}

View File

@ -1,114 +0,0 @@
package io.github.wulkanowy.data.db.dao.migrations;
import android.database.Cursor;
import android.os.AsyncTask;
import org.greenrobot.greendao.database.Database;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import io.github.wulkanowy.api.Vulcan;
import io.github.wulkanowy.api.generic.Diary;
import io.github.wulkanowy.data.db.dao.DbHelper;
import io.github.wulkanowy.data.db.shared.SharedPrefContract;
import io.github.wulkanowy.utils.security.Scrambler;
public class Migration23 implements DbHelper.Migration {
@Override
public Integer getVersion() {
return 23;
}
@Override
public void runMigration(final Database db, final SharedPrefContract sharedPref, final Vulcan vulcan) throws Exception {
createDiaryTable(db);
migrateAccountsTable(db);
final Map<String, String> user = getAccountData(db);
vulcan.setCredentials(
user.get("email"),
Scrambler.decrypt(user.get("password")),
user.get("symbol"),
user.get("school_id"),
"", // inserted in code bellow
""
);
AsyncTask.execute(new Runnable() {
@Override
public void run() {
try {
insertDiaries(db, vulcan.getStudentAndParent().getDiaries());
updateAccount(db, vulcan.getStudentAndParent().getStudentID());
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
private void createDiaryTable(Database db) {
db.execSQL("DROP TABLE IF EXISTS Diaries");
db.execSQL("CREATE TABLE IF NOT EXISTS \"Diaries\" (" + //
"\"_id\" INTEGER PRIMARY KEY AUTOINCREMENT ," + // 0: id
"\"STUDENT_ID\" TEXT," + // 1: studentId
"\"NAME\" TEXT," + // 2: name
"\"VALUE\" TEXT," + // 3: value
"\"IS_CURRENT\" INTEGER NOT NULL );"); // 4: isCurrent
}
private void migrateAccountsTable(Database db) {
db.execSQL("DROP TABLE IF EXISTS tmp_account");
db.execSQL("ALTER TABLE Accounts RENAME TO tmp_account");
db.execSQL("CREATE TABLE IF NOT EXISTS \"Accounts\" (" + //
"\"_id\" INTEGER PRIMARY KEY AUTOINCREMENT ," + // 0: id
"\"REAL_ID\" TEXT," + // 1: realId
"\"SYMBOL\" TEXT," + // 2: symbol
"\"SCHOOL_ID\" TEXT," + // 3: schoolId
"\"NAME\" TEXT," + // 4: name
"\"E_MAIL\" TEXT," + // 5: email
"\"PASSWORD\" TEXT);"); // 6: password
// Add Indexes
db.execSQL("CREATE UNIQUE INDEX IF NOT EXISTS IDX_Accounts_REAL_ID ON \"Accounts\" (\"REAL_ID\" ASC);");
db.execSQL("INSERT INTO Accounts(NAME, E_MAIL, PASSWORD, SYMBOL, SCHOOL_ID)" +
"SELECT `NAME`, `E-MAIL`, `PASSWORD`, `SYMBOL`, `SNPID` FROM tmp_account");
db.execSQL("DROP TABLE tmp_account");
}
private Map<String, String> getAccountData(Database db) {
Map<String, String> values = new HashMap<>();
Cursor cursor = db.rawQuery("SELECT SYMBOL, SCHOOL_ID, NAME, E_MAIL, PASSWORD FROM Accounts", null);
if (cursor.moveToFirst()) {
do {
values.put("symbol", cursor.getString(cursor.getColumnIndex("SYMBOL")));
values.put("school_id", cursor.getString(cursor.getColumnIndex("SCHOOL_ID")));
values.put("name", cursor.getString(cursor.getColumnIndex("NAME")));
values.put("email", cursor.getString(cursor.getColumnIndex("E_MAIL")));
values.put("password", cursor.getString(cursor.getColumnIndex("PASSWORD")));
} while (cursor.moveToNext());
}
cursor.close();
return values;
}
private void insertDiaries(Database db, List<Diary> list) {
for (Diary diary : list) {
db.execSQL("INSERT INTO Diaries(STUDENT_ID, NAME, VALUE, IS_CURRENT) VALUES(" +
"\"" + diary.getId() + "\"," +
"\"" + diary.getName() + "\"," +
"\"" + diary.getId() + "\"," +
"\"" + (diary.isCurrent() ? "1" : "0") + "\"" +
")");
}
}
private void updateAccount(Database db, String realId) {
db.execSQL("UPDATE Accounts SET REAL_ID = ?", new String[]{realId});
}
}

View File

@ -1,20 +0,0 @@
package io.github.wulkanowy.data.db.dao.migrations;
import org.greenrobot.greendao.database.Database;
import io.github.wulkanowy.api.Vulcan;
import io.github.wulkanowy.data.db.dao.DbHelper;
import io.github.wulkanowy.data.db.shared.SharedPrefContract;
public class Migration26 implements DbHelper.Migration {
@Override
public Integer getVersion() {
return 26;
}
@Override
public void runMigration(final Database db, final SharedPrefContract sharedPref, final Vulcan vulcan) throws Exception {
throw new Exception("No migrations");
}
}

View File

@ -1,24 +0,0 @@
package io.github.wulkanowy.data.db.dao.migrations;
import org.greenrobot.greendao.database.Database;
import io.github.wulkanowy.api.Vulcan;
import io.github.wulkanowy.data.db.dao.DbHelper;
import io.github.wulkanowy.data.db.dao.entities.ExamDao;
import io.github.wulkanowy.data.db.shared.SharedPrefContract;
public class Migration27 implements DbHelper.Migration {
@Override
public Integer getVersion() {
return 27;
}
@Override
public void runMigration(Database db, SharedPrefContract sharedPref, Vulcan vulcan) {
ExamDao.dropTable(db, true);
ExamDao.createTable(db, true);
db.execSQL("UPDATE Weeks SET exams_synced = 0");
}
}

View File

@ -1,20 +0,0 @@
package io.github.wulkanowy.data.db.dao.migrations;
import org.greenrobot.greendao.database.Database;
import io.github.wulkanowy.api.Vulcan;
import io.github.wulkanowy.data.db.dao.DbHelper;
import io.github.wulkanowy.data.db.shared.SharedPrefContract;
public class Migration28 implements DbHelper.Migration {
@Override
public Integer getVersion() {
return 28;
}
@Override
public void runMigration(final Database db, final SharedPrefContract sharedPref, final Vulcan vulcan) throws Exception {
throw new Exception("No migrations");
}
}

View File

@ -1,60 +0,0 @@
package io.github.wulkanowy.data.db.dao.migrations
import android.database.Cursor
import org.greenrobot.greendao.database.Database
import io.github.wulkanowy.api.Vulcan
import io.github.wulkanowy.data.db.dao.DbHelper
import io.github.wulkanowy.data.db.shared.SharedPrefContract
class Migration29 : DbHelper.Migration {
override fun getVersion(): Int? {
return 29
}
override fun runMigration(db: Database, sharedPref: SharedPrefContract, vulcan: Vulcan) {
createSchoolsTable(db)
modifyStudents(db)
insertSchool(db, getRealSchoolId(db))
}
private fun createSchoolsTable(db: Database) {
db.execSQL("DROP TABLE IF EXISTS \"Schools\";")
db.execSQL("CREATE TABLE IF NOT EXISTS \"Schools\" (" + //
"\"_id\" INTEGER PRIMARY KEY AUTOINCREMENT ," + // 0: id
"\"symbol_id\" INTEGER," + // 1: symbolId
"\"current\" INTEGER NOT NULL ," + // 2: current
"\"real_id\" TEXT," + // 3: realId
"\"name\" TEXT);") // 4: name
}
private fun modifyStudents(db: Database) {
db.execSQL("ALTER TABLE Students ADD COLUMN school_id INTEGER")
db.execSQL("UPDATE Students SET school_id = '1'")
}
private fun getRealSchoolId(db: Database): String {
var cursor: Cursor? = null
try {
cursor = db.rawQuery("SELECT school_id FROM Symbols WHERE _id=?", arrayOf("1"))
return if (cursor!!.count > 0) {
cursor.moveToFirst()
cursor.getString(cursor.getColumnIndex("school_id"))
} else ""
} finally {
cursor!!.close()
}
}
private fun insertSchool(db: Database, realId: String) {
db.execSQL("INSERT INTO Schools(symbol_id, current, real_id, name) VALUES(" +
"\"1\"," +
"\"1\"," +
"\"" + realId + "\"," +
"\"Uczeń\"" +
")")
}
}

View File

@ -0,0 +1,32 @@
package io.github.wulkanowy.data.db.entities
import android.arch.persistence.room.ColumnInfo
import android.arch.persistence.room.Entity
import android.arch.persistence.room.Index
import android.arch.persistence.room.PrimaryKey
@Entity(tableName = "Students",
indices = [Index(value = ["student_id", "student_name"], unique = true)])
data class Student(
@PrimaryKey(autoGenerate = true)
var id: Long = 0,
var email: String,
var password: String,
var symbol: String = "",
@ColumnInfo(name = "student_id")
var studentId: String = "",
@ColumnInfo(name = "student_name")
var studentName: String = "",
@ColumnInfo(name = "school_id")
var schoolId: String = "",
@ColumnInfo(name = "school_name")
var schoolName: String = ""
)

View File

@ -1,17 +0,0 @@
package io.github.wulkanowy.data.db.resources;
import javax.inject.Singleton;
import io.github.wulkanowy.data.db.dao.entities.AttendanceLesson;
@Singleton
public interface ResourcesContract {
String[] getSymbolsKeysArray();
String[] getSymbolsValuesArray();
String getErrorLoginMessage(Exception e);
String getAttendanceLessonDescription(AttendanceLesson lesson);
}

View File

@ -1,84 +0,0 @@
package io.github.wulkanowy.data.db.resources;
import android.content.Context;
import android.content.res.Resources;
import java.io.IOException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import javax.inject.Inject;
import javax.inject.Singleton;
import io.github.wulkanowy.R;
import io.github.wulkanowy.api.NotLoggedInErrorException;
import io.github.wulkanowy.data.db.dao.entities.AttendanceLesson;
import io.github.wulkanowy.utils.AppConstant;
import timber.log.Timber;
@Singleton
public class ResourcesRepository implements ResourcesContract {
private Resources resources;
@Inject
ResourcesRepository(Context context) {
resources = context.getResources();
}
@Override
public String[] getSymbolsKeysArray() {
return resources.getStringArray(R.array.symbols);
}
@Override
public String[] getSymbolsValuesArray() {
return resources.getStringArray(R.array.symbols_values);
}
@Override
public String getErrorLoginMessage(Exception exception) {
Timber.e(exception, "%s encountered a error", AppConstant.APP_NAME);
if (exception instanceof UnknownHostException) {
return resources.getString(R.string.noInternet_text);
} else if (exception instanceof SocketTimeoutException) {
return resources.getString(R.string.generic_timeout_error);
} else if (exception instanceof NotLoggedInErrorException || exception instanceof IOException) {
return resources.getString(R.string.login_failed_text);
} else {
return exception.getMessage();
}
}
@Override
public String getAttendanceLessonDescription(AttendanceLesson lesson) {
int id = R.string.attendance_present;
if (lesson.getAbsenceForSchoolReasons()) {
id = R.string.attendance_absence_for_school_reasons;
}
if (lesson.getAbsenceExcused()) {
id = R.string.attendance_absence_excused;
}
if (lesson.getAbsenceUnexcused()) {
id = R.string.attendance_absence_unexcused;
}
if (lesson.getExemption()) {
id = R.string.attendance_exemption;
}
if (lesson.getExcusedLateness()) {
id = R.string.attendance_excused_lateness;
}
if (lesson.getUnexcusedLateness()) {
id = R.string.attendance_unexcused_lateness;
}
return resources.getString(id);
}
}

View File

@ -1,35 +0,0 @@
package io.github.wulkanowy.data.db.shared;
import javax.inject.Singleton;
@Singleton
public interface SharedPrefContract {
long getCurrentUserId();
boolean isUserLoggedIn();
void setCurrentUserId(long userId);
void setTimetableWidgetState(boolean nextDay);
boolean getTimetableWidgetState();
int getStartupTab();
boolean isShowGradesSummary();
boolean isShowAttendancePresent();
int getCurrentTheme();
int getServicesInterval();
boolean isMobileDisable();
boolean isServicesEnable();
boolean isNotifyEnable();
void cleanSharedPref();
}

View File

@ -1,102 +0,0 @@
package io.github.wulkanowy.data.db.shared;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import io.github.wulkanowy.ui.main.settings.SettingsFragment;
@Singleton
public class SharedPrefRepository implements SharedPrefContract {
private static final String SHARED_KEY_USER_ID = "USER_ID";
private static final String SHARED_KEY_TIMETABLE_WIDGET_STATE = "TIMETABLE_WIDGET_STATE";
private final SharedPreferences appSharedPref;
private final SharedPreferences settingsSharedPref;
@Inject
SharedPrefRepository(Context context, @Named("sharedPrefName") String sharedName) {
appSharedPref = context.getSharedPreferences(sharedName, Context.MODE_PRIVATE);
settingsSharedPref = PreferenceManager.getDefaultSharedPreferences(context);
}
@Override
public long getCurrentUserId() {
return appSharedPref.getLong(SHARED_KEY_USER_ID, 0);
}
@Override
public boolean isUserLoggedIn() {
return getCurrentUserId() != 0;
}
@Override
public void setCurrentUserId(long userId) {
appSharedPref.edit().putLong(SHARED_KEY_USER_ID, userId).apply();
}
@SuppressLint("ApplySharedPref")
@Override
public void setTimetableWidgetState(boolean nextDay) {
appSharedPref.edit().putBoolean(SHARED_KEY_TIMETABLE_WIDGET_STATE, nextDay).commit();
}
@Override
public boolean getTimetableWidgetState() {
return appSharedPref.getBoolean(SHARED_KEY_TIMETABLE_WIDGET_STATE, false);
}
@Override
public int getStartupTab() {
return Integer.parseInt(settingsSharedPref.getString(SettingsFragment.SHARED_KEY_START_TAB, "0"));
}
@Override
public boolean isShowGradesSummary() {
return settingsSharedPref.getBoolean(SettingsFragment.SHARED_KEY_GRADES_SUMMARY, false);
}
@Override
public boolean isShowAttendancePresent() {
return settingsSharedPref.getBoolean(SettingsFragment.SHARED_KEY_ATTENDANCE_PRESENT, false);
}
@Override
public int getCurrentTheme() {
return Integer.parseInt(settingsSharedPref.getString(SettingsFragment.SHARED_KEY_THEME, "1"));
}
@Override
public int getServicesInterval() {
return Integer.parseInt(settingsSharedPref.getString(SettingsFragment.SHARED_KEY_SERVICES_INTERVAL, "60"));
}
@Override
public boolean isServicesEnable() {
return settingsSharedPref.getBoolean(SettingsFragment.SHARED_KEY_SERVICES_ENABLE, true);
}
@Override
public boolean isNotifyEnable() {
return settingsSharedPref.getBoolean(SettingsFragment.SHARED_KEY_NOTIFY_ENABLE, true);
}
@Override
public boolean isMobileDisable() {
return settingsSharedPref.getBoolean(SettingsFragment.SHARED_KEY_SERVICES_MOBILE_DISABLED, false);
}
@Override
public void cleanSharedPref() {
appSharedPref.edit().clear().apply();
settingsSharedPref.edit().clear().apply();
}
}

View File

@ -0,0 +1,43 @@
package io.github.wulkanowy.data.repositories
import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork
import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings
import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.data.repositories.local.StudentLocal
import io.github.wulkanowy.data.repositories.remote.StudentRemote
import io.reactivex.Single
import java.net.UnknownHostException
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class StudentRepository @Inject constructor(
private val local: StudentLocal,
private val remote: StudentRemote,
private val settings: InternetObservingSettings) {
lateinit var cachedStudents: Single<List<Student>>
private set
val isStudentLoggedIn: Boolean
get() = local.isStudentLoggedIn
fun getConnectedStudents(email: String, password: String, symbol: String): Single<List<Student>> {
cachedStudents = ReactiveNetwork.checkInternetConnectivity(settings)
.flatMap { isConnected ->
if (isConnected) remote.getConnectedStudents(email, password, symbol)
else Single.error<List<Student>>(UnknownHostException("No internet connection"))
}.doOnSuccess { cachedStudents = Single.just(it) }
return cachedStudents
}
fun save(student: Student) {
local.save(student)
}
fun getCurrentStudent(): Single<Student> = local.getCurrentStudent()
fun clearCache() {
cachedStudents = Single.just(emptyList())
}
}

View File

@ -0,0 +1,35 @@
package io.github.wulkanowy.data.repositories.local
import android.content.Context
import io.github.wulkanowy.data.db.SharedPrefHelper
import io.github.wulkanowy.data.db.dao.StudentDao
import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.utils.security.Scrambler.decrypt
import io.github.wulkanowy.utils.security.Scrambler.encrypt
import io.reactivex.Single
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class StudentLocal @Inject constructor(
private val studentDb: StudentDao,
private val sharedPref: SharedPrefHelper,
private val context: Context) {
companion object {
const val CURRENT_USER_KEY: String = "current_user_id"
}
val isStudentLoggedIn: Boolean
get() = sharedPref.getLong(CURRENT_USER_KEY, 0) != 0L
fun save(student: Student) {
sharedPref.putLong(CURRENT_USER_KEY, studentDb.insert(student.copy(
password = encrypt(student.password, context))))
}
fun getCurrentStudent(): Single<Student> {
return studentDb.load(sharedPref.getLong(CURRENT_USER_KEY, defaultValue = 0))
.map { it.apply { password = decrypt(password) } }
}
}

View File

@ -0,0 +1,55 @@
package io.github.wulkanowy.data.repositories.remote
import io.github.wulkanowy.api.Vulcan
import io.github.wulkanowy.api.login.AccountPermissionException
import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.utils.DEFAULT_SYMBOL
import io.reactivex.Single
import org.apache.commons.lang3.StringUtils.stripAccents
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class StudentRemote @Inject constructor(private val api: Vulcan) {
fun getConnectedStudents(email: String, password: String, symbol: String): Single<List<Student>> {
return Single.fromCallable {
initApi(email, password, symbol)
getSymbols().filterNot { it == DEFAULT_SYMBOL }
.mapNotNull { symbol ->
try {
initApi(email, password, symbol)
api.schools.flatMap { school ->
initApi(email, password, symbol, school.id)
api.studentAndParent.students.map { student ->
Student(
email = email,
password = password,
symbol = symbol,
studentId = student.id,
studentName = student.name,
schoolId = school.id,
schoolName = school.name
)
}
}
} catch (e: AccountPermissionException) {
null
}
}.flatten()
}
}
private fun initApi(email: String, password: String, symbol: String, schoolId: String? = null) {
api.apply {
logout()
setCredentials(email, password, symbol, schoolId, null, null)
}
}
private fun getSymbols(): List<String> {
return api.symbols.map {
stripAccents(it.replace("[\\s \\W]".toRegex(), ""))
}
}
}

View File

@ -1,197 +0,0 @@
package io.github.wulkanowy.data.sync;
import android.content.Context;
import org.greenrobot.greendao.database.Database;
import java.io.IOException;
import java.util.List;
import javax.inject.Inject;
import javax.inject.Singleton;
import io.github.wulkanowy.api.Vulcan;
import io.github.wulkanowy.api.VulcanException;
import io.github.wulkanowy.data.db.dao.entities.Account;
import io.github.wulkanowy.data.db.dao.entities.DaoMaster;
import io.github.wulkanowy.data.db.dao.entities.DaoSession;
import io.github.wulkanowy.data.db.dao.entities.Diary;
import io.github.wulkanowy.data.db.dao.entities.DiaryDao;
import io.github.wulkanowy.data.db.dao.entities.School;
import io.github.wulkanowy.data.db.dao.entities.SchoolDao;
import io.github.wulkanowy.data.db.dao.entities.Semester;
import io.github.wulkanowy.data.db.dao.entities.Student;
import io.github.wulkanowy.data.db.dao.entities.StudentDao;
import io.github.wulkanowy.data.db.dao.entities.Symbol;
import io.github.wulkanowy.data.db.dao.entities.SymbolDao;
import io.github.wulkanowy.data.db.shared.SharedPrefContract;
import io.github.wulkanowy.utils.DataObjectConverter;
import io.github.wulkanowy.utils.security.Scrambler;
import io.github.wulkanowy.utils.security.ScramblerException;
import timber.log.Timber;
@Singleton
public class AccountSync {
private final DaoSession daoSession;
private final SharedPrefContract sharedPref;
private final Vulcan vulcan;
private final Context context;
@Inject
AccountSync(DaoSession daoSession, SharedPrefContract sharedPref,
Vulcan vulcan, Context context) {
this.daoSession = daoSession;
this.sharedPref = sharedPref;
this.vulcan = vulcan;
this.context = context;
}
public void registerUser(String email, String password, String symbol)
throws VulcanException, IOException, ScramblerException {
clearUserData();
vulcan.setCredentials(email, password, symbol, null, null, null);
daoSession.getDatabase().beginTransaction();
Timber.i("Register start");
try {
Account account = insertAccount(email, password);
Symbol symbolEntity = insertSymbol(account);
School schoolEntity = insertSchools(symbolEntity);
Student student = insertStudents(schoolEntity);
Diary diary = insertDiaries(student);
insertSemesters(diary);
sharedPref.setCurrentUserId(account.getId());
daoSession.getDatabase().setTransactionSuccessful();
} finally {
daoSession.getDatabase().endTransaction();
}
Timber.i("Register end");
}
private Account insertAccount(String email, String password) throws ScramblerException {
Timber.d("Register account");
Account account = new Account()
.setEmail(email)
.setPassword(Scrambler.encrypt(password, context));
daoSession.getAccountDao().insert(account);
return account;
}
private Symbol insertSymbol(Account account) throws VulcanException, IOException {
vulcan.getSchools();
Timber.d("Register symbol (%s)", vulcan.getSymbol());
Symbol symbol = new Symbol()
.setUserId(account.getId())
.setSymbol(vulcan.getSymbol());
daoSession.getSymbolDao().insert(symbol);
return symbol;
}
private School insertSchools(Symbol symbol) throws VulcanException, IOException {
List<School> schoolList = DataObjectConverter.schoolsToSchoolsEntities(
vulcan.getSchools(),
symbol.getId()
);
Timber.d("Register schools (%s)", schoolList.size());
daoSession.getSchoolDao().insertInTx(schoolList);
return daoSession.getSchoolDao().queryBuilder().where(
SchoolDao.Properties.SymbolId.eq(symbol.getId()),
SchoolDao.Properties.Current.eq(true)
).unique();
}
private Student insertStudents(School school) throws VulcanException, IOException {
List<Student> studentList = DataObjectConverter.studentsToStudentEntities(
vulcan.getStudentAndParent().getStudents(),
school.getId()
);
Timber.d("Register students (%s)", studentList.size());
daoSession.getStudentDao().insertInTx(studentList);
return daoSession.getStudentDao().queryBuilder().where(
StudentDao.Properties.SchoolId.eq(school.getId()),
StudentDao.Properties.Current.eq(true)
).unique();
}
private Diary insertDiaries(Student student) throws VulcanException, IOException {
List<Diary> diaryList = DataObjectConverter.diariesToDiaryEntities(
vulcan.getStudentAndParent().getDiaries(),
student.getId()
);
Timber.d("Register diaries (%s)", diaryList.size());
daoSession.getDiaryDao().insertInTx(diaryList);
return daoSession.getDiaryDao().queryBuilder().where(
DiaryDao.Properties.StudentId.eq(student.getId()),
DiaryDao.Properties.Current.eq(true)
).unique();
}
private void insertSemesters(Diary diary) throws VulcanException, IOException {
List<Semester> semesterList = DataObjectConverter.semestersToSemesterEntities(
vulcan.getStudentAndParent().getSemesters(),
diary.getId()
);
Timber.d("Register semesters (%s)", semesterList.size());
daoSession.getSemesterDao().insertInTx(semesterList);
}
public void initLastUser() throws ScramblerException {
long userId = sharedPref.getCurrentUserId();
if (userId == 0) {
throw new NotRegisteredUserException("Can't find user id in SharedPreferences");
}
Timber.d("Init current user (%s)", userId);
Account account = daoSession.getAccountDao().load(userId);
Symbol symbol = daoSession.getSymbolDao().queryBuilder().where(
SymbolDao.Properties.UserId.eq(account.getId())).unique();
School school = daoSession.getSchoolDao().queryBuilder().where(
SchoolDao.Properties.SymbolId.eq(symbol.getId())).unique();
Student student = daoSession.getStudentDao().queryBuilder().where(
StudentDao.Properties.SchoolId.eq(school.getId()),
StudentDao.Properties.Current.eq(true)
).unique();
Diary diary = daoSession.getDiaryDao().queryBuilder().where(
DiaryDao.Properties.StudentId.eq(student.getId()),
DiaryDao.Properties.Current.eq(true)
).unique();
vulcan.setCredentials(
account.getEmail(),
Scrambler.decrypt(account.getPassword()),
symbol.getSymbol(),
school.getRealId(),
student.getRealId(),
diary.getValue()
);
}
private void clearUserData() {
Database database = daoSession.getDatabase();
DaoMaster.dropAllTables(database, true);
DaoMaster.createAllTables(database, true);
sharedPref.setCurrentUserId(0);
}
}

View File

@ -1,140 +0,0 @@
package io.github.wulkanowy.data.sync;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.inject.Inject;
import javax.inject.Singleton;
import io.github.wulkanowy.api.Vulcan;
import io.github.wulkanowy.api.VulcanException;
import io.github.wulkanowy.api.generic.Lesson;
import io.github.wulkanowy.data.db.dao.entities.AttendanceLesson;
import io.github.wulkanowy.data.db.dao.entities.AttendanceLessonDao;
import io.github.wulkanowy.data.db.dao.entities.DaoSession;
import io.github.wulkanowy.data.db.dao.entities.Day;
import io.github.wulkanowy.data.db.dao.entities.DayDao;
import io.github.wulkanowy.data.db.dao.entities.Week;
import io.github.wulkanowy.data.db.dao.entities.WeekDao;
import io.github.wulkanowy.utils.DataObjectConverter;
import timber.log.Timber;
@Singleton
public class AttendanceSync {
private final DaoSession daoSession;
private final Vulcan vulcan;
private long diaryId;
@Inject
AttendanceSync(DaoSession daoSession, Vulcan vulcan) {
this.daoSession = daoSession;
this.vulcan = vulcan;
}
public void syncAttendance(long diaryId, String date) throws IOException, VulcanException {
this.diaryId = diaryId;
io.github.wulkanowy.api.generic.Week<io.github.wulkanowy.api.generic.Day> weekApi = getWeekFromApi(date);
Week weekDb = getWeekFromDb(weekApi.getStartDayDate());
long weekId = updateWeekInDb(weekDb, weekApi);
List<AttendanceLesson> lessonList = updateDays(weekApi.getDays(), weekId);
daoSession.getAttendanceLessonDao().saveInTx(lessonList);
Timber.d("Attendance synchronization complete (%s)", lessonList.size());
}
private io.github.wulkanowy.api.generic.Week<io.github.wulkanowy.api.generic.Day> getWeekFromApi(String date)
throws IOException, VulcanException {
return vulcan.getAttendanceTable().getWeekTable(date);
}
private Week getWeekFromDb(String date) {
return daoSession.getWeekDao().queryBuilder().where(
WeekDao.Properties.DiaryId.eq(diaryId),
WeekDao.Properties.StartDayDate.eq(date)
).unique();
}
private Long updateWeekInDb(Week dbWeekEntity, io.github.wulkanowy.api.generic.Week fromApi) {
if (dbWeekEntity != null) {
dbWeekEntity.setAttendanceSynced(true);
dbWeekEntity.update();
return dbWeekEntity.getId();
}
Week apiWeekEntity = DataObjectConverter.weekToWeekEntity(fromApi).setDiaryId(diaryId);
apiWeekEntity.setAttendanceSynced(true);
return daoSession.getWeekDao().insert(apiWeekEntity);
}
private List<AttendanceLesson> updateDays(List<io.github.wulkanowy.api.generic.Day> dayListFromApi, long weekId) {
List<AttendanceLesson> updatedLessonList = new ArrayList<>();
for (io.github.wulkanowy.api.generic.Day dayFromApi : dayListFromApi) {
Day dbDayEntity = getDayFromDb(dayFromApi.getDate(), weekId);
Day apiDayEntity = DataObjectConverter.dayToDayEntity(dayFromApi);
long dayId = updateDay(dbDayEntity, apiDayEntity, weekId);
updateLessons(dayFromApi.getLessons(), updatedLessonList, dayId);
}
return updatedLessonList;
}
private Day getDayFromDb(String date, long weekId) {
return daoSession.getDayDao().queryBuilder()
.where(
DayDao.Properties.WeekId.eq(weekId),
DayDao.Properties.Date.eq(date)
).unique();
}
private long updateDay(Day dbDayEntity, Day apiDayEntity, long weekId) {
if (null != dbDayEntity) {
return dbDayEntity.getId();
}
apiDayEntity.setWeekId(weekId);
return daoSession.getDayDao().insert(apiDayEntity);
}
private void updateLessons(List<Lesson> lessons, List<AttendanceLesson> updatedLessons, long dayId) {
List<AttendanceLesson> lessonsFromApiEntities = DataObjectConverter
.lessonsToAttendanceLessonsEntities(lessons);
for (AttendanceLesson apiLessonEntity : lessonsFromApiEntities) {
AttendanceLesson lessonFromDb = getLessonFromDb(apiLessonEntity, dayId);
apiLessonEntity.setDayId(dayId);
if (lessonFromDb != null) {
apiLessonEntity.setId(lessonFromDb.getId());
}
if (!"".equals(apiLessonEntity.getSubject())) {
updatedLessons.add(apiLessonEntity);
}
}
}
private AttendanceLesson getLessonFromDb(AttendanceLesson apiEntity, long dayId) {
return daoSession.getAttendanceLessonDao().queryBuilder()
.where(AttendanceLessonDao.Properties.DayId.eq(dayId),
AttendanceLessonDao.Properties.Date.eq(apiEntity.getDate()),
AttendanceLessonDao.Properties.Number.eq(apiEntity.getNumber()))
.unique();
}
}

View File

@ -1,135 +0,0 @@
package io.github.wulkanowy.data.sync;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.inject.Inject;
import io.github.wulkanowy.api.Vulcan;
import io.github.wulkanowy.api.VulcanException;
import io.github.wulkanowy.api.exams.ExamDay;
import io.github.wulkanowy.data.db.dao.entities.DaoSession;
import io.github.wulkanowy.data.db.dao.entities.Day;
import io.github.wulkanowy.data.db.dao.entities.DayDao;
import io.github.wulkanowy.data.db.dao.entities.Exam;
import io.github.wulkanowy.data.db.dao.entities.ExamDao;
import io.github.wulkanowy.data.db.dao.entities.Week;
import io.github.wulkanowy.data.db.dao.entities.WeekDao;
import io.github.wulkanowy.utils.DataObjectConverter;
import timber.log.Timber;
public class ExamsSync {
private final DaoSession daoSession;
private final Vulcan vulcan;
private long diaryId;
@Inject
ExamsSync(DaoSession daoSession, Vulcan vulcan) {
this.daoSession = daoSession;
this.vulcan = vulcan;
}
public void syncExams(long diaryId, String date) throws IOException, VulcanException {
this.diaryId = diaryId;
io.github.wulkanowy.api.generic.Week<ExamDay> weekApi = getWeekFromApi(date);
Week weekDb = getWeekFromDb(weekApi.getStartDayDate());
long weekId = updateWeekInDb(weekDb, weekApi);
List<Exam> examList = getPreparedExams(weekApi.getDays(), weekId);
daoSession.getExamDao().saveInTx(examList);
Timber.d("Exams synchronization complete (%s)", examList.size());
}
private Week getWeekFromDb(String date) {
return daoSession.getWeekDao().queryBuilder().where(
WeekDao.Properties.DiaryId.eq(diaryId),
WeekDao.Properties.StartDayDate.eq(date)
).unique();
}
private io.github.wulkanowy.api.generic.Week<ExamDay> getWeekFromApi(String date)
throws VulcanException, IOException {
return vulcan.getExamsList().getWeek(date, true);
}
private Long updateWeekInDb(Week weekDb, io.github.wulkanowy.api.generic.Week weekApi) {
if (weekDb != null) {
weekDb.setExamsSynced(true);
weekDb.update();
return weekDb.getId();
}
Week weekApiEntity = DataObjectConverter.weekToWeekEntity(weekApi).setDiaryId(diaryId);
weekApiEntity.setExamsSynced(true);
return daoSession.getWeekDao().insert(weekApiEntity);
}
private Day getDayFromDb(String date, long weekId) {
return daoSession.getDayDao().queryBuilder().where(
DayDao.Properties.WeekId.eq(weekId),
DayDao.Properties.Date.eq(date)
).unique();
}
private List<Exam> getPreparedExams(List<ExamDay> dayListFromApi,
long weekId) {
List<Exam> preparedExamList = new ArrayList<>();
for (ExamDay dayFromApi : dayListFromApi) {
Day dayDb = getDayFromDb(dayFromApi.getDate(), weekId);
Day dayApiEntity = DataObjectConverter.dayToDayEntity(dayFromApi);
long dayId = updateDayInDb(dayDb, dayApiEntity, weekId);
prepareExam(dayFromApi.getExamList(), preparedExamList, dayId);
}
return preparedExamList;
}
private long updateDayInDb(Day dayDb, Day dayApi, long weekId) {
dayApi.setWeekId(weekId);
if (null != dayDb) {
return dayDb.getId();
}
return daoSession.getDayDao().insert(dayApi);
}
private void prepareExam(List<io.github.wulkanowy.api.exams.Exam> examList,
List<Exam> preparedExams, long dayId) {
List<Exam> examsApiEntity = DataObjectConverter.examsToExamsEntity(examList);
for (Exam examApi : examsApiEntity) {
Exam examDb = getExamFromDb(examApi, dayId);
examApi.setDayId(dayId);
if (examDb != null) {
examApi.setId(examDb.getId());
}
preparedExams.add(examApi);
}
}
private Exam getExamFromDb(Exam examApi, long dayId) {
return daoSession.getExamDao().queryBuilder()
.where(ExamDao.Properties.DayId.eq(dayId),
ExamDao.Properties.EntryDate.eq(examApi.getEntryDate()),
ExamDao.Properties.SubjectAndGroup.eq(examApi.getSubjectAndGroup()),
ExamDao.Properties.Type.eq(examApi.getType()),
ExamDao.Properties.Teacher.eq(examApi.getTeacher()))
.unique();
}
}

View File

@ -1,81 +0,0 @@
package io.github.wulkanowy.data.sync;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.inject.Inject;
import javax.inject.Singleton;
import io.github.wulkanowy.api.Vulcan;
import io.github.wulkanowy.api.VulcanException;
import io.github.wulkanowy.data.db.dao.entities.DaoSession;
import io.github.wulkanowy.data.db.dao.entities.Grade;
import io.github.wulkanowy.data.db.dao.entities.Semester;
import io.github.wulkanowy.data.db.dao.entities.SubjectDao;
import io.github.wulkanowy.utils.DataObjectConverter;
import io.github.wulkanowy.utils.EntitiesCompare;
import timber.log.Timber;
@Singleton
public class GradeSync {
private final DaoSession daoSession;
private final Vulcan vulcan;
private long semesterId;
@Inject
GradeSync(DaoSession daoSession, Vulcan vulcan) {
this.daoSession = daoSession;
this.vulcan = vulcan;
}
public void sync(long semesterId) throws IOException, VulcanException {
this.semesterId = semesterId;
Semester semester = daoSession.getSemesterDao().load(semesterId);
resetSemesterRelations(semester);
List<Grade> lastList = getUpdatedList(getComparedList(semester));
daoSession.getGradeDao().deleteInTx(semester.getGradeList());
daoSession.getGradeDao().insertInTx(lastList);
Timber.d("Grades synchronization complete (%s)", lastList.size());
}
private void resetSemesterRelations(Semester semester) {
semester.resetSubjectList();
semester.resetGradeList();
}
private List<Grade> getUpdatedList(List<Grade> comparedList) {
List<Grade> updatedList = new ArrayList<>();
for (Grade grade : comparedList) {
grade.setSemesterId(semesterId);
grade.setSubjectId(getSubjectId(grade.getSubject()));
updatedList.add(grade);
}
return updatedList;
}
private List<Grade> getComparedList(Semester semester) throws IOException, VulcanException {
List<Grade> gradesFromNet = DataObjectConverter.gradesToGradeEntities(
vulcan.getGradesList().getAll(semester.getValue()), semesterId);
List<Grade> gradesFromDb = semester.getGradeList();
return EntitiesCompare.compareGradeList(gradesFromNet, gradesFromDb);
}
private Long getSubjectId(String subjectName) {
return daoSession.getSubjectDao().queryBuilder().where(
SubjectDao.Properties.Name.eq(subjectName),
SubjectDao.Properties.SemesterId.eq(semesterId)
).build().uniqueOrThrow().getId();
}
}

View File

@ -1,8 +0,0 @@
package io.github.wulkanowy.data.sync;
public class NotRegisteredUserException extends RuntimeException {
public NotRegisteredUserException(String message) {
super(message);
}
}

View File

@ -1,66 +0,0 @@
package io.github.wulkanowy.data.sync;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.inject.Inject;
import javax.inject.Singleton;
import io.github.wulkanowy.api.Vulcan;
import io.github.wulkanowy.api.VulcanException;
import io.github.wulkanowy.data.db.dao.entities.DaoSession;
import io.github.wulkanowy.data.db.dao.entities.Semester;
import io.github.wulkanowy.data.db.dao.entities.Subject;
import io.github.wulkanowy.utils.DataObjectConverter;
import timber.log.Timber;
@Singleton
public class SubjectSync {
private final DaoSession daoSession;
private final Vulcan vulcan;
private long semesterId;
@Inject
SubjectSync(DaoSession daoSession, Vulcan vulcan) {
this.daoSession = daoSession;
this.vulcan = vulcan;
}
public void sync(long semesterId) throws VulcanException, IOException {
this.semesterId = semesterId;
Semester semester = daoSession.getSemesterDao().load(semesterId);
List<Subject> lastList = getUpdatedList(getSubjectsFromNet(semester));
daoSession.getSubjectDao().deleteInTx(getSubjectsFromDb());
daoSession.getSubjectDao().insertInTx(lastList);
Timber.d("Subjects synchronization complete (%s)", lastList.size());
}
private List<Subject> getSubjectsFromNet(Semester semester) throws VulcanException, IOException {
return DataObjectConverter.subjectsToSubjectEntities(
vulcan.getSubjectsList().getAll(semester.getValue()), semesterId);
}
private List<Subject> getSubjectsFromDb() {
Semester semester = daoSession.getSemesterDao().load(semesterId);
semester.resetSubjectList();
return semester.getSubjectList();
}
private List<Subject> getUpdatedList(List<Subject> subjectsFromNet) {
List<Subject> updatedList = new ArrayList<>();
for (Subject subject : subjectsFromNet) {
subject.setSemesterId(semesterId);
updatedList.add(subject);
}
return updatedList;
}
}

View File

@ -1,41 +0,0 @@
package io.github.wulkanowy.data.sync;
import java.io.IOException;
import java.text.ParseException;
import javax.inject.Singleton;
import io.github.wulkanowy.api.VulcanException;
import io.github.wulkanowy.utils.security.ScramblerException;
@Singleton
public interface SyncContract {
void registerUser(String email, String password, String symbol) throws VulcanException,
IOException, ScramblerException;
void initLastUser() throws IOException, ScramblerException;
void syncGrades(int semesterName) throws VulcanException, IOException, ParseException;
void syncGrades() throws VulcanException, IOException, ParseException;
void syncSubjects(int semesterName) throws VulcanException, IOException;
void syncSubjects() throws VulcanException, IOException;
void syncAttendance() throws ParseException, IOException, VulcanException;
void syncAttendance(long diaryId, String date) throws ParseException, IOException, VulcanException;
void syncTimetable() throws VulcanException, IOException, ParseException;
void syncTimetable(long diaryId, String date) throws VulcanException, IOException, ParseException;
void syncExams() throws VulcanException, IOException, ParseException;
void syncExams(long diaryId, String date) throws VulcanException, IOException, ParseException;
void syncAll() throws VulcanException, IOException, ParseException;
}

View File

@ -1,123 +0,0 @@
package io.github.wulkanowy.data.sync;
import java.io.IOException;
import javax.inject.Inject;
import javax.inject.Singleton;
import io.github.wulkanowy.api.VulcanException;
import io.github.wulkanowy.data.db.dao.DbContract;
import io.github.wulkanowy.utils.security.ScramblerException;
@Singleton
public class SyncRepository implements SyncContract {
private final GradeSync gradeSync;
private final SubjectSync subjectSync;
private final AttendanceSync attendanceSync;
private final TimetableSync timetableSync;
private final AccountSync accountSync;
private final ExamsSync examsSync;
private final DbContract database;
@Inject
SyncRepository(GradeSync gradeSync, SubjectSync subjectSync, AttendanceSync attendanceSync,
TimetableSync timetableSync, AccountSync accountSync, ExamsSync examsSync,
DbContract database) {
this.gradeSync = gradeSync;
this.subjectSync = subjectSync;
this.attendanceSync = attendanceSync;
this.timetableSync = timetableSync;
this.accountSync = accountSync;
this.examsSync = examsSync;
this.database = database;
}
@Override
public void registerUser(String email, String password, String symbol) throws VulcanException,
IOException, ScramblerException {
accountSync.registerUser(email, password, symbol);
}
@Override
public void initLastUser() throws ScramblerException {
accountSync.initLastUser();
}
@Override
public void syncGrades(int semesterName) throws VulcanException, IOException {
gradeSync.sync(semesterName);
}
@Override
public void syncGrades() throws VulcanException, IOException {
gradeSync.sync(database.getCurrentSemesterId());
}
@Override
public void syncSubjects(int semesterName) throws VulcanException, IOException {
subjectSync.sync(semesterName);
}
@Override
public void syncSubjects() throws VulcanException, IOException {
subjectSync.sync(database.getCurrentSemesterId());
}
@Override
public void syncAttendance() throws IOException, VulcanException {
attendanceSync.syncAttendance(database.getCurrentDiaryId(), null);
}
@Override
public void syncAttendance(long diaryId, String date) throws IOException, VulcanException {
if (diaryId != 0) {
attendanceSync.syncAttendance(diaryId, date);
} else {
attendanceSync.syncAttendance(database.getCurrentDiaryId(), date);
}
}
@Override
public void syncTimetable() throws VulcanException, IOException {
timetableSync.syncTimetable(database.getCurrentDiaryId(), null);
}
@Override
public void syncTimetable(long diaryId, String date) throws VulcanException, IOException {
if (diaryId != 0) {
timetableSync.syncTimetable(diaryId, date);
} else {
timetableSync.syncTimetable(database.getCurrentDiaryId(), date);
}
}
@Override
public void syncExams() throws VulcanException, IOException {
examsSync.syncExams(database.getCurrentDiaryId(), null);
}
@Override
public void syncExams(long diaryId, String date) throws VulcanException, IOException {
if (diaryId != 0) {
examsSync.syncExams(diaryId, date);
} else {
examsSync.syncExams(database.getCurrentDiaryId(), date);
}
}
@Override
public void syncAll() throws VulcanException, IOException {
syncSubjects();
syncGrades();
syncAttendance();
syncTimetable();
syncExams();
}
}

View File

@ -1,161 +0,0 @@
package io.github.wulkanowy.data.sync;
import org.apache.commons.collections4.CollectionUtils;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.inject.Inject;
import javax.inject.Singleton;
import io.github.wulkanowy.api.Vulcan;
import io.github.wulkanowy.api.VulcanException;
import io.github.wulkanowy.api.generic.Lesson;
import io.github.wulkanowy.data.db.dao.entities.DaoSession;
import io.github.wulkanowy.data.db.dao.entities.Day;
import io.github.wulkanowy.data.db.dao.entities.DayDao;
import io.github.wulkanowy.data.db.dao.entities.TimetableLesson;
import io.github.wulkanowy.data.db.dao.entities.TimetableLessonDao;
import io.github.wulkanowy.data.db.dao.entities.Week;
import io.github.wulkanowy.data.db.dao.entities.WeekDao;
import io.github.wulkanowy.utils.DataObjectConverter;
import timber.log.Timber;
@Singleton
public class TimetableSync {
private final DaoSession daoSession;
private final Vulcan vulcan;
private long diaryId;
@Inject
TimetableSync(DaoSession daoSession, Vulcan vulcan) {
this.daoSession = daoSession;
this.vulcan = vulcan;
}
public void syncTimetable(long diaryId, String date) throws IOException, VulcanException {
this.diaryId = diaryId;
io.github.wulkanowy.api.generic.Week<io.github.wulkanowy.api.timetable.TimetableDay> weekApi = getWeekFromApi(date);
Week weekDb = getWeekFromDb(weekApi.getStartDayDate());
long weekId = updateWeekInDb(weekDb, weekApi);
List<TimetableLesson> lessonList = updateDays(weekApi.getDays(), weekId);
daoSession.getTimetableLessonDao().saveInTx(lessonList);
Timber.d("Timetable synchronization complete (%s)", lessonList.size());
}
private io.github.wulkanowy.api.generic.Week<io.github.wulkanowy.api.timetable.TimetableDay> getWeekFromApi(String date)
throws IOException, VulcanException {
return vulcan.getTimetable().getWeekTable(date);
}
private Week getWeekFromDb(String date) {
return daoSession.getWeekDao().queryBuilder().where(
WeekDao.Properties.DiaryId.eq(diaryId),
WeekDao.Properties.StartDayDate.eq(date)
).unique();
}
private Long updateWeekInDb(Week dbEntity, io.github.wulkanowy.api.generic.Week fromApi) {
if (dbEntity != null) {
dbEntity.setTimetableSynced(true);
dbEntity.update();
return dbEntity.getId();
}
Week apiEntity = DataObjectConverter.weekToWeekEntity(fromApi).setDiaryId(diaryId);
apiEntity.setTimetableSynced(true);
return daoSession.getWeekDao().insert(apiEntity);
}
private List<TimetableLesson> updateDays(List<io.github.wulkanowy.api.timetable.TimetableDay> dayListFromApi, long weekId) {
List<TimetableLesson> updatedLessonList = new ArrayList<>();
for (io.github.wulkanowy.api.timetable.TimetableDay dayFromApi : dayListFromApi) {
Day dbDayEntity = getDayFromDb(dayFromApi.getDate(), weekId);
Day apiDayEntity = DataObjectConverter.timetableDayToDayEntity(dayFromApi);
long dayId = updateDay(dbDayEntity, apiDayEntity, weekId);
updateLessons(dayFromApi.getLessons(), updatedLessonList, dayId);
}
return updatedLessonList;
}
private Day getDayFromDb(String date, long weekId) {
return daoSession.getDayDao().queryBuilder().where(
DayDao.Properties.WeekId.eq(weekId),
DayDao.Properties.Date.eq(date)
).unique();
}
private long updateDay(Day dayFromDb, Day apiDayEntity, long weekId) {
apiDayEntity.setWeekId(weekId);
if (null != dayFromDb) {
apiDayEntity.setId(dayFromDb.getId());
daoSession.getDayDao().save(apiDayEntity);
dayFromDb.refresh();
return dayFromDb.getId();
}
return daoSession.getDayDao().insert(apiDayEntity);
}
private void updateLessons(List<Lesson> lessons, List<TimetableLesson> updatedLessons, long dayId) {
List<TimetableLesson> lessonsFromApiEntities = DataObjectConverter
.lessonsToTimetableLessonsEntities(lessons);
List<TimetableLesson> lessonsFromDbEntities = getLessonsFromDb(dayId);
if (!lessonsFromDbEntities.isEmpty()) {
List<TimetableLesson> lessonToRemove = new ArrayList<>(CollectionUtils.removeAll(lessonsFromDbEntities, lessonsFromApiEntities));
for (TimetableLesson timetableLesson : lessonToRemove) {
daoSession.getTimetableLessonDao().delete(timetableLesson);
}
}
for (TimetableLesson apiLessonEntity : lessonsFromApiEntities) {
TimetableLesson lessonFromDb = getLessonFromDb(apiLessonEntity, dayId);
apiLessonEntity.setDayId(dayId);
if (lessonFromDb != null) {
apiLessonEntity.setId(lessonFromDb.getId());
}
if (!"".equals(apiLessonEntity.getSubject())) {
updatedLessons.add(apiLessonEntity);
}
}
}
private TimetableLesson getLessonFromDb(TimetableLesson apiEntity, long dayId) {
return daoSession.getTimetableLessonDao().queryBuilder()
.where(TimetableLessonDao.Properties.DayId.eq(dayId),
TimetableLessonDao.Properties.Date.eq(apiEntity.getDate()),
TimetableLessonDao.Properties.StartTime.eq(apiEntity.getStartTime()),
TimetableLessonDao.Properties.EndTime.eq(apiEntity.getEndTime()))
.unique();
}
private List<TimetableLesson> getLessonsFromDb(long dayId) {
return daoSession.getDayDao().load(dayId).getTimetableLessons();
}
}

View File

@ -1,20 +0,0 @@
package io.github.wulkanowy.di;
import javax.inject.Singleton;
import dagger.Component;
import dagger.android.AndroidInjector;
import dagger.android.support.AndroidSupportInjectionModule;
import io.github.wulkanowy.WulkanowyApp;
@Singleton
@Component(modules = {
AndroidSupportInjectionModule.class,
AppModule.class,
BuilderModule.class
})
public interface AppComponent extends AndroidInjector<WulkanowyApp> {
@Component.Builder
abstract class Builder extends AndroidInjector.Builder<WulkanowyApp> {
}
}

View File

@ -0,0 +1,19 @@
package io.github.wulkanowy.di
import dagger.Component
import dagger.android.AndroidInjector
import dagger.android.support.AndroidSupportInjectionModule
import io.github.wulkanowy.WulkanowyApp
import io.github.wulkanowy.data.RepositoryModule
import javax.inject.Singleton
@Singleton
@Component(modules = [
AndroidSupportInjectionModule::class,
AppModule::class,
RepositoryModule::class,
BuilderModule::class])
interface AppComponent : AndroidInjector<WulkanowyApp> {
@Component.Builder
abstract class Builder : AndroidInjector.Builder<WulkanowyApp>()
}

View File

@ -1,78 +0,0 @@
package io.github.wulkanowy.di;
import android.content.Context;
import javax.inject.Named;
import javax.inject.Singleton;
import dagger.Binds;
import dagger.Module;
import dagger.Provides;
import io.github.wulkanowy.WulkanowyApp;
import io.github.wulkanowy.api.Vulcan;
import io.github.wulkanowy.data.Repository;
import io.github.wulkanowy.data.RepositoryContract;
import io.github.wulkanowy.data.db.dao.DbContract;
import io.github.wulkanowy.data.db.dao.DbHelper;
import io.github.wulkanowy.data.db.dao.DbRepository;
import io.github.wulkanowy.data.db.dao.entities.DaoMaster;
import io.github.wulkanowy.data.db.dao.entities.DaoSession;
import io.github.wulkanowy.data.db.resources.ResourcesContract;
import io.github.wulkanowy.data.db.resources.ResourcesRepository;
import io.github.wulkanowy.data.db.shared.SharedPrefContract;
import io.github.wulkanowy.data.db.shared.SharedPrefRepository;
import io.github.wulkanowy.data.sync.SyncContract;
import io.github.wulkanowy.data.sync.SyncRepository;
import io.github.wulkanowy.utils.AppConstant;
@Module
public abstract class AppModule {
@Binds
abstract Context provideContext(WulkanowyApp app);
@Singleton
@Binds
abstract RepositoryContract provideRepository(Repository repository);
@Singleton
@Binds
abstract DbContract provideDatabse(DbRepository dbRepository);
@Singleton
@Binds
abstract SharedPrefContract provideSharedPref(SharedPrefRepository sharedPrefRepository);
@Singleton
@Binds
abstract SyncContract provideSync(SyncRepository syncRepository);
@Singleton
@Binds
abstract ResourcesContract provideResources(ResourcesRepository resourcesRepository);
@Singleton
@Provides
static DaoSession provideDaoSession(DbHelper dbHelper) {
return new DaoMaster(dbHelper.getWritableDb()).newSession();
}
@Singleton
@Provides
static Vulcan provideVulcan() {
return new Vulcan();
}
@Provides
@Named("dbName")
static String provideDbName() {
return AppConstant.DATABASE_NAME;
}
@Provides
@Named("sharedPrefName")
static String provideSharedPrefName() {
return AppConstant.SHARED_PREFERENCES_NAME;
}
}

View File

@ -0,0 +1,22 @@
package io.github.wulkanowy.di
import android.content.Context
import dagger.Module
import dagger.Provides
import io.github.wulkanowy.WulkanowyApp
import io.github.wulkanowy.data.ErrorHandler
import io.github.wulkanowy.utils.schedulers.SchedulersManager
import io.github.wulkanowy.utils.schedulers.SchedulersProvider
@Module
internal class AppModule {
@Provides
fun provideContext(app: WulkanowyApp): Context = app
@Provides
fun provideSchedulers(): SchedulersManager = SchedulersProvider()
@Provides
fun provideErrorHandler(context: Context): ErrorHandler = ErrorHandler(context.resources)
}

View File

@ -1,39 +0,0 @@
package io.github.wulkanowy.di;
import dagger.Module;
import dagger.android.ContributesAndroidInjector;
import io.github.wulkanowy.di.scopes.PerActivity;
import io.github.wulkanowy.services.jobs.SyncJob;
import io.github.wulkanowy.services.widgets.TimetableWidgetServices;
import io.github.wulkanowy.ui.login.LoginActivity;
import io.github.wulkanowy.ui.login.LoginModule;
import io.github.wulkanowy.ui.main.MainActivity;
import io.github.wulkanowy.ui.main.MainModule;
import io.github.wulkanowy.ui.splash.SplashActivity;
import io.github.wulkanowy.ui.splash.SplashModule;
import io.github.wulkanowy.ui.widgets.TimetableWidgetProvider;
@Module
abstract class BuilderModule {
@PerActivity
@ContributesAndroidInjector(modules = SplashModule.class)
abstract SplashActivity bindSplashActivity();
@PerActivity
@ContributesAndroidInjector(modules = LoginModule.class)
abstract LoginActivity bindLoginActivity();
@PerActivity
@ContributesAndroidInjector(modules = MainModule.class)
abstract MainActivity bindMainActivity();
@ContributesAndroidInjector
abstract SyncJob bindSyncJob();
@ContributesAndroidInjector
abstract TimetableWidgetServices bindTimetableWidgetServices();
@ContributesAndroidInjector
abstract TimetableWidgetProvider bindTimetableWidgetProvider();
}

View File

@ -0,0 +1,25 @@
package io.github.wulkanowy.di
import dagger.Module
import dagger.android.ContributesAndroidInjector
import io.github.wulkanowy.di.scopes.PerActivity
import io.github.wulkanowy.ui.login.LoginActivity
import io.github.wulkanowy.ui.login.LoginModule
import io.github.wulkanowy.ui.main.MainActivity
import io.github.wulkanowy.ui.splash.SplashActivity
@Module
internal abstract class BuilderModule {
@PerActivity
@ContributesAndroidInjector()
abstract fun bindSplashActivity(): SplashActivity
@PerActivity
@ContributesAndroidInjector(modules = [LoginModule::class])
abstract fun bindLoginActivity(): LoginActivity
@PerActivity
@ContributesAndroidInjector()
abstract fun bindMainActivity(): MainActivity
}

View File

@ -1,11 +0,0 @@
package io.github.wulkanowy.di.scopes;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import javax.inject.Scope;
@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface PerActivity {
}

View File

@ -0,0 +1,7 @@
package io.github.wulkanowy.di.scopes
import javax.inject.Scope
@Scope
@Retention(AnnotationRetention.RUNTIME)
annotation class PerActivity

View File

@ -1,11 +0,0 @@
package io.github.wulkanowy.di.scopes;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import javax.inject.Scope;
@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface PerChildFragment {
}

View File

@ -0,0 +1,7 @@
package io.github.wulkanowy.di.scopes
import javax.inject.Scope
@Scope
@Retention(AnnotationRetention.RUNTIME)
annotation class PerChildFragment

View File

@ -1,11 +0,0 @@
package io.github.wulkanowy.di.scopes;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import javax.inject.Scope;
@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface PerFragment {
}

View File

@ -0,0 +1,7 @@
package io.github.wulkanowy.di.scopes
import javax.inject.Scope
@Scope
@Retention(AnnotationRetention.RUNTIME)
annotation class PerFragment

View File

@ -1,148 +0,0 @@
package io.github.wulkanowy.services.jobs;
import android.app.PendingIntent;
import android.content.Context;
import android.support.v4.app.NotificationCompat;
import com.firebase.jobdispatcher.Constraint;
import com.firebase.jobdispatcher.FirebaseJobDispatcher;
import com.firebase.jobdispatcher.GooglePlayDriver;
import com.firebase.jobdispatcher.JobParameters;
import com.firebase.jobdispatcher.JobService;
import com.firebase.jobdispatcher.Lifetime;
import com.firebase.jobdispatcher.RetryStrategy;
import com.firebase.jobdispatcher.SimpleJobService;
import com.firebase.jobdispatcher.Trigger;
import java.util.ArrayList;
import java.util.List;
import javax.inject.Inject;
import dagger.android.AndroidInjection;
import io.github.wulkanowy.R;
import io.github.wulkanowy.api.login.BadCredentialsException;
import io.github.wulkanowy.data.RepositoryContract;
import io.github.wulkanowy.data.db.dao.entities.Grade;
import io.github.wulkanowy.data.sync.NotRegisteredUserException;
import io.github.wulkanowy.services.notifies.GradeNotify;
import io.github.wulkanowy.ui.main.MainActivity;
import io.github.wulkanowy.utils.FabricUtils;
import timber.log.Timber;
import static io.github.wulkanowy.utils.TimeUtilsKt.isHolidays;
public class SyncJob extends SimpleJobService {
public static final String JOB_TAG = "SyncJob";
private List<Grade> gradeList = new ArrayList<>();
@Inject
RepositoryContract repository;
public static void start(Context context, int interval, boolean useOnlyWifi) {
FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(new GooglePlayDriver(context));
dispatcher.mustSchedule(dispatcher.newJobBuilder()
.setLifetime(Lifetime.FOREVER)
.setService(SyncJob.class)
.setTag(JOB_TAG)
.setRecurring(true)
.setTrigger(Trigger.executionWindow(interval * 60, (interval + 10) * 60))
.setConstraints(useOnlyWifi ? Constraint.ON_UNMETERED_NETWORK : Constraint.ON_ANY_NETWORK)
.setReplaceCurrent(false)
.setRetryStrategy(RetryStrategy.DEFAULT_EXPONENTIAL)
.build());
}
public static void stop(Context context) {
new FirebaseJobDispatcher(new GooglePlayDriver(context)).cancel(JOB_TAG);
}
@Override
public void onCreate() {
super.onCreate();
AndroidInjection.inject(this);
}
@Override
public int onRunJob(JobParameters job) {
if (isHolidays()) {
stop(getApplicationContext());
return JobService.RESULT_FAIL_NORETRY;
}
try {
repository.getSyncRepo().initLastUser();
repository.getSyncRepo().syncAll();
gradeList = repository.getDbRepo().getNewGrades(repository.getDbRepo().getCurrentSemesterName());
if (!gradeList.isEmpty() && repository.getSharedRepo().isNotifyEnable()) {
showNotification();
}
FabricUtils.logLogin("Background", true);
return JobService.RESULT_SUCCESS;
} catch (NotRegisteredUserException e) {
logError(e);
stop(getApplicationContext());
return JobService.RESULT_FAIL_NORETRY;
} catch (BadCredentialsException e) {
logError(e);
repository.cleanAllData();
stop(getApplicationContext());
return JobService.RESULT_FAIL_NORETRY;
} catch (Exception e) {
logError(e);
return JobService.RESULT_FAIL_RETRY;
}
}
private void showNotification() {
GradeNotify gradeNotify = new GradeNotify(getApplicationContext());
gradeNotify.notify(gradeNotify.notificationBuilder()
.setContentTitle(getStringTitle())
.setContentText(getStringContent())
.setSmallIcon(R.drawable.ic_notify_grade)
.setAutoCancel(true)
.setDefaults(NotificationCompat.DEFAULT_ALL)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setColor(getResources().getColor(R.color.colorPrimary))
.setContentIntent(PendingIntent.getActivity(getApplicationContext(), 0,
MainActivity.getStartIntent(getApplicationContext())
.putExtra(MainActivity.EXTRA_CARD_ID_KEY, 0)
, PendingIntent.FLAG_UPDATE_CURRENT
))
.build());
}
private String getStringTitle() {
if (gradeList.size() == 1) {
return getResources().getQuantityString(R.plurals.newGradePlurals, 1);
} else {
return getResources().getQuantityString(R.plurals.newGradePlurals, 2);
}
}
private String getStringContent() {
if (gradeList.size() == 1) {
return gradeList.get(0).getSubject();
} else {
return getResources().getQuantityString(R.plurals.receivedNewGradePlurals,
gradeList.size(), gradeList.size());
}
}
private void logError(Exception e) {
FabricUtils.logLogin("Background", false);
Timber.e(e, "During background synchronization an error occurred");
}
}

View File

@ -1,36 +0,0 @@
package io.github.wulkanowy.services.notifies;
import android.annotation.TargetApi;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Context;
import io.github.wulkanowy.R;
public class GradeNotify extends NotificationService {
private static final String CHANNEL_ID = "Grade_Notify";
public GradeNotify(Context context) {
super(context);
}
@Override
@TargetApi(26)
void createChannel() {
String channelName = getString(R.string.notify_grade_channel);
NotificationChannel notificationChannel = new NotificationChannel(CHANNEL_ID, channelName,
NotificationManager.IMPORTANCE_HIGH);
notificationChannel.enableLights(true);
notificationChannel.enableVibration(true);
notificationChannel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
getManager().createNotificationChannel(notificationChannel);
}
@Override
String getChannelId() {
return CHANNEL_ID;
}
}

View File

@ -1,57 +0,0 @@
package io.github.wulkanowy.services.notifies;
import android.annotation.TargetApi;
import android.app.Notification;
import android.app.NotificationManager;
import android.content.Context;
import android.os.Build;
import android.support.annotation.StringRes;
import android.support.v4.app.NotificationCompat;
import java.util.Random;
public class NotificationService {
private NotificationManager manager;
private Context context;
public NotificationService(Context context) {
this.context = context;
}
public void notify(Notification notification) {
getManager().notify(new Random().nextInt(1000), notification);
}
public NotificationCompat.Builder notificationBuilder() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
createChannel();
}
return new NotificationCompat.Builder(context, getChannelId());
}
public void cancelAll() {
getManager().cancelAll();
}
NotificationManager getManager() {
if (manager == null) {
manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
}
return manager;
}
String getString(@StringRes int stringId) {
return context.getString(stringId);
}
@TargetApi(26)
void createChannel() {
}
String getChannelId() {
return null;
}
}

View File

@ -1,22 +0,0 @@
package io.github.wulkanowy.services.widgets;
import android.content.Intent;
import android.widget.RemoteViewsService;
import javax.inject.Inject;
import dagger.android.AndroidInjection;
import io.github.wulkanowy.data.RepositoryContract;
import io.github.wulkanowy.ui.widgets.TimetableWidgetFactory;
public class TimetableWidgetServices extends RemoteViewsService {
@Inject
RepositoryContract repository;
@Override
public RemoteViewsFactory onGetViewFactory(Intent intent) {
AndroidInjection.inject(this);
return new TimetableWidgetFactory(getApplicationContext(), repository);
}
}

View File

@ -1,59 +0,0 @@
package io.github.wulkanowy.ui.base;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatDelegate;
import android.view.View;
import butterknife.ButterKnife;
import butterknife.Unbinder;
import dagger.android.support.DaggerAppCompatActivity;
import io.github.wulkanowy.R;
import io.github.wulkanowy.utils.NetworkUtils;
public abstract class BaseActivity extends DaggerAppCompatActivity implements BaseContract.View {
private Unbinder unbinder;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}
protected void injectViews() {
unbinder = ButterKnife.bind(this);
}
@Override
public void showMessage(@NonNull String text) {
if (getMessageView() != null) {
Snackbar.make(getMessageView(), text, Snackbar.LENGTH_LONG).show();
}
}
@Override
public void showNoNetworkMessage() {
showMessage(getString(R.string.noInternet_text));
}
@Override
public boolean isNetworkConnected() {
return NetworkUtils.isOnline(getApplicationContext());
}
protected View getMessageView() {
return null;
}
@Override
protected void onDestroy() {
super.onDestroy();
if (unbinder != null) {
unbinder.unbind();
}
invalidateOptionsMenu();
}
}

View File

@ -0,0 +1,33 @@
package io.github.wulkanowy.ui.base
import android.os.Bundle
import android.support.design.widget.Snackbar
import android.support.design.widget.Snackbar.LENGTH_LONG
import android.support.v7.app.AppCompatDelegate
import android.view.View
import dagger.android.support.DaggerAppCompatActivity
import io.github.wulkanowy.R
abstract class BaseActivity : DaggerAppCompatActivity(), BaseView {
protected lateinit var messageView: View
public override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
}
override fun showMessage(text: String) {
Snackbar.make(messageView, text, LENGTH_LONG).show()
}
override fun showNoNetworkMessage() {
showMessage(getString(R.string.noInternet_text))
}
override fun onDestroy() {
super.onDestroy()
invalidateOptionsMenu()
}
}

View File

@ -1,22 +0,0 @@
package io.github.wulkanowy.ui.base;
import android.support.annotation.NonNull;
public interface BaseContract {
interface View {
void showMessage(@NonNull String text);
void showNoNetworkMessage();
boolean isNetworkConnected();
}
interface Presenter<V extends View> {
void attachView(@NonNull V view);
void detachView();
}
}

View File

@ -1,56 +0,0 @@
package io.github.wulkanowy.ui.base;
import android.support.annotation.NonNull;
import android.support.annotation.StringRes;
import android.view.View;
import butterknife.ButterKnife;
import butterknife.Unbinder;
import dagger.android.support.DaggerFragment;
import io.github.wulkanowy.utils.NetworkUtils;
public abstract class BaseFragment extends DaggerFragment implements BaseContract.View {
private Unbinder unbinder;
protected void injectViews(@NonNull View view) {
unbinder = ButterKnife.bind(this, view);
}
@Override
public void onDestroyView() {
if (unbinder != null) {
unbinder.unbind();
}
super.onDestroyView();
}
public void setTitle(String title) {
if (getActivity() != null) {
getActivity().setTitle(title);
}
}
@Override
public void showMessage(@NonNull String text) {
if (getActivity() != null) {
((BaseActivity) getActivity()).showMessage(text);
}
}
public void showMessage(@StringRes int stringId) {
showMessage(getString(stringId));
}
@Override
public void showNoNetworkMessage() {
if (getActivity() != null) {
((BaseActivity) getActivity()).showNoNetworkMessage();
}
}
@Override
public boolean isNetworkConnected() {
return NetworkUtils.isOnline(getContext());
}
}

View File

@ -0,0 +1,24 @@
package io.github.wulkanowy.ui.base
import android.support.annotation.StringRes
import dagger.android.support.DaggerFragment
abstract class BaseFragment : DaggerFragment(), BaseView {
fun setTitle(title: String) {
activity?.title = title
}
override fun showMessage(text: String) {
(activity as BaseActivity?)?.showMessage(text)
}
fun showMessage(@StringRes stringId: Int) {
showMessage(getString(stringId))
}
override fun showNoNetworkMessage() {
(activity as BaseActivity?)?.showNoNetworkMessage()
}
}

View File

@ -1,47 +0,0 @@
package io.github.wulkanowy.ui.base;
import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import java.util.ArrayList;
import java.util.List;
public class BasePagerAdapter extends FragmentStatePagerAdapter {
private List<Fragment> fragmentList = new ArrayList<>();
private List<String> titleList = new ArrayList<>();
public BasePagerAdapter(FragmentManager fragmentManager) {
super(fragmentManager);
}
public void addFragment(@NonNull Fragment fragment, @NonNull String title) {
fragmentList.add(fragment);
titleList.add(title);
}
public void addFragment(@NonNull Fragment fragment) {
fragmentList.add(fragment);
}
@Override
public Fragment getItem(int position) {
return fragmentList.get(position);
}
@Override
public int getCount() {
return fragmentList.size();
}
@Override
public CharSequence getPageTitle(int position) {
if (!titleList.isEmpty()) {
return titleList.get(position);
}
return null;
}
}

View File

@ -0,0 +1,30 @@
package io.github.wulkanowy.ui.base
import android.support.v4.app.Fragment
import android.support.v4.app.FragmentManager
import android.support.v4.app.FragmentStatePagerAdapter
class BasePagerAdapter(fragmentManager: FragmentManager) : FragmentStatePagerAdapter(fragmentManager) {
private val fragmentList = mutableListOf<Fragment>()
private val titleList = mutableListOf<String>()
fun addFragment(fragment: Fragment, title: String) {
fragmentList.add(fragment)
titleList.add(title)
}
fun addFragments(vararg fragments: Fragment) {
fragmentList.addAll(fragments)
}
override fun getItem(position: Int): Fragment = fragmentList[position]
override fun getCount(): Int = fragmentList.size
override fun getPageTitle(position: Int): CharSequence? {
return if (!titleList.isEmpty() && titleList.size == fragmentList.size) titleList[position]
else null
}
}

View File

@ -1,41 +0,0 @@
package io.github.wulkanowy.ui.base;
import android.support.annotation.NonNull;
import javax.inject.Inject;
import io.github.wulkanowy.data.RepositoryContract;
public class BasePresenter<V extends BaseContract.View> implements BaseContract.Presenter<V> {
private final RepositoryContract repository;
private V view;
@Inject
public BasePresenter(RepositoryContract repository) {
this.repository = repository;
}
@Override
public void attachView(@NonNull V view) {
this.view = view;
}
@Override
public void detachView() {
view = null;
}
protected boolean isViewAttached() {
return view != null;
}
public final RepositoryContract getRepository() {
return repository;
}
public V getView() {
return view;
}
}

View File

@ -0,0 +1,25 @@
package io.github.wulkanowy.ui.base
import io.github.wulkanowy.data.ErrorHandler
import io.reactivex.disposables.CompositeDisposable
open class BasePresenter<T : BaseView>(private val errorHandler: ErrorHandler) {
val disposable = CompositeDisposable()
var view: T? = null
val isViewAttached: Boolean
get() = view != null
open fun attachView(view: T) {
this.view = view
errorHandler.showErrorMessage = { view.showMessage(it) }
}
open fun detachView() {
view = null
disposable.clear()
errorHandler.clear()
}
}

View File

@ -0,0 +1,8 @@
package io.github.wulkanowy.ui.base
interface BaseView {
fun showMessage(text: String)
fun showNoNetworkMessage()
}

View File

@ -1,236 +0,0 @@
package io.github.wulkanowy.ui.login;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.TextInputLayout;
import android.support.v7.app.ActionBar;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import javax.inject.Inject;
import butterknife.BindView;
import butterknife.OnClick;
import butterknife.OnEditorAction;
import io.github.wulkanowy.R;
import io.github.wulkanowy.ui.base.BaseActivity;
import io.github.wulkanowy.ui.main.MainActivity;
import io.github.wulkanowy.utils.AppConstant;
import io.github.wulkanowy.utils.CommonUtils;
import io.github.wulkanowy.utils.KeyboardUtils;
public class LoginActivity extends BaseActivity implements LoginContract.View {
@BindView(R.id.login_activity_email_edit)
EditText emailView;
@BindView(R.id.login_activity_pass_edit)
EditText passwordView;
@BindView(R.id.login_activity_symbol_edit)
AutoCompleteTextView symbolView;
@BindView(R.id.login_activity_form_scroll)
View loginFormView;
@BindView(R.id.login_activity_progress_container)
View loadingBarView;
@BindView(R.id.login_activity_progress_text)
TextView loginProgressText;
@BindView(R.id.login_activity_symbol_text_input)
TextInputLayout symbolLayout;
@Inject
LoginContract.Presenter presenter;
private EditText requestedView;
public static Intent getStartIntent(Context context) {
return new Intent(context, LoginActivity.class);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
injectViews();
presenter.attachView(this);
setUpOnCreate();
}
protected void setUpOnCreate() {
symbolView.setAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1,
getResources().getStringArray(R.array.symbols)));
}
@OnClick(R.id.login_activity_sign_button)
void onLoginButtonClick() {
presenter.attemptLogin(
emailView.getText().toString(),
passwordView.getText().toString(),
symbolView.getText().toString());
}
@OnEditorAction(value = {R.id.login_activity_symbol_edit, R.id.login_activity_pass_edit})
boolean onEditorAction(int id) {
if (id == EditorInfo.IME_ACTION_DONE || id == EditorInfo.IME_NULL) {
onLoginButtonClick();
return true;
}
return false;
}
@OnClick(R.id.login_activity_create_text)
void onCreateAccountButtonClick() {
CommonUtils.openInternalBrowserViewer(this, AppConstant.VULCAN_CREATE_ACCOUNT_URL);
}
@OnClick(R.id.login_activity_forgot_text)
void onForgotPasswordButtonClick() {
CommonUtils.openInternalBrowserViewer(this, AppConstant.VULCAN_FORGOT_PASS_URL);
}
@Override
public void setErrorEmailRequired() {
emailView.requestFocus();
emailView.setError(getString(R.string.error_field_required));
requestedView = emailView;
}
@Override
public void setErrorEmailInvalid() {
emailView.requestFocus();
emailView.setError(getString(R.string.error_invalid_email));
requestedView = emailView;
}
@Override
public void setErrorPassRequired() {
passwordView.requestFocus();
passwordView.setError(getString(R.string.error_field_required));
requestedView = passwordView;
}
@Override
public void setErrorPassInvalid() {
passwordView.requestFocus();
passwordView.setError(getString(R.string.error_invalid_password));
requestedView = passwordView;
}
@Override
public void setErrorPassIncorrect() {
passwordView.requestFocus();
passwordView.setError(getString(R.string.error_incorrect_password));
requestedView = passwordView;
}
@Override
public void setErrorSymbolRequired() {
symbolLayout.setVisibility(View.VISIBLE);
symbolView.setError(getString(R.string.error_bad_account_permission));
symbolView.requestFocus();
requestedView = symbolView;
}
@Override
public void resetViewErrors() {
emailView.setError(null);
passwordView.setError(null);
}
@Override
public void showSoftInput() {
KeyboardUtils.showSoftInput(requestedView, this);
}
@Override
public void hideSoftInput() {
KeyboardUtils.hideSoftInput(this);
}
@Override
public void setStepOneLoginProgress() {
onLoginProgressUpdate("1", getString(R.string.step_login));
}
@Override
public void setStepTwoLoginProgress() {
onLoginProgressUpdate("2", getString(R.string.step_synchronization));
}
@Override
public void openMainActivity() {
startActivity(MainActivity.getStartIntent(this));
finish();
}
@Override
public void showLoginProgress(final boolean show) {
int animTime = getResources().getInteger(android.R.integer.config_shortAnimTime);
loginFormView.setVisibility(show ? View.GONE : View.VISIBLE);
loginFormView.animate().setDuration(animTime).alpha(
show ? 0 : 1).setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
loginFormView.setVisibility(show ? View.GONE : View.VISIBLE);
}
});
loadingBarView.setVisibility(show ? View.VISIBLE : View.GONE);
loadingBarView.animate().setDuration(animTime).alpha(
show ? 1 : 0).setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
loadingBarView.setVisibility(show ? View.VISIBLE : View.GONE);
}
});
}
@Override
public void showActionBar(boolean show) {
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
if (show) {
actionBar.show();
} else {
actionBar.hide();
}
}
}
@NonNull
@Override
protected View getMessageView() {
return findViewById(R.id.login_activity_container);
}
@Override
public void onSyncFailed() {
Toast.makeText(getApplicationContext(), R.string.login_sync_error, Toast.LENGTH_LONG).show();
}
private void onLoginProgressUpdate(String step, String message) {
loginProgressText.setText(String.format("%1$s/2 - %2$s...", step, message));
}
@Override
public void onDestroy() {
presenter.detachView();
super.onDestroy();
}
}

View File

@ -0,0 +1,70 @@
package io.github.wulkanowy.ui.login
import android.content.Context
import android.content.Intent
import android.os.Bundle
import io.github.wulkanowy.R
import io.github.wulkanowy.ui.base.BaseActivity
import io.github.wulkanowy.ui.base.BasePagerAdapter
import io.github.wulkanowy.ui.login.form.LoginFormFragment
import io.github.wulkanowy.ui.login.options.LoginOptionsFragment
import io.github.wulkanowy.utils.extension.setOnSelectPageListener
import kotlinx.android.synthetic.main.activity_login.*
import javax.inject.Inject
import javax.inject.Named
class LoginActivity : BaseActivity(), LoginView, LoginSwitchListener {
@Inject
lateinit var presenter: LoginPresenter
@Inject
@field:Named("Login")
lateinit var loginAdapter: BasePagerAdapter
companion object {
fun getStartIntent(context: Context) = Intent(context, LoginActivity::class.java)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_login)
presenter.attachView(this)
messageView = loginContainer
}
override fun onBackPressed() {
presenter.onBackPressed { super.onBackPressed() }
}
override fun initAdapter() {
loginAdapter.addFragments(LoginFormFragment(), LoginOptionsFragment())
loginViewpager.run {
adapter = loginAdapter
setOnSelectPageListener { presenter.onPageSelected(it) }
}
}
override fun switchFragment(position: Int) {
presenter.onSwitchFragment(position)
}
override fun switchView(position: Int) {
loginViewpager.setCurrentItem(position, false)
}
override fun hideActionBar() {
supportActionBar?.hide()
}
override fun loadOptionsView(index: Int) {
(loginAdapter.getItem(index) as LoginOptionsFragment).loadData()
}
override fun currentViewPosition(): Int = loginViewpager.currentItem
public override fun onDestroy() {
presenter.detachView()
super.onDestroy()
}
}

View File

@ -1,54 +0,0 @@
package io.github.wulkanowy.ui.login;
import io.github.wulkanowy.ui.base.BaseContract;
public interface LoginContract {
interface View extends BaseContract.View {
void setErrorEmailRequired();
void setErrorPassRequired();
void setErrorSymbolRequired();
void setErrorEmailInvalid();
void setErrorPassInvalid();
void setErrorPassIncorrect();
void resetViewErrors();
void setStepOneLoginProgress();
void setStepTwoLoginProgress();
void openMainActivity();
void showLoginProgress(boolean show);
void showSoftInput();
void hideSoftInput();
void showActionBar(boolean show);
void onSyncFailed();
}
interface Presenter extends BaseContract.Presenter<View> {
void attemptLogin(String email, String password, String symbol);
void onStartAsync();
void onDoInBackground(int stepNumber) throws Exception;
void onLoginProgress(int step);
void onEndAsync(int success, Exception exception);
void onCanceledAsync();
}
}

View File

@ -0,0 +1,23 @@
package io.github.wulkanowy.ui.login
import android.content.res.Resources
import io.github.wulkanowy.api.login.BadCredentialsException
import io.github.wulkanowy.data.ErrorHandler
class LoginErrorHandler(resources: Resources) : ErrorHandler(resources) {
var doOnBadCredentials: () -> Unit = {}
override fun proceed(error: Throwable) {
when (error) {
is BadCredentialsException -> doOnBadCredentials()
else -> super.proceed(error)
}
}
override fun clear() {
super.clear()
doOnBadCredentials = {}
}
}

View File

@ -1,13 +0,0 @@
package io.github.wulkanowy.ui.login;
import dagger.Binds;
import dagger.Module;
import io.github.wulkanowy.di.scopes.PerActivity;
@Module
public abstract class LoginModule {
@PerActivity
@Binds
abstract LoginContract.Presenter provideLoginPresenter(LoginPresenter loginPresenter);
}

View File

@ -0,0 +1,39 @@
package io.github.wulkanowy.ui.login
import android.content.Context
import dagger.Module
import dagger.Provides
import dagger.android.ContributesAndroidInjector
import io.github.wulkanowy.di.scopes.PerActivity
import io.github.wulkanowy.di.scopes.PerFragment
import io.github.wulkanowy.ui.base.BasePagerAdapter
import io.github.wulkanowy.ui.login.form.LoginFormFragment
import io.github.wulkanowy.ui.login.options.LoginOptionsFragment
import io.github.wulkanowy.ui.login.options.LoginOptionsModule
import javax.inject.Named
@Module
internal abstract class LoginModule {
@Module
companion object {
@JvmStatic
@Provides
@Named("Login")
fun provideLoginAdapter(activity: LoginActivity) = BasePagerAdapter(activity.supportFragmentManager)
@JvmStatic
@PerActivity
@Provides
fun provideLoginErrorHandler(context: Context) = LoginErrorHandler(context.resources)
}
@PerFragment
@ContributesAndroidInjector()
abstract fun bindLoginFormFragment(): LoginFormFragment
@PerFragment
@ContributesAndroidInjector(modules = [LoginOptionsModule::class])
abstract fun bindLoginOptionsFragment(): LoginOptionsFragment
}

Some files were not shown because too many files have changed in this diff Show More