diff --git a/eno-ws/pom.xml b/eno-ws/pom.xml
index 786397caa..869d26548 100644
--- a/eno-ws/pom.xml
+++ b/eno-ws/pom.xml
@@ -9,13 +9,185 @@
eno-ws
Eno - Web-Service
- http://maven.apache.org
-
-
- junit
- junit
- 3.8.1
- test
-
-
+
+
+
+ eno-ws
+ ${project.encoding}
+ ${project.encoding}
+
+
+ ${java.version}
+ ${java.version}
+
+ 2.7.3
+ 1.2.0
+ 2.3.1
+ 2.3.9
+ 4.0.5
+ 2.8.13
+
+
+ 0.8.13
+ jacoco
+ jacoco
+ reuseReports
+ Eno-WS
+ java
+ -Xms256m -Xmx512m -XX:MaxMetaspaceSize=128m -ea -Dfile.encoding=UTF-8
+
+
+
+
+ oss.sonatype.org-snapshot
+ https://oss.sonatype.org/content/repositories/snapshots
+
+ false
+
+
+ true
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springdoc
+ springdoc-openapi-starter-webmvc-ui
+ ${springdoc-openapi-ui.version}
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+
+
+ fr.insee.eno
+ eno-core
+ ${project.version}
+
+
+ commons-logging
+ commons-logging
+
+
+
+
+
+
+ fr.insee.lunatic
+ lunatic-model
+ ${lunatic-model.version}
+
+
+
+
+ com.sun.activation
+ javax.activation
+ ${javax.activation.version}
+
+
+ javax.xml.bind
+ jaxb-api
+ ${jaxb-api.version}
+
+
+ com.sun.xml.bind
+ jaxb-impl
+ ${jaxb-impl.version}
+
+
+ com.sun.xml.bind
+ jaxb-core
+ ${jaxb-core.version}
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.springframework
+ spring-test
+ test
+
+
+ org.springframework.boot
+ spring-boot-test-autoconfigure
+ test
+
+
+ junit
+ junit
+ test
+
+
+
+
+ org.projectlombok
+ lombok
+ provided
+
+
+
+
+ ${final.jar.name}
+
+
+ org.jacoco
+ jacoco-maven-plugin
+ ${jacoco.version}
+
+
+ prepare-agent
+
+ prepare-agent
+
+
+
+ report
+
+ report
+
+
+
+ XML
+
+
+
+
+
+
+ org.sonarsource.scanner.maven
+ sonar-maven-plugin
+ 4.0.0.4121
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+ build-info
+
+ build-info
+
+
+
+ ${project.description}
+
+
+
+
+
+
+
+
diff --git a/eno-ws/src/main/java/fr/insee/eno/App.java b/eno-ws/src/main/java/fr/insee/eno/App.java
deleted file mode 100644
index d0d2ead49..000000000
--- a/eno-ws/src/main/java/fr/insee/eno/App.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package fr.insee.eno;
-
-/**
- * Hello world!
- *
- */
-public class App
-{
- public static void main( String[] args )
- {
- System.out.println( "Hello World!" );
- }
-}
diff --git a/eno-ws/src/main/java/fr/insee/eno/ws/EnoWS.java b/eno-ws/src/main/java/fr/insee/eno/ws/EnoWS.java
new file mode 100644
index 000000000..46d9c2c0a
--- /dev/null
+++ b/eno-ws/src/main/java/fr/insee/eno/ws/EnoWS.java
@@ -0,0 +1,19 @@
+package fr.insee.eno.ws;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
+import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
+
+@SpringBootApplication(scanBasePackages = "fr.insee.eno.ws")
+@ConfigurationPropertiesScan
+public class EnoWS extends SpringBootServletInitializer{
+
+ @Override
+ protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
+ return application.sources(EnoWS.class);
+ }
+
+ public static void main(String[] args) { SpringApplication.run(EnoWS.class, args); }
+}
diff --git a/eno-ws/src/main/java/fr/insee/eno/ws/config/CorsConfig.java b/eno-ws/src/main/java/fr/insee/eno/ws/config/CorsConfig.java
new file mode 100644
index 000000000..e582ff973
--- /dev/null
+++ b/eno-ws/src/main/java/fr/insee/eno/ws/config/CorsConfig.java
@@ -0,0 +1,29 @@
+package fr.insee.eno.ws.config;
+
+import lombok.AllArgsConstructor;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.CorsConfigurationSource;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+
+import java.util.List;
+
+@Configuration
+@AllArgsConstructor
+public class CorsConfig {
+
+ @Bean
+ protected CorsConfigurationSource corsWebFilter () {
+ CorsConfiguration configuration = new CorsConfiguration();
+ configuration.setAllowedOriginPatterns(List.of("*"));
+ configuration.setAllowedMethods(List.of("GET", "PUT", "POST", "DELETE", "OPTIONS"));
+ configuration.setAllowedHeaders(List.of("Authorization", "Content-Type"));
+ configuration.addExposedHeader("Content-Disposition");
+ configuration.setMaxAge(3600L);
+ configuration.setAllowCredentials(true);
+ UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+ source.registerCorsConfiguration("/**", configuration);
+ return source;
+ }
+}
\ No newline at end of file
diff --git a/eno-ws/src/main/java/fr/insee/eno/ws/config/OpenApiConfiguration.java b/eno-ws/src/main/java/fr/insee/eno/ws/config/OpenApiConfiguration.java
new file mode 100644
index 000000000..fa16af598
--- /dev/null
+++ b/eno-ws/src/main/java/fr/insee/eno/ws/config/OpenApiConfiguration.java
@@ -0,0 +1,54 @@
+package fr.insee.eno.ws.config;
+
+import io.swagger.v3.oas.models.OpenAPI;
+import io.swagger.v3.oas.models.info.Info;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.info.BuildProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.MediaType;
+import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
+
+import java.util.ArrayList;
+
+@Configuration
+public class OpenApiConfiguration {
+
+ @Value("${fr.insee.enows.api.scheme}")
+ private String apiScheme;
+
+ @Value("${fr.insee.enows.api.host}")
+ private String apiHost;
+
+ @Value("${fr.insee.enows.enocore.version}")
+ private String enoVersion;
+
+ @Value("${fr.insee.enows.lunatic.model.version}")
+ private String lunaticModelVersion;
+
+ @Value("${fr.insee.enows.version}")
+ private String projectVersion;
+
+ @Autowired
+ private BuildProperties buildProperties;
+
+ @Bean
+ protected OpenAPI noAuthOpenAPI() {
+ return new OpenAPI().info(
+ new Info()
+ .title(buildProperties.getName())
+ .description(String.format("""
+ Generator using :
+ Eno version : %s
+ Lunatic-Model version : %s
+ """,enoVersion,lunaticModelVersion))
+ .version(buildProperties.getVersion())
+ ); }
+
+ public OpenApiConfiguration(MappingJackson2HttpMessageConverter converter) {
+ var supportedMediaTypes = new ArrayList<>(converter.getSupportedMediaTypes());
+ supportedMediaTypes.add(new MediaType("application", "octet-stream"));
+ converter.setSupportedMediaTypes(supportedMediaTypes);
+ }
+}
diff --git a/eno-ws/src/main/java/fr/insee/eno/ws/controller/GenerationCustomController.java b/eno-ws/src/main/java/fr/insee/eno/ws/controller/GenerationCustomController.java
new file mode 100644
index 000000000..683d6fbe4
--- /dev/null
+++ b/eno-ws/src/main/java/fr/insee/eno/ws/controller/GenerationCustomController.java
@@ -0,0 +1,157 @@
+package fr.insee.eno.ws.controller;
+
+import fr.insee.eno.exception.EnoParametersException;
+import fr.insee.eno.parameters.*;
+import fr.insee.eno.params.ValorizatorParameters;
+import fr.insee.eno.params.ValorizatorParametersImpl;
+import fr.insee.eno.service.MultiModelService;
+import fr.insee.eno.service.ParameterizedGenerationService;
+import fr.insee.eno.ws.controller.utils.ResponseUtils;
+import fr.insee.eno.ws.service.ParameterService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+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.RestController;
+import org.springframework.web.multipart.MultipartFile;
+import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
+
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+
+@Tag(name="Generation from DDI (custom parameters)")
+@RestController
+@RequestMapping("/questionnaire")
+@Slf4j
+public class GenerationCustomController {
+ // Eno-WS services
+ private final ParameterService parameterService;
+
+ // Eno core service
+ private final MultiModelService multiModelService = new MultiModelService();
+ private final ValorizatorParameters valorizatorParameters = new ValorizatorParametersImpl();
+
+ public GenerationCustomController(ParameterService parameterService) {
+ this.parameterService = parameterService;
+ }
+
+ @Operation(
+ summary = "Generation of Xforms questionnaire from DDI.",
+ description = "Generation of a Xforms questionnaire from the given DDI with default business " +
+ "pipeline, using a custom parameters file _(required)_, a metadata file _(required)_ and a " +
+ "specific treatment file _(optional)_."
+ )
+ @PostMapping(value = "ddi-2-xforms",
+ produces = MediaType.APPLICATION_OCTET_STREAM_VALUE, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
+ public ResponseEntity generateXformsCustomParams(
+ @RequestPart(value="in") MultipartFile in,
+ @RequestPart(value="params") MultipartFile params,
+ @RequestPart(value="metadata") MultipartFile metadata,
+ @RequestPart(value="specificTreatment",required=false) MultipartFile specificTreatment) throws Exception {
+
+ log.info("Received request to transform DDI to a Xforms questionnaire.");
+
+ InputStream paramsIS = params != null ? params.getInputStream() : null;
+ ENOParameters enoParameters = valorizatorParameters.getParameters(paramsIS);
+ Context context = enoParameters.getParameters().getContext();
+ Mode mode = enoParameters.getMode();
+
+ nonNullContextCheck(context);
+ if (Context.HOUSEHOLD.equals(context))
+ throw new EnoParametersException("Context 'HOUSEHOLD' is not compatible with Xforms format.");
+ nonNullModeCheck(mode);
+ if (Mode.CAPI.equals(mode) || Mode.CATI.equals(mode) || Mode.PAPI.equals(mode))
+ throw new EnoParametersException("Mode '" + mode + "' is not compatible with Xforms format.");
+
+ logModeAndContext(context, mode);
+
+ ENOParameters defaultEnoParamsDDI2Xforms = parameterService.getDefaultCustomParameters(
+ context, OutFormat.XFORMS, null);
+
+ Pipeline defaultPipeline = defaultEnoParamsDDI2Xforms.getPipeline();
+ enoParameters.setPipeline(defaultPipeline);
+
+ ByteArrayOutputStream enoOutput;
+ try(
+ InputStream enoInput = in.getInputStream();
+ InputStream metadataIS = metadata != null ? metadata.getInputStream() : null;
+ InputStream specificTreatmentIS = specificTreatment != null ? specificTreatment.getInputStream() : null){
+
+ enoOutput = multiModelService.generateQuestionnaire(enoInput, enoParameters, metadataIS, specificTreatmentIS, null);
+ }
+ log.info("END of Eno Xforms generation processing");
+
+ return ResponseUtils.generateResponseFromOutputStream(enoOutput, parameterService.getFileNameFromCampagneName(enoParameters));
+ }
+
+ @Operation(
+ summary = "Generation of FO questionnaire from DDI.",
+ description = "Generation of a FO questionnaire from the given DDI with default pipeline, " +
+ "using a custom parameters file _(required)_, a metadata file _(optional)_ and a " +
+ "specific treatment file _(optional)_."
+ )
+ @PostMapping(value = "ddi-2-fo",
+ produces = MediaType.APPLICATION_OCTET_STREAM_VALUE, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
+ public ResponseEntity generateFOCustomParams(
+ @RequestPart(value="in") MultipartFile in,
+ @RequestPart(value="params") MultipartFile params,
+ @RequestPart(value="metadata", required = false) MultipartFile metadata,
+ @RequestPart(value="specificTreatment",required=false) MultipartFile specificTreatment) throws Exception {
+
+ log.info("Received request to transform DDI to a FO questionnaire.");
+
+ InputStream paramsIS = params != null ? params.getInputStream() : null;
+ if (paramsIS == null)
+ throw new EnoParametersException("Parameters file's content is null.");
+
+ log.debug("Parsing XML parameters file...");
+ ENOParameters enoParameters = valorizatorParameters.getParameters(paramsIS);
+ log.debug("XML parameters parsed.");
+ Context context = enoParameters.getParameters().getContext();
+ Mode mode = enoParameters.getMode();
+
+ nonNullContextCheck(context);
+ nonNullModeCheck(mode);
+ if (Mode.CAPI.equals(mode) || Mode.CATI.equals(mode) || Mode.CAWI.equals(mode))
+ throw new EnoParametersException("Mode '" + mode + "' is not compatible with FO format.");
+
+ logModeAndContext(context, mode);
+
+ ENOParameters defaultEnoParamsDDI2Fo = parameterService.getDefaultCustomParameters(
+ context, OutFormat.FO, null);
+
+ Pipeline defaultPipeline = defaultEnoParamsDDI2Fo.getPipeline();
+ enoParameters.setPipeline(defaultPipeline);
+
+ ByteArrayOutputStream enoOutput;
+ try(
+ InputStream enoInput = in.getInputStream();
+ InputStream metadataIS = metadata != null ? metadata.getInputStream() : null;
+ InputStream specificTreatmentIS = specificTreatment != null ? specificTreatment.getInputStream() : null) {
+
+ enoOutput = multiModelService.generateQuestionnaire(enoInput, enoParameters, metadataIS, specificTreatmentIS, null);
+ }
+ log.info("END of Eno FO generation processing");
+ return ResponseUtils.generateResponseFromOutputStream(enoOutput, parameterService.getFileNameFromCampagneName(enoParameters));
+
+ }
+
+ private static void nonNullContextCheck(Context context) {
+ if (context == null)
+ throw new EnoParametersException("No context defined in Eno parameters file given.");
+ }
+
+ private static void nonNullModeCheck(Mode mode) {
+ if (mode == null)
+ throw new EnoParametersException("No mode defined in Eno parameters file given.");
+ }
+
+ private static void logModeAndContext(Context context, Mode mode) {
+ log.info("Context={}, Mode={} defined in parameters file", context, mode);
+ }
+
+}
diff --git a/eno-ws/src/main/java/fr/insee/eno/ws/controller/GenerationPoguesController.java b/eno-ws/src/main/java/fr/insee/eno/ws/controller/GenerationPoguesController.java
new file mode 100644
index 000000000..2a18b9af4
--- /dev/null
+++ b/eno-ws/src/main/java/fr/insee/eno/ws/controller/GenerationPoguesController.java
@@ -0,0 +1,66 @@
+package fr.insee.eno.ws.controller;
+
+import fr.insee.eno.parameters.*;
+import fr.insee.eno.service.ParameterizedGenerationService;
+import fr.insee.eno.ws.controller.utils.ResponseUtils;
+import fr.insee.eno.ws.service.ParameterService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+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.RestController;
+import org.springframework.web.multipart.MultipartFile;
+import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
+
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+
+@Tag(name="Generation from Pogues")
+@RestController
+@RequestMapping("/questionnaire")
+@Slf4j
+public class GenerationPoguesController {
+ private final ParameterService parameterService;
+
+ // Eno core service
+ private final ParameterizedGenerationService parametrizedGenerationService = new ParameterizedGenerationService();
+
+ public GenerationPoguesController(ParameterService parameterService) {
+ this.parameterService = parameterService;
+ }
+
+ @Operation(
+ summary = "Generation DDI from Pogues XML questionnaire.",
+ description = "Generation of a DDI from the given Pogues XML questionnaire."
+ )
+ @PostMapping(value="poguesxml-2-ddi", produces=MediaType.APPLICATION_OCTET_STREAM_VALUE, consumes= MediaType.MULTIPART_FORM_DATA_VALUE)
+ public ResponseEntity generateDDIQuestionnaire(
+ @RequestPart(value="in") MultipartFile in) throws Exception {
+
+ InputStream enoInput = in.getInputStream();
+ ENOParameters enoParameters = new ENOParameters();
+ Pipeline pipeline = new Pipeline();
+ pipeline.setInFormat(InFormat.POGUES_XML);
+ pipeline.setOutFormat(OutFormat.DDI);
+ pipeline.getPreProcessing().add(PreProcessing.POGUES_XML_INSERT_FILTER_LOOP_INTO_QUESTION_TREE);
+ pipeline.getPreProcessing().add(PreProcessing.POGUES_XML_GOTO_2_ITE);
+
+ enoParameters.setPipeline(pipeline);
+
+ ByteArrayOutputStream enoOutput = parametrizedGenerationService.generateQuestionnaire(
+ enoInput, enoParameters, null, null, null);
+
+
+ log.info("END of Eno DDI generation processing");
+
+ StreamingResponseBody stream = out -> out.write(enoOutput.toByteArray());
+ enoOutput.close();
+
+ return ResponseUtils.generateResponseFromOutputStream(enoOutput, parameterService.getFileNameFromParameters(enoParameters, false));
+ }
+
+}
diff --git a/eno-ws/src/main/java/fr/insee/eno/ws/controller/GenerationStandardController.java b/eno-ws/src/main/java/fr/insee/eno/ws/controller/GenerationStandardController.java
new file mode 100644
index 000000000..d3a3739ae
--- /dev/null
+++ b/eno-ws/src/main/java/fr/insee/eno/ws/controller/GenerationStandardController.java
@@ -0,0 +1,149 @@
+package fr.insee.eno.ws.controller;
+
+import fr.insee.eno.parameters.*;
+import fr.insee.eno.service.MultiModelService;
+import fr.insee.eno.service.ParameterizedGenerationService;
+import fr.insee.eno.ws.controller.utils.ResponseUtils;
+import fr.insee.eno.ws.service.ParameterService;
+import fr.insee.eno.ws.service.QuestionnaireGenerateService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
+
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+
+@Tag(name="Generation from DDI (standard parameters)")
+@RestController
+@RequestMapping("/questionnaire")
+@Slf4j
+public class GenerationStandardController {
+
+ // Eno-WS services
+ private final ParameterService parameterService;
+ private final QuestionnaireGenerateService generateQuestionnaireService;
+
+ // Eno core services
+ private final ParameterizedGenerationService parametrizedGenerationService;
+ private final MultiModelService multiModelService = new MultiModelService();
+
+
+ public GenerationStandardController(ParameterService parameterService,
+ QuestionnaireGenerateService generateQuestionnaireService) {
+ this.parameterService = parameterService;
+ this.generateQuestionnaireService = generateQuestionnaireService;
+ this.parametrizedGenerationService = new ParameterizedGenerationService();
+ }
+
+ @Operation(
+ summary="Generation of Xforms questionnaire from DDI.",
+ description="Generation of one or multiple Xforms questionnaires from given DDI with standard parameters. " +
+ "If the multi-model option is set to true, the output questionnaire(s) are put in a zip file."
+ )
+ @PostMapping(value="{context}/xforms", produces=MediaType.APPLICATION_OCTET_STREAM_VALUE, consumes= MediaType.MULTIPART_FORM_DATA_VALUE)
+ public ResponseEntity generateXforms(
+ //
+ @RequestPart(value="in") MultipartFile in,
+ @RequestPart(value="metadata",required=false) MultipartFile metadata,
+ @RequestPart(value="specificTreatment",required=false) MultipartFile specificTreatment,
+ //
+ @PathVariable Context context,
+ //
+ @RequestParam(value="multi-model",required=false,defaultValue="false") boolean multiModel) throws Exception {
+
+ log.info(
+ "Received request to transform DDI to a Xforms questionnaire with context '{}' using standard parameters.",
+ context);
+
+ ByteArrayOutputStream enoOutput;
+ if (!multiModel)
+ enoOutput = generateQuestionnaireService.generateQuestionnaireFile(
+ context, OutFormat.XFORMS, null, in, metadata, specificTreatment);
+ else
+ enoOutput = generateQuestionnaireService.generateMultiModelQuestionnaires(
+ context, OutFormat.XFORMS, null, in, metadata, specificTreatment);
+
+ return ResponseUtils.generateResponseFromOutputStream(enoOutput, parameterService.getFileNameFromParameters(OutFormat.XFORMS, multiModel));
+ }
+
+ @Operation(
+ summary="Generation of FO questionnaire from DDI.",
+ description="Generation of a FO questionnaire from the given DDI with standard parameters. " +
+ "Custom values can be passed for format of columns and capture mode."
+ )
+ @PostMapping(value="{context}/fo", produces=MediaType.APPLICATION_OCTET_STREAM_VALUE, consumes= MediaType.MULTIPART_FORM_DATA_VALUE)
+ public ResponseEntity generateFO(
+ //
+ @RequestPart(value="in") MultipartFile in,
+ @RequestPart(value="metadata",required=false) MultipartFile metadata,
+ @RequestPart(value="specificTreatment",required=false) MultipartFile specificTreatment,
+ //
+ @RequestParam(value="Format-column",required=false) Integer nbColumn,
+ @RequestParam(value="Capture",required=false) CaptureEnum capture,
+ //
+ @PathVariable Context context,
+ //
+ @RequestParam(value="multi-model",required=false,defaultValue="false") boolean multiModel) throws Exception {
+
+ log.info(
+ "Received request to transform DDI to a FO questionnaire with context '{}' using standard parameters.",
+ context);
+
+ InputStream enoInput = in.getInputStream();
+
+ ENOParameters enoParameters = parameterService.getDefaultCustomParameters(context,OutFormat.FO,null);
+
+ FOParameters foParameters = enoParameters.getParameters().getFoParameters();
+ if(capture!=null) {
+ Capture capture2 = foParameters.getCapture();
+ capture2.setNumeric(capture);
+ foParameters.setCapture(capture2);
+ }
+
+ if(nbColumn!=null) {
+ Format format = foParameters.getFormat();
+ format.setColumns(nbColumn);}
+
+ InputStream metadataIS = metadata != null ? metadata.getInputStream() : null;
+ InputStream specificTreatmentIS = specificTreatment!=null ? specificTreatment.getInputStream():null;
+
+ ByteArrayOutputStream enoOutput;
+ if (! multiModel)
+ enoOutput = parametrizedGenerationService.generateQuestionnaire(
+ enoInput, enoParameters, metadataIS, specificTreatmentIS, null);
+ else
+ enoOutput = multiModelService.generateQuestionnaire(
+ enoInput, enoParameters, metadataIS, specificTreatmentIS, null);
+
+
+ log.info("END of Eno FO questionnaire processing");
+ return ResponseUtils.generateResponseFromOutputStream(enoOutput,parameterService.getFileNameFromParameters(enoParameters, multiModel));
+ }
+
+ @Operation(
+ summary="Generation of FODT specifications from DDI.",
+ description="Generation of a FODT description of the questionnaire from the given DDI."
+ )
+ @PostMapping(value="{context}/fodt", produces=MediaType.APPLICATION_OCTET_STREAM_VALUE, consumes= MediaType.MULTIPART_FORM_DATA_VALUE)
+ public ResponseEntity generateFODT(
+ //
+ @RequestPart(value="in") MultipartFile in,
+ //
+ @PathVariable Context context) throws Exception {
+
+ log.info(
+ "Received request to transform DDI to a fodt specification file with context '{}' using standard parameters.",
+ context);
+
+ ByteArrayOutputStream enoOutput = generateQuestionnaireService.generateQuestionnaireFile(
+ context, OutFormat.FODT, null, in, null, null);
+
+ return ResponseUtils.generateResponseFromOutputStream(enoOutput, parameterService.getFileNameFromParameters(OutFormat.FODT, false));
+ }
+
+}
\ No newline at end of file
diff --git a/eno-ws/src/main/java/fr/insee/eno/ws/controller/GenerationWithMappingController.java b/eno-ws/src/main/java/fr/insee/eno/ws/controller/GenerationWithMappingController.java
new file mode 100644
index 000000000..64e152112
--- /dev/null
+++ b/eno-ws/src/main/java/fr/insee/eno/ws/controller/GenerationWithMappingController.java
@@ -0,0 +1,87 @@
+package fr.insee.eno.ws.controller;
+
+import fr.insee.eno.parameters.ENOParameters;
+import fr.insee.eno.params.ValorizatorParameters;
+import fr.insee.eno.params.ValorizatorParametersImpl;
+import fr.insee.eno.service.MultiModelService;
+import fr.insee.eno.service.ParameterizedGenerationService;
+import fr.insee.eno.ws.controller.utils.ResponseUtils;
+import fr.insee.eno.ws.service.ParameterService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+
+@Tag(name="Generation with custom mapping")
+@RestController
+@RequestMapping("/questionnaire")
+@Slf4j
+public class GenerationWithMappingController {
+
+ private final ParameterService parameterService;
+ // Eno core services
+ private final ParameterizedGenerationService parametrizedGenerationService = new ParameterizedGenerationService();
+
+ private ValorizatorParameters valorizatorParameters = new ValorizatorParametersImpl();
+ private final MultiModelService multiModelService = new MultiModelService();
+
+ public GenerationWithMappingController(ParameterService parameterService) {
+ this.parameterService = parameterService;
+ }
+
+ // Weird endpoint to do weird things
+ @Operation(
+ summary = "Questionnaire generation according to params, metadata, specific treatment and mapping.",
+ description = "Generation of one or multiple questionnaires from the input file given, " +
+ "using a parameters file _(required)_, a metadata file _(optional)_, a specific treatment file " +
+ "_(optional)_ and a mapping file _(optional)_. " +
+ "If the multi-model option is set to true, the output questionnaire(s) are put in a zip file."
+ )
+ @PostMapping(value = "in-2-out",
+ produces = MediaType.APPLICATION_OCTET_STREAM_VALUE, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
+ public ResponseEntity generate(
+ //
+ @RequestPart(value="in") MultipartFile in,
+ @RequestPart(value="params") MultipartFile params,
+ @RequestPart(value="metadata",required=false) MultipartFile metadata,
+ @RequestPart(value="specificTreatment",required=false) MultipartFile specificTreatment,
+ @RequestPart(value="mapping",required=false) MultipartFile mapping,
+ //
+ @RequestParam(value="multi-model",required=false,defaultValue="false") boolean multiModel) throws Exception {
+
+
+ byte[] paramsBytes = params.getBytes();
+
+ ENOParameters enoParameters = valorizatorParameters.getParameters(new ByteArrayInputStream(paramsBytes));
+ ByteArrayOutputStream enoOutput;
+
+ try(
+ InputStream inputIS = in.getInputStream();
+ InputStream paramIS = new ByteArrayInputStream(paramsBytes);
+ InputStream metadataIS = metadata!=null ? metadata.getInputStream():null;
+ InputStream specificTreatmentIS = specificTreatment!=null ? specificTreatment.getInputStream():null;
+ InputStream mappingIS = mapping!=null ? mapping.getInputStream():null){
+ if(multiModel) {
+ enoOutput = multiModelService.generateQuestionnaire(
+ inputIS, paramIS, metadataIS, specificTreatmentIS, mappingIS);
+ }
+ else {
+ enoOutput = parametrizedGenerationService.generateQuestionnaire(
+ inputIS, paramIS, metadataIS, specificTreatmentIS, mappingIS);
+ }
+
+ log.info("END of Eno 'in to out' processing");
+ }
+
+ return ResponseUtils.generateResponseFromOutputStream(enoOutput, parameterService.getFileNameFromParameters(enoParameters, multiModel));
+ }
+
+}
diff --git a/eno-ws/src/main/java/fr/insee/eno/ws/controller/HomeController.java b/eno-ws/src/main/java/fr/insee/eno/ws/controller/HomeController.java
new file mode 100644
index 000000000..6e47fdf7f
--- /dev/null
+++ b/eno-ws/src/main/java/fr/insee/eno/ws/controller/HomeController.java
@@ -0,0 +1,14 @@
+package fr.insee.eno.ws.controller;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+@Controller
+public class HomeController {
+
+
+ @RequestMapping("/")
+ public String redirectToSwaggerUI() {
+ return "redirect:/swagger-ui.html";
+ }
+}
diff --git a/eno-ws/src/main/java/fr/insee/eno/ws/controller/ParametersController.java b/eno-ws/src/main/java/fr/insee/eno/ws/controller/ParametersController.java
new file mode 100644
index 000000000..0a57d4709
--- /dev/null
+++ b/eno-ws/src/main/java/fr/insee/eno/ws/controller/ParametersController.java
@@ -0,0 +1,71 @@
+package fr.insee.eno.ws.controller;
+
+import fr.insee.eno.parameters.Context;
+import fr.insee.eno.parameters.Mode;
+import fr.insee.eno.parameters.OutFormat;
+import fr.insee.eno.ws.controller.utils.ResponseUtils;
+import fr.insee.eno.ws.service.ParameterService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
+
+import java.io.InputStream;
+
+@Tag(name="Parameters")
+@RestController
+@RequestMapping("/parameters/xml")
+@Slf4j
+public class ParametersController {
+
+ private final ParameterService parameterService;
+
+ public ParametersController(ParameterService parameterService) {
+ this.parameterService = parameterService;
+ }
+
+ @Operation(
+ summary="Get all default out format parameters.",
+ description="It returns the default parameters file without Pipeline which is overloaded. This file don't be used directly : you have to fill Pipeline.")
+ @GetMapping(value="all", produces=MediaType.APPLICATION_OCTET_STREAM_VALUE)
+ public ResponseEntity getAllParameters() throws Exception {
+
+ log.info("Get request for parameters file with all params.");
+
+
+ InputStream paramsInputStream = parameterService.getDefaultParametersIS();
+
+ return ResponseUtils.generateResponseFromInputStream(paramsInputStream, "default-params.xml");
+ }
+
+ @Operation(
+ summary="Get default xml parameters file for the given context according to the outFormat",
+ description="It returns parameters used by default according to the study unit and the outFormat.")
+ @GetMapping(value="{context}/{outFormat}", produces=MediaType.APPLICATION_OCTET_STREAM_VALUE)
+ public ResponseEntity getParameters(
+ @PathVariable Context context,
+ @PathVariable OutFormat outFormat,
+ @RequestParam(value="Mode",required=false) Mode mode) throws Exception {
+
+ log.info("Get request for parameters file with context {}, mode {}, out format {}.",
+ context, mode, outFormat);
+
+ InputStream fileParam = switch (outFormat) {
+ case XFORMS -> parameterService.getDefaultCustomParametersFile(context, OutFormat.XFORMS, mode);
+ case FO -> parameterService.getDefaultCustomParametersFile(context, OutFormat.FO, mode);
+ case LUNATIC_XML -> parameterService.getDefaultCustomParametersFile(context, OutFormat.LUNATIC_XML, mode);
+ case DDI -> parameterService.getDefaultCustomParametersFile(Context.DEFAULT, OutFormat.DDI, mode);
+ case FODT -> parameterService.getDefaultCustomParametersFile(context, OutFormat.FODT, mode);
+ };
+
+ return ResponseUtils.generateResponseFromInputStream(fileParam, parametersFileName(context, mode, outFormat));
+ }
+
+ public static String parametersFileName(Context context, Mode mode, OutFormat outFormat) {
+ return "eno-parameters-" + context + "-" + (mode != null ? mode + "-" : "") + outFormat + ".xml";
+ }
+
+}
diff --git a/eno-ws/src/main/java/fr/insee/eno/ws/controller/exception/EnoExceptionController.java b/eno-ws/src/main/java/fr/insee/eno/ws/controller/exception/EnoExceptionController.java
new file mode 100644
index 000000000..946af379c
--- /dev/null
+++ b/eno-ws/src/main/java/fr/insee/eno/ws/controller/exception/EnoExceptionController.java
@@ -0,0 +1,27 @@
+package fr.insee.eno.ws.controller.exception;
+
+import fr.insee.eno.exception.EnoGenerationException;
+import fr.insee.eno.exception.EnoParametersException;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+
+@ControllerAdvice
+public class EnoExceptionController {
+
+ @ExceptionHandler(value = EnoParametersException.class)
+ public ResponseEntity