Skip to content
Snippets Groups Projects
Commit d14fa5d0 authored by OZGCloud's avatar OZGCloud
Browse files

Merge pull request 'OZG-5677 FormCycle: Ermittlung Antragstellerdaten...

Merge pull request 'OZG-5677 FormCycle: Ermittlung Antragstellerdaten (PostfachId)' (#28) from OZG-5677-Ermittlung-Antragstellerdaten into master

Reviewed-on: https://git.ozg-sh.de/ozgcloud-app/formcycle-plugin/pulls/28


Reviewed-by: default avatarOZGCloud <ozgcloud@mgm-tp.com>
parents 1d15962f d7f80bd3
No related branches found
No related tags found
No related merge requests found
......@@ -11,50 +11,64 @@ import java.util.Objects;
import java.util.Optional;
import de.xima.fc.form.common.items.XItem;
import de.xima.fc.form.common.models.XPropertyValue;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
class FormStructureParser {
static final String CONTAINER_NAME_ANTRAGSTELLER = "fsBKAllDaten";
private final Map<String, XItem> formularElementsSorted;
private final Deque<FormNode> containerNodes = new ArrayDeque<>();
private final List<FormNode> nodes = new ArrayList<>();
private final List<FormNode> resultNodes = new ArrayList<>();
public List<FormNode> parse() {
nodes.clear();
resultNodes.clear();
for (Map.Entry<String, XItem> entry : formularElementsSorted.entrySet()) {
var xItem = entry.getValue();
var itemClass = ItemClass.fromString(xItem.getClassName());
if (isInputNode(itemClass)) {
addItem(xItem);
handleInputNode(xItem);
} else if (isNestedContainer(itemClass)) {
var formNode = buildNode(xItem);
getNodes(xItem.getParentId()).add(formNode);
containerNodes.push(formNode);
handleContainerNode(xItem);
}
}
return nodes;
return resultNodes;
}
void addItem(XItem xItem) {
getNodes(xItem.getParentId()).add(buildNode(xItem));
void handleInputNode(XItem xItem) {
getResultNodes(xItem).add(buildNode(xItem));
}
void handleContainerNode(XItem xItem) {
var formNode = buildNode(xItem);
getResultNodes(xItem).add(formNode);
containerNodes.push(formNode);
}
FormNode buildNode(XItem xItem) {
var formNode = FormNode.builder().itemId(xItem.getId()).name(xItem.getName());
ItemClass.fromString(xItem.getClassName()).getTitleProperty().map(xItem::get).ifPresent(propertyValue -> formNode.title(propertyValue.getString()));
getTitle(xItem).ifPresent(formNode::title);
return formNode.build();
}
List<FormNode> getNodes(String parentId) {
return containerNodes.isEmpty()
? nodes
: getNextContainerNode(parentId).map(FormNode::getNestedElements).orElse(nodes);
Optional<String> getTitle(XItem xItem) {
return ItemClass.fromString(xItem.getClassName()).getTitleProperty().map(xItem::get).map(XPropertyValue::getString);
}
List<FormNode> getResultNodes(XItem xItem) {
if (CONTAINER_NAME_ANTRAGSTELLER.equalsIgnoreCase(xItem.getName())) {
return resultNodes;
}
return getNextContainerNode(xItem.getParentId()).map(FormNode::getNestedElements).orElse(resultNodes);
}
Optional<FormNode> getNextContainerNode(String parentId) {
var nextContainerNode = containerNodes.peekFirst();
Objects.requireNonNull(nextContainerNode);
if (Objects.isNull(nextContainerNode)) {
return Optional.empty();
}
while (nonParent(nextContainerNode, parentId)) {
containerNodes.pollFirst();
if (containerNodes.isEmpty()) {
......
/*
* Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
* Ministerpräsidenten des Landes Schleswig-Holstein
* Staatskanzlei
* Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
*
* Lizenziert unter der EUPL, Version 1.2 oder - sobald
* diese von der Europäischen Kommission genehmigt wurden -
* Folgeversionen der EUPL ("Lizenz");
* Sie dürfen dieses Werk ausschließlich gemäß
* dieser Lizenz nutzen.
* Eine Kopie der Lizenz finden Sie hier:
*
* https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
*
* Sofern nicht durch anwendbare Rechtsvorschriften
* gefordert oder in schriftlicher Form vereinbart, wird
* die unter der Lizenz verbreitete Software "so wie sie
* ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
* ausdrücklich oder stillschweigend - verbreitet.
* Die sprachspezifischen Genehmigungen und Beschränkungen
* unter der Lizenz sind dem Lizenztext zu entnehmen.
*/
package de.ozgcloud.formcycle.formdata;
import static de.ozgcloud.formcycle.formdata.ItemClass.*;
import static de.ozgcloud.formcycle.formdata.StructureMockFactory.*;
import static org.assertj.core.api.Assertions.*;
import java.util.Map;
import org.junit.jupiter.api.Test;
import de.xima.fc.form.common.items.XItem;
class FormStructureParserITCase {
private static final String FS_CONTAINER_ID = "xi-fs-n";
private static final String NEXT_ITEM_ID = "new-item";
private static final FormNode EXPECTED_FIELD_SET_NODE = FormNodeTestFactory.createBuilder().values(null).itemId(FS_CONTAINER_ID).build();
private static final FormNode EXPECTED_TEXT_FIELD_NODE = FormNodeTestFactory.createBuilder().values(null).itemId(NEXT_ITEM_ID).build();
@Test
void shouldParseInputItem() {
var expected = FormNodeTestFactory.createBuilder().values(null).build();
var formNodes = new FormStructureParser(createItem(TEXT_FIELD)).parse();
assertThat(formNodes).hasSize(1).first().usingRecursiveComparison().isEqualTo(expected);
}
@Test
void shouldParseContainerItem() {
var expected = FormNodeTestFactory.createBuilder().values(null).build();
var formNodes = new FormStructureParser(createItem(FIELD_SET)).parse();
assertThat(formNodes).hasSize(1).first().usingRecursiveComparison().isEqualTo(expected);
}
@Test
void shouldNotParseSpanItem() {
var formNodes = new FormStructureParser(createItem(SPAN)).parse();
assertThat(formNodes).isEmpty();
}
@Test
void shouldParseNestedFieldSetContainer() {
var formNodes = new FormStructureParser(initNestedMap()).parse();
assertThat(formNodes).hasSize(2);
var containerNodes = formNodes.get(0).getNestedElements();
assertThat(containerNodes).hasSize(2);
assertThat(containerNodes.get(0)).usingRecursiveComparison().isEqualTo(EXPECTED_FIELD_SET_NODE);
assertThat(containerNodes.get(1)).usingRecursiveComparison().isEqualTo(EXPECTED_TEXT_FIELD_NODE);
assertThat(formNodes.get(1).getItemId()).isEqualTo(ITEM_ID);
}
private Map<String, XItem> initNestedMap() {
var containerWithItem = createPageItem();
containerWithItem.put(CONTAINER_ITEM_ID, getMock(CONTAINER, PAGE_ITEM_ID));
containerWithItem.put(FS_CONTAINER_ID, getMock(FIELD_SET, FS_CONTAINER_ID, CONTAINER_ITEM_ID, ITEM_TITLE, ITEM_NAME));
containerWithItem.put(NEXT_ITEM_ID, getMock(TEXT_FIELD, NEXT_ITEM_ID, CONTAINER_ITEM_ID, ITEM_TITLE, ITEM_NAME));
containerWithItem.put(ITEM_ID, getMock(CHECKBOX, PAGE_ITEM_ID));
return containerWithItem;
}
}
......@@ -3,11 +3,15 @@ package de.ozgcloud.formcycle.formdata;
import static de.ozgcloud.formcycle.formdata.ItemClass.*;
import static de.ozgcloud.formcycle.formdata.StructureMockFactory.*;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.Mockito.*;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Deque;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
......@@ -20,103 +24,186 @@ import lombok.SneakyThrows;
class FormStructureParserTest {
private static final String NEXT_ITEM_ID = "new-item";
private FormStructureParser structureParser;
@Nested
class TestItems {
class TestParse {
@Test
void shouldParseInputItem() {
var expected = FormNodeTestFactory.createBuilder().values(null).build();
var structureParser = createParser(TEXT_FIELD);
void shouldClearResultNodes() {
structureParser = new FormStructureParser(Collections.emptyMap());
injectResultNodes(new ArrayList<>(List.of(FormNodeTestFactory.create())));
var formNodes = structureParser.parse();
var result = structureParser.parse();
assertThat(formNodes).hasSize(1).first().usingRecursiveComparison().isEqualTo(expected);
assertThat(result).isEmpty();
}
@Test
void shouldParseContainerItem() {
var expected = FormNodeTestFactory.createBuilder().values(null).build();
var structureParser = createParser(FIELD_SET);
void shouldReturnResultNodes() {
structureParser = new FormStructureParser(Collections.emptyMap());
var expectedResultNode = new ArrayList<>(List.of(FormNodeTestFactory.create()));
injectResultNodes(expectedResultNode);
var formNodes = structureParser.parse();
var result = structureParser.parse();
assertThat(formNodes).hasSize(1).first().usingRecursiveComparison().isEqualTo(expected);
assertThat(result).isSameAs(expectedResultNode);
}
@Nested
class TestHandleInputNode {
@Test
void shouldNotParseTextItem() {
var structureParser = createParser(SPAN);
void shouldCallHandleInputNode() {
var items = createItem(TEXT_FIELD);
structureParser = spy(createParser(items));
var formNodes = structureParser.parse();
structureParser.parse();
assertThat(formNodes).isEmpty();
verify(structureParser).handleInputNode(items.get(ITEM_ID));
}
private FormStructureParser createParser(ItemClass itemClass) {
return new FormStructureParser(createItem(itemClass));
@Test
void shouldNotCallHandleContainerNode() {
var items = createItem(TEXT_FIELD);
structureParser = spy(createParser(items));
structureParser.parse();
verify(structureParser, never()).handleContainerNode(any());
}
}
@Nested
class TestNestedItems {
class TestHandleContainerNode {
private static final String FS_CONTAINER_ID = "xi-fs-n";
private static final String NESTED_ITEM_ID1 = "nested1";
private static final String NESTED_ITEM_ID2 = "nested2";
@Test
void shouldHandleContainerNode() {
var items = createItem(FIELD_SET);
structureParser = spy(createParser(items));
private FormStructureParser structureParser;
structureParser.parse();
verify(structureParser).handleContainerNode(items.get(ITEM_ID));
}
@Test
void shouldNotCallHandleInputNode() {
var items = createItem(FIELD_SET);
structureParser = spy(createParser(items));
structureParser.parse();
verify(structureParser, never()).handleInputNode(any());
}
}
private FormStructureParser createParser(Map<String, XItem> items) {
return new FormStructureParser(items);
}
}
@Nested
class TestHandleInputNode {
@BeforeEach
void init() {
structureParser = spy(new FormStructureParser(createItem(FIELD_SET)));
}
@Test
void shouldCallGetResultNodes() {
var xItem = getMock(TEXT_FIELD);
structureParser.handleInputNode(xItem);
verify(structureParser).getResultNodes(xItem);
}
@Test
void shouldCallBuildNode() {
var xItem = getMock(TEXT_FIELD);
doReturn(new ArrayList<>()).when(structureParser).getResultNodes(any());
structureParser.handleInputNode(xItem);
verify(structureParser).buildNode(xItem);
}
@Test
void shouldAddNodeToResultNodes() {
var resultNodes = new ArrayList<FormNode>();
doReturn(resultNodes).when(structureParser).getResultNodes(any());
var formNode = FormNodeTestFactory.create();
doReturn(formNode).when(structureParser).buildNode(any());
structureParser.handleInputNode(getMock(TEXT_FIELD));
assertThat(resultNodes).containsExactly(formNode);
}
}
@Nested
class TestHandleContainerNode {
@BeforeEach
void setup() {
var containerWithItem = initNestedMap();
structureParser = new FormStructureParser(containerWithItem);
void init() {
structureParser = spy(new FormStructureParser(createItem(FIELD_SET)));
}
@Test
void shouldParseAllInputItems() {
var structure = new FormStructureParser(StructureMockFactory.create());
void shouldCallBuildNode() {
var xItem = getMock(FIELD_SET);
var formNodes = structure.parse();
structureParser.handleContainerNode(xItem);
assertThat(formNodes).hasSize(2);
verify(structureParser).buildNode(xItem);
}
@Test
void shouldParseNestedFieldSetContainer() {
var expectedFsNode = FormNodeTestFactory.createBuilder().values(null).itemId(FS_CONTAINER_ID).build();
var expectedTfNode = FormNodeTestFactory.createBuilder().values(null).itemId(NEXT_ITEM_ID).build();
void shouldCallGetResultNodes() {
var xItem = getMock(FIELD_SET);
var formNodes = structureParser.parse();
structureParser.handleContainerNode(xItem);
assertThat(formNodes).hasSize(2);
var containerNodes = formNodes.get(0).getNestedElements();
assertThat(containerNodes).hasSize(2).first().usingRecursiveComparison().ignoringFields("nestedElements").isEqualTo(expectedFsNode);
assertThat(containerNodes.get(1)).usingRecursiveComparison().ignoringFields("nestedElements").isEqualTo(expectedTfNode);
verify(structureParser).getResultNodes(xItem);
}
@Test
void shouldParseItemsInFieldSet() {
var expectedTfNode = FormNodeTestFactory.createBuilder().values(null).itemId(NESTED_ITEM_ID1).build();
void shouldAddNodeToResultNodes() {
var resultNodes = new ArrayList<FormNode>();
doReturn(resultNodes).when(structureParser).getResultNodes(any());
var formNode = FormNodeTestFactory.create();
doReturn(formNode).when(structureParser).buildNode(any());
var fieldSetNodes = structureParser.parse().get(0).getNestedElements().get(0).getNestedElements();
structureParser.handleContainerNode(getMock(FIELD_SET));
assertThat(fieldSetNodes).hasSize(1).first().usingRecursiveComparison().ignoringFields("nestedElements").isEqualTo(expectedTfNode);
assertThat(resultNodes).containsExactly(formNode);
}
private Map<String, XItem> initNestedMap() {
var containerWithItem = createPageItem();
containerWithItem.put(CONTAINER_ITEM_ID, getMock(CONTAINER, PAGE_ITEM_ID));
containerWithItem.put(FS_CONTAINER_ID, getMock(FIELD_SET, FS_CONTAINER_ID, CONTAINER_ITEM_ID, ITEM_TITLE, ITEM_NAME));
containerWithItem.put(NESTED_ITEM_ID1, getMock(TEXT_FIELD, NESTED_ITEM_ID1, FS_CONTAINER_ID, ITEM_TITLE, ITEM_NAME));
containerWithItem.put(NESTED_ITEM_ID2, getMock(SPAN, NESTED_ITEM_ID2, FS_CONTAINER_ID, ITEM_TITLE, ITEM_NAME));
containerWithItem.put(NEXT_ITEM_ID, getMock(TEXT_FIELD, NEXT_ITEM_ID, CONTAINER_ITEM_ID, ITEM_TITLE, ITEM_NAME));
containerWithItem.put(ITEM_ID, getMock(CHECKBOX, PAGE_ITEM_ID));
@Test
void shouldAddNodeToTopOfContainerNodes() {
var formNode = FormNodeTestFactory.create();
doReturn(formNode).when(structureParser).buildNode(any());
var parentNode = injectContainerNodes();
var fieldSetMock = getMock(FIELD_SET);
when(fieldSetMock.getParentId()).thenReturn(parentNode.getFirst().getItemId());
structureParser.handleContainerNode(fieldSetMock);
return containerWithItem;
assertThat(getContainerNodes()).first().isSameAs(formNode);
}
@SuppressWarnings("unchecked")
@SneakyThrows
private Deque<FormNode> getContainerNodes() {
var containerNodesField = FormStructureParser.class.getDeclaredField("containerNodes");
containerNodesField.setAccessible(true);
return (Deque<FormNode>) containerNodesField.get(structureParser);
}
}
@Nested
......@@ -178,131 +265,130 @@ class FormStructureParserTest {
}
@Nested
class TestMethods {
private static final String PARENT_ID = "parentId";
class TestGetResultNodes {
@InjectMocks
private FormStructureParser structureParser;
private final List<FormNode> expectedResultNodes = List.of(FormNodeTestFactory.create());
private Deque<FormNode> containerNodes;
private FormNode containerNode;
@SneakyThrows
@BeforeEach
void setup() {
containerNode = FormNodeTestFactory.create();
containerNodes = new ArrayDeque<>();
containerNodes.push(containerNode);
var stackField = structureParser.getClass().getDeclaredField("containerNodes");
stackField.setAccessible(true);
stackField.set(structureParser, containerNodes);
void init() {
structureParser = spy(new FormStructureParser(createItem(FIELD_SET)));
injectResultNodes(expectedResultNodes);
}
@Nested
@DisplayName("GetNextContainerNode")
class TestNextContainerNode {
@Test
void shouldReturnRootNodesWhenNoContainerNodes() {
var nodes = structureParser.getResultNodes(StructureMockFactory.getMock(TEXT_FIELD));
assertThat(nodes).isSameAs(expectedResultNodes);
}
@Test
@DisplayName("should return empty when container stack is empty")
void shouldReturnEmpty() {
injectNodesField();
void shouldReturnRootWhenAntragsteller() {
var antragstellerXItem = getMock(CONTAINER);
when(antragstellerXItem.getName()).thenReturn(FormStructureParser.CONTAINER_NAME_ANTRAGSTELLER);
injectContainerNodes(new ArrayDeque<>(List.of(FormNodeTestFactory.createBuilder().itemId(CONTAINER_ITEM_ID).build())));
var nextContainerNode = structureParser.getNextContainerNode(PARENT_ID);
var nodes = structureParser.getResultNodes(antragstellerXItem);
assertThat(nextContainerNode).isEmpty();
assertThat(nodes).isSameAs(expectedResultNodes);
}
@Test
void shouldReturnParent() {
var nextContainerNode = structureParser.getNextContainerNode(ITEM_ID);
@Nested
class TestGetNextContainer {
assertThat(nextContainerNode).isPresent().get().isEqualTo(containerNode);
@BeforeEach
void init() {
injectContainerNodes();
}
@Test
void shouldReturnNestedParent() {
var parentContainer = FormNodeTestFactory.createBuilder().itemId(NEXT_ITEM_ID).build();
containerNodes.addLast(parentContainer);
void shouldReturnRootWhenNoParentNode() {
var nodes = structureParser.getResultNodes(getMock(CONTAINER));
var nextContainerNode = structureParser.getNextContainerNode(NEXT_ITEM_ID);
assertThat(nextContainerNode).isPresent().get().isEqualTo(parentContainer);
assertThat(nodes).isSameAs(expectedResultNodes);
}
@Test
@DisplayName("should return empty when no parent on stack")
void shouldReturnEmptyNoParents() {
var parentContainer = FormNodeTestFactory.createBuilder().itemId(NEXT_ITEM_ID).build();
containerNodes.addLast(parentContainer);
void shouldCallGetNextContainerNode() {
var parentId = "parentId";
var xItem = getMock(CONTAINER);
when(xItem.getParentId()).thenReturn(parentId);
var nextContainerNode = structureParser.getNextContainerNode("id");
structureParser.getResultNodes(xItem);
assertThat(nextContainerNode).isEmpty();
verify(structureParser).getNextContainerNode(parentId);
}
@Test
@DisplayName("should clear stack when no parent found")
void shouldClearStack() {
structureParser.getNextContainerNode("id");
void shouldReturnNestedNodes() {
var formNode = FormNodeTestFactory.create();
doReturn(Optional.of(formNode)).when(structureParser).getNextContainerNode(anyString());
var expectedNestedCollection = formNode.getNestedElements();
assertThat(getStackCollection()).isEmpty();
}
var nodes = structureParser.getResultNodes(getMock(CONTAINER));
assertThat(nodes).isSameAs(expectedNestedCollection);
}
}
}
@Nested
@DisplayName("GetNodes")
class TestGetNodes {
class TestGetNextContainerNode {
@Test
@DisplayName("should return result collection when container stack is empty")
void shouldReturnResultCollectionStackEmpty() {
getStackCollection().clear();
var expectedNodes = injectNodesField();
@BeforeEach
void init() {
structureParser = spy(new FormStructureParser(createItem(FIELD_SET)));
}
var resultNodes = structureParser.getNodes(ITEM_ID);
@Test
void shouldReturnEmptyWhenNodeStackEmpty() {
var nextContainerNode = structureParser.getNextContainerNode(ITEM_ID);
assertThat(resultNodes).isEqualTo(expectedNodes);
assertThat(nextContainerNode).isEmpty();
}
@Test
@DisplayName("should return result collection when no parent found")
void shouldReturnResultCollectionNoParent() {
var expectedNodes = injectNodesField();
void shouldReturnEmpty() {
injectContainerNodes(new ArrayDeque<>(List.of(FormNodeTestFactory.create())));
var resultNodes = structureParser.getNodes(PARENT_ID);
var nextContainerNode = structureParser.getNextContainerNode("parentId");
assertThat(resultNodes).isEqualTo(expectedNodes);
assertThat(nextContainerNode).isEmpty();
}
@Test
@DisplayName("should return container collection when parent found")
void shouldReturnResultContainerCollection() {
var expectedCollection = containerNode.getNestedElements();
void shouldReturnParent() {
var parentId = "parentId";
FormNode parentNode = FormNodeTestFactory.createBuilder().itemId(parentId).build();
var parentNodes = injectContainerNodes(new ArrayDeque<>());
parentNodes.push(parentNode);
parentNodes.push(FormNodeTestFactory.create());
var resultNodes = structureParser.getNodes(ITEM_ID);
var nextContainerNode = structureParser.getNextContainerNode(parentId);
assertThat(resultNodes).isEqualTo(expectedCollection);
assertThat(nextContainerNode).contains(parentNode);
}
}
@SneakyThrows
private List<FormNode> injectNodesField() {
List<FormNode> nodes = List.of(FormNodeTestFactory.create());
var nodesField = structureParser.getClass().getDeclaredField("nodes");
nodesField.setAccessible(true);
nodesField.set(structureParser, nodes);
private List<FormNode> injectResultNodes(List<FormNode> nodes) {
var containerNodesField = FormStructureParser.class.getDeclaredField("resultNodes");
containerNodesField.setAccessible(true);
containerNodesField.set(structureParser, nodes);
return nodes;
}
@SneakyThrows
private Deque<FormNode> getStackCollection() {
var stackField = structureParser.getClass().getDeclaredField("containerNodes");
stackField.setAccessible(true);
return (Deque<FormNode>) stackField.get(structureParser);
private Deque<FormNode> injectContainerNodes() {
return injectContainerNodes(new ArrayDeque<>(List.of(FormNodeTestFactory.create())));
}
@SneakyThrows
private Deque<FormNode> injectContainerNodes(Deque<FormNode> containerNodes) {
var containerNodesField = FormStructureParser.class.getDeclaredField("containerNodes");
containerNodesField.setAccessible(true);
containerNodesField.set(structureParser, containerNodes);
return containerNodes;
}
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment