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

Merge branch 'master' into optional-ingress-class-name

parents c652e7db 50aa1a62
Branches
Tags
No related merge requests found
Showing
with 488 additions and 11 deletions
...@@ -34,18 +34,19 @@ pipeline { ...@@ -34,18 +34,19 @@ pipeline {
def fsAdapterVersion = getParentPomVersion('formsolutions-adapter/pom.xml') def fsAdapterVersion = getParentPomVersion('formsolutions-adapter/pom.xml')
def formCycleAdapterVersion = getParentPomVersion('formcycle-adapter/pom.xml') def formCycleAdapterVersion = getParentPomVersion('formcycle-adapter/pom.xml')
def xtaAdapterVersion = getParentPomVersion('xta-adapter/pom.xml') def xtaAdapterVersion = getParentPomVersion('xta-adapter/pom.xml')
def enterpriseAdapterVersion = getParentPomVersion('enterprise-adapter/pom.xml')
if(env.BRANCH_NAME == 'release'){ if(env.BRANCH_NAME == 'release'){
if ( !isReleaseVersion([rootVersion, plutoVersion, commonVersion, routerVersion, ifAdapterVersion, fsAdapterVersion, formCycleAdapterVersion, xtaAdapterVersion])) { if ( !isReleaseVersion([rootVersion, plutoVersion, commonVersion, routerVersion, ifAdapterVersion, fsAdapterVersion, formCycleAdapterVersion, xtaAdapterVersion, enterpriseAdapterVersion])) {
error("Keine Release Version für Branch ${env.BRANCH_NAME}.") error("Keine Release Version für Branch ${env.BRANCH_NAME}.")
} }
} else { } else {
if ( !isSnapshotVersion([rootVersion, commonVersion, routerVersion, ifAdapterVersion, fsAdapterVersion, formCycleAdapterVersion, xtaAdapterVersion])) { if ( !isSnapshotVersion([rootVersion, commonVersion, routerVersion, ifAdapterVersion, fsAdapterVersion, formCycleAdapterVersion, xtaAdapterVersion, enterpriseAdapterVersion])) {
error("Keine Snapshot Version für Branch ${env.BRANCH_NAME}.") error("Keine Snapshot Version für Branch ${env.BRANCH_NAME}.")
} }
} }
if ( !isSameVersion([commonVersion, routerVersion, ifAdapterVersion, fsAdapterVersion, formCycleAdapterVersion, xtaAdapterVersion], rootVersion)) { if ( !isSameVersion([commonVersion, routerVersion, ifAdapterVersion, fsAdapterVersion, formCycleAdapterVersion, xtaAdapterVersion, enterpriseAdapterVersion], rootVersion)) {
error("Versionen sind nicht identisch") error("Versionen sind nicht identisch")
} }
} }
...@@ -107,18 +108,21 @@ pipeline { ...@@ -107,18 +108,21 @@ pipeline {
tagAndPushDockerImage('formsolutions-adapter', IMAGE_TAG) tagAndPushDockerImage('formsolutions-adapter', IMAGE_TAG)
tagAndPushDockerImage('formcycle-adapter', IMAGE_TAG) tagAndPushDockerImage('formcycle-adapter', IMAGE_TAG)
tagAndPushDockerImage('xta-adapter', IMAGE_TAG) tagAndPushDockerImage('xta-adapter', IMAGE_TAG)
tagAndPushDockerImage('enterprise-adapter', IMAGE_TAG)
if (env.BRANCH_NAME == 'master') { if (env.BRANCH_NAME == 'master') {
tagAndPushDockerImage('intelliform-adapter', 'snapshot-latest') tagAndPushDockerImage('intelliform-adapter', 'snapshot-latest')
tagAndPushDockerImage('formsolutions-adapter', 'snapshot-latest') tagAndPushDockerImage('formsolutions-adapter', 'snapshot-latest')
tagAndPushDockerImage('formcycle-adapter', 'snapshot-latest') tagAndPushDockerImage('formcycle-adapter', 'snapshot-latest')
tagAndPushDockerImage('xta-adapter', 'snapshot-latest') tagAndPushDockerImage('xta-adapter', 'snapshot-latest')
tagAndPushDockerImage('enterprise-adapter', 'snapshot-latest')
} }
else if (env.BRANCH_NAME == 'release') { else if (env.BRANCH_NAME == 'release') {
tagAndPushDockerImage('intelliform-adapter', 'latest') tagAndPushDockerImage('intelliform-adapter', 'latest')
tagAndPushDockerImage('formsolutions-adapter', 'latest') tagAndPushDockerImage('formsolutions-adapter', 'latest')
tagAndPushDockerImage('formcycle-adapter', 'latest') tagAndPushDockerImage('formcycle-adapter', 'latest')
tagAndPushDockerImage('xta-adapter', 'latest') tagAndPushDockerImage('xta-adapter', 'latest')
tagAndPushDockerImage('enterprise-adapter', 'latest')
} }
} }
} }
...@@ -285,12 +289,14 @@ Void setNewDevAdapterVersion() { ...@@ -285,12 +289,14 @@ Void setNewDevAdapterVersion() {
setNewFsAdapterVersion('dev') setNewFsAdapterVersion('dev')
setNewFormcycleAdapterVersion('dev') setNewFormcycleAdapterVersion('dev')
setNewXtaAdapterVersion('dev') setNewXtaAdapterVersion('dev')
setNewEnterpriseAdapterVersion('dev')
} }
Void setNewTestAdapterVersion() { Void setNewTestAdapterVersion() {
setNewAfmAdapterVersion('test') setNewAfmAdapterVersion('test')
setNewFsAdapterVersion('test') setNewFsAdapterVersion('test')
setNewFormcycleAdapterVersion('test') setNewFormcycleAdapterVersion('test')
setNewEnterpriseAdapterVersion('test')
} }
Void setNewAfmAdapterVersion(String environment) { Void setNewAfmAdapterVersion(String environment) {
...@@ -341,6 +347,18 @@ Void setNewXtaAdapterVersion(String environment) { ...@@ -341,6 +347,18 @@ Void setNewXtaAdapterVersion(String environment) {
} }
} }
Void setNewEnterpriseAdapterVersion(String environment) {
dir("gitops") {
def envFile = "${environment}/application/values/enterprise-adapter-values.yaml"
def envVersions = readYaml file: envFile
envVersions.enterprise_adapter.image.tag = IMAGE_TAG
envVersions.enterprise_adapter.helm.version = HELM_CHART_VERSION
writeYaml file: envFile, data: envVersions, overwrite: true
}
}
Void pushNewDevVersion() { Void pushNewDevVersion() {
pushNewGitopsVersion('dev') pushNewGitopsVersion('dev')
} }
......
...@@ -23,6 +23,8 @@ ...@@ -23,6 +23,8 @@
*/ */
package de.ozgcloud.eingang; package de.ozgcloud.eingang;
import java.util.TimeZone;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.EnableScheduling;
...@@ -32,6 +34,7 @@ import org.springframework.scheduling.annotation.EnableScheduling; ...@@ -32,6 +34,7 @@ import org.springframework.scheduling.annotation.EnableScheduling;
public class Application { public class Application {
public static void main(String[] args) { public static void main(String[] args) {
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
SpringApplication.run(Application.class, args); SpringApplication.run(Application.class, args);
} }
} }
package de.ozgcloud.eingang;
import java.nio.charset.Charset;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
import lombok.extern.log4j.Log4j2;
@Log4j2
@Component
class LogRunner implements ApplicationListener<ContextRefreshedEvent> {
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
LOG.info("Standard Charset: " + Charset.defaultCharset());
}
}
...@@ -37,6 +37,7 @@ import lombok.ToString; ...@@ -37,6 +37,7 @@ import lombok.ToString;
public class FormHeader { public class FormHeader {
private String requestId; private String requestId;
private String vorgangNummer;
@Builder.Default @Builder.Default
private ZonedDateTime createdAt = ZonedDateTime.now(); private ZonedDateTime createdAt = ZonedDateTime.now();
private String formId; private String formId;
......
package de.ozgcloud.eingang.formcycle; package de.ozgcloud.eingang.common.vorgang;
import java.time.Instant; import java.time.Instant;
import java.time.LocalDate; import java.time.LocalDate;
...@@ -6,7 +6,7 @@ import java.time.LocalDate; ...@@ -6,7 +6,7 @@ import java.time.LocalDate;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@Component @Component
class VorgangNummerSupplier { public class VorgangNummerSupplier {
static final String BASE30_ALPHABET = "23456789ABCDEFGHJKMNPQRSTVWXYZ"; static final String BASE30_ALPHABET = "23456789ABCDEFGHJKMNPQRSTVWXYZ";
static final int SUFFIX_LENGTH = 6; static final int SUFFIX_LENGTH = 6;
......
...@@ -37,9 +37,9 @@ public class AntragstellerTestFactory { ...@@ -37,9 +37,9 @@ public class AntragstellerTestFactory {
public static final String SUB_VERBOTENE_VEREINIGUNG_KEY = "MitgliedschaftInVerboternerVereinigung"; public static final String SUB_VERBOTENE_VEREINIGUNG_KEY = "MitgliedschaftInVerboternerVereinigung";
public static final String SUB_VERBOTENE_VEREINIGUNG_VALUE = "true"; public static final String SUB_VERBOTENE_VEREINIGUNG_VALUE = "true";
public static final String VORNAME = "Helge"; public static final String VORNAME = "Theo";
public static final String NACHNAME = "Schneider"; public static final String NACHNAME = "Test";
public static final String GEBURTSNAME = "Schneider"; public static final String GEBURTSNAME = "Toast";
public static final String GEBURTSDATUM = "30.8.1955"; public static final String GEBURTSDATUM = "30.8.1955";
public static final String GEBURTSORT = "Mülheim an der Ruhr"; public static final String GEBURTSORT = "Mülheim an der Ruhr";
public static final String EMAIL = "schneider@helgeschneider.local"; public static final String EMAIL = "schneider@helgeschneider.local";
......
...@@ -3,17 +3,26 @@ package de.ozgcloud.eingang.common.formdata; ...@@ -3,17 +3,26 @@ package de.ozgcloud.eingang.common.formdata;
import static org.assertj.core.api.Assertions.*; import static org.assertj.core.api.Assertions.*;
import java.io.File; import java.io.File;
import java.io.IOException;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import de.itvsh.kop.common.errorhandling.TechnicalException; import de.itvsh.kop.common.errorhandling.TechnicalException;
class DeleteOnCloseInputStreamTest { class DeleteOnCloseInputStreamTest {
@InjectMocks
private DeleteOnCloseInputStream stream; private DeleteOnCloseInputStream stream;
@Test
void shouldDeleteFileOnClose() throws IOException {
File file = File.createTempFile("Test", "test");
stream = new DeleteOnCloseInputStream(file);
stream.close();
assertThat(file).doesNotExist();
}
@Test @Test
void shouldThrowException() { void shouldThrowException() {
var notExists = new File("notExists"); var notExists = new File("notExists");
......
...@@ -35,6 +35,7 @@ public class FormHeaderTestFactory { ...@@ -35,6 +35,7 @@ public class FormHeaderTestFactory {
public static final String FORM_NAME = "formName"; public static final String FORM_NAME = "formName";
public static final String FORM_ID = "formId"; public static final String FORM_ID = "formId";
public static final String REQUEST_ID = "requestId"; public static final String REQUEST_ID = "requestId";
public static final String VORGANG_NUMMER = "ABCD-1234";
public static final ZonedDateTime CREATED_AT = ZonedDateTime.now(); public static final ZonedDateTime CREATED_AT = ZonedDateTime.now();
public static FormHeader create() { public static FormHeader create() {
...@@ -44,6 +45,7 @@ public class FormHeaderTestFactory { ...@@ -44,6 +45,7 @@ public class FormHeaderTestFactory {
public static FormHeader.FormHeaderBuilder createBuilder() { public static FormHeader.FormHeaderBuilder createBuilder() {
return FormHeader.builder() return FormHeader.builder()
.requestId(REQUEST_ID) .requestId(REQUEST_ID)
.vorgangNummer(VORGANG_NUMMER)
.createdAt(CREATED_AT) .createdAt(CREATED_AT)
.formId(FORM_ID) .formId(FORM_ID)
.formName(FORM_NAME) .formName(FORM_NAME)
......
package de.ozgcloud.eingang.formcycle; package de.ozgcloud.eingang.common.vorgang;
import static org.assertj.core.api.Assertions.*; import static org.assertj.core.api.Assertions.*;
import static org.mockito.Mockito.*; import static org.mockito.Mockito.*;
......
org.mockito.junit.jupiter.MockitoExtension
\ No newline at end of file
junit.jupiter.extensions.autodetection.enabled = true
\ No newline at end of file
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>de.itvsh.kop.eingangsadapter</groupId>
<artifactId>parent</artifactId>
<version>1.13.0-SNAPSHOT</version>
</parent>
<artifactId>enterprise-adapter</artifactId>
<name>EM - Enterprise Interface Adapter</name>
<properties>
<spring-boot.build-image.imageName>
docker.ozg-sh.de/enterprise-adapter:build-latest
</spring-boot.build-image.imageName>
</properties>
<dependencies>
<!--ozg-Cloud-->
<dependency>
<groupId>de.itvsh.kop.eingangsadapter</groupId>
<artifactId>common</artifactId>
</dependency>
<dependency>
<groupId>de.itvsh.kop.eingangsadapter</groupId>
<artifactId>semantik-adapter</artifactId>
</dependency>
<!--spring-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--dev tools-->
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
</dependency>
<!--test -->
<dependency>
<groupId>de.itvsh.kop.eingangsadapter</groupId>
<artifactId>common</artifactId>
<type>test-jar</type>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>ci-build</id>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<id>build-image</id>
<phase>
install</phase>
<goals>
<goal>build-image</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
\ No newline at end of file
package de.ozgcloud.eingang.enterprise.entry;
import java.io.IOException;
import java.time.ZonedDateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import de.ozgcloud.eingang.common.formdata.FormData;
import de.ozgcloud.eingang.common.vorgang.VorgangNummerSupplier;
import de.ozgcloud.eingang.enterprise.entry.EntryResponse.ResponseVorgang;
import de.ozgcloud.eingang.semantik.SemantikAdapter;
@Controller
@ResponseBody
@RequestMapping("antrag")
public class EntryController {
private static final String STARTING_STATUS = "NEU";
@Autowired
private EntryDataMapper mapper;
@Autowired
private SemantikAdapter semantikAdapter;
@Autowired
private VorgangNummerSupplier vorgangNummerSupplier;
@ResponseStatus(HttpStatus.ACCEPTED)
@PostMapping(consumes = "multipart/form-data", produces = MediaType.APPLICATION_JSON_VALUE)
public EntryResponse receiveAntrag(@RequestPart Resource formData) throws IOException {
var mapped = mapper.mapEntryData(formData.getInputStream());
mapped = addVorgangNummer(mapped);
var vorgangId = semantikAdapter.processFormData(mapped);
return buildResponse(mapped, vorgangId);
}
private FormData addVorgangNummer(FormData formData) {
var header = formData.getHeader().toBuilder().vorgangNummer(vorgangNummerSupplier.get()).build();
return formData.toBuilder().header(header).build();
}
EntryResponse buildResponse(FormData formData, String vorgangId) {
return EntryResponse.builder()
.transactionId(formData.getHeader().getRequestId())
.vorgang(ResponseVorgang.builder()
.vorgangId(vorgangId)
.vorgangNummer(formData.getHeader().getVorgangNummer())
.status(STARTING_STATUS)
.statusSince(ZonedDateTime.now().withNano(0))
.build())
.build();
}
}
package de.ozgcloud.eingang.enterprise.entry;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Builder;
import lombok.Getter;
import lombok.extern.jackson.Jacksonized;
@Builder
@Getter
@Jacksonized
public class EntryData {
private ControlData control;
private List<EntryFormDataItem> formData;
@Builder
@Getter
@Jacksonized
public static class ControlData {
private String transactionId;
private String zustaendigeStelle;
private String[] leikaIds;
private ResultEndpoint resultEndpoint;
private String formId;
@JsonProperty("name")
private String formName;
@Builder
@Getter
@Jacksonized
public static class ResultEndpoint {
private String address;
}
}
}
package de.ozgcloud.eingang.enterprise.entry;
import java.io.IOException;
import java.io.InputStream;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.fasterxml.jackson.databind.ObjectMapper;
import de.ozgcloud.eingang.common.formdata.FormData;
@Component
class EntryDataMapper {
@Autowired
private ObjectMapper objectMapper;
@Autowired
private FormDataMapper formDataMapper;
public FormData mapEntryData(InputStream request) {
return formDataMapper.mapEntryData(readRequest(request));
}
EntryData readRequest(InputStream request) {
try {
return objectMapper.readValue(request, EntryData.class);
} catch (IOException e) {
throw new ReadingRequestException(e);
}
}
}
package de.ozgcloud.eingang.enterprise.entry;
import java.time.LocalDate;
import java.util.Objects;
import org.apache.commons.lang3.StringUtils;
import lombok.Builder;
import lombok.Getter;
import lombok.ToString;
import lombok.extern.jackson.Jacksonized;
@Builder
@Getter
@Jacksonized
@ToString(onlyExplicitlyIncluded = true)
public class EntryFormDataField implements EntryFormDataItem {
private String name;
@ToString.Include
private String label;
private String stringValue;
private Boolean booleanValue;
private Number numberValue;
private LocalDate dateValue;
@Override
public boolean isFormField() {
return true;
}
public Object getValue() {
if (StringUtils.isNotBlank(stringValue)) {
return stringValue;
}
if (Objects.nonNull(booleanValue)) {
return booleanValue;
}
if (Objects.nonNull(numberValue)) {
return numberValue;
}
if (Objects.nonNull(dateValue)) {
return dateValue;
}
return null;
}
}
package de.ozgcloud.eingang.enterprise.entry;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonSubTypes.Type;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;
@JsonTypeInfo(use = Id.DEDUCTION)
@JsonSubTypes({ @Type(EntryFormDataField.class), @Type(EntryFormDataSubForm.class) })
public interface EntryFormDataItem {
String getName();
String getLabel();
default boolean isSubForm() {
return false;
}
default boolean isFormField() {
return false;
}
}
package de.ozgcloud.eingang.enterprise.entry;
import java.util.List;
import lombok.Builder;
import lombok.Getter;
import lombok.Singular;
import lombok.ToString;
import lombok.extern.jackson.Jacksonized;
@Builder
@Getter
@Jacksonized
@ToString(onlyExplicitlyIncluded = true)
public class EntryFormDataSubForm implements EntryFormDataItem {
private String name;
@ToString.Include
private String label;
@Singular
private List<EntryFormDataItem> formItems;
@Override
public boolean isSubForm() {
return true;
}
}
package de.ozgcloud.eingang.enterprise.entry;
import java.time.ZonedDateTime;
import lombok.Builder;
import lombok.Getter;
@Builder
@Getter
class EntryResponse {
private String transactionId;
private ResponseVorgang vorgang;
@Builder
@Getter
static class ResponseVorgang {
private String vorgangId;
private String vorgangNummer;
private String status;
private ZonedDateTime statusSince;
}
}
package de.ozgcloud.eingang.enterprise.entry;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.apache.commons.lang3.tuple.Pair;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import de.ozgcloud.eingang.common.formdata.FormData;
import de.ozgcloud.eingang.common.formdata.FormHeader;
import de.ozgcloud.eingang.common.formdata.ZustaendigeStelle;
@Mapper
public interface FormDataMapper {
public static final String VALUE_KEY = "value";
public static final String LABEL_KEY = "label";
@Mapping(target = "antragsteller", ignore = true)
@Mapping(target = "attachment", ignore = true)
@Mapping(target = "attachments", ignore = true)
@Mapping(target = "numberOfAttachments", ignore = true)
@Mapping(target = "representation", ignore = true)
@Mapping(target = "representations", ignore = true)
@Mapping(target = "numberOfRepresentations", ignore = true)
@Mapping(target = "id", ignore = true)
@Mapping(target = "header", source = "control")
@Mapping(target = "zustaendigeStelle", source = "control.zustaendigeStelle")
FormData mapEntryData(EntryData entryData);
@Mapping(target = "createdAt", ignore = true)
@Mapping(target = "formEngineName", constant = "EnterpriseSoftware")
@Mapping(target = "requestId", source = "transactionId")
@Mapping(target = "sender", ignore = true) // TODO fill from authentication
@Mapping(target = "serviceKonto", ignore = true)
FormHeader mapHeader(EntryData.ControlData controlData);
default ZustaendigeStelle fromId(String organisationsEinheitenId) {
return ZustaendigeStelle.builder().organisationseinheitenId(organisationsEinheitenId).build();
}
default Map<String, Object> mapFormItems(List<EntryFormDataItem> items) {
return items.stream().map(item -> Pair.of(item.getName(),
item.isFormField() ? mapFormField((EntryFormDataField) item) : mapSubForm((EntryFormDataSubForm) item)))
.collect(Collectors.toMap(Pair::getKey, Pair::getValue));
}
default Map<String, Object> mapFormField(EntryFormDataField field) {
return Map.of(LABEL_KEY, field.getLabel(), VALUE_KEY, field.getValue());
}
default Map<String, Object> mapSubForm(EntryFormDataSubForm subForm) {
return Map.of(LABEL_KEY, subForm.getLabel(), VALUE_KEY, mapFormItems(subForm.getFormItems()));
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment