Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle entities without IDs #763

Merged
merged 5 commits into from
May 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 16 additions & 8 deletions src/main/java/org/javarosa/core/model/instance/TreeElement.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,6 @@
*/
package org.javarosa.core.model.instance;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.javarosa.core.model.Constants;
import org.javarosa.core.model.FormDef;
import org.javarosa.core.model.FormElementStateListener;
Expand Down Expand Up @@ -52,6 +45,13 @@
import org.javarosa.xpath.expr.XPathStringLiteral;
import org.jetbrains.annotations.Nullable;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
* <p>An element of a FormInstance.</p>
*
Expand Down Expand Up @@ -580,11 +580,18 @@ private String getAttributeValue(TreeElement attribute) {
}
}

@Nullable
public String getAttributeValue() {
if ( !isAttribute() ) {
throw new IllegalStateException("this is not an attribute");
}
return getValue().uncast().getString();

IAnswerData value = getValue();
if (value != null) {
return value.uncast().getString();
} else {
return null;
}
}

@Override
Expand All @@ -593,6 +600,7 @@ public TreeElement getAttribute(String namespace, String name) {
}

@Override
@Nullable
public String getAttributeValue(String namespace, String name) {
TreeElement element = getAttribute(namespace,name);
return element == null ? null: getAttributeValue(element);
Expand Down
5 changes: 4 additions & 1 deletion src/main/java/org/javarosa/entities/Entity.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,17 @@ public class Entity {

public final String dataset;
public final List<Pair<String, String>> properties;

@Nullable
public final String id;

@Nullable
public final String label;

public final Integer version;
public final EntityAction action;

public Entity(EntityAction action, String dataset, String id, @Nullable String label, Integer version, List<Pair<String, String>> properties) {
public Entity(EntityAction action, String dataset, @Nullable String id, @Nullable String label, Integer version, List<Pair<String, String>> properties) {
this.dataset = dataset;
this.id = id;
this.label = label;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.javarosa.entities.internal;

import org.javarosa.core.model.data.IAnswerData;
import org.javarosa.core.model.instance.FormInstance;
import org.javarosa.core.model.instance.TreeElement;
import org.javarosa.entities.EntityAction;
Expand All @@ -22,12 +23,19 @@ public static String parseLabel(TreeElement entity) {
TreeElement labelElement = entity.getFirstChild("label");

if (labelElement != null) {
return (String) labelElement.getValue().getValue();
IAnswerData labelValue = labelElement.getValue();

if (labelValue != null) {
return (String) labelValue.getValue();
} else {
return null;
}
} else {
return null;
}
}

@Nullable
public static String parseId(TreeElement entity) {
return entity.getAttributeValue("", "id");
}
Expand Down
89 changes: 83 additions & 6 deletions src/test/java/org/javarosa/entities/EntitiesTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,47 @@ public void fillingFormWithCreate_makesEntityAvailable() throws IOException, XFo
assertThat(entities.get(0).action, equalTo(EntityAction.CREATE));
}

@Test
public void fillingFormWithCreate_withoutAnId_makesEntityAvailable() throws IOException, XFormParser.ParseException {
Scenario scenario = Scenario.init("Create entity form", XFormsElement.html(
asList(
new Pair<>("entities", "http://www.opendatakit.org/xforms/entities")
),
head(
title("Create entity form"),
model(asList(new Pair<>("entities:entities-version", "2022.1.1")),
mainInstance(
t("data id=\"create-entity-form\"",
t("id"),
t("name"),
t("meta",
t("entity dataset=\"people\" create=\"1\" id=\"\"",
t("label")
)
)
)
),
bind("/data/id").type("string"),
bind("/data/meta/entity/@id").type("string").calculate("/data/id"),
bind("/data/meta/entity/label").type("string").calculate("/data/name")
)
),
body(
input("/data/id"),
input("/data/name")
)
));

scenario.getFormEntryController().addPostProcessor(new EntityFormFinalizationProcessor());
scenario.finalizeInstance();

List<Entity> entities = scenario.getFormEntryController().getModel().getExtras().get(Entities.class).getEntities();
assertThat(entities.size(), equalTo(1));
assertThat(entities.get(0).dataset, equalTo("people"));
assertThat(entities.get(0).id, equalTo(null));
assertThat(entities.get(0).action, equalTo(EntityAction.CREATE));
}

@Test
public void fillingFormWithUpdate_makesEntityAvailable() throws IOException, XFormParser.ParseException {
Scenario scenario = Scenario.init("Create entity form", XFormsElement.html(
Expand Down Expand Up @@ -174,7 +215,7 @@ public void fillingFormWithUpdate_makesEntityAvailable() throws IOException, XFo

@Test
public void fillingFormWithUpdate_andNoLabel_makesEntityAvailableWithNullLabel() throws IOException, XFormParser.ParseException {
Scenario scenario = Scenario.init("Create entity form", XFormsElement.html(
Scenario scenario = Scenario.init("Update entity form", XFormsElement.html(
asList(
new Pair<>("entities", "http://www.opendatakit.org/xforms/entities")
),
Expand Down Expand Up @@ -213,6 +254,42 @@ public void fillingFormWithUpdate_andNoLabel_makesEntityAvailableWithNullLabel()
assertThat(entities.get(0).properties, equalTo(asList(new Pair<>("name", "Tom Wambsgans"))));
}

@Test
public void fillingFormWithUpdate_withNullId_makesEntityAvailable() throws IOException, XFormParser.ParseException {
Scenario scenario = Scenario.init("Create entity form", XFormsElement.html(
seadowg marked this conversation as resolved.
Show resolved Hide resolved
asList(
new Pair<>("entities", "http://www.opendatakit.org/xforms/entities")
),
head(
title("Update entity form"),
model(asList(new Pair<>("entities:entities-version", "2023.1.0")),
mainInstance(
t("data id=\"update-entity-form\"",
t("id"),
t("meta",
t("entity dataset=\"people\" update=\"1\" id=\"\" baseVersion=\"\"")
)
)
),
bind("/data/id").type("string"),
bind("/data/meta/entity/@id").type("string").calculate("/data/id").readonly()
)
),
body(
input("/data/id")
)
));

scenario.getFormEntryController().addPostProcessor(new EntityFormFinalizationProcessor());
scenario.finalizeInstance();

List<Entity> entities = scenario.getFormEntryController().getModel().getExtras().get(Entities.class).getEntities();
assertThat(entities.size(), equalTo(1));
assertThat(entities.get(0).dataset, equalTo("people"));
assertThat(entities.get(0).id, equalTo(null));
assertThat(entities.get(0).action, equalTo(EntityAction.UPDATE));
}

@Test
public void fillingFormWithCreateAndUpdate_makesEntityAvailableAsSecondVersion() throws IOException, XFormParser.ParseException {
Scenario scenario = Scenario.init("Create entity form", XFormsElement.html(
Expand Down Expand Up @@ -315,7 +392,7 @@ public void fillingFormWithDynamicCreateExpression_conditionallyCreatesEntities(
t("name"),
t("join"),
t("meta",
t("entity dataset=\"members\" create=\"\"")
t("entity dataset=\"members\" create=\"\" id=\"1\"")
)
)
),
Expand Down Expand Up @@ -365,7 +442,7 @@ public void entityFormCanBeSerialized() throws IOException, DeserializationExcep
t("data id=\"create-entity-form\"",
t("name"),
t("meta",
t("entities:entity dataset=\"people\" create=\"1\"")
t("entities:entity dataset=\"people\" create=\"1\" id=\"1\"")
)
)
),
Expand Down Expand Up @@ -405,7 +482,7 @@ public void entitiesNamespaceWorksRegardlessOfName() throws IOException, Deseria
t("data id=\"create-entity-form\"",
t("name"),
t("meta",
t("entity dataset=\"people\" create=\"1\"")
t("entity dataset=\"people\" create=\"1\" id=\"1\"")
)
)
),
Expand Down Expand Up @@ -441,7 +518,7 @@ public void fillingFormWithSelectSaveTo_andWithCreate_savesValuesCorrectlyToEnti
t("data id=\"create-entity-form\"",
t("team"),
t("meta",
t("entity dataset=\"people\" create=\"1\"")
t("entity dataset=\"people\" create=\"1\" id=\"1\"")
)
)
),
Expand Down Expand Up @@ -477,7 +554,7 @@ public void whenSaveToQuestionIsNotAnswered_entityPropertyIsEmptyString() throws
t("data id=\"create-entity-form\"",
t("name"),
t("meta",
t("entity dataset=\"people\" create=\"1\"")
t("entity dataset=\"people\" create=\"1\" id=\"1\"")
)
)
),
Expand Down