Skip to content

Commit

Permalink
Rc uniqueness updates (#361)
Browse files Browse the repository at this point in the history
* Chapter audio directory change

- now includes source language in path

* Initial rc updates

- schema, dao, mapper, repository, directory provider updates

* Add book slug to project audio path

* Set derivedFromFk when creating project metadata
  • Loading branch information
mbr4477 authored and jsarabia committed Dec 18, 2018
1 parent e6abc14 commit d73c7e0
Show file tree
Hide file tree
Showing 10 changed files with 112 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class MainMenuViewModel : ViewModel() {
ImportResourceContainer.Result.UNSUPPORTED_CONTENT -> messages["importErrorUnsupportedContent"]
ImportResourceContainer.Result.IMPORT_ERROR -> messages["importErrorImportError"]
ImportResourceContainer.Result.LOAD_RC_ERROR -> messages["importErrorLoadRcError"]
ImportResourceContainer.Result.UNKNOWN_ERROR -> messages["importErrorUnknownError"]
ImportResourceContainer.Result.ALREADY_EXISTS -> messages["importErrorAlreadyExists"]
else -> null
}
showImportDialogProperty.value = false
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package org.wycliffeassociates.otter.jvm.persistence

import org.wycliffeassociates.otter.common.data.model.Collection
import org.wycliffeassociates.otter.common.data.model.ResourceMetadata
import org.wycliffeassociates.otter.common.persistence.IDirectoryProvider
import org.wycliffeassociates.resourcecontainer.ResourceContainer
import java.io.File
import java.nio.file.FileSystems

Expand Down Expand Up @@ -55,13 +57,16 @@ class DirectoryProvider(private val appName: String) : IDirectoryProvider {
}

override fun getProjectAudioDirectory(
sourceMetadata: ResourceMetadata,
book: Collection,
chapterDirName: String
): File {
// <user data directory>/{language slug}/{rc slug}/{book slug}/{%02d, chapter number}/
val appendedPath = listOf(
book.resourceContainer?.creator ?: ".",
sourceMetadata.creator,
"${sourceMetadata.language.slug}_${sourceMetadata.identifier}",
"v${book.resourceContainer?.version ?: "-none"}",
book.resourceContainer?.language?.slug ?: "no_language",
book.resourceContainer?.identifier ?: "no_rc",
book.slug,
chapterDirName
).joinToString(separator)
Expand All @@ -70,6 +75,33 @@ class DirectoryProvider(private val appName: String) : IDirectoryProvider {
return path
}

override fun getSourceContainerDirectory(container: ResourceContainer): File {
val dublinCore = container.manifest.dublinCore
val appendedPath = listOf(
"src",
dublinCore.creator,
"${dublinCore.language.identifier}_${dublinCore.identifier}",
"v${dublinCore.version}"
).joinToString(separator)
val path = resourceContainerDirectory.resolve(appendedPath)
path.mkdirs()
return path
}

override fun getDerivedContainerDirectory(metadata: ResourceMetadata, source: ResourceMetadata): File {
val appendedPath = listOf(
"der",
metadata.creator,
source.creator,
"${source.language.slug}_${source.identifier}",
"v${metadata.version}",
metadata.language.slug
).joinToString(separator)
val path = resourceContainerDirectory.resolve(appendedPath)
path.mkdirs()
return path
}

override val resourceContainerDirectory: File
get() = getAppDataDirectory("rc")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ class RecordMappers {
record.getValue(DUBLIN_CORE_ENTITY.TYPE),
record.getValue(DUBLIN_CORE_ENTITY.TITLE),
record.getValue(DUBLIN_CORE_ENTITY.VERSION),
record.getValue(DUBLIN_CORE_ENTITY.PATH)
record.getValue(DUBLIN_CORE_ENTITY.PATH),
record.getValue(DUBLIN_CORE_ENTITY.DERIVEDFROM_FK)
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ class ResourceMetadataDao(
DUBLIN_CORE_ENTITY.TYPE,
DUBLIN_CORE_ENTITY.TITLE,
DUBLIN_CORE_ENTITY.VERSION,
DUBLIN_CORE_ENTITY.PATH
DUBLIN_CORE_ENTITY.PATH,
DUBLIN_CORE_ENTITY.DERIVEDFROM_FK
)
.values(
entity.conformsTo,
Expand All @@ -90,7 +91,8 @@ class ResourceMetadataDao(
entity.type,
entity.title,
entity.version,
entity.path
entity.path,
entity.derivedFromFk
)
.execute()

Expand Down Expand Up @@ -139,6 +141,7 @@ class ResourceMetadataDao(
.set(DUBLIN_CORE_ENTITY.TITLE, entity.title)
.set(DUBLIN_CORE_ENTITY.VERSION, entity.version)
.set(DUBLIN_CORE_ENTITY.PATH, entity.path)
.set(DUBLIN_CORE_ENTITY.DERIVEDFROM_FK, entity.derivedFromFk)
.where(DUBLIN_CORE_ENTITY.ID.eq(entity.id))
.execute()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@ data class ResourceMetadataEntity(
var type: String,
var title: String,
var version: String,
var path: String
var path: String,
var derivedFromFk: Int?
)
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import org.wycliffeassociates.resourcecontainer.ResourceContainer
import org.wycliffeassociates.resourcecontainer.entity.*
import java.io.File
import java.lang.NullPointerException
import java.lang.RuntimeException
import java.time.LocalDate


Expand Down Expand Up @@ -74,12 +75,18 @@ class CollectionRepository(
metadataDao.delete(metadataMapper.mapToEntity(metadata))
}
}
// 5. If project audio should be deleted, get the folder for the project audio and delete it
if (deleteAudio) {
val audioDirectory = directoryProvider.getProjectAudioDirectory(project, ".").parentFile
audioDirectory.deleteRecursively()
}
}.subscribeOn(Schedulers.io())
}.andThen(
getSource(project).doOnSuccess {
// If project audio should be deleted, get the folder for the project audio and delete it
if (deleteAudio) {
val audioDirectory = directoryProvider.getProjectAudioDirectory(
it.resourceContainer ?: throw RuntimeException("No source metadata found."),
project, ".").parentFile
audioDirectory.deleteRecursively()
}
}.ignoreElement()
)
.subscribeOn(Schedulers.io())
}

override fun getAll(): Single<List<Collection>> {
Expand Down Expand Up @@ -186,25 +193,30 @@ class CollectionRepository(
val metadata = source.resourceContainer
metadata ?: throw NullPointerException("Source has no resource metadata")

val slug = "${targetLanguage.slug}_${metadata.identifier}"
val directory = directoryProvider.resourceContainerDirectory.resolve(slug)
val dublinCore = dublincore {
identifier = metadata.identifier
issued = LocalDate.now().toString()
modified = LocalDate.now().toString()
language = language {
identifier = targetLanguage.slug
direction = targetLanguage.direction
title = targetLanguage.name
}
creator = "otter"
version = metadata.version
format = "text/usfm"
subject = metadata.subject
type = "book"
title = metadata.title
}
val directory = directoryProvider.getDerivedContainerDirectory(
dublinCore.mapToMetadata(File("."), targetLanguage),
metadata
)
val container = ResourceContainer.create(directory) {
// Set up the manifest
manifest = Manifest(
dublincore {
identifier = metadata.identifier
issued = LocalDate.now().toString()
modified = LocalDate.now().toString()
language = language {
identifier = targetLanguage.slug
direction = targetLanguage.direction
title = targetLanguage.name
}
format = "text/usfm"
subject = metadata.subject
type = "book"
title = metadata.title
},
dublinCore,
listOf(),
Checking()
)
Expand All @@ -222,6 +234,9 @@ class CollectionRepository(
val matches = existingMetadata.filter {
it.identifier == source.resourceContainer?.identifier
&& it.languageFk == language.id
&& it.creator == "otter"
&& it.version == source.resourceContainer?.version
&& it.derivedFromFk == source.resourceContainer?.id
}

val metadataEntity = if (matches.isEmpty()) {
Expand All @@ -233,6 +248,7 @@ class CollectionRepository(

// Insert ResourceMetadata into database
val entity = metadataMapper.mapToEntity(metadata)
entity.derivedFromFk = source.resourceContainer?.id
entity.id = metadataDao.insert(entity, dsl)
/* return@if */ entity
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.wycliffeassociates.otter.jvm.persistence.repositories

import io.reactivex.Completable
import io.reactivex.Maybe
import io.reactivex.Single
import io.reactivex.schedulers.Schedulers
import org.wycliffeassociates.otter.common.data.model.ResourceMetadata
Expand All @@ -9,6 +10,7 @@ import org.wycliffeassociates.otter.jvm.persistence.database.AppDatabase
import org.wycliffeassociates.otter.jvm.persistence.entities.ResourceMetadataEntity
import org.wycliffeassociates.otter.jvm.persistence.repositories.mapping.LanguageMapper
import org.wycliffeassociates.otter.jvm.persistence.repositories.mapping.ResourceMetadataMapper
import java.sql.DatabaseMetaData

class ResourceMetadataRepository(
database: AppDatabase,
Expand Down Expand Up @@ -36,6 +38,15 @@ class ResourceMetadataRepository(
.subscribeOn(Schedulers.io())
}

override fun getSource(metadata: ResourceMetadata): Maybe<ResourceMetadata> {
return Maybe
.fromCallable {
resourceMetadataDao.fetchById(metadata.id).derivedFromFk
}
.map { buildMetadata(resourceMetadataDao.fetchById(it)) }
.subscribeOn(Schedulers.io())
}

override fun getLinked(metadata: ResourceMetadata): Single<List<ResourceMetadata>> {
return Single
.fromCallable {
Expand All @@ -46,10 +57,21 @@ class ResourceMetadataRepository(
.subscribeOn(Schedulers.io())
}

override fun updateSource(metadata: ResourceMetadata, source: ResourceMetadata?): Completable {
return Completable
.fromAction {
val updated = metadataMapper.mapToEntity(metadata, source?.id)
resourceMetadataDao.update(updated)
}
.subscribeOn(Schedulers.io())
}

override fun update(obj: ResourceMetadata): Completable {
return Completable
.fromAction {
resourceMetadataDao.update(metadataMapper.mapToEntity(obj))
val existing = resourceMetadataDao.fetchById(obj.id)
val updated = metadataMapper.mapToEntity(obj, existing.derivedFromFk)
resourceMetadataDao.update(updated)
}
.subscribeOn(Schedulers.io())
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class ResourceMetadataMapper {
)
}

fun mapToEntity(obj: ResourceMetadata): ResourceMetadataEntity {
fun mapToEntity(obj: ResourceMetadata, derivedFromFk: Int? = null): ResourceMetadataEntity {
return ResourceMetadataEntity(
obj.id,
obj.conformsTo,
Expand All @@ -43,7 +43,8 @@ class ResourceMetadataMapper {
obj.type,
obj.title,
obj.version,
obj.path.toURI().path
obj.path.toURI().path,
derivedFromFk
)
}
}
2 changes: 1 addition & 1 deletion src/main/resources/Messages_en.properties
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ importErrorInvalidContent = Invalid or corrupted resource container content
importErrorUnsupportedContent = Unsupported content file found
importErrorImportError = Failed to save resource container. Try restarting the application.
importErrorLoadRcError = Failed to parse resource container metadata
importErrorUnknownError = Failed with unknown error
importErrorAlreadyExists = The resource container has already been imported
audioEditor = Audio Editor
audioRecorder = Audio Recorder
noProjects = No Projects Available
Expand Down
4 changes: 3 additions & 1 deletion src/main/resources/sql/CreateAppDb.sql
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ CREATE TABLE IF NOT EXISTS dublin_core_entity (
type TEXT NOT NULL,
title TEXT NOT NULL,
version TEXT NOT NULL,
path TEXT NOT NULL
path TEXT NOT NULL,
derivedFrom_fk INTEGER REFERENCES dublin_core_entity(id),
UNIQUE (language_fk, identifier, version, creator, derivedFrom_fk)
);

CREATE TABLE IF NOT EXISTS rc_link_entity (
Expand Down

0 comments on commit d73c7e0

Please sign in to comment.