Skip to content

Commit

Permalink
Added prefillForm method in FormsInteractor.
Browse files Browse the repository at this point in the history
  • Loading branch information
chinmoy12c committed Mar 17, 2023
1 parent 1a0ec8f commit 3856173
Show file tree
Hide file tree
Showing 6 changed files with 123 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@
import org.odk.collect.android.utilities.AuthDialogUtility;
import org.odk.collect.android.utilities.FormsRepositoryProvider;
import org.odk.collect.android.utilities.InstancesRepositoryProvider;
import org.odk.collect.android.utilities.MediaUtils;
import org.odk.collect.android.utilities.ProjectResetter;
import org.odk.collect.android.utilities.ThemeUtils;
import org.odk.collect.android.widgets.ExStringWidget;
Expand Down Expand Up @@ -349,4 +350,6 @@ interface Builder {
ServerFormsDetailsFetcher providesServerFormsDetailsFetcher();

FormDownloader providesFormDownloader();

MediaUtils providesMediaUtils();
}
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,8 @@ public SaveToDiskResult saveForm(FormSaver.ProgressListener progressListener) {
}

// close all open databases of external data.
Collect.getInstance().getExternalDataManager().close();
if (Collect.getInstance().getExternalDataManager() != null)
Collect.getInstance().getExternalDataManager().close();

// if there is a meta/instanceName field, be sure we are using the latest value
// just in case the validate somehow triggered an update.
Expand Down
8 changes: 8 additions & 0 deletions odk/extension/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ dependencies {
api project(":odk:collect:settings")
api project(":odk:collect:permissions")
api project(":odk:collect:strings")
implementation project(":odk:collect:analytics")

implementation packages.androidx_core_ktx
implementation packages.androidx_appcompat
Expand All @@ -55,6 +56,13 @@ dependencies {
implementation packages.kotlinx_coroutines_android
implementation packages.rx_java
implementation packages.rx_android
implementation(packages.javarosa) {
exclude group: 'commons-io'
exclude group: 'joda-time'
exclude group: 'org.slf4j'
exclude group: 'org.hamcrest', module: 'hamcrest-all'
}
implementation project(path: ':odk:collect:entities')
compileOnly packages.firebase_analytics
compileOnly packages.firebase_storage
compileOnly packages.firebase_config
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,23 @@ import android.util.Log
import io.samagra.odk.collect.extension.interactors.FormsDatabaseInteractor
import io.samagra.odk.collect.extension.interactors.FormsInteractor
import io.samagra.odk.collect.extension.listeners.FormsProcessListener
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import org.javarosa.core.model.FormDef
import org.odk.collect.android.activities.FormEntryActivity
import org.odk.collect.android.events.FormEventBus
import org.odk.collect.android.external.FormsContract
import org.odk.collect.android.formentry.loading.FormInstanceFileCreator
import org.odk.collect.android.formentry.saving.DiskFormSaver
import org.odk.collect.android.listeners.FormLoaderListener
import org.odk.collect.android.projects.CurrentProjectProvider
import org.odk.collect.android.storage.StoragePathProvider
import org.odk.collect.android.tasks.FormLoaderTask
import org.odk.collect.android.tasks.SaveFormToDisk
import org.odk.collect.android.utilities.ApplicationConstants
import org.odk.collect.android.utilities.MediaUtils
import org.odk.collect.entities.EntitiesRepository
import org.odk.collect.forms.Form
import org.w3c.dom.Document
import java.io.File
Expand All @@ -22,8 +35,11 @@ import javax.xml.transform.dom.DOMSource
import javax.xml.transform.stream.StreamResult

class ODKFormsHandler @Inject constructor(
private val currentProjectProvider: CurrentProjectProvider,
private val formsDatabaseInteractor: FormsDatabaseInteractor
private val currentProjectProvider: CurrentProjectProvider,
private val formsDatabaseInteractor: FormsDatabaseInteractor,
private val storagePathProvider: StoragePathProvider,
private val mediaUtils: MediaUtils,
private val entitiesRepository: EntitiesRepository
): FormsInteractor {

override fun openFormWithFormId(formId: String, context: Context) {
Expand All @@ -46,6 +62,59 @@ class ODKFormsHandler @Inject constructor(
openForm(form, context)
}

override fun prefillForm(formId: String, tagValueMap: HashMap<String, String>) {
CoroutineScope(Job()).launch {
val form = formsDatabaseInteractor.getLatestFormById(formId)
val formInstanceUri = FormsContract.getUri(currentProjectProvider.getCurrentProject().uuid, form?.dbId)
if (form != null && formInstanceUri != null) {
val formLoaderTask = FormLoaderTask(null, null, null)
formLoaderTask.setFormLoaderListener(object: FormLoaderListener {
override fun onProgressStep(stepMessage: String?) {}
override fun loadingComplete(task: FormLoaderTask?, fd: FormDef?, warningMsg: String?) {
val formController = formLoaderTask.formController
if (formController != null) {
val formInstanceFileCreator = FormInstanceFileCreator(
storagePathProvider
) { System.currentTimeMillis() }
val instanceFile = formInstanceFileCreator.createInstanceFile(form.formFilePath)
if (instanceFile != null) {
formController.setInstanceFile(instanceFile)
val saveToDiskResult = DiskFormSaver().save(
formInstanceUri, formController, mediaUtils, false,
false, null, {}, null, arrayListOf(),
currentProjectProvider.getCurrentProject().uuid, entitiesRepository
)
if (saveToDiskResult.saveResult == SaveFormToDisk.SAVED) {
updateForm(instanceFile.absolutePath, tagValueMap, null)
FormEventBus.formSaved(formId, instanceFile.absolutePath)
}
else {
FormEventBus.formSaveError(formId, "Form could not be saved!")
}
} else {
FormEventBus.formOpenFailed(formId, "Form instance could not be created!")
}
}
else {
FormEventBus.formOpenFailed(formId, "FormController is null!")
}
}
override fun loadingError(errorMsg: String?) {
FormEventBus.formOpenFailed(formId, errorMsg ?: "Form cannot be loaded!")
}
})
formLoaderTask.execute(form.formFilePath)
}
else {
FormEventBus.formOpenFailed(formId, "Form does not exist in database!")
}
}
}

override fun prefillForm(formId: String, tag: String, value: String) {
prefillForm(formId, hashMapOf(tag to value))
}

private fun openForm(form: Form, context: Context) {
val contentUri = FormsContract.getUri(currentProjectProvider.getCurrentProject().uuid, form.dbId)
val formEntryIntent = Intent(context, FormEntryActivity::class.java)
Expand All @@ -58,8 +127,7 @@ class ODKFormsHandler @Inject constructor(
context.startActivity(formEntryIntent)
}

override fun updateForm(form: Form, tag: String, tagValue: String, listener: FormsProcessListener?) {
val formPath: String = form.formFilePath
override fun updateForm(formPath: String, tag: String, tagValue: String, listener: FormsProcessListener?) {
var fos: FileOutputStream? = null
try {
val factory = DocumentBuilderFactory.newInstance()
Expand Down Expand Up @@ -89,14 +157,10 @@ class ODKFormsHandler @Inject constructor(
}
}

override fun updateForm(
form: Form,
values: HashMap<String, String>,
listener: FormsProcessListener?
) {
override fun updateForm(formPath: String, values: HashMap<String, String>, listener: FormsProcessListener?) {
var progress = 0
for (entry in values.entries) {
updateForm(form, entry.key, entry.value, object : FormsProcessListener {
updateForm(formPath, entry.key, entry.value, object : FormsProcessListener {
override fun onProcessed() {
progress++
if (progress == values.size)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,35 @@ interface FormsInteractor {
/** Opens a form with the given md5 hash. */
fun openFormWithMd5Hash(md5Hash: String, context: Context)

/** Prefills the values of a form given a tag and value. */
fun updateForm(form: Form, tag: String, tagValue: String, listener: FormsProcessListener?)
/**
* This function is used to prefill a single form field.
* This function takes three parameters: the unique identifier of the ODK form,
* the tag or name of the form field, and the value to be pre-filled in the form field.
* Note: This creates a separate form instance of the original form and does not alter
* the original form in any way.
*/
fun prefillForm(formId: String, tag: String, value: String)

/** Prefills the values of a form given a list of tags and values. */
fun updateForm(form: Form, values: HashMap<String, String>,listener: FormsProcessListener?)
/**
* This function is used to prefill multiple form fields.
* This function takes two parameters: the unique identifier of the ODK form
* and a map of tag-value pairs.
* Note: This creates a separate form instance of the original form and does not alter
* the original form in any way.
*/
fun prefillForm(formId: String, tagValueMap: HashMap<String, String>)

/**
* Prefills the values of a form given a tag and value. The formPath may be the
* path of a form itself or an instance of a form.
* Note: This modifies the original form described by the form path.
*/
fun updateForm(formPath: String, tag: String, tagValue: String, listener: FormsProcessListener?)

/**
* Prefills the values of a form given a list of tags and values. The formPath may be the
* path of a form itself or an instance of a form.
* Note: This modifies the original form described by the form path.
*/
fun updateForm(formPath: String, values: HashMap<String, String>,listener: FormsProcessListener?)
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,12 @@ class FormsInteractorModule {
@Singleton
@ODKFormsInteractor
fun getODKFormsHandler(application: Application): FormsInteractor {
val currentProjectProvider = DaggerAppDependencyComponent.builder().application(application).build().currentProjectProvider()
val appDependencyComponent = DaggerAppDependencyComponent.builder().application(application).build()
val currentProjectProvider = appDependencyComponent.currentProjectProvider()
val mediaUtils = appDependencyComponent.providesMediaUtils()
val storagePathProvider = appDependencyComponent.storagePathProvider()
val entitiesRepository = appDependencyComponent.entitiesRepositoryProvider().get(currentProjectProvider.getCurrentProject().uuid)
val formsDatabaseInteractor = DaggerFormsDatabaseInteractorComponent.factory().create(application).getFormsDatabaseInteractor()
return ODKFormsHandler(currentProjectProvider, formsDatabaseInteractor)
return ODKFormsHandler(currentProjectProvider, formsDatabaseInteractor, storagePathProvider, mediaUtils, entitiesRepository)
}
}

0 comments on commit 3856173

Please sign in to comment.