Realm
// Don't forget to apply realm plugin.
// See build.gradle(app and project)
// MyApp
private fun initRealm() {
Realm.init(this)
val configuration = RealmConfiguration.Builder().build()
// val configuration = RealmConfiguration.Builder()
// .name(Realm.DEFAULT_REALM_NAME)
// .schemaVersion(0)
// .deleteRealmIfMigrationNeeded()
// .build()
Realm.setDefaultConfiguration(configuration)
}
// build.gradle
/* Realm */
compile 'io.realm:android-adapters:1.3.0'
class RealmController(val realm: Realm) {
/** Groups */
fun addBooksToGroup(group: Group, books: ArrayList<Book>) {
// I want to check if there some books in a specific group
// inside realm which are not returned anymore from backend
val oldBooks = realm.copyFromRealm(getGroupBooks(group))
for (newBook in books) {
// removing books existing in backend response leaves only books to delete from realm
oldBooks.remove(newBook)
val book = realm.where(Book::class.java).equalTo("id", newBook.id).findFirst() ?: newBook
val time = System.currentTimeMillis()
val groupName = realm.where(RealmString::class.java).equalTo("name", group.name).findFirst()
realm.executeTransaction {
// keep only data that needed locally
// override the rest
book.isBought = newBook.isBought
book.dateAdd = time
book.createdAt = newBook.createdAt
book.icon = newBook.icon
if (groupName == null || !book.group.contains(groupName)) book.group.add(RealmString(group.name))
realm.copyToRealmOrUpdate(book)
}
}
removeBooksFromGroup(oldBooks, group)
if (books.isNotEmpty())logGroups(books[0])
}
private fun removeBooksFromGroup(books: List<Book>, group: Group) {
for (book in books) {
val oldBook = getBook(book.id) ?: continue
val groupName = realm.where(RealmString::class.java).equalTo("name", group.name).findFirst() ?: continue
realm.executeTransaction {
oldBook.group.remove(groupName)
}
}
}
fun getGroupBooks(group: Group): RealmResults<Book> {
var results = realm.where(Book::class.java).contains("group.name", group.name).findAll()
if (group == Group.new) results = results.sort("createdAt", Sort.DESCENDING)
else results = results.sort("id", Sort.ASCENDING)
return results
}
/** Bookmarks */
fun getBookmarkedBooks(): RealmResults<Book> {
return realm.where(Book::class.java).equalTo("inBookmark", 1).findAll()
}
fun setBookmarked(book: Book, add: Boolean) {
val mBook = getBook(book.id) ?: book
realm.executeTransaction {
mBook.inBookmark = if (add) 1 else 0
}
}
fun deleteFromBookmarks(book: Book) {
setBookmarked(book, false)
}
fun markBooksAsBookmarked(books: List<Book>) {
for (book in books) {
setBookmarked(book, true)
}
if (books.isNotEmpty()) logGroups(books[0])
}
/** History */
fun addToHistory(book: Book) {
val time = System.currentTimeMillis()
val oldBook = realm.where(Book::class.java).equalTo("id", book.id).findFirst() ?: book
realm.executeTransaction {
// keep only data that needed locally
// override the rest
oldBook.dateView = time
// if (oldBook.description.isNotEmpty()) book.description = oldBook.description
if (oldBook.dateAdd == 0.toLong()) oldBook.dateAdd = time
oldBook.size = book.size
oldBook.duration = book.duration
oldBook.icon = book.icon
oldBook.authors = book.authors
// oldBook.readers = book.readers
// book.files = oldBook.files
realm.copyToRealmOrUpdate(oldBook)
}
}
fun getHistoryBooks(): RealmResults<Book> {
return realm.where(Book::class.java).greaterThan("dateView", 0).findAll().sort("dateView", Sort.DESCENDING)
}
/** Book */
fun getBook(bookId: Int): Book? {
return realm.where(Book::class.java).equalTo("id", bookId).findFirst()
}
fun savePlayedBook(playedBook: PlayedBook) {
realm.executeTransaction {
realm.copyToRealmOrUpdate(playedBook)
}
}
fun getPlayedBook(id: Int): PlayedBook? {
val playedBook = realm.where(PlayedBook::class.java).equalTo("id", id).findFirst() ?: return null
return realm.copyFromRealm(playedBook)
}
fun deletePlayedBook(id: Int) {
realm.executeTransaction {
realm.where(PlayedBook::class.java).equalTo("id", id).findAll().deleteAllFromRealm()
}
}
/** Book Files*/
fun saveBookFiles(book: Book, files: ArrayList<BookFile>): RealmResults<BookFile> {
realm.executeTransaction {
book.files.addAll(files)
realm.copyToRealmOrUpdate(book)
}
val results = realm.where(BookFile::class.java).equalTo("bookId", book.id).findAllAsync()
return results
}
fun getBookFiles(bookId: Int): RealmResults<BookFile> {
// return only BookFiles where at least one item has localPath set
val result = realm.where(BookFile::class.java).equalTo("bookId", bookId)/*.isNotEmpty("localPath")*/.findAll().sort("trackNumber", Sort.ASCENDING)
return result
}
fun getBookFile(id: Int, name: String?): BookFile? {
return realm.where(BookFile::class.java).equalTo("bookId", id).equalTo("filename", name).findFirst()
}
fun deleteDemoFile(id: Int) {
realm.where(BookFile::class.java).equalTo("bookId", id).equalTo("id", 0).findAll().deleteAllFromRealm()
}
fun deleteBookFiles(bookId: Int) {
realm.executeTransaction { realm ->
val results = realm.where(BookFile::class.java).equalTo("bookId", bookId).findAll()
results.deleteAllFromRealm()
}
}
fun removeBook(id: Int) {
realm.executeTransaction {
realm.where(Book::class.java).equalTo("id", id).findAll().deleteAllFromRealm()
}
}
fun hasBookFiles(id: Int): Boolean {
val result = realm.where(BookFile::class.java).equalTo("bookId", id).findAll()
return result.isNotEmpty()
}
/** Categories */
//find all objects in the Book.class
fun getCategories(): RealmResults<Category> {
return realm.where(Category::class.java).findAllSorted("name")
}
fun saveCategories(categories: ArrayList<Category>) {
// I want to check if there some categories
// inside realm which are not returned anymore from backend
val oldCategories = realm.copyFromRealm(getCategories())
for (newCategory in categories) {
oldCategories.remove(newCategory)
realm.executeTransaction {
realm.copyToRealmOrUpdate(newCategory)
}
}
// delete all categories which are not in backend results anymore
for (oldCategory in oldCategories) {
realm.executeTransaction {
realm.where(Category::class.java).equalTo("id", oldCategory.id).findAll().deleteAllFromRealm()
}
}
}
/** Collections */
fun addCustomCollections(newCollections: List<CustomCollection>) {
realm.executeTransaction {
// First, remove stored in realm collections
realm.delete(CustomCollection::class.java)
// Then, store new CustomCollections
realm.copyToRealmOrUpdate(newCollections)
}
}
fun getCustomCollections(): RealmResults<CustomCollection> {
return realm.where(CustomCollection::class.java).findAllSorted("ordering")
}
/** Other */
fun logGroups(book: Book) {
for (group in book.group) {
Log.d("RealmController", "setBookmarked, group = ${group.name}")
}
}
/** Bought books*/
fun getBoughtBooks(): RealmResults<Book> {
return realm.where(Book::class.java).equalTo("isBought", 1).findAll()
}
fun setBought(bookId: Int) {
val book = getBook(bookId) ?: return
realm.executeTransaction {
book.isBought = 1
realm.copyToRealmOrUpdate(book)
}
}
fun markBooksAsBought(books: List<Book>) {
for (newBook in books) {
val book = realm.where(Book::class.java).equalTo("id", newBook.id).findFirst() ?: newBook
realm.executeTransaction {
book.isBought = 1
realm.copyToRealmOrUpdate(book)
}
}
if (books.isNotEmpty()) logGroups(books[0])
}
/** ListenBookFragment */
//
fun saveProgress(bookId: Int, duration: Long) {
if (duration == 0.toLong()) return
val book = getBook(bookId) ?: return
val progressPercent = duration * 100 / book.duration
val progress = if (progressPercent > 0) progressPercent else 1
realm.executeTransaction {
book.progress = progress
realm.copyToRealmOrUpdate(book)
}
}
fun getListenedBooks(): RealmResults<Book> {
return realm.where(Book::class.java).greaterThan("progress", 0).findAll()
}
fun deleteBookFromListened(bookId: Int) {
val book = getBook(bookId) ?: return
realm.executeTransaction {
book.progress = 0
}
}
fun saveLocalPath(id: Int, path: String, name: String?) {
val bookFile = getBookFile(id, name) ?: return
if (bookFile.localPath.isEmpty()) realm.executeTransaction { bookFile.localPath = path + name }
}
fun filterBoughtBooks(query: String): RealmResults<Book> {
val queryCap = query.substring(0, 1).toUpperCase() + query.substring(1)
return realm.where(Book::class.java).equalTo("isBought", 1)
.contains("name", query, Case.INSENSITIVE)
.or().contains("name", queryCap)
.or().contains("authors", query)
.or().contains("authors", queryCap)
.findAll()
}
fun saveDownloadProgress(bookId: Int, downloadProgress: Long) {
val book = realm.where(Book::class.java).equalTo("id", bookId).findFirst() ?: return
realm.executeTransaction {
book.downloadProgress = downloadProgress
}
}
fun cleanBook(bookId: Int) {
deleteBookFiles(bookId)
deletePlayedBook(bookId)
deleteBookFromListened(bookId)
}
fun <R: RealmModel> detach(realmObject: R): R {
return realm.copyFromRealm(realmObject)
}
fun saveBookFilePath(fileId: Int, filePath: String) {
val file = realm.where(BookFile::class.java).equalTo("id", fileId).findFirst() ?: return
realm.executeTransaction {
file.pathfile = filePath
realm.copyToRealmOrUpdate(file)
}
}
fun getUnmanagedBookFiles(bookId: Int): RealmResults<BookFile> {
// return only BookFiles where at least one item has localPath set
val result = realm.where(BookFile::class.java).equalTo("bookId", bookId).isEmpty("localPath").findAll()
return result
}
fun setBookmarked(book: Book) {
val mBook = getBook(book.id) ?: book
realm.executeTransaction {
mBook.inBookmark = if (mBook.inBookmark == 0) 1 else 0
realm.copyToRealmOrUpdate(mBook)
}
}
private fun isInHistory(id: Int): Boolean {
val book = realm.where(Book::class.java).equalTo("id", id).findFirst() ?: return false
return book.dateView != 0.toLong()
}
fun isInBookmarks(id: Int): Boolean {
val book = getBook(id) ?: return false
return book.inBookmark == 1
}
}
// example on how to populate realm with dummy objects
private val INTEGER_COUNTER = AtomicInteger(0)
private fun putItemsIntoRealm() {
(1..10).forEach { i ->
val item = HistoryItem(INTEGER_COUNTER.getAndIncrement(), "surname $i", "name $i", "code $i", "date $i")
realm.executeTransaction {
realm.copyToRealmOrUpdate(item)
}
}
}
@RealmClass
open class Book(@PrimaryKey var id: Int = 0,
@SerializedName("price_sale") var priceSale: Int = 0,
var status: Int = 0,
var publisher: String = "",
var files: RealmList<BookFile> = RealmList(),
var group: RealmList<RealmString> = RealmList()): RealmModel {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other?.javaClass != javaClass) return false
other as Book
if (id != other.id) return false
return true
}
override fun hashCode(): Int {
return id
}
}