Created
September 4, 2018 00:39
-
-
Save rcketscientist/4e619aa75fd43ec9453af58f7c1add9a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import androidx.lifecycle.LiveData | |
import androidx.paging.DataSource | |
import androidx.room.* | |
import androidx.sqlite.db.SimpleSQLiteQuery | |
import androidx.sqlite.db.SupportSQLiteQuery | |
import com.anthonymandra.content.Meta | |
import com.anthonymandra.rawdroid.XmpFilter | |
import com.anthonymandra.util.DbUtil | |
import java.util.* | |
@Dao | |
abstract class MetadataDao { | |
@get:Query("SELECT uri, id FROM meta") | |
abstract val uriId: LiveData<List<UriIdResult>> | |
@get:Query("SELECT * FROM meta") | |
abstract val allImages: LiveData<List<MetadataEntity>> | |
val allMetadata: LiveData<List<MetadataTest>> = getImages() | |
@Query("SELECT COUNT(*) FROM meta") | |
abstract fun count(): Int | |
@RawQuery(observedEntities = [ MetadataEntity::class, SubjectJunction::class ]) | |
internal abstract fun internalGetImages(query: SupportSQLiteQuery): LiveData<List<MetadataTest>> | |
@RawQuery(observedEntities = [ MetadataEntity::class, SubjectJunction::class ]) | |
internal abstract fun internalGetImageFactory(query: SupportSQLiteQuery): DataSource.Factory<Int, MetadataTest> | |
@Transaction | |
@Query("SELECT * FROM meta WHERE id IN (:ids)") | |
internal abstract fun getImagesById(ids: List<Long>): DataSource.Factory<Int, MetadataTest> | |
@Transaction | |
@Query("SELECT * FROM meta WHERE uri = :uri") | |
abstract operator fun get(uri: String): LiveData<MetadataTest> | |
@Transaction | |
@Query("SELECT * FROM meta WHERE uri IN (:uris)") | |
abstract fun blocking(uris: List<String>): List<MetadataTest> | |
@Transaction | |
@Query("SELECT * FROM meta WHERE uri = :uri") | |
abstract fun blocking(uri: String): MetadataTest | |
@Transaction | |
@Query("SELECT * FROM meta WHERE uri IN (:uris)") | |
abstract fun stream(uris: List<String>): LiveData<List<MetadataTest>> | |
@Transaction | |
@Query("SELECT * FROM meta WHERE processed = 0") // 0 = true | |
abstract fun unprocessedImages() : List<MetadataTest> // TODO: maybe page this? | |
@Insert(onConflict = OnConflictStrategy.REPLACE) | |
internal abstract fun insert(datum: MetadataEntity): Long | |
@Insert(onConflict = OnConflictStrategy.REPLACE) | |
internal abstract fun insert(vararg datums: MetadataEntity): List<Long> | |
@Update | |
abstract fun update(vararg datums: MetadataEntity) | |
@Delete | |
abstract fun delete(vararg datums: MetadataEntity) | |
@Query("DELETE FROM meta WHERE id = :id") | |
abstract fun delete(id: Long) | |
@Query("DELETE FROM meta WHERE id IN (:ids)") | |
abstract fun delete(ids: List<Long>) | |
@Query("DELETE FROM meta") | |
abstract fun deleteAll() | |
// TODO: We could potentially use a static source in viewer to maintain order and update the | |
// appropriate meta tables when edited. | |
// fun getImageFactory(filter: XmpFilter) : PositionalDataSource<MetadataTest> { | |
// return internalGetImageFactory(this.createFilterQuery(filter)).create() | |
// } | |
fun getImageFactory(filter: XmpFilter) : DataSource.Factory<Int, MetadataTest> { | |
return internalGetImageFactory(this.createFilterQuery(filter)) | |
} | |
fun getImageFactory() : DataSource.Factory<Int, MetadataTest> { | |
return getImageFactory(XmpFilter()) | |
} | |
fun getImages(filter: XmpFilter) : LiveData<List<MetadataTest>> { | |
return internalGetImages(this.createFilterQuery(filter)) | |
} | |
/** | |
* get with default filter will return all with default sorting | |
*/ | |
private fun getImages() : LiveData<List<MetadataTest>> { | |
return getImages(XmpFilter()) | |
} | |
private fun createFilterQuery(filter: XmpFilter): SupportSQLiteQuery { | |
val query = StringBuilder() | |
val selection = StringBuilder() | |
val order = StringBuilder() | |
val selectionArgs = ArrayList<Any>() | |
val and = " AND " | |
val or = " OR " | |
val joiner = if (filter.andTrueOrFalse) and else or | |
if (filter.xmp != null) { | |
// Special case, append to join query | |
if (filter.xmp.subject.isNotEmpty()) { | |
if (!selection.isEmpty()) | |
selection.append(joiner) | |
selection.append(DbUtil.createIN("subjectId", filter.xmp.subject.size)) | |
filter.xmp.subject.mapTo(selectionArgs) { it.id } | |
} | |
if (filter.xmp.label.isNotEmpty()) { | |
if (!selection.isEmpty()) | |
selection.append(joiner) | |
selection.append(DbUtil.createIN(Meta.LABEL, filter.xmp.label.size)) | |
selectionArgs.addAll(filter.xmp.label) | |
} | |
if (filter.xmp.rating.isNotEmpty()) { | |
if (!selection.isEmpty()) | |
selection.append(joiner) | |
selection.append(DbUtil.createIN(Meta.RATING, filter.xmp.rating.size)) | |
filter.xmp.rating.mapTo(selectionArgs) { java.lang.Double.toString(it.toDouble()) } | |
} | |
} | |
if (filter.hiddenFolders.isNotEmpty()) { | |
if (selection.isNotEmpty()) | |
selection.append(and) // Always exclude the folders, don't OR | |
selection.append(DbUtil.createIN("parentId", filter.hiddenFolders, true)) | |
} | |
order.append(" ORDER BY ") | |
val direction = if (filter.sortAscending) " ASC" else " DESC" | |
if (filter.segregateByType) { | |
order.append(Meta.TYPE).append(" COLLATE NOCASE").append(" ASC, ") | |
} | |
when (filter.sortColumn) { | |
XmpFilter.SortColumns.Date -> order.append(Meta.TIMESTAMP).append(direction) | |
XmpFilter.SortColumns.Name -> order.append(Meta.NAME).append(" COLLATE NOCASE").append(direction) | |
} | |
query.append(relationQuery) | |
if (selection.isNotEmpty()) { | |
query.append(" WHERE ") | |
query.append(selection) | |
} | |
query.append(groupBy) | |
query.append(order) | |
return SimpleSQLiteQuery(query.toString(), selectionArgs.toArray()) | |
} | |
companion object { | |
/** | |
* If using a relation for subject this is a far simpler solution. | |
* Requires [groupBy] | |
*/ | |
private const val relationQuery = | |
"SELECT *" + | |
" FROM meta" + | |
" LEFT JOIN meta_subject_junction ON meta_subject_junction.metaId = meta.id" | |
private const val groupBy = " GROUP BY meta.id" | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment