Skip to content

Commit 69dc9a0

Browse files
authored
Merge pull request #4 from marmoure/feature/validate
Validate csv files
2 parents 20d64cb + 902b9bc commit 69dc9a0

11 files changed

Lines changed: 503 additions & 11 deletions

File tree

pom.xml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,23 @@
9797
<artifactId>jackson-databind</artifactId>
9898
<version>2.15.3</version>
9999
</dependency>
100+
101+
<!-- CSV validator -->
102+
<dependency>
103+
<groupId>uk.gov.nationalarchives</groupId>
104+
<artifactId>csv-validator-java-api</artifactId>
105+
<version>1.4.1</version>
106+
</dependency>
100107
</dependencies>
101108

102109
<build>
110+
<resources>
111+
<resource>
112+
<directory>src/main/resources</directory>
113+
<filtering>true</filtering>
114+
</resource>
115+
</resources>
116+
103117
<plugins>
104118
<!-- Maven Compiler Plugin -->
105119
<plugin>

src/main/java/com/evolvedbinary/bblValidator/controller/SchemaController.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,15 @@
77
import io.micronaut.http.annotation.Get;
88
import io.micronaut.http.annotation.Produces;
99
import io.micronaut.http.annotation.PathVariable;
10+
import jakarta.inject.Inject;
1011

1112
import java.util.List;
1213

1314
@Controller("/schema")
1415
public class SchemaController {
1516

16-
private final SchemaService schemaService;
17-
18-
public SchemaController(SchemaService schemaService) {
19-
this.schemaService = schemaService;
20-
}
17+
@Inject
18+
SchemaService schemaService;
2119

2220
@Get
2321
@Produces(MediaType.APPLICATION_JSON)
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
package com.evolvedbinary.bblValidator.controller;
2+
3+
import com.evolvedbinary.bblValidator.dto.ValidationError;
4+
import com.evolvedbinary.bblValidator.dto.ValidationForm;
5+
import com.evolvedbinary.bblValidator.dto.ValidationResponse;
6+
import com.evolvedbinary.bblValidator.service.CsvValidationService;
7+
import com.evolvedbinary.bblValidator.service.FileDownloadService;
8+
import io.micronaut.http.MediaType;
9+
import io.micronaut.http.annotation.Body;
10+
import io.micronaut.http.annotation.Consumes;
11+
import io.micronaut.http.annotation.Controller;
12+
import io.micronaut.http.annotation.Post;
13+
import io.micronaut.http.annotation.QueryValue;
14+
import jakarta.inject.Inject;
15+
import org.slf4j.Logger;
16+
import org.slf4j.LoggerFactory;
17+
18+
import java.io.IOException;
19+
import java.nio.file.Path;
20+
import java.util.List;
21+
22+
@Controller("/validate")
23+
public class ValidateController {
24+
25+
private static final Logger LOG = LoggerFactory.getLogger(ValidateController.class);
26+
@Inject
27+
FileDownloadService fileDownloadService;
28+
@Inject
29+
CsvValidationService csvValidationService;
30+
31+
/**
32+
* Handles form URL encoded validation requests.
33+
*
34+
* @param form validation form
35+
* @return validation response
36+
*/
37+
@Post
38+
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
39+
public ValidationResponse validateForm(@Body ValidationForm form) {
40+
try {
41+
Path downloadedFile = fileDownloadService.downloadToTemp(form.url());
42+
LOG.info("File downloaded to: {}", downloadedFile);
43+
return performValidation(downloadedFile, form.schemaId());
44+
} catch (IOException e) {
45+
LOG.error("Failed to download file from URL: {}", form.url(), e);
46+
return createErrorResponse("Download failed: " + e.getMessage(), 0);
47+
}
48+
}
49+
50+
/**
51+
* Handles CSV body + query param validation requests.
52+
*
53+
* @param schemaId schema ID
54+
* @param csvContent CSV content
55+
* @return validation response
56+
*/
57+
@Post
58+
@Consumes(MediaType.TEXT_CSV)
59+
public ValidationResponse validateCsv(@QueryValue("schema-id") String schemaId,
60+
@Body String csvContent) {
61+
try {
62+
Path tempFile = fileDownloadService.saveContentToTemp(csvContent, "uploaded-content.csv");
63+
LOG.info("CSV content saved to: {}", tempFile);
64+
return performValidation(tempFile, schemaId);
65+
} catch (IOException e) {
66+
LOG.error("Failed to save CSV content to temp file", e);
67+
return createErrorResponse("Failed to save content: " + e.getMessage(), 0);
68+
}
69+
}
70+
71+
/**
72+
* Handles query params only validation requests.
73+
*
74+
* @param schemaId schema ID
75+
* @param url URL
76+
* @return validation response
77+
*/
78+
@Post
79+
@Consumes(MediaType.ALL)
80+
public ValidationResponse validateParams(@QueryValue("schema-id") String schemaId,
81+
@QueryValue String url) {
82+
try {
83+
Path downloadedFile = fileDownloadService.downloadToTemp(url);
84+
LOG.info("File downloaded to: {}", downloadedFile);
85+
return performValidation(downloadedFile, schemaId);
86+
} catch (IOException e) {
87+
LOG.error("Failed to download file from URL: {}", url, e);
88+
return createErrorResponse("Download failed: " + e.getMessage(), 0);
89+
}
90+
}
91+
92+
private ValidationResponse performValidation(Path csvFile, String schemaId) {
93+
CsvValidationService.ValidationResult result = csvValidationService.validateCsvFile(csvFile, schemaId);
94+
95+
if (result.hasErrorMessage()) {
96+
return createErrorResponse(result.getErrorMessage(), result.getExecutionTimeMs());
97+
}
98+
99+
return new ValidationResponse(result.isValid(), result.getErrors(), result.getExecutionTimeMs());
100+
}
101+
102+
private ValidationResponse createErrorResponse(String errorMessage, long executionTimeMs) {
103+
return new ValidationResponse(false,
104+
List.of(new ValidationError(errorMessage, 0, 0)),
105+
executionTimeMs);
106+
}
107+
}

src/main/java/com/evolvedbinary/bblValidator/controller/VersionController.java

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,8 @@
1010
@Controller
1111
public class VersionController {
1212

13-
private final String version;
14-
15-
public VersionController(@Value("${api.version}") String version) {
16-
this.version = version;
17-
}
13+
@Value("${api.version}")
14+
String version;
1815

1916
@Get("/version")
2017
@Produces(MediaType.APPLICATION_JSON)
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package com.evolvedbinary.bblValidator.dto;
2+
3+
import io.micronaut.serde.annotation.Serdeable;
4+
5+
@Serdeable
6+
public class ValidationError {
7+
8+
private String message;
9+
private int lineNumber;
10+
private int columnIndex;
11+
12+
public ValidationError() {
13+
}
14+
15+
public ValidationError(String message, int lineNumber, int columnIndex) {
16+
this.message = message;
17+
this.lineNumber = lineNumber;
18+
this.columnIndex = columnIndex;
19+
}
20+
21+
public String getMessage() {
22+
return message;
23+
}
24+
25+
public void setMessage(String message) {
26+
this.message = message;
27+
}
28+
29+
public int getLineNumber() {
30+
return lineNumber;
31+
}
32+
33+
public void setLineNumber(int lineNumber) {
34+
this.lineNumber = lineNumber;
35+
}
36+
37+
public int getColumnIndex() {
38+
return columnIndex;
39+
}
40+
41+
public void setColumnIndex(int columnIndex) {
42+
this.columnIndex = columnIndex;
43+
}
44+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package com.evolvedbinary.bblValidator.dto;
2+
3+
import io.micronaut.serde.annotation.Serdeable;
4+
5+
@Serdeable
6+
public record ValidationForm(
7+
String schemaId,
8+
String url) {
9+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package com.evolvedbinary.bblValidator.dto;
2+
3+
import io.micronaut.serde.annotation.Serdeable;
4+
5+
import java.util.ArrayList;
6+
import java.util.List;
7+
8+
@Serdeable
9+
public class ValidationResponse {
10+
11+
private boolean valid;
12+
private List<ValidationError> errors;
13+
private long executionTimeMs;
14+
15+
public ValidationResponse() {
16+
this.errors = new ArrayList<>();
17+
}
18+
19+
public ValidationResponse(boolean valid,
20+
List<ValidationError> errors, long executionTimeMs) {
21+
this.executionTimeMs = executionTimeMs;
22+
this.valid = valid;
23+
this.errors = errors != null ? errors : new ArrayList<>();
24+
}
25+
26+
27+
public boolean isValid() {
28+
return valid;
29+
}
30+
31+
public void setValid(boolean valid) {
32+
this.valid = valid;
33+
}
34+
35+
public List<ValidationError> getErrors() {
36+
return errors;
37+
}
38+
39+
public void setErrors(List<ValidationError> errors) {
40+
this.errors = errors;
41+
}
42+
43+
public long getExecutionTimeMs() {
44+
return executionTimeMs;
45+
}
46+
47+
public void setExecutionTimeMs(long executionTimeMs) {
48+
this.executionTimeMs = executionTimeMs;
49+
}
50+
}

0 commit comments

Comments
 (0)