diff --git a/odk/collect/collect_app/src/main/java/org/odk/collect/android/events/FormEventExporter.kt b/odk/collect/collect_app/src/main/java/org/odk/collect/android/events/FormEventExporter.kt index 7d7080eb174..23c1f51fb25 100644 --- a/odk/collect/collect_app/src/main/java/org/odk/collect/android/events/FormEventExporter.kt +++ b/odk/collect/collect_app/src/main/java/org/odk/collect/android/events/FormEventExporter.kt @@ -1,5 +1,7 @@ package org.odk.collect.android.events +import org.json.JSONObject + /** * Events exporter class for form events. This class contains all the * events that occur during the lifecycle of a form. @@ -21,8 +23,8 @@ object FormEventExporter: ODKEventExporter() { state.onNext(FormStateEvent.OnFormSaveError(formId, errorMessage)) } - fun formUploaded(formId: String, instancePath: String) { - state.onNext(FormStateEvent.OnFormUploaded(formId, instancePath)) + fun formUploaded(formId: String, submittedData: JSONObject) { + state.onNext(FormStateEvent.OnFormUploaded(formId, submittedData)) } fun formUploadError(formId: String, errorMessage: String) { @@ -51,7 +53,7 @@ sealed class FormStateEvent { data class OnFormSaveError(val formId: String, val errorMessage: String): FormStateEvent() /** Called when a form upload is successful. */ - data class OnFormUploaded(val formId: String, val instancePath: String): FormStateEvent() + data class OnFormUploaded(val formId: String, val submittedData: JSONObject): FormStateEvent() /** Called when a form upload fails. */ data class OnFormUploadFailed(val formId: String, val errorMessage: String): FormStateEvent() diff --git a/odk/collect/collect_app/src/main/java/org/odk/collect/android/instancemanagement/autosend/InstanceAutoSender.kt b/odk/collect/collect_app/src/main/java/org/odk/collect/android/instancemanagement/autosend/InstanceAutoSender.kt index 585d2be2350..3c2fc96a57d 100644 --- a/odk/collect/collect_app/src/main/java/org/odk/collect/android/instancemanagement/autosend/InstanceAutoSender.kt +++ b/odk/collect/collect_app/src/main/java/org/odk/collect/android/instancemanagement/autosend/InstanceAutoSender.kt @@ -14,6 +14,8 @@ import org.odk.collect.android.projects.ProjectDependencyProvider import org.odk.collect.android.upload.FormUploadException import org.odk.collect.forms.instances.Instance import org.odk.collect.permissions.PermissionsProvider +import org.odk.collect.utilities.XmlJsonUtility +import java.io.File class InstanceAutoSender( private val instanceAutoSendFetcher: InstanceAutoSendFetcher, @@ -46,7 +48,12 @@ class InstanceAutoSender( val result: Map = instanceSubmitter.submitInstances(toUpload) result.entries.stream().forEach { entry -> if (entry.value == null) { - FormEventExporter.formUploaded(entry.key.formId, entry.key.instanceFilePath) + try { + val submittedData = XmlJsonUtility.convertToJson(File(entry.key.instanceFilePath)) + FormEventExporter.formUploaded(entry.key.formId, submittedData) + } catch (e: Exception) { + FormEventExporter.formUploadError(entry.key.formId, e.message ?: "Failed to read submitted data!") + } } else { FormEventExporter.formUploadError(entry.key.formId, entry.value!!.message) diff --git a/odk/collect/collect_app/src/main/java/org/odk/collect/utilities/XmlJsonUtility.kt b/odk/collect/collect_app/src/main/java/org/odk/collect/utilities/XmlJsonUtility.kt new file mode 100644 index 00000000000..9ed2cdb72ab --- /dev/null +++ b/odk/collect/collect_app/src/main/java/org/odk/collect/utilities/XmlJsonUtility.kt @@ -0,0 +1,66 @@ +package org.odk.collect.utilities + +import org.json.JSONArray +import org.json.JSONException +import org.json.JSONObject +import org.xmlpull.v1.XmlPullParser +import org.xmlpull.v1.XmlPullParserException +import org.xmlpull.v1.XmlPullParserFactory +import java.io.File +import java.io.IOException +import java.io.StringReader + +object XmlJsonUtility { + + @Throws(XmlPullParserException::class, IOException::class, JSONException::class) + fun convertToJson(xml: String?): JSONObject { + val factory = XmlPullParserFactory.newInstance() + val parser = factory.newPullParser() + parser.setInput(StringReader(xml)) + val jsonObject = JSONObject() + var jsonArray = JSONArray() + var tagName = "" + var eventType = parser.eventType + while (eventType != XmlPullParser.END_DOCUMENT) { + when (eventType) { + XmlPullParser.START_DOCUMENT -> {} + XmlPullParser.START_TAG -> { + tagName = parser.name + if (jsonObject.has(tagName)) { + // If the tag already exists in the object, convert it to an array + val existingValue = jsonObject[tagName] + if (existingValue is JSONArray) { + jsonArray = existingValue + } else { + jsonArray = JSONArray() + jsonArray.put(existingValue) + jsonObject.put(tagName, jsonArray) + } + } + } + XmlPullParser.TEXT -> if (tagName.isNotEmpty()) { + jsonArray.put(parser.text) + } + XmlPullParser.END_TAG -> { + if (tagName.isNotEmpty()) { + if (jsonArray.length() > 0) { + jsonObject.put(tagName, jsonArray) + jsonArray = JSONArray() + } else { + jsonObject.put(tagName, "") + } + } + tagName = "" + } + } + eventType = parser.next() + } + return jsonObject + } + + @Throws(IOException::class) + fun convertToJson(xmlFile: File): JSONObject { + val xmlString = xmlFile.readText() + return convertToJson(xmlString) + } +} diff --git a/sample/src/main/java/io/samagra/oce_sample/ODKFeatureTesterActivity.kt b/sample/src/main/java/io/samagra/oce_sample/ODKFeatureTesterActivity.kt index 82f9b1dc502..bce56b3aa15 100644 --- a/sample/src/main/java/io/samagra/oce_sample/ODKFeatureTesterActivity.kt +++ b/sample/src/main/java/io/samagra/oce_sample/ODKFeatureTesterActivity.kt @@ -11,21 +11,16 @@ import android.widget.ProgressBar import android.widget.Toast import io.reactivex.rxjava3.disposables.CompositeDisposable -import io.samagra.odk.collect.extension.components.DaggerFormsDatabaseInteractorComponent -import io.samagra.odk.collect.extension.components.DaggerFormsNetworkInteractorComponent -import io.samagra.odk.collect.extension.components.DaggerODKInteractorComponent import io.samagra.odk.collect.extension.interactors.FormsDatabaseInteractor import io.samagra.odk.collect.extension.interactors.FormsNetworkInteractor import io.samagra.odk.collect.extension.interactors.ODKInteractor import io.samagra.odk.collect.extension.listeners.FileDownloadListener -import io.samagra.odk.collect.extension.listeners.FormsProcessListener import io.samagra.odk.collect.extension.listeners.ODKProcessListener import io.samagra.odk.collect.extension.utilities.ODKProvider import org.apache.commons.io.IOUtils import org.odk.collect.android.events.FormEventExporter import org.odk.collect.android.events.FormStateEvent import org.odk.collect.android.injection.config.DaggerAppDependencyComponent -import org.odk.collect.forms.instances.InstancesRepository import timber.log.Timber import java.io.File @@ -110,7 +105,7 @@ class ODKFeatureTesterActivity : AppCompatActivity(), View.OnClickListener { is FormStateEvent.OnFormSaveError -> Timber.tag("FORM EVENT").d("Form with id: %s could not be saved. Reason: %s", event.formId, event.errorMessage) is FormStateEvent.OnFormSaved -> Timber.tag("FORM EVENT").d("Form with id: %s was saved. Saved instance path: %s", event.formId, event.instancePath) is FormStateEvent.OnFormUploadFailed -> Timber.tag("FORM EVENT").d("Form upload failed for form id: %s. Reason: %s", event.formId, event.errorMessage) - is FormStateEvent.OnFormUploaded -> Timber.tag("FORM EVENT").d("Form with id: %s was uploaded", event.formId) + is FormStateEvent.OnFormUploaded -> Timber.tag("FORM EVENT").d("Form with id: %s was uploaded. Form response: %s", event.formId, event.submittedData) } progressBar.visibility = View.INVISIBLE }