Skip to content

Commit d825348

Browse files
authored
Merge pull request #7141 from grzesiek2010/COLLECT-7138_1
Fix reading form metadata in forms containing multiple meta sections
2 parents f62dfbf + 03b73ff commit d825348

4 files changed

Lines changed: 66 additions & 71 deletions

File tree

collect_app/src/main/java/org/odk/collect/android/javarosawrapper/InstanceMetadata.java

Lines changed: 0 additions & 24 deletions
This file was deleted.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package org.odk.collect.android.javarosawrapper
2+
3+
import org.odk.collect.android.formentry.audit.AuditConfig
4+
import org.odk.collect.android.utilities.FormNameUtils
5+
6+
data class InstanceMetadata(
7+
@JvmField val instanceId: String?,
8+
private val rawInstanceName: String?,
9+
@JvmField val auditConfig: AuditConfig?
10+
) {
11+
@JvmField val instanceName: String? = FormNameUtils.normalizeFormName(rawInstanceName, false)
12+
}

collect_app/src/main/java/org/odk/collect/android/javarosawrapper/JavaRosaFormController.java

Lines changed: 12 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1010,76 +1010,41 @@ public ByteArrayPayload getSubmissionXml() throws IOException {
10101010
getSubmissionDataReference());
10111011
}
10121012

1013-
/**
1014-
* Traverse the submission looking for the first matching tag in depth-first order.
1015-
*/
1016-
private TreeElement findDepthFirst(TreeElement parent, String name) {
1017-
int len = parent.getNumChildren();
1018-
for (int i = 0; i < len; ++i) {
1019-
TreeElement e = parent.getChildAt(i);
1020-
if (name.equals(e.getName())) {
1021-
return e;
1022-
} else if (e.getNumChildren() != 0) {
1023-
TreeElement v = findDepthFirst(e, name);
1024-
if (v != null) {
1025-
return v;
1026-
}
1027-
}
1028-
}
1029-
return null;
1030-
}
1031-
10321013
public InstanceMetadata getSubmissionMetadata() {
10331014
FormDef formDef = formEntryController.getModel().getForm();
10341015
TreeElement rootElement = formDef.getInstance().getRoot();
1035-
1036-
TreeElement trueSubmissionElement;
1037-
// Determine the information about the submission...
1038-
SubmissionProfile p = formDef.getSubmissionProfile();
1039-
if (p == null || p.getRef() == null) {
1040-
trueSubmissionElement = rootElement;
1041-
} else {
1042-
IDataReference ref = p.getRef();
1043-
trueSubmissionElement = formDef.getInstance().resolveReference(ref);
1044-
// resolveReference returns null if the reference is to the root element...
1045-
if (trueSubmissionElement == null) {
1046-
trueSubmissionElement = rootElement;
1047-
}
1048-
}
1049-
1050-
// and find the depth-first meta block in this...
1051-
TreeElement e = findDepthFirst(trueSubmissionElement, "meta");
1016+
TreeElement meta = rootElement.getFirstChild("meta");
10521017

10531018
String instanceId = null;
10541019
String instanceName = null;
10551020
AuditConfig auditConfig = null;
10561021

1057-
if (e != null) {
1058-
List<TreeElement> v;
1022+
if (meta != null) {
1023+
List<TreeElement> metaElements;
10591024

10601025
// instance id...
1061-
v = e.getChildrenWithName(INSTANCE_ID);
1062-
if (v.size() == 1) {
1063-
IAnswerData sa = v.get(0).getValue();
1026+
metaElements = meta.getChildrenWithName(INSTANCE_ID);
1027+
if (metaElements.size() == 1) {
1028+
IAnswerData sa = metaElements.get(0).getValue();
10641029
if (sa != null) {
10651030
instanceId = sa.getDisplayText();
10661031
}
10671032
}
10681033

10691034
// instance name...
1070-
v = e.getChildrenWithName(INSTANCE_NAME);
1071-
if (v.size() == 1) {
1072-
IAnswerData sa = v.get(0).getValue();
1035+
metaElements = meta.getChildrenWithName(INSTANCE_NAME);
1036+
if (metaElements.size() == 1) {
1037+
IAnswerData sa = metaElements.get(0).getValue();
10731038
if (sa != null) {
10741039
instanceName = sa.getDisplayText();
10751040
}
10761041
}
10771042

10781043
// timing element...
1079-
v = e.getChildrenWithName(AUDIT);
1080-
if (v.size() == 1) {
1044+
metaElements = meta.getChildrenWithName(AUDIT);
1045+
if (metaElements.size() == 1) {
10811046

1082-
TreeElement auditElement = v.get(0);
1047+
TreeElement auditElement = metaElements.get(0);
10831048

10841049
String locationPriority = auditElement.getBindAttributeValue(XML_OPENDATAKIT_NAMESPACE, "location-priority");
10851050
String locationMinInterval = auditElement.getBindAttributeValue(XML_OPENDATAKIT_NAMESPACE, "location-min-interval");

collect_app/src/test/java/org/odk/collect/android/javarosawrapper/FormControllerTest.java

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,11 @@ public void whenInstanceFileAndAuditConfigNull_getAuditEventLogger_isNotNull() t
121121
assertThat(formController.getAuditEventLogger(), notNullValue());
122122
}
123123

124+
@Test
125+
public void getSubmissionMetadata_usesTopLevelMeta_whenMultipleMetaSectionsExist() throws Exception {
126+
FormController formController = createFormController(MULTIPLE_META_SECTIONS);
127+
assertThat(formController.getSubmissionMetadata().instanceName, is(notNullValue()));
128+
}
124129

125130
//region indexIsInFieldList
126131
@Test
@@ -149,6 +154,7 @@ private FormController createFormController(String xform) throws IOException, XF
149154
ByteArrayInputStream inputStream = new ByteArrayInputStream(xform.getBytes());
150155
final FormEntryModel fem = new FormEntryModel(XFormUtils.getFormFromInputStream(inputStream));
151156
final FormEntryController formEntryController = new FormEntryController(fem);
157+
formEntryController.getModel().getForm().initialize(true, null);
152158
return new JavaRosaFormController(Files.createTempDir(), formEntryController, File.createTempFile("instance", ""));
153159
}
154160

@@ -293,4 +299,40 @@ private FormController createFormController(String xform) throws IOException, XF
293299
" </group>\n" +
294300
" </h:body>\n" +
295301
"</h:html>\n";
302+
303+
private static final String MULTIPLE_META_SECTIONS = "<?xml version=\"1.0\"?>\n" +
304+
"<h:html xmlns=\"http://www.w3.org/2002/xforms\" xmlns:h=\"http://www.w3.org/1999/xhtml\" xmlns:entities=\"http://www.opendatakit.org/xforms/entities\" xmlns:jr=\"http://openrosa.org/javarosa\">\n" +
305+
" <h:head>\n" +
306+
" <h:title>Multiple meta sections</h:title>\n" +
307+
" <model entities:entities-version=\"2024.1.0\">\n" +
308+
" <instance>\n" +
309+
" <data id=\"multiple-meta-sections\">\n" +
310+
" <group>\n" +
311+
" <question>xxx</question>\n" +
312+
" <meta>\n" +
313+
" <entity dataset=\"entity_test\" create=\"1\" id=\"\">\n" +
314+
" <label/>\n" +
315+
" </entity>\n" +
316+
" </meta>\n" +
317+
" </group>\n" +
318+
" <meta>\n" +
319+
" <instanceName/>\n" +
320+
" </meta>\n" +
321+
" </data>\n" +
322+
" </instance>\n" +
323+
" <bind nodeset=\"/data/group/question\" type=\"int\"/>\n" +
324+
" <bind nodeset=\"/data/group/meta/entity/@id\" readonly=\"true()\" type=\"string\"/>\n" +
325+
" <setvalue ref=\"/data/group/meta/entity/@id\" event=\"odk-instance-first-load\" value=\"uuid()\"/>\n" +
326+
" <bind nodeset=\"/data/group/meta/entity/label\" calculate=\"/data/group/question\" readonly=\"true()\" type=\"string\"/>\n" +
327+
" <bind nodeset=\"/data/meta/instanceName\" type=\"string\" calculate=\"uuid()\"/>\n" +
328+
" </model>\n" +
329+
" </h:head>\n" +
330+
" <h:body>\n" +
331+
" <group ref=\"/data/group\">\n" +
332+
" <input ref=\"/data/group/question\">\n" +
333+
" <label>Question</label>\n" +
334+
" </input>\n" +
335+
" </group>\n" +
336+
" </h:body>\n" +
337+
"</h:html>\n";
296338
}

0 commit comments

Comments
 (0)