Skip to content

Commit

Permalink
Merge pull request #6276 from seadowg/trunk-version
Browse files Browse the repository at this point in the history
Add `trunkVersion` and `branchId` support
  • Loading branch information
grzesiek2010 authored Jul 31, 2024
2 parents 7bda554 + 9d45729 commit 4741fec
Show file tree
Hide file tree
Showing 21 changed files with 493 additions and 171 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class EntityFormTest {
.around(rule)

@Test
fun fillingEntityRegistrationForm_beforeCreatingEntityList_doesNotCreateEntityForFollowUpForms() {
fun fillingEntityRegistrationForm_doesNotShowEntitiesInNonEntityListForm() {
testDependencies.server.addForm("one-question-entity-registration.xml")
testDependencies.server.addForm(
"one-question-entity-update.xml",
Expand Down Expand Up @@ -109,6 +109,49 @@ class EntityFormTest {
.assertTextDoesNotExist("Roman Roy")
}

@Test
fun fillingEntityCreateForm_withUpdate_doesNotCreateEntityForFollowUpForms() {
testDependencies.server.addForm("one-question-entity-create-and-update.xml")
testDependencies.server.addForm(
"one-question-entity-update.xml",
listOf(EntityListItem("people.csv"))
)

rule.withMatchExactlyProject(testDependencies.server.url)
.enableLocalEntitiesInForms()

.startBlankForm("One Question Entity Registration")
.fillOutAndFinalize(FormEntryPage.QuestionAndAnswer("Name", "Logan Roy"))

.startBlankForm("One Question Entity Update")
.assertQuestion("Select person")
.assertText("Roman Roy")
.assertTextDoesNotExist("Logan Roy")
}

@Test
fun fillingEntityUpdateForm_withCreate_doesNotUpdateEntityForFollowUpForms() {
testDependencies.server.addForm(
"one-question-entity-update-and-create.xml",
listOf(EntityListItem("people.csv"))
)

rule.withMatchExactlyProject(testDependencies.server.url)
.enableLocalEntitiesInForms()

.startBlankForm("One Question Entity Update")
.assertQuestion("Select person")
.clickOnText("Roman Roy")
.swipeToNextQuestion("Name")
.answerQuestion("Name", "Romulus Roy")
.swipeToEndScreen()
.clickFinalize()

.startBlankForm("One Question Entity Update")
.assertTextDoesNotExist("Romulus Roy")
.assertText("Roman Roy")
}

@Test
fun entityListSecondaryInstancesAreConsistentBetweenFollowUpForms() {
testDependencies.server.apply {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ class JsonFileEntitiesRepository(directory: File) : EntitiesRepository {
entity.version,
entity.properties,
entity.state,
index
index,
entity.trunkVersion,
entity.branchId
)
}
}
Expand All @@ -51,7 +53,9 @@ class JsonFileEntitiesRepository(directory: File) : EntitiesRepository {
entity.label ?: existing.label,
version = entity.version,
properties = mergeProperties(existing.toEntity(entity.list), entity),
state = state
state = state,
trunkVersion = entity.trunkVersion,
branchId = entity.branchId
).toJson()
)
} else {
Expand Down Expand Up @@ -86,7 +90,11 @@ class JsonFileEntitiesRepository(directory: File) : EntitiesRepository {
return getEntities(list).firstOrNull { it.id == id }
}

override fun getAllByProperty(list: String, property: String, value: String): List<Entity.Saved> {
override fun getAllByProperty(
list: String,
property: String,
value: String
): List<Entity.Saved> {
return getEntities(list).filter { entity ->
entity.properties.any { (first, second) -> first == property && second == value }
}
Expand Down Expand Up @@ -163,7 +171,9 @@ class JsonFileEntitiesRepository(directory: File) : EntitiesRepository {
val label: String?,
val version: Int,
val properties: Map<String, String>,
val offline: Boolean
val offline: Boolean,
val trunkVersion: Int?,
val branchId: String
)

private fun JsonEntity.toEntity(list: String): Entity.New {
Expand All @@ -179,7 +189,9 @@ class JsonFileEntitiesRepository(directory: File) : EntitiesRepository {
this.label,
this.version,
this.properties.entries.map { Pair(it.key, it.value) },
state
state,
this.trunkVersion,
this.branchId
)
}

Expand All @@ -189,7 +201,9 @@ class JsonFileEntitiesRepository(directory: File) : EntitiesRepository {
this.label,
this.version,
this.properties.toMap(),
this.state == Entity.State.OFFLINE
this.state == Entity.State.OFFLINE,
this.trunkVersion,
this.branchId
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,22 @@ abstract class EntitiesRepositoryTest {
fun `#getEntities returns entities for list`() {
val repository = buildSubject()

val wine = Entity.New("wines", "1", "Léoville Barton 2008")
val whisky = Entity.New("whiskys", "2", "Lagavulin 16")
val wine = Entity.New(
"wines",
"1",
"Léoville Barton 2008",
version = 2,
trunkVersion = 1
)

val whisky = Entity.New(
"whiskys",
"2",
"Lagavulin 16",
version = 3,
trunkVersion = 1
)

repository.save(wine)
repository.save(whisky)

Expand All @@ -47,10 +61,15 @@ abstract class EntitiesRepositoryTest {
fun `#save updates existing entity with matching id`() {
val repository = buildSubject()

val wine = Entity.New("wines", "1", "Léoville Barton 2008", version = 1)
val wine = Entity.New(
"wines",
"1",
"Léoville Barton 2008",
trunkVersion = 1
)
repository.save(wine)

val updatedWine = Entity.New("wines", wine.id, "Léoville Barton 2009", version = 2)
val updatedWine = wine.copy(label = "Léoville Barton 2009", version = 2)
repository.save(updatedWine)

val wines = repository.getEntities("wines")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,31 @@ object LocalEntityUseCases {
formEntities?.entities?.forEach { formEntity ->
val id = formEntity.id
if (id != null && entitiesRepository.getLists().contains(formEntity.dataset)) {
if (formEntity.action != EntityAction.UPDATE || entitiesRepository.getEntities(formEntity.dataset).any { it.id == id }) {
val entity = Entity.New(
formEntity.dataset,
id,
formEntity.label,
formEntity.version,
formEntity.properties
)
when (formEntity.action) {
EntityAction.CREATE -> {
val entity = Entity.New(
formEntity.dataset,
id,
formEntity.label,
1,
formEntity.properties
)

entitiesRepository.save(entity)
entitiesRepository.save(entity)
}

EntityAction.UPDATE -> {
val existing = entitiesRepository.getById(formEntity.dataset, formEntity.id)
if (existing != null) {
entitiesRepository.save(
existing.copy(
label = formEntity.label,
properties = formEntity.properties,
version = existing.version + 1
)
)
}
}
}
}
}
Expand All @@ -54,10 +69,11 @@ object LocalEntityUseCases {
val entity = parseEntityFromItem(item, list) ?: return
val existing = missing.remove(entity.id)

if (existing == null || existing.version < entity.version) {
if (existing == null || existing.version <= entity.version) {
Pair(new + entity, missing)
} else if (existing.state == Entity.State.OFFLINE) {
Pair(new + existing.copy(state = Entity.State.ONLINE), missing)
val update = existing.copy(state = Entity.State.ONLINE)
Pair(new + update, missing)
} else {
Pair(new, missing)
}
Expand Down Expand Up @@ -100,7 +116,14 @@ object LocalEntityUseCases {
}
}

val entity = Entity.New(list, id, label, version, properties, state = Entity.State.ONLINE)
return entity
return Entity.New(
list,
id,
label,
version,
properties,
state = Entity.State.ONLINE,
trunkVersion = version
)
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
package org.odk.collect.entities.javarosa.finalization

data class EntitiesExtra(val entities: List<Entity>)
data class EntitiesExtra(val entities: List<FormEntity>)
Original file line number Diff line number Diff line change
Expand Up @@ -35,21 +35,16 @@ public void processForm(FormEntryModel formEntryModel) {
EntityAction action = EntityFormParser.parseAction(entityElement);
String dataset = EntityFormParser.parseDataset(entityElement);

if (action == EntityAction.CREATE) {
Entity entity = createEntity(entityElement, 1, dataset, saveTos, mainInstance, action);
formEntryModel.getExtras().put(new EntitiesExtra(asList(entity)));
} else if (action == EntityAction.UPDATE) {
int baseVersion = EntityFormParser.parseBaseVersion(entityElement);
int newVersion = baseVersion + 1;
Entity entity = createEntity(entityElement, newVersion, dataset, saveTos, mainInstance, action);
if (action == EntityAction.CREATE || action == EntityAction.UPDATE) {
FormEntity entity = createEntity(entityElement, dataset, saveTos, mainInstance, action);
formEntryModel.getExtras().put(new EntitiesExtra(asList(entity)));
} else {
formEntryModel.getExtras().put(new EntitiesExtra(emptyList()));
}
}
}

private Entity createEntity(TreeElement entityElement, int version, String dataset, List<Pair<XPathReference, String>> saveTos, FormInstance mainInstance, EntityAction action) {
private FormEntity createEntity(TreeElement entityElement, String dataset, List<Pair<XPathReference, String>> saveTos, FormInstance mainInstance, EntityAction action) {
List<Pair<String, String>> fields = saveTos.stream().map(saveTo -> {
IDataReference reference = saveTo.getFirst();
IAnswerData answerData = mainInstance.resolveReference(reference).getValue();
Expand All @@ -63,6 +58,6 @@ private Entity createEntity(TreeElement entityElement, int version, String datas

String id = EntityFormParser.parseId(entityElement);
String label = EntityFormParser.parseLabel(entityElement);
return new Entity(action, dataset, id, label, version, fields);
return new FormEntity(action, dataset, id, label, fields);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@ package org.odk.collect.entities.javarosa.finalization

import org.odk.collect.entities.javarosa.spec.EntityAction

class Entity(
class FormEntity(
@JvmField val action: EntityAction,
@JvmField val dataset: String,
@JvmField val id: String?,
@JvmField val label: String?,
@JvmField val version: Int,
@JvmField val properties: List<Pair<String, String>>
)
Original file line number Diff line number Diff line change
Expand Up @@ -59,17 +59,26 @@ class LocalEntitiesInstanceAdapter(private val entitiesRepository: EntitiesRepos
val name = TreeElement(EntityItemElement.ID)
val label = TreeElement(EntityItemElement.LABEL)
val version = TreeElement(EntityItemElement.VERSION)
val trunkVersion = TreeElement(EntityItemElement.TRUNK_VERSION)
val branchId = TreeElement(EntityItemElement.BRANCH_ID)

if (!partial) {
name.value = StringData(entity.id)
label.value = StringData(entity.label)
version.value = StringData(entity.version.toString())
branchId.value = StringData(entity.branchId)

if (entity.trunkVersion != null) {
trunkVersion.value = StringData(entity.trunkVersion.toString())
}
}

val item = TreeElement("item", entity.index, partial)
item.addChild(name)
item.addChild(label)
item.addChild(version)
item.addChild(trunkVersion)
item.addChild(branchId)

entity.properties.forEach { property ->
val propertyElement = TreeElement(property.first)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
public class EntityFormParseProcessor implements XFormParser.BindAttributeProcessor, XFormParser.FormDefProcessor, XFormParser.ModelAttributeProcessor {

private static final String ENTITIES_NAMESPACE = "http://www.opendatakit.org/xforms/entities";
private static final String[] SUPPORTED_VERSIONS = {"2022.1", "2023.1"};
private static final String[] SUPPORTED_VERSIONS = {"2022.1", "2023.1", "2024.1"};

private final List<Pair<XPathReference, String>> saveTos = new ArrayList<>();
private boolean versionPresent;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,6 @@ internal object EntityItemElement {
const val ID = "name"
const val LABEL = "label"
const val VERSION = "__version"
const val TRUNK_VERSION = "__trunkVersion"
const val BRANCH_ID = "__branchId"
}
Loading

0 comments on commit 4741fec

Please sign in to comment.