From e064615a9dee75d517da86a6a92b2c1ebd0667e8 Mon Sep 17 00:00:00 2001 From: Alexis DRAI Date: Sat, 4 Feb 2023 15:41:10 +0100 Subject: [PATCH] :poop: yikes --- app/build.gradle | 9 +- .../iut/urbandictionarylight/MainActivity.kt | 1 + .../data/DefinitionDao.kt | 22 +++++ .../iut/urbandictionarylight/data/EntryDao.kt | 23 +++++ .../data/UrbanDictionaryDatabase.kt | 96 +++++++++++++++++++ .../urbandictionarylight/model/Definition.kt | 17 ++-- .../urbandictionarylight/model/Dictionary.kt | 6 +- .../iut/urbandictionarylight/model/Entry.kt | 65 ++----------- .../model/EntryWithDefinitions.kt | 12 +++ app/src/main/res/layout/activity_main.xml | 34 +++---- build.gradle | 2 +- 11 files changed, 203 insertions(+), 84 deletions(-) create mode 100644 app/src/main/java/fr/uca/iut/urbandictionarylight/data/DefinitionDao.kt create mode 100644 app/src/main/java/fr/uca/iut/urbandictionarylight/data/EntryDao.kt create mode 100644 app/src/main/java/fr/uca/iut/urbandictionarylight/data/UrbanDictionaryDatabase.kt create mode 100644 app/src/main/java/fr/uca/iut/urbandictionarylight/model/EntryWithDefinitions.kt diff --git a/app/build.gradle b/app/build.gradle index 07a2160..75fbc7c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,8 +1,10 @@ plugins { id 'com.android.application' id 'org.jetbrains.kotlin.android' + id 'kotlin-kapt' } + android { namespace 'fr.uca.iut.urbandictionarylight' compileSdk 33 @@ -39,7 +41,6 @@ android { } dependencies { - implementation 'androidx.core:core-ktx:1.9.0' implementation 'androidx.appcompat:appcompat:1.6.0' implementation 'com.google.android.material:material:1.8.0' @@ -47,4 +48,10 @@ dependencies { testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.5' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' + def room_version = "2.5.0" + def kotlin_version = "1.7.21" + def nav_version = "2.5.3" + implementation "androidx.room:room-runtime:$room_version" + kapt "androidx.room:room-compiler:$room_version" + implementation "androidx.room:room-ktx:$room_version" } \ No newline at end of file diff --git a/app/src/main/java/fr/uca/iut/urbandictionarylight/MainActivity.kt b/app/src/main/java/fr/uca/iut/urbandictionarylight/MainActivity.kt index f0c9d4f..16ad1dd 100644 --- a/app/src/main/java/fr/uca/iut/urbandictionarylight/MainActivity.kt +++ b/app/src/main/java/fr/uca/iut/urbandictionarylight/MainActivity.kt @@ -2,6 +2,7 @@ package fr.uca.iut.urbandictionarylight import android.os.Bundle import androidx.appcompat.app.AppCompatActivity +import fr.uca.iut.urbandictionarylight.data.UrbanDictionaryDatabase import fr.uca.iut.urbandictionarylight.databinding.ActivityMainBinding class MainActivity : AppCompatActivity() { diff --git a/app/src/main/java/fr/uca/iut/urbandictionarylight/data/DefinitionDao.kt b/app/src/main/java/fr/uca/iut/urbandictionarylight/data/DefinitionDao.kt new file mode 100644 index 0000000..d655bdc --- /dev/null +++ b/app/src/main/java/fr/uca/iut/urbandictionarylight/data/DefinitionDao.kt @@ -0,0 +1,22 @@ +package fr.uca.iut.urbandictionarylight.data + +import androidx.room.* +import fr.uca.iut.urbandictionarylight.model.Definition + +@Dao +interface DefinitionDao { + @Query("SELECT * FROM definitions") + fun queryAll(): Set + + @Query("SELECT * FROM entries WHERE id == :id") + fun query(id: Int): Definition? + + @Insert(onConflict = OnConflictStrategy.REPLACE) + fun insert(entry: Definition) + + @Update + fun update(entry: Definition) + + @Delete + fun delete(entry: Definition) +} \ No newline at end of file diff --git a/app/src/main/java/fr/uca/iut/urbandictionarylight/data/EntryDao.kt b/app/src/main/java/fr/uca/iut/urbandictionarylight/data/EntryDao.kt new file mode 100644 index 0000000..e134831 --- /dev/null +++ b/app/src/main/java/fr/uca/iut/urbandictionarylight/data/EntryDao.kt @@ -0,0 +1,23 @@ +package fr.uca.iut.urbandictionarylight.data + +import androidx.room.* +import fr.uca.iut.urbandictionarylight.model.EntryWithDefinitions + + +@Dao +interface EntryDao { + @Query("SELECT * FROM entries") + fun queryAll(): List + + @Query("SELECT * FROM entries WHERE id == :id") + fun query(id: Int): EntryWithDefinitions? + + @Insert(onConflict = OnConflictStrategy.REPLACE) + fun insert(entry: EntryWithDefinitions) + + @Update + fun update(entry: EntryWithDefinitions) + + @Delete + fun delete(entry: EntryWithDefinitions) +} \ No newline at end of file diff --git a/app/src/main/java/fr/uca/iut/urbandictionarylight/data/UrbanDictionaryDatabase.kt b/app/src/main/java/fr/uca/iut/urbandictionarylight/data/UrbanDictionaryDatabase.kt new file mode 100644 index 0000000..5987386 --- /dev/null +++ b/app/src/main/java/fr/uca/iut/urbandictionarylight/data/UrbanDictionaryDatabase.kt @@ -0,0 +1,96 @@ +package fr.uca.iut.urbandictionarylight.data + +import android.app.Application +import androidx.room.Database +import androidx.room.Room +import androidx.room.RoomDatabase +import fr.uca.iut.urbandictionarylight.model.Definition +import fr.uca.iut.urbandictionarylight.model.Entry +import fr.uca.iut.urbandictionarylight.model.EntryWithDefinitions + +private const val DB_FILE = "u_d_light.db" + +@Database(entities = [Entry::class, Definition::class], version = 1) +abstract class UrbanDictionaryDatabase : RoomDatabase() { + + abstract fun entryDao(): EntryDao + abstract fun definitionDao(): DefinitionDao + + companion object { + private lateinit var application: Application + + @Volatile + private var instance: UrbanDictionaryDatabase? = null + + fun getInstance(): UrbanDictionaryDatabase { + if (Companion::application.isInitialized) { + if (instance == null) + synchronized(this) { + if (instance == null) { + instance = Room.databaseBuilder( + application.applicationContext, + UrbanDictionaryDatabase::class.java, + DB_FILE + ) + .allowMainThreadQueries() + .build() + + instance?.entryDao()?.let { + if (it.queryAll().isEmpty()) emptyDatabaseStub(it) + } + } + } + return instance!! + } else + throw RuntimeException("the database must be initialized first") + } + + //???? + @Synchronized + fun initialize(app: Application) { + if (Companion::application.isInitialized) + throw RuntimeException("the database must not be initialized twice") + + application = app + } + + + private fun emptyDatabaseStub( + entryDao: EntryDao, + definitionDao: DefinitionDao + ): () -> Unit = { + + val def1 = Definition("bleep", "bleep blap bloop", 1) + val def2 = Definition("blarp", "bleeeep blap bloop", 7) + val def3 = Definition("blep", "bleep blap blooop", 4) + val def4 = Definition("blupo", "bleep blaap bloop", 56) + + with(definitionDao) { + insert(def1) + insert(def2) + insert(def3) + insert(def4) + } + with(entryDao) { + insert( + EntryWithDefinitions( + Entry("shrimping"), + listOf(def1, def4) + ) + ) + insert( + EntryWithDefinitions( + Entry("blunderkegel"), + listOf(def2) + ) + ) + insert( + EntryWithDefinitions( + Entry("something horrible and dumb"), + listOf(def3) + ) + ) + } + } + } +} diff --git a/app/src/main/java/fr/uca/iut/urbandictionarylight/model/Definition.kt b/app/src/main/java/fr/uca/iut/urbandictionarylight/model/Definition.kt index 2b3aaac..095f1b3 100644 --- a/app/src/main/java/fr/uca/iut/urbandictionarylight/model/Definition.kt +++ b/app/src/main/java/fr/uca/iut/urbandictionarylight/model/Definition.kt @@ -1,11 +1,14 @@ package fr.uca.iut.urbandictionarylight.model -data class Definition(val content: String, val example: String) { - private var upvotes: UInt = 0u +import androidx.room.Entity +import androidx.room.PrimaryKey - fun getUpvotes() = upvotes +const val NEW_DEFINITION_ID = 0L - fun upvote() { - upvotes++ - } -} \ No newline at end of file +@Entity(tableName = "definitions") +data class Definition( + val content: String, + val example: String, + var upvotes: Int = 0, + @PrimaryKey(autoGenerate = true) val id: Long = NEW_DEFINITION_ID +) \ No newline at end of file diff --git a/app/src/main/java/fr/uca/iut/urbandictionarylight/model/Dictionary.kt b/app/src/main/java/fr/uca/iut/urbandictionarylight/model/Dictionary.kt index b05b611..5f72e47 100644 --- a/app/src/main/java/fr/uca/iut/urbandictionarylight/model/Dictionary.kt +++ b/app/src/main/java/fr/uca/iut/urbandictionarylight/model/Dictionary.kt @@ -1,5 +1,9 @@ +// UHM THIS WILL PROBABLY BE THE REPOSITORY ITSELF + +/* package fr.uca.iut.urbandictionarylight.model +@Entity class Dictionary { private val entries: MutableSet = mutableSetOf() @@ -38,4 +42,4 @@ class Dictionary { } // TODO ? redefine equals and hashset ? -} \ No newline at end of file +}*/ diff --git a/app/src/main/java/fr/uca/iut/urbandictionarylight/model/Entry.kt b/app/src/main/java/fr/uca/iut/urbandictionarylight/model/Entry.kt index cf9f301..929debf 100644 --- a/app/src/main/java/fr/uca/iut/urbandictionarylight/model/Entry.kt +++ b/app/src/main/java/fr/uca/iut/urbandictionarylight/model/Entry.kt @@ -1,61 +1,12 @@ package fr.uca.iut.urbandictionarylight.model -import fr.uca.iut.urbandictionarylight.utils.Sorting +import androidx.room.Entity +import androidx.room.PrimaryKey -class Entry(val phrase: String) { - private val definitions: MutableSet = mutableSetOf() +const val NEW_ENTRY_ID = 0L - fun createDefinition(definition: Definition) { - if (definition.content.isNotBlank() && definition.example.isNotBlank()) { - definitions.add(definition) - } - } - - fun readDefinition(id: Int): Definition { - // TODO implement once ORM is in place - return Definition( - content = "poopy butt", - example = "Yeah, that's right -- poopy butt. This method hasn't been implemented yet." - ) - } - - fun readAllDefinitions() = definitions.toSet() - - // TODO implement - fun readAllDefinitions(criterion: Sorting): Set { - when (criterion) { - Sorting.ASC -> { - print("implement asc sorting!") - return readAllDefinitions() - } - Sorting.DESC -> { - print("implement desc sorting!") - return readAllDefinitions() - } - else -> return readAllDefinitions() - } - } - - fun updateDefinition(definition: Definition) { - // TODO implement once ORM is in place -// removeDefinition(definition.id) - createDefinition(definition) - } - - // TODO throw this away soon - fun updateDefinition(old: Definition, new: Definition) { - deleteDefinition(old) - createDefinition(new) - } - - fun deleteDefinition(definition: Definition) { - definitions.remove(definition) - } - - fun deleteDefinition(id: Int) { - // TODO implement once ORM is in place -// definitions.removeIf { def -> id == def.id } - } - - // TODO redefine equals and hashset -} \ No newline at end of file +@Entity(tableName = "entries") +data class Entry( + val phrase: String, + @PrimaryKey(autoGenerate = true) val id: Long = NEW_ENTRY_ID +) \ No newline at end of file diff --git a/app/src/main/java/fr/uca/iut/urbandictionarylight/model/EntryWithDefinitions.kt b/app/src/main/java/fr/uca/iut/urbandictionarylight/model/EntryWithDefinitions.kt new file mode 100644 index 0000000..2611045 --- /dev/null +++ b/app/src/main/java/fr/uca/iut/urbandictionarylight/model/EntryWithDefinitions.kt @@ -0,0 +1,12 @@ +package fr.uca.iut.urbandictionarylight.model + +import androidx.room.Embedded +import androidx.room.Relation + +data class EntryWithDefinitions( + @Embedded val entry: Entry, + @Relation( + parentColumn = "id", + entityColumn = "entryId" + ) val definitions: List +) \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 420d97f..05d671d 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -7,7 +7,7 @@ tools:context=".MainActivity"> + app:layout_constraintTop_toBottomOf="@+id/search_view" /> + android:layout_marginEnd="16dp" + android:text="@string/add_def_lbl" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toBottomOf="@+id/add_definition_btn" /> + android:text="@string/add_term_lbl" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/add_term_btn" /> \ No newline at end of file diff --git a/build.gradle b/build.gradle index a3b3ffd..04ced7c 100644 --- a/build.gradle +++ b/build.gradle @@ -3,4 +3,4 @@ plugins { id 'com.android.application' version '7.4.0' apply false id 'com.android.library' version '7.4.0' apply false id 'org.jetbrains.kotlin.android' version '1.7.10' apply false -} \ No newline at end of file +}