diff --git a/.gitignore b/.gitignore
index fd45b12..e133b7a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,3 +9,16 @@
/build
/captures
.externalNativeBuild
+app
+appbase
+dbapp
+modelapp
+netapp
+modelapp
+promise
+promisedb
+promisemodel
+promisenet
+promiseui
+uiapp
+
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
index 6a22d2f..3a92786 100644
--- a/.idea/gradle.xml
+++ b/.idea/gradle.xml
@@ -8,14 +8,8 @@
diff --git a/app/build.gradle b/app/build.gradle
index 8cbbe9c..d841078 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -43,7 +43,7 @@ android {
multiDexEnabled = true
}
}
- buildToolsVersion = '29.0.0 rc3'
+ buildToolsVersion = '29.0.1'
}
dependencies {
@@ -56,7 +56,11 @@ dependencies {
testImplementation 'junit:junit:4.13-beta-3'
androidTestImplementation 'androidx.test:runner:1.2.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
- implementation project(path: ':promise')
+ implementation project(path: ':promisecommons')
+ implementation project(path: ':promisedb')
+ implementation project(path: ':promisemodel')
+ implementation project(path: ':promisenet')
+ implementation project(path: ':promiseui')
/* implementation 'com.google.dagger:dagger:2.23'
kapt 'com.google.dagger:dagger-compiler:2.23'*/
}
diff --git a/app/src/main/java/promise/app/App.java b/app/src/main/java/promise/app/App.java
index 22f8dc1..13ff2fe 100644
--- a/app/src/main/java/promise/app/App.java
+++ b/app/src/main/java/promise/app/App.java
@@ -10,7 +10,5 @@ public class App extends Application {
public void onCreate() {
super.onCreate();
Promise.init(this).threads(100);
-
}
-
}
diff --git a/build.gradle b/build.gradle
index 53c7c20..8141dcd 100644
--- a/build.gradle
+++ b/build.gradle
@@ -2,6 +2,7 @@
buildscript {
ext.kotlin_version = '1.3.41'
+ ext.supportLibVersion = "28.0.0"
repositories {
google()
diff --git a/promisepref/.gitignore b/commonsapp/.gitignore
similarity index 100%
rename from promisepref/.gitignore
rename to commonsapp/.gitignore
diff --git a/commonsapp/build.gradle b/commonsapp/build.gradle
new file mode 100644
index 0000000..98a7332
--- /dev/null
+++ b/commonsapp/build.gradle
@@ -0,0 +1,45 @@
+apply plugin: 'com.android.application'
+apply plugin: 'kotlin-android'
+apply plugin: 'kotlin-android-extensions'
+android {
+ compileSdkVersion 29
+ buildToolsVersion "29.0.1"
+
+
+ defaultConfig {
+ applicationId "promise.commonsapp"
+ minSdkVersion 17
+ targetSdkVersion 29
+ versionCode 1
+ versionName "1.0"
+
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+
+ }
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+
+}
+
+dependencies {
+ implementation fileTree(dir: 'libs', include: ['*.jar'])
+ implementation project(path: ':promisecommons')
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+ implementation 'androidx.appcompat:appcompat:1.0.2'
+ implementation 'androidx.core:core-ktx:1.0.2'
+ implementation 'io.reactivex.rxjava2:rxjava:2.2.7'
+ implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
+ testImplementation 'junit:junit:4.12'
+ androidTestImplementation 'androidx.test:runner:1.2.0'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
+}
diff --git a/promisepref/proguard-rules.pro b/commonsapp/proguard-rules.pro
similarity index 100%
rename from promisepref/proguard-rules.pro
rename to commonsapp/proguard-rules.pro
diff --git a/commonsapp/src/androidTest/java/promise/commonsapp/ExampleInstrumentedTest.kt b/commonsapp/src/androidTest/java/promise/commonsapp/ExampleInstrumentedTest.kt
new file mode 100644
index 0000000..e2ac35f
--- /dev/null
+++ b/commonsapp/src/androidTest/java/promise/commonsapp/ExampleInstrumentedTest.kt
@@ -0,0 +1,24 @@
+package promise.commonsapp
+
+import androidx.test.InstrumentationRegistry
+import androidx.test.runner.AndroidJUnit4
+
+import org.junit.Test
+import org.junit.runner.RunWith
+
+import org.junit.Assert.*
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+@RunWith(AndroidJUnit4::class)
+class ExampleInstrumentedTest {
+ @Test
+ fun useAppContext() {
+ // Context of the app under test.
+ val appContext = InstrumentationRegistry.getTargetContext()
+ assertEquals("promise.commonsapp", appContext.packageName)
+ }
+}
diff --git a/commonsapp/src/main/AndroidManifest.xml b/commonsapp/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..74cbdd3
--- /dev/null
+++ b/commonsapp/src/main/AndroidManifest.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/commonsapp/src/main/java/promise/commonsapp/MainActivity.kt b/commonsapp/src/main/java/promise/commonsapp/MainActivity.kt
new file mode 100644
index 0000000..cc7f614
--- /dev/null
+++ b/commonsapp/src/main/java/promise/commonsapp/MainActivity.kt
@@ -0,0 +1,31 @@
+package promise.commonsapp
+
+import android.os.Bundle
+import androidx.appcompat.app.AppCompatActivity
+import androidx.collection.ArrayMap
+import kotlinx.android.synthetic.main.activity_main.*
+import promise.pref.Preferences
+
+class MainActivity : AppCompatActivity() {
+
+ private val preferences: Preferences = Preferences(PREFERENCE_NAMR)
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_main)
+ preferences.save(ArrayMap().apply {
+ put("somekey", "key")
+ put("somekey1", "key1")
+ put("somekey2", "key3")
+ })
+ }
+
+ override fun onPostCreate(savedInstanceState: Bundle?) {
+ super.onPostCreate(savedInstanceState)
+ preferences_textview.text = preferences.all.toString()
+ }
+
+ companion object {
+ const val PREFERENCE_NAMR = "pref_name"
+ }
+}
diff --git a/commonsapp/src/main/res/drawable-v24/ic_launcher_foreground.xml b/commonsapp/src/main/res/drawable-v24/ic_launcher_foreground.xml
new file mode 100644
index 0000000..1f6bb29
--- /dev/null
+++ b/commonsapp/src/main/res/drawable-v24/ic_launcher_foreground.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/commonsapp/src/main/res/drawable/ic_launcher_background.xml b/commonsapp/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 0000000..0d025f9
--- /dev/null
+++ b/commonsapp/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/commonsapp/src/main/res/layout/activity_main.xml b/commonsapp/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000..769f9c2
--- /dev/null
+++ b/commonsapp/src/main/res/layout/activity_main.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/commonsapp/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/commonsapp/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
new file mode 100644
index 0000000..eca70cf
--- /dev/null
+++ b/commonsapp/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/commonsapp/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/commonsapp/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 0000000..eca70cf
--- /dev/null
+++ b/commonsapp/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/commonsapp/src/main/res/mipmap-hdpi/ic_launcher.png b/commonsapp/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..898f3ed
Binary files /dev/null and b/commonsapp/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/commonsapp/src/main/res/mipmap-hdpi/ic_launcher_round.png b/commonsapp/src/main/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100644
index 0000000..dffca36
Binary files /dev/null and b/commonsapp/src/main/res/mipmap-hdpi/ic_launcher_round.png differ
diff --git a/commonsapp/src/main/res/mipmap-mdpi/ic_launcher.png b/commonsapp/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..64ba76f
Binary files /dev/null and b/commonsapp/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/commonsapp/src/main/res/mipmap-mdpi/ic_launcher_round.png b/commonsapp/src/main/res/mipmap-mdpi/ic_launcher_round.png
new file mode 100644
index 0000000..dae5e08
Binary files /dev/null and b/commonsapp/src/main/res/mipmap-mdpi/ic_launcher_round.png differ
diff --git a/commonsapp/src/main/res/mipmap-xhdpi/ic_launcher.png b/commonsapp/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..e5ed465
Binary files /dev/null and b/commonsapp/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/commonsapp/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/commonsapp/src/main/res/mipmap-xhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..14ed0af
Binary files /dev/null and b/commonsapp/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ
diff --git a/commonsapp/src/main/res/mipmap-xxhdpi/ic_launcher.png b/commonsapp/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..b0907ca
Binary files /dev/null and b/commonsapp/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/commonsapp/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/commonsapp/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..d8ae031
Binary files /dev/null and b/commonsapp/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ
diff --git a/commonsapp/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/commonsapp/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..2c18de9
Binary files /dev/null and b/commonsapp/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/commonsapp/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/commonsapp/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..beed3cd
Binary files /dev/null and b/commonsapp/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ
diff --git a/commonsapp/src/main/res/values/colors.xml b/commonsapp/src/main/res/values/colors.xml
new file mode 100644
index 0000000..69b2233
--- /dev/null
+++ b/commonsapp/src/main/res/values/colors.xml
@@ -0,0 +1,6 @@
+
+
+ #008577
+ #00574B
+ #D81B60
+
diff --git a/commonsapp/src/main/res/values/strings.xml b/commonsapp/src/main/res/values/strings.xml
new file mode 100644
index 0000000..1efa3ec
--- /dev/null
+++ b/commonsapp/src/main/res/values/strings.xml
@@ -0,0 +1,3 @@
+
+ CommonsApp
+
diff --git a/commonsapp/src/main/res/values/styles.xml b/commonsapp/src/main/res/values/styles.xml
new file mode 100644
index 0000000..5885930
--- /dev/null
+++ b/commonsapp/src/main/res/values/styles.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
diff --git a/commonsapp/src/test/java/promise/commonsapp/ExampleUnitTest.kt b/commonsapp/src/test/java/promise/commonsapp/ExampleUnitTest.kt
new file mode 100644
index 0000000..40a8096
--- /dev/null
+++ b/commonsapp/src/test/java/promise/commonsapp/ExampleUnitTest.kt
@@ -0,0 +1,17 @@
+package promise.commonsapp
+
+import org.junit.Test
+
+import org.junit.Assert.*
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+class ExampleUnitTest {
+ @Test
+ fun addition_isCorrect() {
+ assertEquals(4, 2 + 2)
+ }
+}
diff --git a/dbapp/.gitignore b/dbapp/.gitignore
new file mode 100644
index 0000000..796b96d
--- /dev/null
+++ b/dbapp/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/dbapp/build.gradle b/dbapp/build.gradle
new file mode 100644
index 0000000..9eda101
--- /dev/null
+++ b/dbapp/build.gradle
@@ -0,0 +1,50 @@
+apply plugin: 'com.android.application'
+apply plugin: 'kotlin-android'
+apply plugin: 'kotlin-android-extensions'
+android {
+ compileSdkVersion 29
+ buildToolsVersion "29.0.1"
+
+
+ defaultConfig {
+ applicationId "promise.dbapp"
+ minSdkVersion 17
+ targetSdkVersion 29
+ versionCode 1
+ versionName "1.0"
+
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+
+ }
+
+ compileOptions {
+ sourceCompatibility 1.8
+ targetCompatibility 1.8
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+
+}
+
+dependencies {
+ implementation fileTree(dir: 'libs', include: ['*.jar'])
+ implementation project(path: ':promisedb')
+ implementation project(path: ':promisecommons')
+ implementation project(path: ':promiseui')
+ implementation "com.android.support:recyclerview-v7:$supportLibVersion"
+ implementation 'io.reactivex.rxjava2:rxjava:2.2.7'
+ implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+ implementation 'androidx.appcompat:appcompat:1.0.2'
+ implementation 'androidx.core:core-ktx:1.0.2'
+ implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
+ implementation 'com.google.android.material:material:1.0.0'
+ testImplementation 'junit:junit:4.12'
+ androidTestImplementation 'androidx.test:runner:1.2.0'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
+}
diff --git a/dbapp/proguard-rules.pro b/dbapp/proguard-rules.pro
new file mode 100644
index 0000000..f1b4245
--- /dev/null
+++ b/dbapp/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
diff --git a/dbapp/src/androidTest/java/promise/dbapp/ExampleInstrumentedTest.kt b/dbapp/src/androidTest/java/promise/dbapp/ExampleInstrumentedTest.kt
new file mode 100644
index 0000000..0b1e914
--- /dev/null
+++ b/dbapp/src/androidTest/java/promise/dbapp/ExampleInstrumentedTest.kt
@@ -0,0 +1,24 @@
+package promise.dbapp
+
+import androidx.test.InstrumentationRegistry
+import androidx.test.runner.AndroidJUnit4
+
+import org.junit.Test
+import org.junit.runner.RunWith
+
+import org.junit.Assert.*
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+@RunWith(AndroidJUnit4::class)
+class ExampleInstrumentedTest {
+ @Test
+ fun useAppContext() {
+ // Context of the app under test.
+ val appContext = InstrumentationRegistry.getTargetContext()
+ assertEquals("promise.dbapp", appContext.packageName)
+ }
+}
diff --git a/dbapp/src/main/AndroidManifest.xml b/dbapp/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..2947075
--- /dev/null
+++ b/dbapp/src/main/AndroidManifest.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dbapp/src/main/java/promise/dbapp/App.kt b/dbapp/src/main/java/promise/dbapp/App.kt
new file mode 100644
index 0000000..abc41c8
--- /dev/null
+++ b/dbapp/src/main/java/promise/dbapp/App.kt
@@ -0,0 +1,11 @@
+package promise.dbapp
+
+import android.app.Application
+import promise.Promise
+
+class App : Application() {
+ override fun onCreate() {
+ super.onCreate()
+ Promise.init(this).threads(10)
+ }
+}
\ No newline at end of file
diff --git a/dbapp/src/main/java/promise/dbapp/MainActivity.kt b/dbapp/src/main/java/promise/dbapp/MainActivity.kt
new file mode 100644
index 0000000..b426b86
--- /dev/null
+++ b/dbapp/src/main/java/promise/dbapp/MainActivity.kt
@@ -0,0 +1,67 @@
+package promise.dbapp
+
+import android.os.Bundle
+import android.os.Handler
+import android.os.Looper
+import com.google.android.material.snackbar.Snackbar
+import androidx.appcompat.app.AppCompatActivity;
+import android.view.Menu
+import android.view.MenuItem
+import io.reactivex.functions.Consumer
+
+import kotlinx.android.synthetic.main.activity_main.*
+import kotlinx.android.synthetic.main.content_main.*
+import promise.Promise
+import promise.dbapp.model.ComplexModel
+import promise.dbapp.model.Database
+import promise.model.Result
+import promise.model.SList
+
+class MainActivity : AppCompatActivity() {
+
+ val handler: Handler by lazy { Handler(Looper.getMainLooper()) }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_main)
+ setSupportActionBar(toolbar)
+
+ fab.setOnClickListener { view ->
+ Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
+ .setAction("Action", null).show()
+ }
+ }
+
+ override fun onPostCreate(savedInstanceState: Bundle?) {
+ super.onPostCreate(savedInstanceState)
+ val database = Database()
+
+ database.allComplexModels(Result, Throwable>()
+ .responseCallBack {
+ if (it.isNotEmpty()) {
+ complex_values_textview.text = it.toString()
+ } else complex_values_textview.text = "empty list"
+ }
+ .errorCallBack { complex_values_textview.text = it.message })
+
+ clear_button.setOnClickListener {
+ database.deleteAll()
+ }
+
+ }
+ override fun onCreateOptionsMenu(menu: Menu): Boolean {
+ // Inflate the menu; this adds items to the action bar if it is present.
+ menuInflater.inflate(R.menu.menu_main, menu)
+ return true
+ }
+
+ override fun onOptionsItemSelected(item: MenuItem): Boolean {
+ // Handle action bar item clicks here. The action bar will
+ // automatically handle clicks on the Home/Up button, so long
+ // as you specify a parent activity in AndroidManifest.xml.
+ return when (item.itemId) {
+ R.id.action_settings -> true
+ else -> super.onOptionsItemSelected(item)
+ }
+ }
+}
diff --git a/dbapp/src/main/java/promise/dbapp/model/ComplexModel.kt b/dbapp/src/main/java/promise/dbapp/model/ComplexModel.kt
new file mode 100644
index 0000000..0219560
--- /dev/null
+++ b/dbapp/src/main/java/promise/dbapp/model/ComplexModel.kt
@@ -0,0 +1,160 @@
+package promise.dbapp.model
+
+import android.os.Parcel
+import android.os.Parcelable
+import android.view.View
+import promise.dbapp.R
+import promise.model.List
+import promise.model.SModel
+import promise.promiseui.model.Viewable
+
+class ComplexModel constructor() : SModel(), Parcelable, Viewable {
+ var index: Int = 0
+
+ override fun layout(): Int = R.layout.complex_layout
+
+ override fun init(view: View?) {
+ TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
+ }
+
+ override fun bind(view: View?) {
+ TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
+ }
+
+ override fun index(index: Int) {
+ this.index = index
+ }
+
+ override fun index(): Int {
+ return this.index
+ }
+
+ var intVariable: Int? = null
+
+ var floatVariable: Float? = null
+
+ var doubleVariable: Double? = null
+
+ var stringVariable: String? = null
+
+ constructor(source: Parcel) : this() {
+ intVariable = source.readInt()
+ }
+
+ override fun describeContents() = 0
+
+ override fun writeToParcel(dest: Parcel, flags: Int) = with(dest) {}
+ override fun toString(): String {
+ return "ComplexModel(intVariable=$intVariable, floatVariable=$floatVariable, doubleVariable=$doubleVariable, stringVariable=$stringVariable)\n"
+ }
+
+ companion object {
+ @JvmField
+ val CREATOR: Parcelable.Creator = object : Parcelable.Creator {
+ override fun createFromParcel(source: Parcel): ComplexModel = ComplexModel(source)
+ override fun newArray(size: Int): Array = arrayOfNulls(size)
+ }
+
+ fun someModels(): List = List.fromArray(ComplexModel().apply {
+ intVariable = 1
+ floatVariable = 0.2f
+ doubleVariable = 3.567
+ stringVariable = "some string"
+ }, ComplexModel().apply {
+ intVariable = 2
+ floatVariable = 0.5f
+ doubleVariable = 3.87
+ stringVariable = "some string 2"
+ }, ComplexModel().apply {
+ intVariable = 5
+ floatVariable = 0.7f
+ doubleVariable = 10.987655
+ stringVariable = "some string 3"
+ }, ComplexModel().apply {
+ intVariable = 10
+ floatVariable = 62f
+ doubleVariable = 567.7865
+ stringVariable = "some string 4"
+ }, ComplexModel().apply {
+ intVariable = 18
+ floatVariable = 100.3f
+ doubleVariable = 456.987
+ stringVariable = "some string 5"
+ },ComplexModel().apply {
+ intVariable = 5
+ floatVariable = 0.7f
+ doubleVariable = 10.987655
+ stringVariable = "some string 3"
+ }, ComplexModel().apply {
+ intVariable = 10
+ floatVariable = 62f
+ doubleVariable = 567.7865
+ stringVariable = "some string 4"
+ }, ComplexModel().apply {
+ intVariable = 18
+ floatVariable = 100.3f
+ doubleVariable = 456.987
+ stringVariable = "some string 5"
+ },ComplexModel().apply {
+ intVariable = 5
+ floatVariable = 0.7f
+ doubleVariable = 10.987655
+ stringVariable = "some string 3"
+ }, ComplexModel().apply {
+ intVariable = 10
+ floatVariable = 62f
+ doubleVariable = 567.7865
+ stringVariable = "some string 4"
+ }, ComplexModel().apply {
+ intVariable = 18
+ floatVariable = 100.3f
+ doubleVariable = 456.987
+ stringVariable = "some string 5"
+ },ComplexModel().apply {
+ intVariable = 5
+ floatVariable = 0.7f
+ doubleVariable = 10.987655
+ stringVariable = "some string 3"
+ }, ComplexModel().apply {
+ intVariable = 10
+ floatVariable = 62f
+ doubleVariable = 567.7865
+ stringVariable = "some string 4"
+ }, ComplexModel().apply {
+ intVariable = 18
+ floatVariable = 100.3f
+ doubleVariable = 456.987
+ stringVariable = "some string 5"
+ },ComplexModel().apply {
+ intVariable = 5
+ floatVariable = 0.7f
+ doubleVariable = 10.987655
+ stringVariable = "some string 3"
+ }, ComplexModel().apply {
+ intVariable = 10
+ floatVariable = 62f
+ doubleVariable = 567.7865
+ stringVariable = "some string 4"
+ }, ComplexModel().apply {
+ intVariable = 18
+ floatVariable = 100.3f
+ doubleVariable = 456.987
+ stringVariable = "some string 5"
+ },ComplexModel().apply {
+ intVariable = 5
+ floatVariable = 0.7f
+ doubleVariable = 10.987655
+ stringVariable = "some string 3"
+ }, ComplexModel().apply {
+ intVariable = 10
+ floatVariable = 62f
+ doubleVariable = 567.7865
+ stringVariable = "some string 4"
+ }, ComplexModel().apply {
+ intVariable = 18
+ floatVariable = 100.3f
+ doubleVariable = 456.987
+ stringVariable = "some string 5"
+ })
+ }
+}
\ No newline at end of file
diff --git a/dbapp/src/main/java/promise/dbapp/model/ComplexModelTable.kt b/dbapp/src/main/java/promise/dbapp/model/ComplexModelTable.kt
new file mode 100644
index 0000000..774aa34
--- /dev/null
+++ b/dbapp/src/main/java/promise/dbapp/model/ComplexModelTable.kt
@@ -0,0 +1,48 @@
+package promise.dbapp.model
+
+import android.content.ContentValues
+import android.database.Cursor
+import promise.model.List
+import promise.promisedb.Column
+import promise.promisedb.Model
+
+class ComplexModelTable : Model() {
+ /**
+ * @return
+ */
+ override fun getName(): String = "name_of_complex_model_table"
+
+ /**
+ * gets all the columns for this model from the child class for creation purposes
+ * see [.onCreate]
+ *
+ * @return list of columns
+ */
+ override fun getColumns(): List> {
+ return List.fromArray(intVariableColumn, floatVariableColumn, doubleVariableColumn, stringVariableColumn)
+ }
+
+ override fun deserialize(e: Cursor): ComplexModel = ComplexModel().apply {
+ intVariable = e.getInt(intVariableColumn.index)
+ floatVariable = e.getFloat(floatVariableColumn.index)
+ doubleVariable = e.getDouble(doubleVariableColumn.index)
+ stringVariable = e.getString(stringVariableColumn.index)
+ }
+
+ override fun serialize(t: ComplexModel): ContentValues = ContentValues().apply {
+ put(intVariableColumn.name, t.intVariable)
+ put(floatVariableColumn.name, t.floatVariable)
+ put(doubleVariableColumn.name, t.doubleVariable)
+ put(stringVariableColumn.name, t.stringVariable)
+ }
+
+ companion object {
+ fun id() = id
+
+ val intVariableColumn: Column = Column("int", Column.Type.INTEGER.NOT_NULL(), 1)
+ val floatVariableColumn: Column = Column("float", Column.Type.INTEGER.NOT_NULL(), 2)
+ val doubleVariableColumn: Column = Column("double", Column.Type.INTEGER.NOT_NULL(), 3)
+ val stringVariableColumn: Column = Column("string", Column.Type.INTEGER.NOT_NULL(), 4)
+
+ }
+}
\ No newline at end of file
diff --git a/dbapp/src/main/java/promise/dbapp/model/Database.kt b/dbapp/src/main/java/promise/dbapp/model/Database.kt
new file mode 100644
index 0000000..f494ff2
--- /dev/null
+++ b/dbapp/src/main/java/promise/dbapp/model/Database.kt
@@ -0,0 +1,70 @@
+package promise.dbapp.model
+
+import android.database.sqlite.SQLiteDatabase
+import io.reactivex.android.schedulers.AndroidSchedulers
+import io.reactivex.disposables.CompositeDisposable
+import promise.model.List
+import promise.model.Result
+import promise.model.SList
+import promise.promisedb.ReactiveDB
+import promise.promisedb.Table
+
+class Database : ReactiveDB(name, version, null, null) {
+ /**
+ *
+ */
+ private val compositeDisposable: CompositeDisposable by lazy { CompositeDisposable() }
+ /**
+ * @return
+ */
+ override fun onTerminate(): CompositeDisposable {
+ return compositeDisposable
+ }
+
+ /**
+ *
+ * @param database
+ * @param oldVersion
+ * @param newVersion
+ * @return
+ */
+ override fun shouldUpgrade(database: SQLiteDatabase?, oldVersion: Int, newVersion: Int): Boolean {
+ return oldVersion < newVersion
+ }
+
+ /**
+ *
+ * @return
+ */
+ override fun tables(): List> = List.fromArray(complexModelTable)
+
+ fun allComplexModels(result: Result, Throwable>) {
+ compositeDisposable.add(readAll(complexModelTable).observeOn(AndroidSchedulers.mainThread())
+ .subscribe({ list ->
+ if (list.isEmpty())
+ saveSomeComplexModels(Result()
+ .responseCallBack { allComplexModels(result) }
+ .errorCallBack { result.error(it) }) else result.response(list)
+
+ }, {
+ result.error(it)
+ }))
+ }
+
+ private fun saveSomeComplexModels(result: Result) {
+ compositeDisposable.add(save(SList(ComplexModel.someModels()), complexModelTable)
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe({
+ result.response(it)
+ }, {
+ result.error(it)
+ }))
+ }
+
+
+ companion object {
+ const val name = "complex_db_name"
+ const val version = 1
+ private val complexModelTable: ComplexModelTable by lazy { ComplexModelTable() }
+ }
+}
\ No newline at end of file
diff --git a/dbapp/src/main/res/drawable-v24/ic_launcher_foreground.xml b/dbapp/src/main/res/drawable-v24/ic_launcher_foreground.xml
new file mode 100644
index 0000000..1f6bb29
--- /dev/null
+++ b/dbapp/src/main/res/drawable-v24/ic_launcher_foreground.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dbapp/src/main/res/drawable/ic_launcher_background.xml b/dbapp/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 0000000..0d025f9
--- /dev/null
+++ b/dbapp/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dbapp/src/main/res/layout/activity_main.xml b/dbapp/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000..e9fa907
--- /dev/null
+++ b/dbapp/src/main/res/layout/activity_main.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dbapp/src/main/res/layout/complex_layout.xml b/dbapp/src/main/res/layout/complex_layout.xml
new file mode 100644
index 0000000..3509b84
--- /dev/null
+++ b/dbapp/src/main/res/layout/complex_layout.xml
@@ -0,0 +1,6 @@
+
+
+
+
\ No newline at end of file
diff --git a/dbapp/src/main/res/layout/content_main.xml b/dbapp/src/main/res/layout/content_main.xml
new file mode 100644
index 0000000..6426ced
--- /dev/null
+++ b/dbapp/src/main/res/layout/content_main.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dbapp/src/main/res/menu/menu_main.xml b/dbapp/src/main/res/menu/menu_main.xml
new file mode 100644
index 0000000..1e3340b
--- /dev/null
+++ b/dbapp/src/main/res/menu/menu_main.xml
@@ -0,0 +1,10 @@
+
diff --git a/dbapp/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/dbapp/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
new file mode 100644
index 0000000..eca70cf
--- /dev/null
+++ b/dbapp/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/dbapp/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/dbapp/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 0000000..eca70cf
--- /dev/null
+++ b/dbapp/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/dbapp/src/main/res/mipmap-hdpi/ic_launcher.png b/dbapp/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..898f3ed
Binary files /dev/null and b/dbapp/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/dbapp/src/main/res/mipmap-hdpi/ic_launcher_round.png b/dbapp/src/main/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100644
index 0000000..dffca36
Binary files /dev/null and b/dbapp/src/main/res/mipmap-hdpi/ic_launcher_round.png differ
diff --git a/dbapp/src/main/res/mipmap-mdpi/ic_launcher.png b/dbapp/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..64ba76f
Binary files /dev/null and b/dbapp/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/dbapp/src/main/res/mipmap-mdpi/ic_launcher_round.png b/dbapp/src/main/res/mipmap-mdpi/ic_launcher_round.png
new file mode 100644
index 0000000..dae5e08
Binary files /dev/null and b/dbapp/src/main/res/mipmap-mdpi/ic_launcher_round.png differ
diff --git a/dbapp/src/main/res/mipmap-xhdpi/ic_launcher.png b/dbapp/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..e5ed465
Binary files /dev/null and b/dbapp/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/dbapp/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/dbapp/src/main/res/mipmap-xhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..14ed0af
Binary files /dev/null and b/dbapp/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ
diff --git a/dbapp/src/main/res/mipmap-xxhdpi/ic_launcher.png b/dbapp/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..b0907ca
Binary files /dev/null and b/dbapp/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/dbapp/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/dbapp/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..d8ae031
Binary files /dev/null and b/dbapp/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ
diff --git a/dbapp/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/dbapp/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..2c18de9
Binary files /dev/null and b/dbapp/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/dbapp/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/dbapp/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..beed3cd
Binary files /dev/null and b/dbapp/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ
diff --git a/dbapp/src/main/res/values/colors.xml b/dbapp/src/main/res/values/colors.xml
new file mode 100644
index 0000000..69b2233
--- /dev/null
+++ b/dbapp/src/main/res/values/colors.xml
@@ -0,0 +1,6 @@
+
+
+ #008577
+ #00574B
+ #D81B60
+
diff --git a/dbapp/src/main/res/values/dimens.xml b/dbapp/src/main/res/values/dimens.xml
new file mode 100644
index 0000000..59a0b0c
--- /dev/null
+++ b/dbapp/src/main/res/values/dimens.xml
@@ -0,0 +1,3 @@
+
+ 16dp
+
diff --git a/dbapp/src/main/res/values/strings.xml b/dbapp/src/main/res/values/strings.xml
new file mode 100644
index 0000000..57d51d3
--- /dev/null
+++ b/dbapp/src/main/res/values/strings.xml
@@ -0,0 +1,4 @@
+
+ DBApp
+ Settings
+
diff --git a/dbapp/src/main/res/values/styles.xml b/dbapp/src/main/res/values/styles.xml
new file mode 100644
index 0000000..545b9c6
--- /dev/null
+++ b/dbapp/src/main/res/values/styles.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dbapp/src/test/java/promise/dbapp/ExampleUnitTest.kt b/dbapp/src/test/java/promise/dbapp/ExampleUnitTest.kt
new file mode 100644
index 0000000..4f975e1
--- /dev/null
+++ b/dbapp/src/test/java/promise/dbapp/ExampleUnitTest.kt
@@ -0,0 +1,17 @@
+package promise.dbapp
+
+import org.junit.Test
+
+import org.junit.Assert.*
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+class ExampleUnitTest {
+ @Test
+ fun addition_isCorrect() {
+ assertEquals(4, 2 + 2)
+ }
+}
diff --git a/modelapp/.gitignore b/modelapp/.gitignore
new file mode 100644
index 0000000..796b96d
--- /dev/null
+++ b/modelapp/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/modelapp/build.gradle b/modelapp/build.gradle
new file mode 100644
index 0000000..2a27093
--- /dev/null
+++ b/modelapp/build.gradle
@@ -0,0 +1,39 @@
+apply plugin: 'com.android.application'
+apply plugin: 'kotlin-android'
+apply plugin: 'kotlin-android-extensions'
+android {
+ compileSdkVersion 29
+ buildToolsVersion "29.0.1"
+
+
+ defaultConfig {
+ applicationId "promise.modelapp"
+ minSdkVersion 17
+ targetSdkVersion 29
+ versionCode 1
+ versionName "1.0"
+
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+
+}
+
+dependencies {
+ implementation fileTree(dir: 'libs', include: ['*.jar'])
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+ implementation 'androidx.appcompat:appcompat:1.0.2'
+ implementation 'androidx.core:core-ktx:1.0.2'
+ implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
+ implementation 'com.google.android.material:material:1.0.0'
+ testImplementation 'junit:junit:4.12'
+ androidTestImplementation 'androidx.test:runner:1.2.0'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
+}
diff --git a/modelapp/proguard-rules.pro b/modelapp/proguard-rules.pro
new file mode 100644
index 0000000..f1b4245
--- /dev/null
+++ b/modelapp/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
diff --git a/modelapp/src/androidTest/java/promise/modelapp/ExampleInstrumentedTest.kt b/modelapp/src/androidTest/java/promise/modelapp/ExampleInstrumentedTest.kt
new file mode 100644
index 0000000..511923a
--- /dev/null
+++ b/modelapp/src/androidTest/java/promise/modelapp/ExampleInstrumentedTest.kt
@@ -0,0 +1,24 @@
+package promise.modelapp
+
+import androidx.test.InstrumentationRegistry
+import androidx.test.runner.AndroidJUnit4
+
+import org.junit.Test
+import org.junit.runner.RunWith
+
+import org.junit.Assert.*
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+@RunWith(AndroidJUnit4::class)
+class ExampleInstrumentedTest {
+ @Test
+ fun useAppContext() {
+ // Context of the app under test.
+ val appContext = InstrumentationRegistry.getTargetContext()
+ assertEquals("promise.modelapp", appContext.packageName)
+ }
+}
diff --git a/modelapp/src/main/AndroidManifest.xml b/modelapp/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..c97afcb
--- /dev/null
+++ b/modelapp/src/main/AndroidManifest.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/modelapp/src/main/java/promise/modelapp/MainActivity.kt b/modelapp/src/main/java/promise/modelapp/MainActivity.kt
new file mode 100644
index 0000000..e3d7d9a
--- /dev/null
+++ b/modelapp/src/main/java/promise/modelapp/MainActivity.kt
@@ -0,0 +1,39 @@
+package promise.modelapp
+
+import android.os.Bundle
+import com.google.android.material.snackbar.Snackbar
+import androidx.appcompat.app.AppCompatActivity;
+import android.view.Menu
+import android.view.MenuItem
+
+import kotlinx.android.synthetic.main.activity_main.*
+
+class MainActivity : AppCompatActivity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_main)
+ setSupportActionBar(toolbar)
+
+ fab.setOnClickListener { view ->
+ Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
+ .setAction("Action", null).show()
+ }
+ }
+
+ override fun onCreateOptionsMenu(menu: Menu): Boolean {
+ // Inflate the menu; this adds items to the action bar if it is present.
+ menuInflater.inflate(R.menu.menu_main, menu)
+ return true
+ }
+
+ override fun onOptionsItemSelected(item: MenuItem): Boolean {
+ // Handle action bar item clicks here. The action bar will
+ // automatically handle clicks on the Home/Up button, so long
+ // as you specify a parent activity in AndroidManifest.xml.
+ return when (item.itemId) {
+ R.id.action_settings -> true
+ else -> super.onOptionsItemSelected(item)
+ }
+ }
+}
diff --git a/modelapp/src/main/res/drawable-v24/ic_launcher_foreground.xml b/modelapp/src/main/res/drawable-v24/ic_launcher_foreground.xml
new file mode 100644
index 0000000..1f6bb29
--- /dev/null
+++ b/modelapp/src/main/res/drawable-v24/ic_launcher_foreground.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modelapp/src/main/res/drawable/ic_launcher_background.xml b/modelapp/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 0000000..0d025f9
--- /dev/null
+++ b/modelapp/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modelapp/src/main/res/layout/activity_main.xml b/modelapp/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000..e9fa907
--- /dev/null
+++ b/modelapp/src/main/res/layout/activity_main.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/modelapp/src/main/res/layout/content_main.xml b/modelapp/src/main/res/layout/content_main.xml
new file mode 100644
index 0000000..926c02e
--- /dev/null
+++ b/modelapp/src/main/res/layout/content_main.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/modelapp/src/main/res/menu/menu_main.xml b/modelapp/src/main/res/menu/menu_main.xml
new file mode 100644
index 0000000..3c7f1d5
--- /dev/null
+++ b/modelapp/src/main/res/menu/menu_main.xml
@@ -0,0 +1,10 @@
+
diff --git a/modelapp/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/modelapp/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
new file mode 100644
index 0000000..eca70cf
--- /dev/null
+++ b/modelapp/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/modelapp/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/modelapp/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 0000000..eca70cf
--- /dev/null
+++ b/modelapp/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/modelapp/src/main/res/mipmap-hdpi/ic_launcher.png b/modelapp/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..898f3ed
Binary files /dev/null and b/modelapp/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/modelapp/src/main/res/mipmap-hdpi/ic_launcher_round.png b/modelapp/src/main/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100644
index 0000000..dffca36
Binary files /dev/null and b/modelapp/src/main/res/mipmap-hdpi/ic_launcher_round.png differ
diff --git a/modelapp/src/main/res/mipmap-mdpi/ic_launcher.png b/modelapp/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..64ba76f
Binary files /dev/null and b/modelapp/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/modelapp/src/main/res/mipmap-mdpi/ic_launcher_round.png b/modelapp/src/main/res/mipmap-mdpi/ic_launcher_round.png
new file mode 100644
index 0000000..dae5e08
Binary files /dev/null and b/modelapp/src/main/res/mipmap-mdpi/ic_launcher_round.png differ
diff --git a/modelapp/src/main/res/mipmap-xhdpi/ic_launcher.png b/modelapp/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..e5ed465
Binary files /dev/null and b/modelapp/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/modelapp/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/modelapp/src/main/res/mipmap-xhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..14ed0af
Binary files /dev/null and b/modelapp/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ
diff --git a/modelapp/src/main/res/mipmap-xxhdpi/ic_launcher.png b/modelapp/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..b0907ca
Binary files /dev/null and b/modelapp/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/modelapp/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/modelapp/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..d8ae031
Binary files /dev/null and b/modelapp/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ
diff --git a/modelapp/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/modelapp/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..2c18de9
Binary files /dev/null and b/modelapp/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/modelapp/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/modelapp/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..beed3cd
Binary files /dev/null and b/modelapp/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ
diff --git a/modelapp/src/main/res/values/colors.xml b/modelapp/src/main/res/values/colors.xml
new file mode 100644
index 0000000..69b2233
--- /dev/null
+++ b/modelapp/src/main/res/values/colors.xml
@@ -0,0 +1,6 @@
+
+
+ #008577
+ #00574B
+ #D81B60
+
diff --git a/modelapp/src/main/res/values/dimens.xml b/modelapp/src/main/res/values/dimens.xml
new file mode 100644
index 0000000..59a0b0c
--- /dev/null
+++ b/modelapp/src/main/res/values/dimens.xml
@@ -0,0 +1,3 @@
+
+ 16dp
+
diff --git a/modelapp/src/main/res/values/strings.xml b/modelapp/src/main/res/values/strings.xml
new file mode 100644
index 0000000..51f3126
--- /dev/null
+++ b/modelapp/src/main/res/values/strings.xml
@@ -0,0 +1,4 @@
+
+ ModelApp
+ Settings
+
diff --git a/modelapp/src/main/res/values/styles.xml b/modelapp/src/main/res/values/styles.xml
new file mode 100644
index 0000000..545b9c6
--- /dev/null
+++ b/modelapp/src/main/res/values/styles.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modelapp/src/test/java/promise/modelapp/ExampleUnitTest.kt b/modelapp/src/test/java/promise/modelapp/ExampleUnitTest.kt
new file mode 100644
index 0000000..cc269ff
--- /dev/null
+++ b/modelapp/src/test/java/promise/modelapp/ExampleUnitTest.kt
@@ -0,0 +1,17 @@
+package promise.modelapp
+
+import org.junit.Test
+
+import org.junit.Assert.*
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+class ExampleUnitTest {
+ @Test
+ fun addition_isCorrect() {
+ assertEquals(4, 2 + 2)
+ }
+}
diff --git a/netapp/.gitignore b/netapp/.gitignore
new file mode 100644
index 0000000..796b96d
--- /dev/null
+++ b/netapp/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/netapp/build.gradle b/netapp/build.gradle
new file mode 100644
index 0000000..2cd68ec
--- /dev/null
+++ b/netapp/build.gradle
@@ -0,0 +1,39 @@
+apply plugin: 'com.android.application'
+apply plugin: 'kotlin-android'
+apply plugin: 'kotlin-android-extensions'
+android {
+ compileSdkVersion 29
+ buildToolsVersion "29.0.1"
+
+
+ defaultConfig {
+ applicationId "promise.netapp"
+ minSdkVersion 17
+ targetSdkVersion 29
+ versionCode 1
+ versionName "1.0"
+
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+
+}
+
+dependencies {
+ implementation fileTree(dir: 'libs', include: ['*.jar'])
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+ implementation 'androidx.appcompat:appcompat:1.0.2'
+ implementation 'androidx.core:core-ktx:1.0.2'
+ implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
+ implementation 'com.google.android.material:material:1.0.0'
+ testImplementation 'junit:junit:4.12'
+ androidTestImplementation 'androidx.test:runner:1.2.0'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
+}
diff --git a/netapp/proguard-rules.pro b/netapp/proguard-rules.pro
new file mode 100644
index 0000000..f1b4245
--- /dev/null
+++ b/netapp/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
diff --git a/netapp/src/androidTest/java/promise/netapp/ExampleInstrumentedTest.kt b/netapp/src/androidTest/java/promise/netapp/ExampleInstrumentedTest.kt
new file mode 100644
index 0000000..41beb8e
--- /dev/null
+++ b/netapp/src/androidTest/java/promise/netapp/ExampleInstrumentedTest.kt
@@ -0,0 +1,24 @@
+package promise.netapp
+
+import androidx.test.InstrumentationRegistry
+import androidx.test.runner.AndroidJUnit4
+
+import org.junit.Test
+import org.junit.runner.RunWith
+
+import org.junit.Assert.*
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+@RunWith(AndroidJUnit4::class)
+class ExampleInstrumentedTest {
+ @Test
+ fun useAppContext() {
+ // Context of the app under test.
+ val appContext = InstrumentationRegistry.getTargetContext()
+ assertEquals("promise.netapp", appContext.packageName)
+ }
+}
diff --git a/netapp/src/main/AndroidManifest.xml b/netapp/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..cfe13dd
--- /dev/null
+++ b/netapp/src/main/AndroidManifest.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/netapp/src/main/java/promise/netapp/MainActivity.kt b/netapp/src/main/java/promise/netapp/MainActivity.kt
new file mode 100644
index 0000000..7514d63
--- /dev/null
+++ b/netapp/src/main/java/promise/netapp/MainActivity.kt
@@ -0,0 +1,39 @@
+package promise.netapp
+
+import android.os.Bundle
+import com.google.android.material.snackbar.Snackbar
+import androidx.appcompat.app.AppCompatActivity;
+import android.view.Menu
+import android.view.MenuItem
+
+import kotlinx.android.synthetic.main.activity_main.*
+
+class MainActivity : AppCompatActivity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_main)
+ setSupportActionBar(toolbar)
+
+ fab.setOnClickListener { view ->
+ Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
+ .setAction("Action", null).show()
+ }
+ }
+
+ override fun onCreateOptionsMenu(menu: Menu): Boolean {
+ // Inflate the menu; this adds items to the action bar if it is present.
+ menuInflater.inflate(R.menu.menu_main, menu)
+ return true
+ }
+
+ override fun onOptionsItemSelected(item: MenuItem): Boolean {
+ // Handle action bar item clicks here. The action bar will
+ // automatically handle clicks on the Home/Up button, so long
+ // as you specify a parent activity in AndroidManifest.xml.
+ return when (item.itemId) {
+ R.id.action_settings -> true
+ else -> super.onOptionsItemSelected(item)
+ }
+ }
+}
diff --git a/netapp/src/main/res/drawable-v24/ic_launcher_foreground.xml b/netapp/src/main/res/drawable-v24/ic_launcher_foreground.xml
new file mode 100644
index 0000000..1f6bb29
--- /dev/null
+++ b/netapp/src/main/res/drawable-v24/ic_launcher_foreground.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/netapp/src/main/res/drawable/ic_launcher_background.xml b/netapp/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 0000000..0d025f9
--- /dev/null
+++ b/netapp/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/netapp/src/main/res/layout/activity_main.xml b/netapp/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000..e9fa907
--- /dev/null
+++ b/netapp/src/main/res/layout/activity_main.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/netapp/src/main/res/layout/content_main.xml b/netapp/src/main/res/layout/content_main.xml
new file mode 100644
index 0000000..926c02e
--- /dev/null
+++ b/netapp/src/main/res/layout/content_main.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/netapp/src/main/res/menu/menu_main.xml b/netapp/src/main/res/menu/menu_main.xml
new file mode 100644
index 0000000..27c1613
--- /dev/null
+++ b/netapp/src/main/res/menu/menu_main.xml
@@ -0,0 +1,10 @@
+
diff --git a/netapp/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/netapp/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
new file mode 100644
index 0000000..eca70cf
--- /dev/null
+++ b/netapp/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/netapp/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/netapp/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 0000000..eca70cf
--- /dev/null
+++ b/netapp/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/netapp/src/main/res/mipmap-hdpi/ic_launcher.png b/netapp/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..898f3ed
Binary files /dev/null and b/netapp/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/netapp/src/main/res/mipmap-hdpi/ic_launcher_round.png b/netapp/src/main/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100644
index 0000000..dffca36
Binary files /dev/null and b/netapp/src/main/res/mipmap-hdpi/ic_launcher_round.png differ
diff --git a/netapp/src/main/res/mipmap-mdpi/ic_launcher.png b/netapp/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..64ba76f
Binary files /dev/null and b/netapp/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/netapp/src/main/res/mipmap-mdpi/ic_launcher_round.png b/netapp/src/main/res/mipmap-mdpi/ic_launcher_round.png
new file mode 100644
index 0000000..dae5e08
Binary files /dev/null and b/netapp/src/main/res/mipmap-mdpi/ic_launcher_round.png differ
diff --git a/netapp/src/main/res/mipmap-xhdpi/ic_launcher.png b/netapp/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..e5ed465
Binary files /dev/null and b/netapp/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/netapp/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/netapp/src/main/res/mipmap-xhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..14ed0af
Binary files /dev/null and b/netapp/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ
diff --git a/netapp/src/main/res/mipmap-xxhdpi/ic_launcher.png b/netapp/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..b0907ca
Binary files /dev/null and b/netapp/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/netapp/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/netapp/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..d8ae031
Binary files /dev/null and b/netapp/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ
diff --git a/netapp/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/netapp/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..2c18de9
Binary files /dev/null and b/netapp/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/netapp/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/netapp/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..beed3cd
Binary files /dev/null and b/netapp/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ
diff --git a/netapp/src/main/res/values/colors.xml b/netapp/src/main/res/values/colors.xml
new file mode 100644
index 0000000..69b2233
--- /dev/null
+++ b/netapp/src/main/res/values/colors.xml
@@ -0,0 +1,6 @@
+
+
+ #008577
+ #00574B
+ #D81B60
+
diff --git a/netapp/src/main/res/values/dimens.xml b/netapp/src/main/res/values/dimens.xml
new file mode 100644
index 0000000..59a0b0c
--- /dev/null
+++ b/netapp/src/main/res/values/dimens.xml
@@ -0,0 +1,3 @@
+
+ 16dp
+
diff --git a/netapp/src/main/res/values/strings.xml b/netapp/src/main/res/values/strings.xml
new file mode 100644
index 0000000..6e6a3f6
--- /dev/null
+++ b/netapp/src/main/res/values/strings.xml
@@ -0,0 +1,4 @@
+
+ NetApp
+ Settings
+
diff --git a/netapp/src/main/res/values/styles.xml b/netapp/src/main/res/values/styles.xml
new file mode 100644
index 0000000..545b9c6
--- /dev/null
+++ b/netapp/src/main/res/values/styles.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/netapp/src/test/java/promise/netapp/ExampleUnitTest.kt b/netapp/src/test/java/promise/netapp/ExampleUnitTest.kt
new file mode 100644
index 0000000..d7b61b5
--- /dev/null
+++ b/netapp/src/test/java/promise/netapp/ExampleUnitTest.kt
@@ -0,0 +1,17 @@
+package promise.netapp
+
+import org.junit.Test
+
+import org.junit.Assert.*
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+class ExampleUnitTest {
+ @Test
+ fun addition_isCorrect() {
+ assertEquals(4, 2 + 2)
+ }
+}
diff --git a/promise/src/main/java/promise/data/db/Model.java b/promise/src/main/java/promise/data/db/Model.java
index 07952b2..00c6ab9 100644
--- a/promise/src/main/java/promise/data/db/Model.java
+++ b/promise/src/main/java/promise/data/db/Model.java
@@ -32,7 +32,6 @@
import promise.data.db.query.criteria.Criteria;
import promise.data.db.query.projection.Projection;
import promise.data.log.LogUtil;
-import promise.data.utils.Converter;
import promise.model.List;
import promise.model.SList;
import promise.model.SModel;
diff --git a/promise/src/main/java/promise/data/db/ReactiveModel.java b/promise/src/main/java/promise/data/db/ReactiveModel.java
index 32fa94f..5e926c6 100644
--- a/promise/src/main/java/promise/data/db/ReactiveModel.java
+++ b/promise/src/main/java/promise/data/db/ReactiveModel.java
@@ -24,12 +24,10 @@
import androidx.annotation.Nullable;
import io.reactivex.Completable;
import io.reactivex.Maybe;
-import io.reactivex.MaybeObserver;
import io.reactivex.MaybeSource;
import io.reactivex.Single;
import io.reactivex.schedulers.Schedulers;
import promise.Promise;
-import promise.data.utils.Converter;
import promise.model.List;
import promise.model.S;
import promise.model.SList;
diff --git a/promise/src/main/java/promise/data/net/extras/CallAdapter.java b/promise/src/main/java/promise/data/net/extras/CallAdapter.java
index 62337ea..97c1eb4 100644
--- a/promise/src/main/java/promise/data/net/extras/CallAdapter.java
+++ b/promise/src/main/java/promise/data/net/extras/CallAdapter.java
@@ -13,15 +13,7 @@
package promise.data.net.extras;
-import org.json.JSONObject;
-
import java.lang.reflect.Type;
-import java.util.Iterator;
-import java.util.Map;
-
-import promise.data.net.extras.HttpResponse;
-import promise.data.utils.Converter;
-import promise.util.Conditions;
/**
* Created on 6/16/18 by yoctopus.
diff --git a/promise/src/main/java/promise/data/net/extras/JsonAdapter.java b/promise/src/main/java/promise/data/net/extras/JsonAdapter.java
index f38ab83..73034fc 100644
--- a/promise/src/main/java/promise/data/net/extras/JsonAdapter.java
+++ b/promise/src/main/java/promise/data/net/extras/JsonAdapter.java
@@ -21,9 +21,6 @@
import java.lang.reflect.Type;
import java.util.Map;
-import promise.data.net.extras.CallAdapter;
-import promise.data.utils.Converter;
-
/**
* Created on 6/16/18 by yoctopus.
*/
diff --git a/promise/src/main/java/promise/data/net/extras/JsonArrayAdapter.java b/promise/src/main/java/promise/data/net/extras/JsonArrayAdapter.java
index fd1ff34..b964b08 100644
--- a/promise/src/main/java/promise/data/net/extras/JsonArrayAdapter.java
+++ b/promise/src/main/java/promise/data/net/extras/JsonArrayAdapter.java
@@ -21,7 +21,6 @@
import java.lang.reflect.Type;
import promise.data.log.LogUtil;
-import promise.data.utils.Converter;
import promise.model.List;
/**
diff --git a/promise/src/main/java/promise/data/pref/PreferenceStorage.java b/promise/src/main/java/promise/data/pref/PreferenceStorage.java
index d2de28b..7890294 100644
--- a/promise/src/main/java/promise/data/pref/PreferenceStorage.java
+++ b/promise/src/main/java/promise/data/pref/PreferenceStorage.java
@@ -7,10 +7,8 @@
import java.util.Map;
import kotlin.Pair;
-import promise.data.utils.Converter;
import promise.model.List;
import promise.model.S;
-import promise.model.function.EachFunction;
import promise.repo.SyncIDataStore;
/**
diff --git a/promise/src/main/java/promise/data/pref/PreferenceStore.kt b/promise/src/main/java/promise/data/pref/PreferenceStore.kt
index 858cdfc..27749f0 100644
--- a/promise/src/main/java/promise/data/pref/PreferenceStore.kt
+++ b/promise/src/main/java/promise/data/pref/PreferenceStore.kt
@@ -8,7 +8,6 @@ import org.json.JSONObject
import promise.data.Extras
import promise.data.Store
-import promise.data.utils.Converter
import promise.model.List
import promise.model.ResponseCallBack
import promise.model.function.EachFunction
diff --git a/promisecommons/build.gradle b/promisecommons/build.gradle
index c28dc86..9d47c11 100644
--- a/promisecommons/build.gradle
+++ b/promisecommons/build.gradle
@@ -31,8 +31,8 @@ android {
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
- api 'io.reactivex.rxjava2:rxjava:2.2.7'
- api 'androidx.appcompat:appcompat:1.0.2'
+ compileOnly 'io.reactivex.rxjava2:rxjava:2.2.7'
+ compileOnly 'androidx.appcompat:appcompat:1.0.2'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.2.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
diff --git a/promisecommons/src/main/java/promise/Promise.java b/promisecommons/src/main/java/promise/Promise.java
index 9779129..c089f33 100644
--- a/promisecommons/src/main/java/promise/Promise.java
+++ b/promisecommons/src/main/java/promise/Promise.java
@@ -198,7 +198,7 @@ public void execute(
observer.onError(e);
}
}),
- List.Companion::fromArray)
+ List::fromArray)
.observeOn(Schedulers.from(executor))
.subscribeOn(Schedulers.from(executor))
.subscribe(
diff --git a/promise/src/main/java/promise/data/utils/Converter.java b/promisecommons/src/main/java/promise/file/Config.java
similarity index 71%
rename from promise/src/main/java/promise/data/utils/Converter.java
rename to promisecommons/src/main/java/promise/file/Config.java
index 8a9abc8..e63bc07 100644
--- a/promise/src/main/java/promise/data/utils/Converter.java
+++ b/promisecommons/src/main/java/promise/file/Config.java
@@ -13,11 +13,19 @@
*
*/
-package promise.data.utils;
+package promise.file;
+/**
+ * Created by yoctopus on 9/8/17.
+ */
-import promise.model.function.MapFunction;
+public class Config {
+ private String mainDir;
-public interface Converter extends MapFunction {
- X get(T t);
+ public Config(String mainDir) {
+ this.mainDir = mainDir;
+ }
+ public Config add(String name) {
+ return this;
+ }
}
diff --git a/promisecommons/src/main/java/promise/file/Dir.java b/promisecommons/src/main/java/promise/file/Dir.java
new file mode 100644
index 0000000..45c248a
--- /dev/null
+++ b/promisecommons/src/main/java/promise/file/Dir.java
@@ -0,0 +1,146 @@
+/*
+ *
+ * * Copyright 2017, Peter Vincent
+ * * Licensed under the Apache License, Version 2.0, Promise.
+ * * you may not use this file except in compliance with the License.
+ * * You may obtain a copy of the License at
+ * * http://www.apache.org/licenses/LICENSE-2.0
+ * * Unless required by applicable law or agreed to in writing,
+ * * software distributed under the License is distributed on an "AS IS" BASIS,
+ * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * * See the License for the specific language governing permissions and
+ * * limitations under the License.
+ *
+ */
+
+package promise.file;
+
+import android.content.Context;
+import android.os.Environment;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import promise.data.log.LogUtil;
+
+public class Dir {
+
+ private static String TAG = LogUtil.makeTag(Dir.class);
+
+ private String name;
+
+ public String getName() {
+ return name;
+ }
+
+ private void setName(String name) {
+ this.name = name;
+ }
+
+ public static String getState() {
+ return Environment.getExternalStorageState();
+ }
+
+ public static boolean isWritable() {
+ return Environment.MEDIA_MOUNTED.equals(getState());
+ }
+
+ public Dir(String name) {
+ map(name);
+ }
+
+ public void map(String... dirs) {
+ String path = Environment.getExternalStorageDirectory().toString();
+ for (String dir: dirs) {
+ setName(path + File.separator + dir);
+ if (make(getName())) setName(getName());
+ }
+ }
+
+ public static boolean make(String path) {
+ File file = new File(path);
+ if (!file.exists()) return file.mkdirs();
+ return true;
+ }
+
+ public String path(String name) {
+ return getName() + File.separator + name;
+ }
+
+ public static void clearAppData(Context context) {
+ try {
+ String packageName = context.getApplicationContext().getPackageName();
+ Runtime runtime = Runtime.getRuntime();
+ runtime.exec("pm clear "+packageName);
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public static File getFile(String path, String fileName) {
+ return new File(path + File.separator + fileName);
+ }
+
+ public static void move(String inputPath, String inputFile, String outputPath) {
+ copy(inputPath, inputFile, outputPath);
+ delete(inputPath, inputFile);
+ }
+
+ public static void delete(String inputPath, String inputFile) {
+ try {
+ new File(inputPath + File.separator + inputFile).delete();
+ }
+ catch (Exception e) {
+ LogUtil.e(TAG, e.getMessage());
+ }
+ }
+
+ public static void copy(String inputPath, String inputFile, String outputPath) {
+ InputStream in;
+ OutputStream out;
+ try {
+ LogUtil.e(TAG, "origin", inputPath + File.separator + inputFile);
+ in = new FileInputStream(inputPath + File.separator + inputFile);
+ out = new FileOutputStream(new Dir(outputPath).getName() + File.separator + inputFile);
+ byte[] buffer = new byte[1024];
+ int read;
+ while ((read = in.read(buffer)) != -1) out.write(buffer, 0, read);
+ in.close();
+ // write the output file
+ out.flush();
+ out.close();
+ LogUtil.e(TAG, "destination", outputPath + File.separator + inputFile);
+ }
+ catch (FileNotFoundException fnfe1) { LogUtil.e(TAG, fnfe1.getMessage()); }
+ catch (Exception e) { LogUtil.e(TAG, e.getMessage()); }
+ }
+
+ public static File save(InputStream in, File file) {
+ try {
+ BufferedInputStream input = new BufferedInputStream(in);
+ OutputStream output = new FileOutputStream(file);
+
+ byte[] data = new byte[1024];
+
+ long total = 0;
+ int count;
+
+ while ((count = input.read(data)) != -1) {
+ total += count;
+ output.write(data, 0, count);
+ }
+
+ output.flush();
+ output.close();
+ input.close();
+ }
+ catch (Exception e) { LogUtil.e(TAG, e.getMessage()); }
+ return file;
+ }
+}
diff --git a/promisecommons/src/main/java/promise/file/Ext.java b/promisecommons/src/main/java/promise/file/Ext.java
new file mode 100644
index 0000000..3901aeb
--- /dev/null
+++ b/promisecommons/src/main/java/promise/file/Ext.java
@@ -0,0 +1,41 @@
+/*
+ *
+ * * Copyright 2017, Peter Vincent
+ * * Licensed under the Apache License, Version 2.0, Promise.
+ * * you may not use this file except in compliance with the License.
+ * * You may obtain a copy of the License at
+ * * http://www.apache.org/licenses/LICENSE-2.0
+ * * Unless required by applicable law or agreed to in writing,
+ * * software distributed under the License is distributed on an "AS IS" BASIS,
+ * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * * See the License for the specific language governing permissions and
+ * * limitations under the License.
+ *
+ */
+
+package promise.file;
+
+/**
+ * Created by octopus on 10/4/16.
+ */
+public enum Ext {
+ CSV(".csv"),
+ XLS(".xls"),
+ PDF(".pdf"),
+ JPEG(".jpg"),
+ PNG(".png");
+ public static final String CS = ".csv";
+ public static final String XL = ".xls";
+ public static final String PD = ".pdf";
+ public static final String JP = ".jpg";
+ public static final String PN = ".png";
+
+ private String extension;
+
+ public String getExtension() {
+ return extension;
+ }
+ private Ext(String extension) {
+ this.extension = extension;
+ }
+}
diff --git a/promisecommons/src/main/java/promise/file/FManager.java b/promisecommons/src/main/java/promise/file/FManager.java
new file mode 100644
index 0000000..4cbde5a
--- /dev/null
+++ b/promisecommons/src/main/java/promise/file/FManager.java
@@ -0,0 +1,192 @@
+/*
+ *
+ * * Copyright 2017, Peter Vincent
+ * * Licensed under the Apache License, Version 2.0, Promise.
+ * * you may not use this file except in compliance with the License.
+ * * You may obtain a copy of the License at
+ * * http://www.apache.org/licenses/LICENSE-2.0
+ * * Unless required by applicable law or agreed to in writing,
+ * * software distributed under the License is distributed on an "AS IS" BASIS,
+ * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * * See the License for the specific language governing permissions and
+ * * limitations under the License.
+ *
+ */
+
+package promise.file;
+
+import android.content.Context;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import promise.data.log.LogUtil;
+
+
+public class FManager {
+ private String TAG = LogUtil.makeTag(FManager.class);
+ private FileOperations fileOperations;
+ private File source,
+ destination;
+ private Dir dir;
+ private Context context;
+
+ public FManager(Context context) {
+ this.context = context;
+ }
+ public List importFiles(Dir dir) throws NoFilesFound {
+ ArrayList files =
+ new ArrayList<>();
+ File folder = new File(dir.getName());
+ if (folder.isDirectory()) {
+ File[] lists = folder.listFiles();
+ if (lists == null || lists.length == 0) {
+ throw new NoFilesFound();
+ }
+ for (File file : lists) {
+ if (file.isDirectory()) {
+ files.addAll(Arrays.asList(file.listFiles()));
+ }
+ if (file.isFile()) {
+ files.add(file);
+ }
+ }
+ } else {
+ throw new NoFilesFound();
+ }
+ return files;
+ }
+ public boolean delete(String fileName) {
+ File file = new File(fileName);
+ return file.delete();
+ }
+ public boolean delete(File file) {
+ if (file.exists()) {
+ file.delete();
+ return true;
+ }
+ return false;
+ }
+ public boolean deleteAll(Dir dir) {
+ File file = new File(dir.getName());
+ if (file.isDirectory()) {
+ for (File file1 : file.listFiles()) file1.delete();
+ }
+ return true;
+ }
+ public boolean copy(File source, File destination) {
+ this.source = source;
+ fileOperations = new FileOperations(source, destination);
+ this.destination = fileOperations.getDestination();
+ return fileOperations.copy();
+ }
+ public boolean rename(File file, String name) {
+ FUri fUri = new FUri(dir, name);
+ File file1 = new File(fUri.getUri().toString());
+ fileOperations = new FileOperations(file, file1);
+ if (fileOperations.copy()) {
+ file.delete();
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+
+ public File getSource() {
+ return source;
+ }
+
+ public void setSource(File source) {
+ this.source = source;
+ }
+
+ public File getDestination() {
+ return destination;
+ }
+
+
+
+ public Dir getDir() {
+ return dir;
+ }
+
+ public void setDir(Dir dir) {
+ this.dir = dir;
+ }
+
+ public Context getContext() {
+ return context;
+ }
+
+ public void setContext(Context context) {
+ this.context = context;
+ }
+
+
+ private static class FileOperations {
+ private String TAG = LogUtil.makeTag(FileOperations.class);
+ private File source,
+ destination;
+ private Dir dir;
+
+ FileOperations(File source,
+ File destination) {
+ this.source = source;
+ this.destination = destination;
+ }
+
+
+
+ protected boolean copy() {
+ if (destination.exists()) {
+ try {
+ InputStream in = new FileInputStream(source);
+ OutputStream out = new FileOutputStream(destination);
+ byte[] buffer = new byte[1024];
+ int read;
+ while ((read = in.read(buffer)) > 0) {
+ out.write(buffer, 0, read);
+ }
+ out.flush();
+ in.close();
+ out.close();
+ return true;
+ } catch (IOException e) {
+ e.printStackTrace();
+ return false;
+ }
+ }
+ return true;
+ }
+
+ protected Dir getDir() {
+ return dir;
+ }
+
+ protected void setDir(Dir dir) {
+ this.dir = dir;
+ }
+
+ protected File getSource() {
+ return source;
+ }
+
+ protected void setSource(File source) {
+ this.source = source;
+ }
+
+ protected File getDestination() {
+ return destination;
+ }
+
+
+ }
+}
diff --git a/promisecommons/src/main/java/promise/file/FUri.java b/promisecommons/src/main/java/promise/file/FUri.java
new file mode 100644
index 0000000..3fe15e0
--- /dev/null
+++ b/promisecommons/src/main/java/promise/file/FUri.java
@@ -0,0 +1,98 @@
+/*
+ *
+ * * Copyright 2017, Peter Vincent
+ * * Licensed under the Apache License, Version 2.0, Promise.
+ * * you may not use this file except in compliance with the License.
+ * * You may obtain a copy of the License at
+ * * http://www.apache.org/licenses/LICENSE-2.0
+ * * Unless required by applicable law or agreed to in writing,
+ * * software distributed under the License is distributed on an "AS IS" BASIS,
+ * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * * See the License for the specific language governing permissions and
+ * * limitations under the License.
+ *
+ */
+
+package promise.file;
+
+
+import android.net.Uri;
+
+import java.io.File;
+import java.io.IOException;
+
+public class FUri {
+ private Dir dir;
+ private String fileName;
+ private Ext ext;
+ private String startString;
+
+ public FUri(Dir dir,
+ String fileName) {
+ this.setDir(dir);
+ this.setFileName(fileName);
+ }
+
+
+ public FUri(Dir dir) {
+ this(dir,
+ null);
+ }
+
+
+
+ public void setStartString(String startString) {
+ this.startString = startString;
+ }
+
+ public Ext getExt() {
+ return ext;
+ }
+
+ public void setExt(Ext ext) {
+ this.ext = ext;
+ }
+
+ public Dir getDir() {
+ return dir;
+ }
+
+ public void setDir(Dir dir) {
+ this.dir = dir;
+ }
+
+ public String getFileName() {
+ return fileName;
+ }
+
+ public void setFileName(String fileName) {
+ this.fileName = fileName;
+ }
+
+ public Uri getUri() {
+ String name = "";
+ if (startString != null &&
+ !startString.isEmpty()) {
+ name = startString;
+ }
+ File file = new File(name +
+ getDir().getName() +
+ File.separator +
+ getFileName() +
+ getExt().getExtension());
+ if (!file.exists()) {
+ try {
+ file.createNewFile();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ return Uri.parse(
+ file.getAbsolutePath());
+ }
+
+ @Override
+ public String toString() {
+ return getUri().toString();
+ }
+}
diff --git a/promisedb/src/main/java/promise/promisedb/ExpandedModel.java b/promisecommons/src/main/java/promise/file/NoFilesFound.java
similarity index 78%
rename from promisedb/src/main/java/promise/promisedb/ExpandedModel.java
rename to promisecommons/src/main/java/promise/file/NoFilesFound.java
index f552904..c131547 100644
--- a/promisedb/src/main/java/promise/promisedb/ExpandedModel.java
+++ b/promisecommons/src/main/java/promise/file/NoFilesFound.java
@@ -13,11 +13,14 @@
*
*/
-package promise.promisedb;
+package promise.file;
/**
- * Created by yoctopus on 9/27/17.
+ * Created by octopus on 10/2/16.
*/
+public class NoFilesFound extends Exception {
-public class ExpandedModel {
+ public NoFilesFound() {
+ super("No files found");
+ }
}
diff --git a/promisedb/src/main/java/promise/model/S.java b/promisecommons/src/main/java/promise/model/S.java
similarity index 100%
rename from promisedb/src/main/java/promise/model/S.java
rename to promisecommons/src/main/java/promise/model/S.java
diff --git a/promisecommons/src/main/java/promise/pref/InvalidPref.java b/promisecommons/src/main/java/promise/pref/InvalidPref.java
new file mode 100644
index 0000000..d78ec7e
--- /dev/null
+++ b/promisecommons/src/main/java/promise/pref/InvalidPref.java
@@ -0,0 +1,30 @@
+/*
+ *
+ * * Copyright 2017, Peter Vincent
+ * * Licensed under the Apache License, Version 2.0, Promise.
+ * * you may not use this file except in compliance with the License.
+ * * You may obtain a copy of the License at
+ * * http://www.apache.org/licenses/LICENSE-2.0
+ * * Unless required by applicable law or agreed to in writing,
+ * * software distributed under the License is distributed on an "AS IS" BASIS,
+ * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * * See the License for the specific language governing permissions and
+ * * limitations under the License.
+ *
+ */
+
+package promise.pref;
+
+/**
+ *
+ */
+class InvalidPref extends Exception {
+ /**
+ *
+ * @param preference
+ */
+ InvalidPref(Preferences.Pref preference) {
+ super("Invalid preference name " + preference.getName() + " data " + preference.get());
+ }
+
+}
diff --git a/promisecommons/src/main/java/promise/pref/InvalidPrefType.java b/promisecommons/src/main/java/promise/pref/InvalidPrefType.java
new file mode 100644
index 0000000..a34a32a
--- /dev/null
+++ b/promisecommons/src/main/java/promise/pref/InvalidPrefType.java
@@ -0,0 +1,37 @@
+/*
+ *
+ * * Copyright 2017, Peter Vincent
+ * * Licensed under the Apache License, Version 2.0, Promise.
+ * * you may not use this file except in compliance with the License.
+ * * You may obtain a copy of the License at
+ * * http://www.apache.org/licenses/LICENSE-2.0
+ * * Unless required by applicable law or agreed to in writing,
+ * * software distributed under the License is distributed on an "AS IS" BASIS,
+ * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * * See the License for the specific language governing permissions and
+ * * limitations under the License.
+ *
+ */
+
+package promise.pref;
+
+/**
+ *
+ */
+public class InvalidPrefType extends Exception {
+ /**
+ *
+ * @param message
+ */
+ InvalidPrefType(String message) {
+ super(message);
+ }
+
+ /**
+ *
+ * @param object
+ */
+ InvalidPrefType(Object object) {
+ super(object.getClass().getSimpleName() + "type is invalid in preferences");
+ }
+}
diff --git a/promisecommons/src/main/java/promise/pref/Preferences.java b/promisecommons/src/main/java/promise/pref/Preferences.java
new file mode 100644
index 0000000..80bfeb1
--- /dev/null
+++ b/promisecommons/src/main/java/promise/pref/Preferences.java
@@ -0,0 +1,497 @@
+/*
+ *
+ * * Copyright 2017, Peter Vincent
+ * * Licensed under the Apache License, Version 2.0, Promise.
+ * * you may not use this file except in compliance with the License.
+ * * You may obtain a copy of the License at
+ * * http://www.apache.org/licenses/LICENSE-2.0
+ * * Unless required by applicable law or agreed to in writing,
+ * * software distributed under the License is distributed on an "AS IS" BASIS,
+ * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * * See the License for the specific language governing permissions and
+ * * limitations under the License.
+ *
+ */
+
+package promise.pref;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.preference.PreferenceManager;
+import android.text.TextUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import promise.Promise;
+import promise.data.log.LogUtil;
+
+/**
+ *
+ */
+public class Preferences {
+ /**
+ *
+ */
+ private String EMPTY_STRING = "";
+ /**
+ *
+ */
+ private boolean EMPTY_BOOLEAN = false;
+ /**
+ *
+ */
+ private long EMPTY_LONG = 0;
+ /**
+ *
+ */
+ private int EMPTY_INT = 0;
+ /**
+ *
+ */
+ private double EMPTY_DOUBLE = 0;
+ /**
+ *
+ */
+ private SharedPreferences preferences;
+ private static final String TAG = LogUtil.makeTag(Preferences.class);
+
+ /**
+ *
+ */
+ public Preferences() {
+ preferences = PreferenceManager
+ .getDefaultSharedPreferences(Promise.instance().context());
+ }
+
+ /**
+ *
+ * @param name
+ */
+ public Preferences(String name) {
+ preferences = Promise.instance().context().getSharedPreferences(name, Context.MODE_PRIVATE);
+
+ }
+
+ /**
+ *
+ * @param preferenceChange
+ * @return
+ */
+ public Preferences preferenceChange(final PreferenceChange preferenceChange) {
+ preferences.registerOnSharedPreferenceChangeListener(
+ (sharedPreferences, key) -> {
+ if (preferenceChange != null) {
+ preferenceChange.onChange(sharedPreferences, key);
+ }
+ });
+ return this;
+ }
+
+ /**
+ *
+ * @return
+ */
+ public Map getAll() {
+ return preferences.getAll();
+ }
+
+ /**
+ *
+ * @param key
+ * @return
+ */
+ public String getString(String key) {
+ Pref pref = new Pref<>(key, EMPTY_STRING);
+ try {
+ return getPreference(pref);
+ } catch (InvalidPrefType invalidPrefType) {
+ invalidPrefType.printStackTrace();
+ LogUtil.e(TAG, invalidPrefType);
+ }
+ return EMPTY_STRING;
+ }
+
+ /**
+ *
+ * @param key
+ * @return
+ */
+ public boolean getBoolean(String key) {
+ Pref pref = new Pref<>(key, EMPTY_BOOLEAN);
+ try {
+ return getPreference(pref);
+ } catch (InvalidPrefType invalidPrefType) {
+ invalidPrefType.printStackTrace();
+ LogUtil.e(TAG, invalidPrefType);
+ }
+ return EMPTY_BOOLEAN;
+ }
+
+ /**
+ *
+ * @param key
+ * @return
+ */
+ public long getLong(String key) {
+ Pref pref = new Pref<>(key, EMPTY_LONG);
+ try {
+ return getPreference(pref);
+ } catch (InvalidPrefType invalidPrefType) {
+ invalidPrefType.printStackTrace();
+ LogUtil.e(TAG, invalidPrefType);
+ }
+ return EMPTY_LONG;
+ }
+
+ /**
+ *
+ * @param key
+ * @return
+ */
+ public int getInt(String key) {
+ Pref pref = new Pref<>(key, EMPTY_INT);
+ try {
+ return getPreference(pref);
+ } catch (InvalidPrefType invalidPrefType) {
+ invalidPrefType.printStackTrace();
+ LogUtil.e(TAG, invalidPrefType);
+ }
+ return EMPTY_INT;
+ }
+
+ /**
+ *
+ * @param key
+ * @return
+ */
+ public double getDouble(String key) {
+ Pref pref = new Pref<>(key, EMPTY_DOUBLE);
+ try {
+ return getPreference(pref);
+ } catch (InvalidPrefType invalidPrefType) {
+ invalidPrefType.printStackTrace();
+ LogUtil.e(TAG, invalidPrefType);
+ }
+ return EMPTY_DOUBLE;
+ }
+
+ /**
+ *
+ * @param key
+ * @param param
+ * @return
+ */
+ public boolean save(String key, String param) {
+ if (TextUtils.isEmpty(param)) param = EMPTY_STRING;
+ Pref pref = new Pref<>(key, param);
+ try {
+ savePreference(pref);
+ return true;
+ } catch (InvalidPref invalidPref) {
+ invalidPref.printStackTrace();
+ LogUtil.e(TAG, invalidPref);
+ return false;
+ }
+ }
+
+ /**
+ *
+ * @param key
+ * @param param
+ * @return
+ */
+ public boolean save(String key, boolean param) {
+ Pref pref = new Pref<>(key, param);
+ try {
+ savePreference(pref);
+ return true;
+ } catch (InvalidPref invalidPref) {
+ invalidPref.printStackTrace();
+ LogUtil.e(TAG, invalidPref);
+ return false;
+ }
+ }
+
+ /**
+ *
+ * @param key
+ * @param param
+ * @return
+ */
+ public boolean save(String key, long param) {
+ Pref pref = new Pref<>(key, param);
+ try {
+ savePreference(pref);
+ return true;
+ } catch (InvalidPref invalidPref) {
+ invalidPref.printStackTrace();
+ LogUtil.e(TAG, invalidPref);
+ return false;
+ }
+ }
+
+ /**
+ *
+ * @param key
+ * @param param
+ * @return
+ */
+ public boolean save(String key, int param) {
+ Pref pref = new Pref<>(key, param);
+ try {
+ savePreference(pref);
+ return true;
+ } catch (InvalidPref invalidPref) {
+ invalidPref.printStackTrace();
+ LogUtil.e(TAG, invalidPref);
+ return false;
+ }
+ }
+
+ /**
+ *
+ * @param key
+ * @param param
+ * @return
+ */
+ public boolean save(String key, double param) {
+ Pref pref = new Pref<>(key, param);
+ try {
+ savePreference(pref);
+ return true;
+ } catch (InvalidPref invalidPref) {
+ invalidPref.printStackTrace();
+ LogUtil.e(TAG, invalidPref);
+ return false;
+ }
+ }
+
+ /**
+ *
+ * @param params
+ * @return
+ */
+ public boolean save(Map params) {
+ List> prefs = new ArrayList<>();
+ for (Map.Entry entry : params.entrySet())
+ prefs.add(new Pref<>(entry.getKey(), entry.getValue()));
+ try {
+ savePreference(prefs.toArray(new Pref[prefs.size()]));
+ return true;
+ } catch (InvalidPref invalidPref) {
+ LogUtil.e(TAG, invalidPref);
+ return false;
+ }
+ }
+
+ /**
+ *
+ * @param pref
+ * @throws InvalidPref
+ */
+ private void savePreference(Pref pref) throws InvalidPref {
+ SharedPreferences.Editor editor = preferences.edit();
+ if (pref.get() instanceof String) editor.putString(pref.getName(), (String) pref.get());
+ else if (pref.get() instanceof Integer) editor.putInt(pref.getName(), (Integer) pref.get());
+ else if (pref.get() instanceof Boolean)
+ editor.putBoolean(pref.getName(), (Boolean) pref.get());
+ else if (pref.get() instanceof Long) editor.putLong(pref.getName(), (Long) pref.get());
+ else if (pref.get() instanceof Float) editor.putFloat(pref.getName(), (Float) pref.get());
+ else throw new InvalidPref(pref);
+ editor.apply();
+ }
+
+ /**
+ *
+ * @param prefs
+ * @throws InvalidPref
+ */
+ private void savePreference(Pref... prefs) throws InvalidPref {
+ SharedPreferences.Editor editor = preferences.edit();
+ for (Pref pref : prefs) {
+ if (pref.get() instanceof String) editor.putString(pref.getName(), (String) pref.get());
+ else if (pref.get() instanceof Integer)
+ editor.putInt(pref.getName(), (Integer) pref.get());
+ else if (pref.get() instanceof Boolean)
+ editor.putBoolean(pref.getName(), (Boolean) pref.get());
+ else if (pref.get() instanceof Long) editor.putLong(pref.getName(), (Long) pref.get());
+ else if (pref.get() instanceof Float)
+ editor.putFloat(pref.getName(), (Float) pref.get());
+ else throw new InvalidPref(pref);
+ }
+ editor.apply();
+ }
+
+ /**
+ *
+ */
+ public void clearAll() {
+ preferences.edit().clear().apply();
+ }
+
+ /**
+ *
+ * @param key
+ */
+ public void clear(String key) {
+ preferences.edit().remove(key).apply();
+ }
+
+ /**
+ *
+ * @param pref
+ * @param
+ * @return
+ * @throws InvalidPrefType
+ */
+ private T getPreference(Pref pref) throws InvalidPrefType {
+ Object data;
+ if (pref.get() instanceof String) data = preferences.getString(pref.getName(),
+ (String) pref.get());
+ else if (pref.get() instanceof Integer) data = preferences.getInt(pref.getName(),
+ (Integer) pref.get());
+ else if (pref.get() instanceof Boolean) data = preferences.getBoolean(pref.getName(),
+ (Boolean) pref.get());
+ else if (pref.get() instanceof Long) data = preferences.getLong(pref.getName(),
+ (Long) pref.get());
+ else if (pref.get() instanceof Float) data = preferences.getFloat(pref.getName(),
+ (Float) pref.get());
+ else throw new InvalidPrefType(pref.get());
+ return (T) data;
+ }
+
+ /**
+ *
+ */
+ public interface PreferenceChange {
+ /**
+ *
+ * @param preferences
+ * @param key
+ */
+ void onChange(SharedPreferences preferences, String key);
+ }
+
+ /**
+ *
+ * @param
+ */
+ public static class Pref {
+ /**
+ *
+ */
+ private String name;
+ /**
+ *
+ */
+ private T data;
+
+ /**
+ *
+ * @param key
+ * @param data
+ */
+ Pref(String key, T data) {
+ this.name = key;
+ this.data = data;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public T get() {
+ return data;
+ }
+
+ public void set(T data) {
+ this.data = data;
+ }
+ }
+
+ /**
+ *
+ */
+ public static class Builder {
+ /**
+ *
+ */
+ private String EMPTY_STRING = "";
+ /**
+ *
+ */
+ private boolean EMPTY_BOOLEAN = false;
+ /**
+ *
+ */
+ private long EMPTY_LONG = 0;
+ /**
+ *
+ */
+ private int EMPTY_INT = 0;
+ /**
+ *
+ */
+ private double EMPTY_DOUBLE = 0;
+
+ public Builder EMPTY_STRING(String EMPTY_STRING) {
+ this.EMPTY_STRING = EMPTY_STRING;
+ return this;
+ }
+
+ public Builder EMPTY_BOOLEAN(boolean EMPTY_BOOLEAN) {
+ this.EMPTY_BOOLEAN = EMPTY_BOOLEAN;
+ return this;
+ }
+
+ public Builder EMPTY_LONG(long EMPTY_LONG) {
+ this.EMPTY_LONG = EMPTY_LONG;
+ return this;
+ }
+
+ public Builder EMPTY_INT(int EMPTY_INT) {
+ this.EMPTY_INT = EMPTY_INT;
+ return this;
+ }
+
+ public Builder EMPTY_DOUBLE(double EMPTY_DOUBLE) {
+ this.EMPTY_DOUBLE = EMPTY_DOUBLE;
+ return this;
+ }
+
+ /**
+ *
+ * @return
+ */
+ public Preferences build() {
+ Preferences preferences = new Preferences();
+ preferences.EMPTY_BOOLEAN = EMPTY_BOOLEAN;
+ preferences.EMPTY_STRING = EMPTY_STRING;
+ preferences.EMPTY_DOUBLE = EMPTY_DOUBLE;
+ preferences.EMPTY_INT = EMPTY_INT;
+ preferences.EMPTY_LONG = EMPTY_LONG;
+ return preferences;
+ }
+
+ /**
+ *
+ * @param name
+ * @return
+ */
+ public Preferences build(String name) {
+ Preferences preferences = new Preferences(name);
+ preferences.EMPTY_BOOLEAN = EMPTY_BOOLEAN;
+ preferences.EMPTY_STRING = EMPTY_STRING;
+ preferences.EMPTY_DOUBLE = EMPTY_DOUBLE;
+ preferences.EMPTY_INT = EMPTY_INT;
+ preferences.EMPTY_LONG = EMPTY_LONG;
+ return preferences;
+ }
+ }
+}
diff --git a/promisecommons/src/main/java/promise/util/ArrayUtil.java b/promisecommons/src/main/java/promise/util/ArrayUtil.java
deleted file mode 100644
index 0fb993a..0000000
--- a/promisecommons/src/main/java/promise/util/ArrayUtil.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2017, Solutech RMS
- * Licensed under the Apache License, Version 2.0, "Solutech Limited".
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * http://www.apache.org/licenses/LICENSE-2.0
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package promise.util;
-
-import promise.model.Category;
-import promise.model.List;
-
-/**
- * Created on 6/8/18 by yoctopus.
- */
-public class ArrayUtil {
- public static List> classify(List list, int chunks) {
- return list.sorted((o1, o2) -> o1 > o2 ? 1 : o1 < o2 ? -1 : 0).groupBy(aDouble -> aDouble);
- }
-
- public static int sum(List items) {
- int sum = 0;
- for (int item: items) sum += item;
- return sum;
- }
-
- public static int sum(Integer... items) {
- return sum(List.Companion.fromArray(items));
- }
-
- public static double average(List items) {
- if (items.isEmpty()) return 0;
- return sum(items) / items.size();
- }
-
- public static double average(Integer... items) {
- return average(List.Companion.fromArray(items));
- }
-}
diff --git a/promisecommons/src/main/java/promise/util/ClassUtil.java b/promisecommons/src/main/java/promise/util/ClassUtil.java
index f9ccc26..99ab6c7 100644
--- a/promisecommons/src/main/java/promise/util/ClassUtil.java
+++ b/promisecommons/src/main/java/promise/util/ClassUtil.java
@@ -15,7 +15,6 @@
package promise.util;
-import com.google.gson.Gson;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
@@ -26,11 +25,6 @@
public class ClassUtil {
- public static T makeCopy(T t, Class tClass) {
- Gson gson = new Gson();
- return gson.fromJson(gson.toJson(t), tClass);
- }
-
public static int getIntFieldIfExists(Class> klass,
String fieldName,
Class> obj,
diff --git a/promisecommons/src/main/java/promise/util/DoubleConverter.java b/promisecommons/src/main/java/promise/util/DoubleConverter.java
index 64463b4..429fc99 100644
--- a/promisecommons/src/main/java/promise/util/DoubleConverter.java
+++ b/promisecommons/src/main/java/promise/util/DoubleConverter.java
@@ -15,9 +15,24 @@
package promise.util;
+/**
+ * The double converter converts a class instance to and from another form
+ * @param the type instance to be converted
+ * @param type to get the instance from during de-serializing
+ * @param type returned after serializing the instance
+ */
+public interface DoubleConverter {
+ /*
+ * deserialize back the instance from the serializes form
+ * @param e serialized form
+ * @return back the instance
+ */
+ T deserialize(E e);
-import promise.model.function.MapFunction;
-
-public interface DoubleConverter extends MapFunction {
- X to(T t);
+ /*
+ * serializes the instance to another form
+ * @param t the instance to be serialized
+ * @return the serialized form of t
+ */
+ X serialize(T t);
}
diff --git a/promisecommons/src/main/java/promise/util/Scheduler.java b/promisecommons/src/main/java/promise/util/Scheduler.java
deleted file mode 100644
index af223c0..0000000
--- a/promisecommons/src/main/java/promise/util/Scheduler.java
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- *
- * * Copyright 2017, Peter Vincent
- * * Licensed under the Apache License, Version 2.0, Promise.
- * * you may not use this file except in compliance with the License.
- * * You may obtain a copy of the License at
- * * http://www.apache.org/licenses/LICENSE-2.0
- * * Unless required by applicable law or agreed to in writing,
- * * software distributed under the License is distributed on an "AS IS" BASIS,
- * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * * See the License for the specific language governing permissions and
- * * limitations under the License.
- *
- */
-
-package promise.util;
-
-import android.annotation.SuppressLint;
-import android.annotation.TargetApi;
-import android.app.AlarmManager;
-import android.app.PendingIntent;
-import android.app.job.JobInfo;
-import android.app.job.JobParameters;
-import android.app.job.JobService;
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Build;
-
-import java.util.Calendar;
-
-
-public abstract class Scheduler {
- public static final String MESSAGE_TITLE = "Message";
- public static final int INTERVAL_DAY = 1;
- public static final int INTERVAL_WEEK = 2;
- private Context context;
- private Class extends BroadcastReceiver> receiver;
-
- public Scheduler(Context context,
- Class extends BroadcastReceiver> receiver) {
- this.context = context;
- this.receiver = receiver;
- }
-
- public abstract Params params();
-
- public void schedule() {
- Params params = params();
- saveSchedule(params);
- }
-
- @SuppressLint("ShortAlarm")
- private void saveSchedule(Params params) {
- AlarmManager manager = (AlarmManager)
- context.getSystemService(
- Context.ALARM_SERVICE);
- Intent intent = new Intent(
- context.getApplicationContext(),
- receiver);
- if (params.intent_action != null) intent.setAction(params.intent_action);
- if (params.intent_message != null) intent.putExtra(MESSAGE_TITLE,
- params.intent_message);
- PendingIntent pendingIntent =
- PendingIntent.getBroadcast(
- context.getApplicationContext(),
- 0,
- intent,
- 0);
- Calendar calendar = params.calendar;
- if (params.repeating) {
- long myInterval =
- 0;
- switch (params.interval) {
- case INTERVAL_DAY: {
- myInterval = AlarmManager.INTERVAL_DAY;
- break;
- }
- case INTERVAL_WEEK: {
- for (int i = 0;
- i < 7;
- i++) {
- myInterval += AlarmManager.INTERVAL_DAY;
- }
- }
- }
- manager.setRepeating(
- AlarmManager.RTC_WAKEUP,
- calendar.getTimeInMillis(),
- myInterval,
- pendingIntent);
- } else manager.set(
- AlarmManager.RTC_WAKEUP,
- calendar.getTimeInMillis(),
- pendingIntent);
- }
-
- private void scheduleUsingJobScheduler(Params params) {
- ComponentName name = new ComponentName(
- context.getApplicationContext(),
- receiver);
- LollipopScheduler scheduler =
- new LollipopScheduler(params,
- name);
- scheduler.schedule();
-
- }
-
- @TargetApi(Build.VERSION_CODES.LOLLIPOP)
- public class LollipopScheduler extends JobService {
- private JobInfo.Builder builder;
- private int id = 0;
- private Calendar calendar;
- private Params params;
-
- public LollipopScheduler(Params params,
- ComponentName name) {
- builder = new JobInfo.Builder(id,
- name);
- builder.setPeriodic(params.interval);
- builder.setPersisted(params.repeating);
- this.calendar = params.calendar;
-
- }
-
- public void schedule() {
- builder.build();
- }
-
- @Override
- public boolean onStartJob(JobParameters jobParameters) {
- return false;
- }
-
- @Override
- public boolean onStopJob(JobParameters jobParameters) {
- return true;
- }
- }
-
- public class Params {
- private String intent_action;
- private String intent_message;
- private boolean repeating = false;
- private int interval = 0;
- private Calendar calendar;
-
- public Params(String intent_action,
- String intent_message,
- Calendar calendar) {
- this.intent_action = intent_action;
- this.intent_message = intent_message;
- this.calendar = calendar;
- }
-
- public void setRepeating(boolean repeating) {
- this.repeating = repeating;
- }
-
- public void setInterval(int interval) {
- this.interval = interval;
- }
- }
-}
diff --git a/promisedb/build.gradle b/promisedb/build.gradle
index 70a3536..e20e16b 100644
--- a/promisedb/build.gradle
+++ b/promisedb/build.gradle
@@ -30,7 +30,9 @@ android {
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
- api project(path: ':promisecommons')
+ compileOnly 'io.reactivex.rxjava2:rxjava:2.2.7'
+ compileOnly 'androidx.appcompat:appcompat:1.0.2'
+ compileOnly project(path: ':promisecommons')
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.2.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
diff --git a/promisecommons/src/main/java/promise/model/SModel.java b/promisedb/src/main/java/promise/model/SModel.java
similarity index 100%
rename from promisecommons/src/main/java/promise/model/SModel.java
rename to promisedb/src/main/java/promise/model/SModel.java
diff --git a/promisedb/src/main/java/promise/promisedb/Column.java b/promisedb/src/main/java/promise/promisedb/Column.java
index 4e12336..d0540ad 100644
--- a/promisedb/src/main/java/promise/promisedb/Column.java
+++ b/promisedb/src/main/java/promise/promisedb/Column.java
@@ -23,12 +23,13 @@ public final class Column {
static Comparator ascending =
(o1, o2) -> o1.getIndex() > o2.getIndex() ? 1 :
o1.getIndex() < o2.getIndex() ? -1 : 0;
+ public static final String ASCENDING = "ASC", DESCENDING = "DESC";
public Column descending() {
- this.order = "DESC";
+ this.order = DESCENDING;
return this;
}
public Column ascending() {
- this.order = "ASC";
+ this.order = ASCENDING;
return this;
}
private String order;
diff --git a/promisedb/src/main/java/promise/promisedb/Corrupt.java b/promisedb/src/main/java/promise/promisedb/Corrupt.java
index 253eeda..f253936 100644
--- a/promisedb/src/main/java/promise/promisedb/Corrupt.java
+++ b/promisedb/src/main/java/promise/promisedb/Corrupt.java
@@ -15,6 +15,12 @@
package promise.promisedb;
+/**
+ *
+ */
public interface Corrupt {
+ /**
+ *
+ */
void onCorrupt();
}
diff --git a/promisedb/src/main/java/promise/promisedb/Crud.java b/promisedb/src/main/java/promise/promisedb/Crud.java
index 3082833..5252c53 100644
--- a/promisedb/src/main/java/promise/promisedb/Crud.java
+++ b/promisedb/src/main/java/promise/promisedb/Crud.java
@@ -35,8 +35,6 @@ interface Crud {
SList readAll(Table table, Column[] columns);
- Table.Extras read(Table table, Column... columns);
-
boolean delete(Table, X> table, Column column);
boolean delete(Table table, T t);
diff --git a/promisedb/src/main/java/promise/promisedb/DBError.java b/promisedb/src/main/java/promise/promisedb/DBError.java
index 7192e7f..3964602 100644
--- a/promisedb/src/main/java/promise/promisedb/DBError.java
+++ b/promisedb/src/main/java/promise/promisedb/DBError.java
@@ -18,15 +18,15 @@
/**
* Created by yoctopus on 2/21/17.
*/
-public final class DBError extends Exception {
- public DBError() {
+public final class DBError extends Exception {
+ DBError() {
}
- public DBError(String message) {
+ DBError(String message) {
super(message);
}
- public DBError(Throwable cause) {
+ DBError(Throwable cause) {
super(cause);
}
}
diff --git a/promisedb/src/main/java/promise/promisedb/FastDB.java b/promisedb/src/main/java/promise/promisedb/FastDB.java
index 16ba469..f7aab4a 100644
--- a/promisedb/src/main/java/promise/promisedb/FastDB.java
+++ b/promisedb/src/main/java/promise/promisedb/FastDB.java
@@ -33,12 +33,28 @@
import promise.promisedb.query.QueryBuilder;
import promise.util.Conditions;
+/**
+ *
+ */
public abstract class FastDB extends SQLiteOpenHelper implements Crud {
+ /**
+ *
+ */
private static final String DEFAULT_NAME = "fast";
/*private static Map> indexCreatedTableHashMap;*/
private String TAG = LogUtil.makeTag(FastDB.class);
+ /**
+ *
+ */
private Context context;
+ /**
+ *
+ * @param name
+ * @param factory
+ * @param version
+ * @param errorHandler
+ */
private FastDB(
String name,
SQLiteDatabase.CursorFactory factory,
@@ -50,6 +66,13 @@ private FastDB(
/*initTables();*/
}
+ /**
+ *
+ * @param name
+ * @param version
+ * @param cursorListener
+ * @param listener
+ */
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public FastDB(String name, int version, final FastDbCursorFactory.Listener cursorListener, final Corrupt listener) {
this(
@@ -62,6 +85,10 @@ public FastDB(String name, int version, final FastDbCursorFactory.Listener curso
});
}
+ /**
+ *
+ * @param version
+ */
public FastDB(int version) {
this(DEFAULT_NAME, version, null,null);
}
@@ -73,11 +100,21 @@ public FastDB(int version) {
indexCreatedTableHashMap.put(new IndexCreated(i, false), tables.get(i));
}*/
+ /**
+ *
+ * @param db
+ */
@Override
public final void onCreate(SQLiteDatabase db) {
create(db);
}
+ /**
+ *
+ * @param database
+ * @param oldVersion
+ * @param newVersion
+ */
@Override
public void onUpgrade(SQLiteDatabase database, int oldVersion, int newVersion) {
LogUtil.d(TAG, "onUpgrade", oldVersion, newVersion);
@@ -87,14 +124,33 @@ public void onUpgrade(SQLiteDatabase database, int oldVersion, int newVersion) {
}
}
+ /**
+ *
+ * @param database
+ * @param oldVersion
+ * @param newVersion
+ * @return
+ */
public abstract boolean shouldUpgrade(SQLiteDatabase database, int oldVersion, int newVersion);
+ /**
+ *
+ * @return
+ */
public String name() {
return this.getDatabaseName();
}
+ /**
+ *
+ * @return
+ */
public abstract List> tables();
+ /**
+ *
+ * @param database
+ */
private void create(SQLiteDatabase database) {
boolean created = true;
@@ -109,6 +165,12 @@ private void create(SQLiteDatabase database) {
}
}
+ /**
+ *
+ * @param database
+ * @param v1
+ * @param v2
+ */
private void upgrade(SQLiteDatabase database, int v1, int v2) {
for (Table, SQLiteDatabase> table: Conditions.checkNotNull(tables())) {
try {
@@ -127,7 +189,13 @@ private void upgrade(SQLiteDatabase database, int v1, int v2) {
}
}
- public boolean add(SQLiteDatabase database, List> tables) {
+ /**
+ *
+ * @param database
+ * @param tables
+ * @return
+ */
+ public boolean add(SQLiteDatabase database, Table, SQLiteDatabase>... tables) {
boolean created = true;
for (Table, SQLiteDatabase> table : tables) {
try {
@@ -140,6 +208,11 @@ public boolean add(SQLiteDatabase database, List> table
return created;
}
+ /**
+ *
+ * @param database
+ * @return
+ */
private boolean drop(SQLiteDatabase database) {
boolean dropped = true;
/*for (Map.Entry> entry :
@@ -154,6 +227,13 @@ private boolean drop(SQLiteDatabase database) {
return dropped;
}
+ /**
+ *
+ * @param table
+ * @param database
+ * @return
+ * @throws DBError
+ */
private boolean create(Table, SQLiteDatabase> table, SQLiteDatabase database) throws DBError {
try {
table.onCreate(database);
@@ -163,6 +243,13 @@ private boolean create(Table, SQLiteDatabase> table, SQLiteDatabase database)
return true;
}
+ /**
+ *
+ * @param table
+ * @param database
+ * @return
+ * @throws DBError
+ */
private boolean drop(Table, SQLiteDatabase> table, SQLiteDatabase database) throws DBError {
try {
checkTableExist(table).onDrop(database);
@@ -172,6 +259,11 @@ private boolean drop(Table, SQLiteDatabase> table, SQLiteDatabase database) th
return true;
}
+ /**
+ *
+ * @param builder
+ * @return
+ */
public Cursor query(QueryBuilder builder) {
String sql = builder.build();
String[] params = builder.buildParameters();
@@ -179,56 +271,120 @@ public Cursor query(QueryBuilder builder) {
return getReadableDatabase().rawQuery(sql, params);
}
+ /**
+ *
+ * @param table
+ * @param
+ * @return
+ */
@Override
public Table.Extras read(Table table) {
return checkTableExist(table).read(getReadableDatabase());
}
- @Override
- public Table.Extras read(Table table, Column... columns) {
- return checkTableExist(table).read(getReadableDatabase(), columns);
- }
-
+ /**
+ *
+ * @param table
+ * @param
+ * @return
+ */
@Override
public SList readAll(Table table) {
return checkTableExist(table).onReadAll(getReadableDatabase(), true);
}
+ /**
+ *
+ * @param table
+ * @param column
+ * @param
+ * @return
+ */
@Override
public SList readAll(Table table, Column column) {
return checkTableExist(table).onReadAll(getReadableDatabase(), column);
}
+ /**
+ *
+ * @param t
+ * @param table
+ * @param
+ * @return
+ */
@Override
public boolean update(T t, Table table) {
return checkTableExist(table).onUpdate(t, getWritableDatabase());
}
+ /**
+ *
+ * @param t
+ * @param table
+ * @param column
+ * @param
+ * @return
+ */
@Override
public boolean update(T t, Table table, Column column) {
- return checkTableExist(table).onUpdate(t, getWritableDatabase(), column);
+ try {
+ return checkTableExist(table).onUpdate(t, getWritableDatabase(), column);
+ } catch (ModelError modelError) {
+ LogUtil.e(TAG, "update error", modelError);
+ return false;
+ }
}
+ /**
+ *
+ * @param table
+ * @param columns
+ * @param
+ * @return
+ */
@Override
public SList readAll(Table table, Column[] columns) {
return checkTableExist(table).onReadAll(getReadableDatabase(), columns);
}
+ /**
+ *
+ * @param table
+ * @param t
+ * @param
+ * @return
+ */
@Override
public boolean delete(Table table, T t) {
return checkTableExist(table).onDelete(t, getWritableDatabase());
}
+ /**
+ *
+ * @param table
+ * @param column
+ * @return
+ */
@Override
public boolean delete(Table, SQLiteDatabase> table, Column column) {
return checkTableExist(table).onDelete(getWritableDatabase(), column);
}
+ /**
+ *
+ * @param table
+ * @return
+ */
@Override
public boolean delete(Table, SQLiteDatabase> table) {
return checkTableExist(table).onDelete(getWritableDatabase());
}
+ /**
+ *
+ * @param tables
+ * @return
+ */
public boolean delete(Table, SQLiteDatabase>... tables) {
boolean delete = true;
for (Table, SQLiteDatabase> table : tables)
@@ -236,21 +392,47 @@ public boolean delete(Table, SQLiteDatabase>... tables) {
return delete;
}
+ /**
+ *
+ * @param table
+ * @param column
+ * @param list
+ * @param
+ * @return
+ */
@Override
public boolean delete(Table, SQLiteDatabase> table, Column column, List list) {
return checkTableExist(table).onDelete(getWritableDatabase(), column, list);
}
+ /**
+ *
+ * @param t
+ * @param table
+ * @param
+ * @return
+ */
@Override
public long save(T t, Table table) {
return checkTableExist(table).onSave(t, getWritableDatabase());
}
+ /**
+ *
+ * @param list
+ * @param table
+ * @param
+ * @return
+ */
@Override
public boolean save(SList list, Table table) {
- return checkTableExist(table).onSave(list, getWritableDatabase(), true);
+ return checkTableExist(table).onSave(list, getWritableDatabase());
}
+ /**
+ *
+ * @return
+ */
@Override
public boolean deleteAll() {
synchronized (FastDB.class) {
@@ -261,15 +443,30 @@ public boolean deleteAll() {
}
}
+ /**
+ *
+ * @param table
+ * @return
+ */
@Override
public int getLastId(Table, SQLiteDatabase> table) {
return checkTableExist(table).onGetLastId(getReadableDatabase());
}
+ /**
+ *
+ * @return
+ */
public Context getContext() {
return context;
}
+ /**
+ *
+ * @param table
+ * @param
+ * @return
+ */
private Table checkTableExist(Table table) {
return Conditions.checkNotNull(table);
/*synchronized (this) {
diff --git a/promisedb/src/main/java/promise/promisedb/Model.java b/promisedb/src/main/java/promise/promisedb/Model.java
index 5da3ee3..4bb1d0f 100644
--- a/promisedb/src/main/java/promise/promisedb/Model.java
+++ b/promisedb/src/main/java/promise/promisedb/Model.java
@@ -38,40 +38,112 @@
import promise.util.Conditions;
import promise.util.DoubleConverter;
+/**
+ * This class models database queries
+ * Each extending class must implement {@link DoubleConverter#serialize(Object)} method to
+ * convert the {@link SModel} instance to a content value see {@link ContentValues}
+ * and {@link DoubleConverter#deserialize(Object)}
+ * method to deserialize a {@link Cursor} back to the instance
+ *
+ * @param {@link SModel} instance to be persisted by the model
+ */
public abstract class Model
implements Table, DoubleConverter {
+ /**
+ * The create prefix in a prefix for queries that create a table structure
+ */
private static final String CREATE_PREFIX = "CREATE TABLE IF NOT EXISTS ";
+ /**
+ * The drop prefix is a prefix for queries that destroy a table in the database
+ */
private static final String DROP_PREFIX = "TRUNCATE TABLE IF EXISTS ";
- private static final String SELECT_PREFIX = "SELECT * FROM ";
+ /**
+ * The alter prefix is used to alter the structure of a column when making upgrades
+ */
+ private String ALTER_COMMAND = "ALTER TABLE";
+ /**
+ * the name of the primary column
+ */
+ private static final String ID_COLUMN_NAME = "id";
+ /**
+ * The name of the timestamp columns
+ */
+ private static final String CREATED_AT_COLUMN_NAME = "CREATED_AT";
+ private static final String UPDATED_AT_COLUMN_NAME = "UPDATED_AT";
+ /**
+ * Each table must have a primary column as well al timestamp columns
+ * see {@link Column} for more info
+ */
public static Column id, createdAt, updatedAt;
+ /*
+ * the primary column of the database if named id and the same name in all tables
+ */
static {
- id = new Column<>("id", Column.Type.INTEGER.PRIMARY_KEY_AUTOINCREMENT());
+ id = new Column<>(ID_COLUMN_NAME, Column.Type.INTEGER.PRIMARY_KEY_AUTOINCREMENT());
+ createdAt = new Column<>(CREATED_AT_COLUMN_NAME, Column.Type.INTEGER.NULLABLE());
+ updatedAt = new Column<>(UPDATED_AT_COLUMN_NAME, Column.Type.INTEGER.NULLABLE());
}
- private String ALTER_COMMAND = "ALTER TABLE";
+ /**
+ * the name of the table to be created
+ * see {@link Table#getName()}
+ */
private String name = "`" + getName() + "`";
+ /**
+ * The specific tag for logging in this table
+ */
private String TAG = LogUtil.makeTag(Model.class).concat(name);
+ /**
+ * Temporary data holder for holding data during dangerous table structure changes
+ */
private SList backup;
+ /**
+ * gets all the columns for this model from the child class for creation purposes
+ * see {@link #onCreate(SQLiteDatabase)}
+ *
+ * @return list of columns
+ */
public abstract List getColumns();
+ /**
+ * optional to get the number of all the columns in this table
+ * noteby the added 3 is for id, and timestamp columns
+ *
+ * @return the number of the columns in this table
+ */
public int getNumberOfColumns() {
return getColumns().size() + 3;
}
+ /**
+ * this handler created a table in the given database instance passed
+ * uses {@link Column#getDescription()} to get the column info
+ * adds the id and timestamp in the table
+ *
+ * @param database writable sql database
+ * @return true if table is created
+ * @throws ModelError if theirs a query error
+ */
@Override
public boolean onCreate(SQLiteDatabase database) throws ModelError {
String sql = CREATE_PREFIX;
+ /*
+ * add the opening braces after select prefix, see {@link Model#CREATE_PREFIX}
+ */
sql = sql.concat(name + "(");
- List columns = getColumns();
- columns = Conditions.checkNotNull(columns);
+ List columns = Conditions.checkNotNull(getColumns());
+ /*
+ * sorts the column in ascending order, see {@link Column#ascending()} comparator
+ */
Collections.sort(columns, Column.ascending);
List columns1 = new List<>();
+ /*
+ * add the three additional columns to the creation script
+ */
columns1.add(id);
columns1.addAll(columns);
- if (createdAt == null) createdAt = new Column<>("CREATED_AT", Column.Type.INTEGER.NULLABLE());
- if (updatedAt == null) updatedAt = new Column<>("UPDATED_AT", Column.Type.INTEGER.NULLABLE());
columns1.add(createdAt);
columns1.add(updatedAt);
for (int i = 0; i < columns1.size(); i++) {
@@ -89,18 +161,33 @@ public boolean onCreate(SQLiteDatabase database) throws ModelError {
return true;
}
+ /*
+ * upgrades the table from one version to the next
+ * if the table doesn't have the timestamps add them
+ * @param database writable sql database
+ * @param v1 previous version
+ * @param v2 next version
+ * @return
+ * @throws ModelError
+ */
@Override
public boolean onUpgrade(SQLiteDatabase database, int v1, int v2) throws ModelError {
- if (createdAt == null) createdAt = new Column<>("CREATED_AT", Column.Type.INTEGER.NULLABLE());
- if (updatedAt == null) updatedAt = new Column<>("UPDATED_AT", Column.Type.INTEGER.NULLABLE());
QueryBuilder builder = new QueryBuilder().from(this);
Cursor c = database.rawQuery(builder.build(), builder.buildParameters());
- Set set = new HashSet<>(List.Companion.fromArray(c.getColumnNames()));
+ Set set = new HashSet<>(List.fromArray(c.getColumnNames()));
if (!set.contains(createdAt.getName())) addColumns(database, createdAt);
if (!set.contains(updatedAt.getName())) addColumns(database, updatedAt);
return false;
}
+ /**
+ * adds column to the database
+ *
+ * @param database writable sql database
+ * @param columns fields to be added must be nullable entry types
+ * @return true if the table is upgraded
+ * @throws ModelError if theirs an sql error
+ */
public boolean addColumns(SQLiteDatabase database, Column... columns) throws ModelError {
for (Column column : columns) {
String alterSql = ALTER_COMMAND + " `" + getName() + "` " + "ADD " + column.toString() + ";";
@@ -114,6 +201,14 @@ public boolean addColumns(SQLiteDatabase database, Column... columns) throws Mod
return true;
}
+ /**
+ * drops column from the database
+ *
+ * @param database writable sql database
+ * @param columns fields to be dropped
+ * @return true if fields are dropped successfully
+ * @throws ModelError if theirs an sql error
+ */
public boolean dropColumns(SQLiteDatabase database, Column... columns) throws ModelError {
for (Column column : columns) {
String alterSql =
@@ -127,43 +222,40 @@ public boolean dropColumns(SQLiteDatabase database, Column... columns) throws Mo
return true;
}
+ /**
+ * more verbose read operation against the database
+ *
+ * @param database readable sql database
+ * @return an extras instance for more concise reads
+ */
@Override
public Extras read(final SQLiteDatabase database) {
return new QueryExtras(database) {
@Override
- public ContentValues to(T t) {
- return Model.this.to(t);
- }
-
- @Override
- public T from(Cursor cursor) {
- return Model.this.from(cursor);
- }
- };
- }
-
- @Override
- public Extras read(SQLiteDatabase database, Column... columns) {
- return new QueryExtras2(database, columns) {
- @Override
- public ContentValues to(T t) {
- return Model.this.to(t);
+ public ContentValues serialize(T t) {
+ return Model.this.serialize(t);
}
@Override
- public T from(Cursor cursor) {
- return Model.this.from(cursor);
+ public T deserialize(Cursor cursor) {
+ return Model.this.deserialize(cursor);
}
};
}
+ /**
+ * read all the rows in the database
+ *
+ * @param database readable sql database
+ * @param close close the connection if this is true
+ * @return a list of records
+ */
@Override
public final SList onReadAll(SQLiteDatabase database, boolean close) {
+ QueryBuilder builder = new QueryBuilder().from(Model.this);
Cursor cursor;
try {
- String sql = SELECT_PREFIX + name + ";";
- LogUtil.d(TAG, sql);
- cursor = database.rawQuery(sql, null);
+ cursor = database.rawQuery(builder.build(), builder.buildParameters());
SList ts = new SList<>();
while (cursor.moveToNext() && !cursor.isClosed()) ts.add(getWithId(cursor));
cursor.close();
@@ -173,36 +265,29 @@ public final SList onReadAll(SQLiteDatabase database, boolean close) {
return new SList<>();
}
}
-
- @Override
- public SList onReadAll(SQLiteDatabase database, Column column) {
- if (column == null) return onReadAll(database, true);
- String where = column.getName() + column.getOperand();
- if (column.value() instanceof String) where = where + "\"" + column.value() + "\"";
- else where = where + column.value();
- Cursor cursor = database.query(name, null, where, null, null, null, null);
- SList ts = new SList<>();
- while (cursor.moveToNext() && !cursor.isClosed()) ts.add(getWithId(cursor));
- cursor.close();
- /*database.close();*/
- return ts;
- }
-
+ /**
+ * read the rows following the criteria specified in the column provided
+ * for each of the columns
+ * if {@link Column#value()} is not null, filter with the value
+ * if {@link Column#order()} is not null, order by that column too
+ *
+ * @param database readable sql database
+ * @param columns the fields to infer where and order by conditions
+ * @return list of records satisfying the criteria
+ */
@Override
public SList onReadAll(SQLiteDatabase database, Column[] columns) {
if (columns == null) return onReadAll(database, true);
- String[] args = new String[columns.length];
- String selection = "";
- for (int i = 0; i < args.length; i++) {
- Column column = columns[i];
- String where = column.getName() + column.getOperand();
- selection = selection.concat(where);
- if (column.value() instanceof String) args[i] = "\"" + column.value() + "\"";
- else args[i] = column.value().toString();
- selection = selection.concat(args[i]);
- if (i < args.length - 1) selection = selection.concat(" AND ");
+ QueryBuilder builder = new QueryBuilder().from(Model.this).takeAll();
+ for (Column column : columns) {
+ if (column.value() != null) builder.whereAnd(Criteria.equals(column, column.value()));
+ if (column.order() != null) {
+ if (column.order().equals(Column.DESCENDING)) {
+ builder.orderByDescending(column);
+ } else builder.orderByAscending(column);
+ }
}
- Cursor cursor = database.query(name, null, selection, null, null, null, null);
+ Cursor cursor = database.rawQuery(builder.build(), builder.buildParameters());
SList ts = new SList<>();
while (cursor.moveToNext() && !cursor.isClosed()) ts.add(getWithId(cursor));
cursor.close();
@@ -210,33 +295,72 @@ public SList onReadAll(SQLiteDatabase database, Column[] columns) {
return ts;
}
+ /**
+ * update a row in the table
+ *
+ * @param t instance to update
+ * @param database writable sql database
+ * @param column field with where condition to update
+ * @return true if instance is updated
+ */
@Override
- public final boolean onUpdate(T t, SQLiteDatabase database, Column column) {
- String where = null;
- if (column != null) where = column.getName() + column.getOperand() + column.value();
- ContentValues values = to(t);
- if (updatedAt == null) updatedAt = new Column<>("UPDATED_AT", Column.Type.INTEGER.NULLABLE());
+ public final boolean onUpdate(T t, SQLiteDatabase database, Column column) throws ModelError {
+ String where;
+ if (column != null && column.getOperand() != null && column.value() != null)
+ where = column.getName() + column.getOperand() + column.value();
+ else throw new ModelError("Cant update the record, missing updating information");
+ ContentValues values = serialize(t);
values.put(updatedAt.getName(), System.currentTimeMillis());
return database.update(name, values, where, null) >= 0;
}
+ /**
+ * updated an instance with an id value more than zero
+ *
+ * @param t the instance to update
+ * @param database writable sql database
+ * @return true if updated
+ */
@Override
public boolean onUpdate(T t, SQLiteDatabase database) {
- return id != null && onUpdate(t, database, id.with(t.id()));
+ try {
+ return id != null && onUpdate(t, database, id.with(t.id()));
+ } catch (ModelError modelError) {
+ return false;
+ }
}
+ /**
+ * deletes multiple rows from the table where the column matches all the
+ * given values in list
+ *
+ * @param database writable sql database
+ * @param column the matching column
+ * @param list values to match with
+ * @param the type of matching, must not be derived data type
+ * @return true if all rows are deleted
+ */
@Override
public final boolean onDelete(SQLiteDatabase database, Column column, List list) {
- boolean deleted = true;
- String where;
+ boolean deleted;
+ String where = "";
for (int i = 0, listSize = list.size(); i < listSize; i++) {
C c = list.get(i);
- where = column.getName() + column.getOperand() + c;
- deleted = database.delete(name, where, null) >= 0;
+ if (i == listSize - 1) {
+ where = column.getName() + " " + column.getOperand() + " " + c;
+ } else where = column.getName() + " " + column.getOperand() + " " + c + " OR ";
+
}
+ deleted = database.delete(name, where, null) >= 0;
return deleted;
}
+ /**
+ * delete a row in the table matching condition in the column
+ * @param database writable sql database
+ * @param column field to match
+ * @return true if row is deleted
+ */
@Override
public final boolean onDelete(SQLiteDatabase database, Column column) {
if (column == null) return false;
@@ -244,29 +368,51 @@ public final boolean onDelete(SQLiteDatabase database, Column column) {
return database.delete(name, where, null) >= 0;
}
+ /**
+ * delete an instance from the table
+ * @param t instance to be removed must have an id more than zero
+ * @param database writable sql database
+ * @return true if item is deleted
+ */
@Override
public boolean onDelete(T t, SQLiteDatabase database) {
return onDelete(database, id.with(t.id()));
}
+ /**
+ * delete all rows in the table
+ * @param database writable sql database
+ * @return true if all rows are deleted
+ */
@Override
public final boolean onDelete(SQLiteDatabase database) {
return !TextUtils.isEmpty(name) && database.delete(name, null, null) >= 0;
}
+ /**
+ * save an instance to the database
+ * serialize it to content values
+ * @param t instance to be saved
+ * @param database writable sql database
+ * @return id of the row affected
+ */
@Override
public final long onSave(T t, SQLiteDatabase database) {
if (t.id() != 0 && onUpdate(t, database)) return t.id();
- ContentValues values = to(t);
- if (createdAt == null) createdAt = new Column<>("CREATED_AT", Column.Type.INTEGER.NULLABLE());
- if (updatedAt == null) updatedAt = new Column<>("UPDATED_AT", Column.Type.INTEGER.NULLABLE());
+ ContentValues values = serialize(t);
values.put(createdAt.getName(), System.currentTimeMillis());
values.put(updatedAt.getName(), System.currentTimeMillis());
return database.insert(name, null, values);
}
+ /**
+ * save a list of items in the database
+ * @param list items to be saved
+ * @param database writable sql database
+ * @return true if all the items are saved
+ */
@Override
- public final boolean onSave(SList list, SQLiteDatabase database, boolean close) {
+ public final boolean onSave(SList list, SQLiteDatabase database) {
boolean saved = true;
int i = 0, listSize = list.size();
while (i < listSize) {
@@ -278,6 +424,12 @@ public final boolean onSave(SList list, SQLiteDatabase database, boolean clos
return saved;
}
+ /**
+ * drop this table from the database
+ * @param database writable sql database
+ * @return true if the table is dropped
+ * @throws ModelError if theirs an sql error
+ */
@Override
public final boolean onDrop(SQLiteDatabase database) throws ModelError {
String sql = DROP_PREFIX + name + ";";
@@ -289,6 +441,12 @@ public final boolean onDrop(SQLiteDatabase database) throws ModelError {
return true;
}
+ /**
+ * get the last id of the last row in the table
+ * uses projection to count the id column as num
+ * @param database readable sql database
+ * @return the id
+ */
@Override
public final int onGetLastId(SQLiteDatabase database) {
if (id == null) return 0;
@@ -297,29 +455,48 @@ public final int onGetLastId(SQLiteDatabase database) {
return cursor.getInt(Model.id.getIndex());
}
+ /**
+ * backup all the items in the table during dangerous upgrdes
+ * @param database readable database instance
+ */
@Override
public void backup(SQLiteDatabase database) {
backup = onReadAll(database, false);
}
+ /**
+ * save back the backed items to the database
+ * @param database writable database
+ */
@Override
public void restore(SQLiteDatabase database) {
- if (backup != null && !backup.isEmpty()) onSave(backup, database, false);
+ if (backup != null && !backup.isEmpty()) onSave(backup, database);
}
+ /**
+ * gets a single from the cursor pre populated with id and timestamps
+ * @param cursor the serialized version of the instance
+ * @return instance from the cursor
+ */
T getWithId(Cursor cursor) {
- T t = from(cursor);
+ T t = deserialize(cursor);
t.id(cursor.getInt(id.getIndex()));
- if (createdAt == null) createdAt = new Column<>("CREATED_AT", Column.Type.INTEGER.NULLABLE());
- if (updatedAt == null) updatedAt = new Column<>("UPDATED_AT", Column.Type.INTEGER.NULLABLE());
t.createdAt(cursor.getInt(createdAt.getIndex(cursor)));
t.updatedAt(cursor.getInt(updatedAt.getIndex(cursor)));
return t;
}
+ /**
+ * This class contains special queries for reading from the table
+ * see {@link SModel} for encapsulating id and timestamps
+ * see {@link DoubleConverter} for serializing and de-serializing
+ * @param The type of the items in the table
+ */
private abstract class QueryExtras
implements Extras, DoubleConverter {
-
+ /**
+ * the database instance to read fromm
+ */
private SQLiteDatabase database;
QueryExtras(SQLiteDatabase database) {
@@ -330,16 +507,23 @@ public SQLiteDatabase database() {
return database;
}
+ /**
+ * get a record pre populated with id and timestamps from each read
+ * @param cursor serialized version of Q
+ * @return Q the de-serialized output of reading the cursor
+ */
Q getWithId(Cursor cursor) {
- Q t = from(cursor);
+ Q t = deserialize(cursor);
t.id(cursor.getInt(id.getIndex()));
- if (createdAt == null) createdAt = new Column<>("CREATED_AT", Column.Type.INTEGER.NULLABLE());
- if (updatedAt == null) updatedAt = new Column<>("UPDATED_AT", Column.Type.INTEGER.NULLABLE());
t.createdAt(cursor.getInt(createdAt.getIndex(cursor)));
t.updatedAt(cursor.getInt(updatedAt.getIndex(cursor)));
return t;
}
+ /**
+ * get the first record in the table
+ * @return the first records or null if theirs none in the table
+ */
@Nullable
@Override
public Q first() {
@@ -354,6 +538,10 @@ public Q first() {
}
}
+ /**
+ * get the last record in the table
+ * @return an item or null if theirs none stored in the table
+ */
@Nullable
@Override
public Q last() {
@@ -368,25 +556,34 @@ public Q last() {
}
}
+ /**
+ * get all the items in the table
+ * @return the items or an empty list if theirs none
+ */
@Override
public SList all() {
Cursor cursor;
try {
QueryBuilder builder = new QueryBuilder().from(Model.this).takeAll();
cursor = database.rawQuery(builder.build(), builder.buildParameters());
+ SList ts = new SList<>();
+ while (cursor.moveToNext() && !cursor.isClosed()) ts.add(getWithId(cursor));
+ return ts;
} catch (SQLiteException e) {
return new SList<>();
}
- SList ts = new SList<>();
- while (cursor.moveToNext() && !cursor.isClosed()) ts.add(getWithId(cursor));
- return ts;
}
+ /**
+ * read the top items in the table
+ * @param limit the number of records to read
+ * @return a list of the items
+ */
@Override
public SList limit(int limit) {
Cursor cursor;
try {
- QueryBuilder builder = new QueryBuilder().from(Model.this).take(1);
+ QueryBuilder builder = new QueryBuilder().from(Model.this).take(limit);
cursor = database.rawQuery(builder.build(), builder.buildParameters());
SList ts = new SList<>();
while (cursor.moveToNext() && !cursor.isClosed()) ts.add(getWithId(cursor));
@@ -397,11 +594,17 @@ public SList limit(int limit) {
}
}
+ /**
+ * reads the records between the skip and limit in the table
+ * @param skip of set from the top to not read
+ * @param limit items to load after skip
+ * @return a list of records
+ */
@Override
- public SList between(Column column, Integer a, Integer b) {
+ public SList paginate(int skip, int limit) {
Cursor cursor;
try {
- QueryBuilder builder = new QueryBuilder().from(Model.this).whereAnd(Criteria.between(column, a, b));
+ QueryBuilder builder = new QueryBuilder().from(Model.this).take(limit).skip(skip);
cursor = database.rawQuery(builder.build(), builder.buildParameters());
SList ts = new SList<>();
while (cursor.moveToNext() && !cursor.isClosed()) ts.add(getWithId(cursor));
@@ -412,26 +615,66 @@ public SList between(Column column, Integer a, Integer b) {
}
}
+ /**
+ * gets all items that match in between the int left and right
+ * @param column column to match between
+ * @param a lower between bound
+ * @param b upper between bound
+ * @return a list of items
+ */
+ @Override
+ public SList between(Column column, N a, N b) {
+ Cursor cursor;
+ try {
+ QueryBuilder builder = new QueryBuilder().from(Model.this).takeAll().whereAnd(Criteria.between(column, a, b));
+ cursor = database.rawQuery(builder.build(), builder.buildParameters());
+ SList ts = new SList<>();
+ while (cursor.moveToNext() && !cursor.isClosed()) ts.add(getWithId(cursor));
+ return ts;
+ } catch (SQLiteException e) {
+ LogUtil.e(TAG, e);
+ return new SList<>();
+ }
+ }
+
+ /**
+ * gets all items matching the multiple columns
+ * @param column fields to match their values
+ * @return a list of items
+ */
@Override
public SList where(Column[] column) {
- return null;
+ Cursor cursor;
+ try {
+ QueryBuilder builder = new QueryBuilder().from(Model.this).takeAll();
+ for (Column column1 : column)
+ if (column1.value() != null) builder.whereAnd(Criteria.equals(column1, column1.value()));
+ cursor = database.rawQuery(builder.build(), builder.buildParameters());
+ SList ts = new SList<>();
+ while (cursor.moveToNext() && !cursor.isClosed()) ts.add(getWithId(cursor));
+ return ts;
+ } catch (SQLiteException e) {
+ LogUtil.e(TAG, e);
+ return new SList<>();
+ }
}
+ /**
+ * gets all the items matching not in any of the columns
+ * @param column field to match
+ * @param bounds not in bounds
+ * @return a list of items
+ */
+ @SafeVarargs
@Override
- public SList notIn(Column column, Integer a, Integer b) {
+ public final SList notIn(Column column, N... bounds) {
Cursor cursor;
+ Object[] items = new Object[bounds.length];
+ System.arraycopy(bounds, 0, items, 0, bounds.length);
+ QueryBuilder builder = new QueryBuilder().from(Model.this).takeAll()
+ .whereAnd(Criteria.notIn(column, items));
try {
- String sql =
- SELECT_PREFIX
- + name
- + " WHERE "
- + column.getName()
- + " NOT BETWEEN "
- + a
- + " AND "
- + b
- + ";";
- cursor = database.rawQuery(sql, null);
+ cursor = database.rawQuery(builder.build(), builder.buildParameters());
SList ts = new SList<>();
while (cursor.moveToNext() && !cursor.isClosed()) {
Q t = getWithId(cursor);
@@ -446,18 +689,47 @@ public SList notIn(Column column, Integer a, Integer b) {
}
}
+ /**
+ * get all the rows where the column is like the columns values
+ * @param column the fields to compute like from
+ * @return a list of columns
+ */
@Override
public SList like(Column[] column) {
- return null;
+ Cursor cursor;
+ QueryBuilder builder = new QueryBuilder().from(Model.this).takeAll();
+ for (Column column1 : column)
+ builder.whereAnd(Criteria.contains(column1, String.valueOf(column1.value())));
+ try {
+ cursor = database.rawQuery(builder.build(), builder.buildParameters());
+ SList ts = new SList<>();
+ while (cursor.moveToNext() && !cursor.isClosed()) {
+ Q t = getWithId(cursor);
+ ts.add(t);
+ }
+ cursor.close();
+ /*database.close();*/
+ return ts;
+ } catch (SQLiteException e) {
+ LogUtil.e(TAG, e);
+ return new SList<>();
+ }
}
+ /**
+ * get all the rows in the oder specified by the column
+ * @param column field to order by
+ * @return a list of ordered items
+ */
@Override
public SList orderBy(Column column) {
Cursor cursor;
+ QueryBuilder builder = new QueryBuilder().from(Model.this).takeAll();
+ if (column.order().equals(Column.DESCENDING)) {
+ builder.orderByDescending(column);
+ } else builder.orderByAscending(column);
try {
- String sql =
- SELECT_PREFIX + name + " ORDER BY " + column.getName() + " " + column.order() + ";";
- cursor = database.rawQuery(sql, null);
+ cursor = database.rawQuery(builder.build(), builder.buildParameters());
SList ts = new SList<>();
while (cursor.moveToNext() && !cursor.isClosed()) {
Q t = getWithId(cursor);
@@ -472,13 +744,17 @@ public SList orderBy(Column column) {
}
}
+ /**
+ * gets all the items grouped by the column
+ * @param column field to group by
+ * @return a list of grouped items
+ */
@Override
public SList groupBy(Column column) {
Cursor cursor;
+ QueryBuilder builder = new QueryBuilder().from(Model.this).takeAll().groupBy(column);
try {
- String sql =
- SELECT_PREFIX + name + " GROUP BY " + column.getName() + " " + column.order() + ";";
- cursor = database.rawQuery(sql, null);
+ cursor = database.rawQuery(builder.build(), builder.buildParameters());
SList ts = new SList<>();
while (cursor.moveToNext() && !cursor.isClosed()) {
Q t = getWithId(cursor);
@@ -493,23 +769,21 @@ public SList groupBy(Column column) {
}
}
+ /**
+ * gets all the items grouped and ordered by the two columns
+ * @param column group by field
+ * @param column1 order by fields
+ * @return a list of items
+ */
@Override
public SList groupAndOrderBy(Column column, Column column1) {
Cursor cursor;
+ QueryBuilder builder = new QueryBuilder().from(Model.this).takeAll().groupBy(column);
+ if (column1.order().equals(Column.DESCENDING)) {
+ builder.orderByDescending(column1);
+ } else builder.orderByAscending(column1);
try {
- String sql =
- SELECT_PREFIX
- + name
- + " GROUP BY "
- + column.getName()
- + " "
- + column.order()
- + " ORDER BY "
- + column.getName()
- + " "
- + column.order()
- + ";";
- cursor = database.rawQuery(sql, null);
+ cursor = database.rawQuery(builder.build(), builder.buildParameters());
SList ts = new SList<>();
while (cursor.moveToNext() && !cursor.isClosed()) {
Q t = getWithId(cursor);
@@ -524,94 +798,4 @@ public SList groupAndOrderBy(Column column, Column column1) {
}
}
}
-
- private abstract class QueryExtras2 extends QueryExtras {
- private Column[] columns;
-
- QueryExtras2(SQLiteDatabase database, Column[] columns) {
- super(database);
- this.columns = columns;
- }
-
- @Nullable
- @Override
- public U first() {
- SList list = all();
- if (!list.isEmpty()) return list.get(0);
- return null;
- }
-
- @Nullable
- @Override
- public U last() {
- SList list = all();
- if (!list.isEmpty()) return list.get(list.size() - 1);
- return null;
- }
-
- @Override
- public SList all() {
- if (columns == null || columns.length == 0) return super.all();
- String[] args = new String[columns.length];
- String selection = "";
- for (int i = 0; i < args.length; i++) {
- Column column = columns[i];
- String where = column.getName() + column.getOperand();
- selection = selection.concat(where);
- if (column.value() instanceof String) args[i] = "\"" + column.value() + "\"";
- else args[i] = column.value().toString();
- selection = selection.concat(args[i]);
- if (i < args.length - 1) selection = selection.concat(" AND ");
- }
- Cursor cursor = database().query(name, null, selection, null, null, null, null);
- SList ts = new SList<>();
- while (cursor.moveToNext() && !cursor.isClosed()) {
- U t = getWithId(cursor);
- ts.add(t);
- }
- cursor.close();
- /*database().close();*/
- return ts;
- }
-
- @Override
- public SList limit(int limit) {
- return null;
- }
-
- @Override
- public SList between(Column column, Integer a, Integer b) {
- return super.between(column, a, b);
- }
-
- @Override
- public SList where(Column[] column) {
- return null;
- }
-
- @Override
- public SList notIn(Column column, Integer a, Integer b) {
- return super.notIn(column, a, b);
- }
-
- @Override
- public SList like(Column[] column) {
- return null;
- }
-
- @Override
- public SList orderBy(Column column) {
- return null;
- }
-
- @Override
- public SList groupBy(Column column) {
- return null;
- }
-
- @Override
- public SList groupAndOrderBy(Column column, Column column1) {
- return null;
- }
- }
}
diff --git a/promisedb/src/main/java/promise/promisedb/ModelError.java b/promisedb/src/main/java/promise/promisedb/ModelError.java
index 5068c1a..5ab16be 100644
--- a/promisedb/src/main/java/promise/promisedb/ModelError.java
+++ b/promisedb/src/main/java/promise/promisedb/ModelError.java
@@ -20,7 +20,10 @@
*/
public final class ModelError extends Exception {
- public ModelError(Throwable cause) {
+ ModelError(Throwable cause) {
+ super(cause);
+ }
+ ModelError(String cause) {
super(cause);
}
}
diff --git a/promisedb/src/main/java/promise/promisedb/ReactiveCrud.java b/promisedb/src/main/java/promise/promisedb/ReactiveCrud.java
index 6c09ab3..ea48a63 100644
--- a/promisedb/src/main/java/promise/promisedb/ReactiveCrud.java
+++ b/promisedb/src/main/java/promise/promisedb/ReactiveCrud.java
@@ -21,36 +21,33 @@
import promise.model.List;
import promise.model.S;
import promise.model.SList;
+import promise.model.SModel;
interface ReactiveCrud {
- ReactiveTable.Extras read(Table table) throws ModelError;
+ ReactiveTable.Extras read(Table table) throws ModelError;
- Maybe> readAll(Table table);
+ Maybe> readAll(Table table);
- Maybe> readAll(Table table, Column column);
+ Maybe> readAll(Table table, Column... column);
- Maybe update(T t, Table table, Column column);
+ Maybe update(T t, Table table, Column column);
- Maybe update(T t, Table table);
+ Maybe update(T t, Table table);
- Maybe> readAll(Table table, Column[] columns);
+ Maybe delete(Table table, Column column);
- ReactiveTable.Extras read(Table table, Column... columns) throws ModelError;
-
- Maybe delete(Table, X> table, Column column);
-
- Maybe delete(Table table, T t);
+ Maybe delete(Table table, T t);
Maybe delete(Table, X> table);
- Maybe delete(Table, X> table, Column column, List list);
+ Maybe