diff --git a/README.md b/README.md index efc1a15..bbc9af7 100644 --- a/README.md +++ b/README.md @@ -30,13 +30,61 @@ described in the URL above that the URL can be overwritten locally with an HTTPS Check the [Development](DEVELOPMENT.md) page for more detail information how to work with this repository, because of the mixture with RiseClipse. +## Custom OCL Files + +There is a way to add custom OCL Files to the validator, for instance to force company specific rules. In the Docker +Image there is a volume `/data/ocl` which can be used to add these files, see our compas-deployment project for an +example how to. + +In this directory, you can use subdirectories like `SemanticConstraints` as RiseClipse is doing. And there is a special +filter that when you create a directory `FileSpecifics`. In this directory you can create for instance a directory `CID` +to put constraints specific for an SCL File Type. Known types are `SSD`, `IID`, `ICD`, `SCD`, `CID`, `SED`, `ISD`, +`STD`. + +For instance, + +``` +data +└── ocl + ├── FileSpecifics + │ └── CID + │ └── Busbar.ocl + └── SemanticConstraints + └── Busbar.ocl +``` + +If you are using the validator are library (using JAR Files) there is a property to configure the directory, see +[Common Environment variables](#common-environment-variables) + +## NSDoc Files + +Because NSDoc File can't be distributed in an OpenSource Project these need to be added during deployment. In the Docker +Image there is a volume `/data/nsdoc` which can be used to add these files, see our compas-deployment project for an +example how to. + +Only direct files found in this directory will be processed. Invalid NSDoc Files will be ignored. A directory can look +like this for instance, + +``` +data +└── nsdoc + ├── IEC_61850-7-2_2007B3-en.nsdoc + ├── IEC_61850-7-3_2007B3-en.nsdoc + └── IEC_61850-7-4_2007B3-en.nsdoc + +``` + +If you are using the validator are library (using JAR Files) there is a property to configure the directory, see +[Common Environment variables](#common-environment-variables) + ## Common Environment variables Below environment variable(s) can be used to configure the validator. -| Environment variable | Java Property | Description | Example | -|---------------------------------------|---------------------------------------|---------------------------------------------------|-----------| -| COMPAS_VALIDATOR_OCL_CUSTOM_DIRECTORY | compas.validator.ocl.custom.directory | Reference to a directory to load custom OCL Files | /data/ocl | +| Environment variable | Java Property | Description | Example | +|---------------------------------------|---------------------------------------|-------------------------------------------------------------|-------------| +| COMPAS_VALIDATOR_OCL_CUSTOM_DIRECTORY | compas.validator.ocl.custom.directory | Reference to a directory to load custom OCL Files | /data/ocl | +| COMPAS_VALIDATOR_NSDOC_DIRECTORY | compas.validator.nsdoc.directory | Reference to a directory where the NSDoc Files can be found | /data/nsdoc | ## Security diff --git a/app/pom.xml b/app/pom.xml index d9ac269..560e0d6 100644 --- a/app/pom.xml +++ b/app/pom.xml @@ -22,11 +22,6 @@ SPDX-License-Identifier: Apache-2.0 compas-scl-validator - - - - - org.lfenergy.compas.scl.validator diff --git a/app/src/main/docker/Dockerfile.jvm b/app/src/main/docker/Dockerfile.jvm index fcbad5c..109e45d 100644 --- a/app/src/main/docker/Dockerfile.jvm +++ b/app/src/main/docker/Dockerfile.jvm @@ -49,10 +49,12 @@ COPY --chown=1001 target/quarkus-app/app/ /deployments/app/ COPY --chown=1001 target/quarkus-app/quarkus/ /deployments/quarkus/ RUN mkdir -p /data/ocl \ + && mkdir -p /data/nsdoc \ && mkdir -p /data/temp \ && chown -R 1001 /data \ && chmod -R "g+rwX" /data VOLUME /data/ocl +VOLUME /data/nsdoc EXPOSE 8080 USER 1001 diff --git a/app/src/main/docker/Dockerfile.native b/app/src/main/docker/Dockerfile.native index 286bd97..96b0f1c 100644 --- a/app/src/main/docker/Dockerfile.native +++ b/app/src/main/docker/Dockerfile.native @@ -22,10 +22,12 @@ RUN chown 1001 /work \ COPY --chown=1001:root target/*-runner /work/application RUN mkdir -p /data/ocl \ + && mkdir -p /data/nsdoc \ && mkdir -p /data/temp \ && chown -R 1001 /data \ && chmod -R "g+rwX" /data VOLUME /data/ocl +VOLUME /data/nsdoc EXPOSE 8080 USER 1001 diff --git a/app/src/main/java/org/lfenergy/compas/scl/validator/rest/CompasSclValidatorConfiguration.java b/app/src/main/java/org/lfenergy/compas/scl/validator/rest/CompasSclValidatorConfiguration.java index eefef07..eb60a4a 100644 --- a/app/src/main/java/org/lfenergy/compas/scl/validator/rest/CompasSclValidatorConfiguration.java +++ b/app/src/main/java/org/lfenergy/compas/scl/validator/rest/CompasSclValidatorConfiguration.java @@ -3,9 +3,11 @@ // SPDX-License-Identifier: Apache-2.0 package org.lfenergy.compas.scl.validator.rest; +import io.quarkus.runtime.Startup; import org.lfenergy.compas.core.commons.ElementConverter; import org.lfenergy.compas.scl.validator.collector.CompasOclFileCollector; import org.lfenergy.compas.scl.validator.collector.OclFileCollector; +import org.lfenergy.compas.scl.validator.common.NsdocFinder; import org.lfenergy.compas.scl.validator.impl.SclRiseClipseValidator; import javax.enterprise.context.ApplicationScoped; @@ -33,4 +35,11 @@ public SclRiseClipseValidator createSclRiseClipseValidator(OclFileCollector oclF ValidatorProperties properties) { return new SclRiseClipseValidator(oclFileCollector, properties.tempDirectory()); } + + @Produces + @Startup + @ApplicationScoped + public NsdocFinder createNsdocFinder(ValidatorProperties properties) { + return new NsdocFinder(properties.nsdocDirectory()); + } } diff --git a/app/src/main/java/org/lfenergy/compas/scl/validator/rest/SclResourceConstants.java b/app/src/main/java/org/lfenergy/compas/scl/validator/rest/SclResourceConstants.java index 325fcbf..90037d5 100644 --- a/app/src/main/java/org/lfenergy/compas/scl/validator/rest/SclResourceConstants.java +++ b/app/src/main/java/org/lfenergy/compas/scl/validator/rest/SclResourceConstants.java @@ -9,4 +9,5 @@ public final class SclResourceConstants { } public static final String TYPE_PATH_PARAM = "type"; + public static final String ID_PARAM = "id"; } diff --git a/app/src/main/java/org/lfenergy/compas/scl/validator/rest/ValidatorProperties.java b/app/src/main/java/org/lfenergy/compas/scl/validator/rest/ValidatorProperties.java index ae11818..6c8db6d 100644 --- a/app/src/main/java/org/lfenergy/compas/scl/validator/rest/ValidatorProperties.java +++ b/app/src/main/java/org/lfenergy/compas/scl/validator/rest/ValidatorProperties.java @@ -13,6 +13,9 @@ public interface ValidatorProperties { @WithName("ocl.custom.directory") String oclCustomDirectory(); + @WithName("nsdoc.directory") + String nsdocDirectory(); + @WithName("temp.directory") Path tempDirectory(); } diff --git a/app/src/main/java/org/lfenergy/compas/scl/validator/rest/exception/NsdocNotFoundExceptionHandler.java b/app/src/main/java/org/lfenergy/compas/scl/validator/rest/exception/NsdocNotFoundExceptionHandler.java new file mode 100644 index 0000000..20f2d72 --- /dev/null +++ b/app/src/main/java/org/lfenergy/compas/scl/validator/rest/exception/NsdocNotFoundExceptionHandler.java @@ -0,0 +1,21 @@ +// SPDX-FileCopyrightText: 2021 Alliander N.V. +// +// SPDX-License-Identifier: Apache-2.0 +package org.lfenergy.compas.scl.validator.rest.exception; + +import org.lfenergy.compas.core.jaxrs.model.ErrorResponse; +import org.lfenergy.compas.scl.validator.exception.NsdocFileNotFoundException; + +import javax.ws.rs.core.Response; +import javax.ws.rs.ext.ExceptionMapper; +import javax.ws.rs.ext.Provider; + +@Provider +public class NsdocNotFoundExceptionHandler implements ExceptionMapper { + @Override + public Response toResponse(NsdocFileNotFoundException exception) { + var response = new ErrorResponse(); + response.addErrorMessage(exception.getErrorCode(), exception.getMessage()); + return Response.status(Response.Status.NOT_FOUND).entity(response).build(); + } +} diff --git a/app/src/main/java/org/lfenergy/compas/scl/validator/rest/v1/NsdocResource.java b/app/src/main/java/org/lfenergy/compas/scl/validator/rest/v1/NsdocResource.java new file mode 100644 index 0000000..3705a3b --- /dev/null +++ b/app/src/main/java/org/lfenergy/compas/scl/validator/rest/v1/NsdocResource.java @@ -0,0 +1,43 @@ +// SPDX-FileCopyrightText: 2022 Alliander N.V. +// +// SPDX-License-Identifier: Apache-2.0 +package org.lfenergy.compas.scl.validator.rest.v1; + +import io.quarkus.security.Authenticated; +import org.lfenergy.compas.scl.validator.rest.v1.model.NsdocListResponse; +import org.lfenergy.compas.scl.validator.service.NsdocService; + +import javax.enterprise.context.RequestScoped; +import javax.ws.rs.*; +import javax.ws.rs.core.MediaType; +import java.util.UUID; + +import static org.lfenergy.compas.scl.validator.rest.SclResourceConstants.ID_PARAM; + +@Authenticated +@RequestScoped +@Path("/nsdoc/v1") +public class NsdocResource { + private final NsdocService nsdocService; + + public NsdocResource(NsdocService nsdocService) { + this.nsdocService = nsdocService; + } + + @GET + @Consumes(MediaType.APPLICATION_XML) + @Produces(MediaType.APPLICATION_XML) + public NsdocListResponse list() { + NsdocListResponse response = new NsdocListResponse(); + response.setNsdocFiles(nsdocService.list()); + return response; + } + + @GET + @Path("{" + ID_PARAM + "}") + @Consumes(MediaType.APPLICATION_XML) + @Produces(MediaType.APPLICATION_XML) + public String get(@PathParam(ID_PARAM) UUID id) { + return nsdocService.get(id); + } +} \ No newline at end of file diff --git a/app/src/main/java/org/lfenergy/compas/scl/validator/rest/v1/model/NsdocListResponse.java b/app/src/main/java/org/lfenergy/compas/scl/validator/rest/v1/model/NsdocListResponse.java new file mode 100644 index 0000000..a2e3bdb --- /dev/null +++ b/app/src/main/java/org/lfenergy/compas/scl/validator/rest/v1/model/NsdocListResponse.java @@ -0,0 +1,32 @@ +// SPDX-FileCopyrightText: 2022 Alliander N.V. +// +// SPDX-License-Identifier: Apache-2.0 +package org.lfenergy.compas.scl.validator.rest.v1.model; + +import org.eclipse.microprofile.openapi.annotations.media.Schema; +import org.lfenergy.compas.scl.validator.model.NsdocFile; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import java.util.Collection; + +import static org.lfenergy.compas.scl.validator.SclValidatorConstants.SCL_VALIDATOR_SERVICE_V1_NS_URI; + +@Schema(description = "The response with the list of known NSDoc Files.") +@XmlRootElement(name = "NsdocListResponse", namespace = SCL_VALIDATOR_SERVICE_V1_NS_URI) +@XmlAccessorType(XmlAccessType.FIELD) +public class NsdocListResponse { + @Schema(description = "The list of known NSDoc Files") + @XmlElement(name = "NsdocFile", namespace = SCL_VALIDATOR_SERVICE_V1_NS_URI) + private Collection nsdocFiles; + + public Collection getNsdocFiles() { + return nsdocFiles; + } + + public void setNsdocFiles(Collection nsdocFiles) { + this.nsdocFiles = nsdocFiles; + } +} diff --git a/app/src/main/java/org/lfenergy/compas/scl/validator/rest/v1/model/SclValidateRequest.java b/app/src/main/java/org/lfenergy/compas/scl/validator/rest/v1/model/SclValidateRequest.java index d6f6069..41c88c8 100644 --- a/app/src/main/java/org/lfenergy/compas/scl/validator/rest/v1/model/SclValidateRequest.java +++ b/app/src/main/java/org/lfenergy/compas/scl/validator/rest/v1/model/SclValidateRequest.java @@ -14,11 +14,11 @@ import static org.lfenergy.compas.scl.validator.SclValidatorConstants.SCL_VALIDATOR_SERVICE_V1_NS_URI; -@Schema(description = "") +@Schema(description = "The Validation Request retrieved") @XmlRootElement(name = "SclValidateRequest", namespace = SCL_VALIDATOR_SERVICE_V1_NS_URI) @XmlAccessorType(XmlAccessType.FIELD) public class SclValidateRequest { - @Schema(description = "") + @Schema(description = "The SCL Data to be validated") @NotBlank @XmlElement(name = "SclData", namespace = SCL_VALIDATOR_SERVICE_V1_NS_URI) protected String sclData; diff --git a/app/src/main/java/org/lfenergy/compas/scl/validator/rest/v1/model/SclValidateResponse.java b/app/src/main/java/org/lfenergy/compas/scl/validator/rest/v1/model/SclValidateResponse.java index 9666534..02462aa 100644 --- a/app/src/main/java/org/lfenergy/compas/scl/validator/rest/v1/model/SclValidateResponse.java +++ b/app/src/main/java/org/lfenergy/compas/scl/validator/rest/v1/model/SclValidateResponse.java @@ -14,11 +14,11 @@ import static org.lfenergy.compas.scl.validator.SclValidatorConstants.SCL_VALIDATOR_SERVICE_V1_NS_URI; -@Schema(description = "") +@Schema(description = "The Validation Response returned") @XmlRootElement(name = "SclValidateResponse", namespace = SCL_VALIDATOR_SERVICE_V1_NS_URI) @XmlAccessorType(XmlAccessType.FIELD) public class SclValidateResponse { - @Schema(description = "") + @Schema(description = "The list with Validation Errors, if any.") @XmlElement(name = "ValidationErrors", namespace = SCL_VALIDATOR_SERVICE_V1_NS_URI) protected List validationErrorList; diff --git a/app/src/main/resources/application.properties b/app/src/main/resources/application.properties index 8b79b95..5e088e7 100644 --- a/app/src/main/resources/application.properties +++ b/app/src/main/resources/application.properties @@ -3,6 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 compas.validator.ocl.custom.directory = /data/ocl +compas.validator.nsdoc.directory = /data/nsdoc compas.validator.temp.directory = /data/temp quarkus.http.cors = false @@ -14,6 +15,7 @@ quarkus.log.category."org.lfenergy.compas.scl.validator".level = INFO # Dev Profile overrides. %dev.compas.validator.ocl.custom.directory = ./src/test/data/ocl +%dev.compas.validator.nsdoc.directory = ./src/test/data/nsdoc %dev.compas.validator.temp.directory = ./target/data/temp %dev.quarkus.http.port = 9093 @@ -24,6 +26,7 @@ quarkus.log.category."org.lfenergy.compas.scl.validator".level = INFO # Test Profile overrides. %test.compas.validator.ocl.custom.directory = ./src/test/data/ocl +%test.compas.validator.nsdoc.directory = ./src/test/data/nsdoc %test.compas.validator.temp.directory = ./target/data/temp %test.quarkus.log.category."org.lfenergy.compas.scl.validator.collector.CompasOclFileCollector".level = WARN @@ -43,5 +46,8 @@ quarkus.http.auth.permission.allow-quarkus-services.policy=permit %dev.quarkus.http.auth.permission.develop-quarkus-services.paths=/compas-scl-validator/q/swagger-ui/*,/compas-scl-validator/index.html %dev.quarkus.http.auth.permission.develop-quarkus-services.policy=permit -quarkus.http.auth.permission.common.paths=/compas-scl-validator/validate/v1/* -quarkus.http.auth.permission.common.policy=authenticated +quarkus.http.auth.permission.validate.paths=/compas-scl-validator/validate/v1/* +quarkus.http.auth.permission.validate.policy=authenticated + +quarkus.http.auth.permission.nsdoc.paths=/compas-scl-validator/nsdoc/v1/* +quarkus.http.auth.permission.nsdoc.policy=authenticated diff --git a/app/src/test/data/nsdoc/invalid.nsdoc b/app/src/test/data/nsdoc/invalid.nsdoc new file mode 100644 index 0000000..99f4ab6 --- /dev/null +++ b/app/src/test/data/nsdoc/invalid.nsdoc @@ -0,0 +1,7 @@ + + + + + + + diff --git a/app/src/test/data/nsdoc/testFile73.nsdoc b/app/src/test/data/nsdoc/testFile73.nsdoc new file mode 100644 index 0000000..12207b3 --- /dev/null +++ b/app/src/test/data/nsdoc/testFile73.nsdoc @@ -0,0 +1,13 @@ + + + + + + + + + diff --git a/app/src/test/data/nsdoc/testFile74.nsdoc b/app/src/test/data/nsdoc/testFile74.nsdoc new file mode 100644 index 0000000..84e699a --- /dev/null +++ b/app/src/test/data/nsdoc/testFile74.nsdoc @@ -0,0 +1,14 @@ + + + + + + + + + + diff --git a/app/src/test/java/org/lfenergy/compas/scl/validator/rest/exception/NsdocNotFoundExceptionHandlerTest.java b/app/src/test/java/org/lfenergy/compas/scl/validator/rest/exception/NsdocNotFoundExceptionHandlerTest.java new file mode 100644 index 0000000..81d548a --- /dev/null +++ b/app/src/test/java/org/lfenergy/compas/scl/validator/rest/exception/NsdocNotFoundExceptionHandlerTest.java @@ -0,0 +1,27 @@ +// SPDX-FileCopyrightText: 2021 Alliander N.V. +// +// SPDX-License-Identifier: Apache-2.0 +package org.lfenergy.compas.scl.validator.rest.exception; + +import org.junit.jupiter.api.Test; +import org.lfenergy.compas.core.jaxrs.model.ErrorResponse; +import org.lfenergy.compas.scl.validator.exception.NsdocFileNotFoundException; + +import static javax.ws.rs.core.Response.Status.NOT_FOUND; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; + +class NsdocNotFoundExceptionHandlerTest { + @Test + void toResponse_WhenCalledWithException_ThenNotFoundReturnedWithBody() { + var exception = new NsdocFileNotFoundException("Some message that will only be logged"); + var handler = new NsdocNotFoundExceptionHandler(); + + var result = handler.toResponse(exception); + assertEquals(NOT_FOUND.getStatusCode(), result.getStatus()); + var errorMessage = ((ErrorResponse) result.getEntity()).getErrorMessages().get(0); + assertEquals(exception.getErrorCode(), errorMessage.getCode()); + assertEquals(exception.getMessage(), errorMessage.getMessage()); + assertNull(errorMessage.getProperty()); + } +} diff --git a/app/src/test/java/org/lfenergy/compas/scl/validator/rest/v1/NsdocResourceTest.java b/app/src/test/java/org/lfenergy/compas/scl/validator/rest/v1/NsdocResourceTest.java new file mode 100644 index 0000000..c177858 --- /dev/null +++ b/app/src/test/java/org/lfenergy/compas/scl/validator/rest/v1/NsdocResourceTest.java @@ -0,0 +1,110 @@ +// SPDX-FileCopyrightText: 2022 Alliander N.V. +// +// SPDX-License-Identifier: Apache-2.0 +package org.lfenergy.compas.scl.validator.rest.v1; + +import io.quarkus.test.common.http.TestHTTPEndpoint; +import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.junit.mockito.InjectMock; +import io.quarkus.test.security.TestSecurity; +import io.restassured.http.ContentType; +import org.junit.jupiter.api.Test; +import org.lfenergy.compas.core.jaxrs.JaxrsConstants; +import org.lfenergy.compas.scl.validator.exception.NsdocFileNotFoundException; +import org.lfenergy.compas.scl.validator.exception.SclValidatorErrorCode; +import org.lfenergy.compas.scl.validator.model.NsdocFile; +import org.lfenergy.compas.scl.validator.service.NsdocService; + +import java.util.List; +import java.util.UUID; + +import static io.restassured.RestAssured.given; +import static io.restassured.path.xml.config.XmlPathConfig.xmlPathConfig; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.lfenergy.compas.scl.validator.SclValidatorConstants.SCL_VALIDATOR_SERVICE_V1_NS_URI; +import static org.lfenergy.compas.scl.validator.rest.SclResourceConstants.ID_PARAM; +import static org.mockito.Mockito.*; + +@QuarkusTest +@TestHTTPEndpoint(NsdocResource.class) +@TestSecurity(user = "test-user") +class NsdocResourceTest { + @InjectMock + private NsdocService nsdocService; + + @Test + void list_WhenCalled_ThenListReturned() { + when(nsdocService.list()) + .thenReturn(List.of(new NsdocFile())); + + var response = given() + .contentType(ContentType.XML) + .when() + .get() + .then() + .statusCode(200) + .extract() + .response(); + + var xmlPath = response.xmlPath() + .using(xmlPathConfig().declaredNamespace("svs", SCL_VALIDATOR_SERVICE_V1_NS_URI)); + var files = xmlPath.getList("svs:NsdocListResponse.svs:NsdocFile"); + assertNotNull(files); + assertEquals(1, files.size()); + verify(nsdocService, times(1)).list(); + } + + @Test + void get_WhenCalled_ThenContentReturned() { + UUID id = UUID.randomUUID(); + String result = ""; + + when(nsdocService.get(id)) + .thenReturn(result); + + var response = given() + .pathParam(ID_PARAM, id) + .contentType(ContentType.XML) + .when() + .get("/{" + ID_PARAM + "}") + .then() + .statusCode(200) + .extract() + .response(); + + var nsdocFile = response.asString(); + assertNotNull(nsdocFile); + assertEquals(result, nsdocFile); + verify(nsdocService, times(1)).get(id); + } + + @Test + void get_WhenCalledWithUnknownFile_Then404Returned() { + UUID id = UUID.randomUUID(); + + when(nsdocService.get(id)) + .thenThrow(new NsdocFileNotFoundException("Some Message")); + + var response = given() + .pathParam(ID_PARAM, id) + .contentType(ContentType.XML) + .when() + .get("/{" + ID_PARAM + "}") + .then() + .statusCode(404) + .extract() + .response(); + + var xmlPath = response.xmlPath() + .using(xmlPathConfig().declaredNamespace("commons", JaxrsConstants.COMPAS_COMMONS_V1_NS_URI)); + var messages = xmlPath.getList("commons:ErrorResponse.commons:ErrorMessage"); + assertNotNull(messages); + assertEquals(1, messages.size()); + + var code = xmlPath.getString("commons:ErrorResponse.commons:ErrorMessage.commons:Code"); + assertEquals(SclValidatorErrorCode.NSDOC_FILE_NOT_FOUND, code); + + verify(nsdocService, times(1)).get(id); + } +} diff --git a/app/src/test/java/org/lfenergy/compas/scl/validator/rest/v1/SclValidatorResourceTest.java b/app/src/test/java/org/lfenergy/compas/scl/validator/rest/v1/SclValidatorResourceTest.java index 634c409..cdea625 100644 --- a/app/src/test/java/org/lfenergy/compas/scl/validator/rest/v1/SclValidatorResourceTest.java +++ b/app/src/test/java/org/lfenergy/compas/scl/validator/rest/v1/SclValidatorResourceTest.java @@ -56,8 +56,8 @@ void updateSCL_WhenCalled_ThenExpectedResponseIsRetrieved() throws IOException { .response(); var xmlPath = response.xmlPath() - .using(xmlPathConfig().declaredNamespace("saa", SCL_VALIDATOR_SERVICE_V1_NS_URI)); - var errors = xmlPath.getList("saa:SclValidateResponse.ValidationErrors"); + .using(xmlPathConfig().declaredNamespace("svs", SCL_VALIDATOR_SERVICE_V1_NS_URI)); + var errors = xmlPath.getList("svs:SclValidateResponse.svs:ValidationErrors"); assertNotNull(errors); assertEquals(1, errors.size()); verify(sclValidatorService, times(1)).validate(sclFileTye, request.getSclData()); @@ -68,4 +68,4 @@ private String readFile() throws IOException { var path = Paths.get(resource.getPath()); return String.join("\n", Files.readAllLines(path)); } -} \ No newline at end of file +} diff --git a/app/src/test/java/org/lfenergy/compas/scl/validator/rest/v1/model/NsdocListResponseTest.java b/app/src/test/java/org/lfenergy/compas/scl/validator/rest/v1/model/NsdocListResponseTest.java new file mode 100644 index 0000000..cb4bda0 --- /dev/null +++ b/app/src/test/java/org/lfenergy/compas/scl/validator/rest/v1/model/NsdocListResponseTest.java @@ -0,0 +1,13 @@ +// SPDX-FileCopyrightText: 2022 Alliander N.V. +// +// SPDX-License-Identifier: Apache-2.0 +package org.lfenergy.compas.scl.validator.rest.v1.model; + +import org.lfenergy.compas.scl.validator.model.AbstractPojoTester; + +class NsdocListResponseTest extends AbstractPojoTester { + @Override + protected Class getClassToBeTested() { + return NsdocListResponse.class; + } +} diff --git a/app/src/test/java/org/lfenergy/compas/scl/validator/rest/v1/model/SclValidateRequestTest.java b/app/src/test/java/org/lfenergy/compas/scl/validator/rest/v1/model/SclValidateRequestTest.java index 9767456..a3fffec 100644 --- a/app/src/test/java/org/lfenergy/compas/scl/validator/rest/v1/model/SclValidateRequestTest.java +++ b/app/src/test/java/org/lfenergy/compas/scl/validator/rest/v1/model/SclValidateRequestTest.java @@ -10,4 +10,4 @@ class SclValidateRequestTest extends AbstractPojoTester { protected Class getClassToBeTested() { return SclValidateRequest.class; } -} \ No newline at end of file +} diff --git a/app/src/test/java/org/lfenergy/compas/scl/validator/rest/v1/model/SclValidateResponseTest.java b/app/src/test/java/org/lfenergy/compas/scl/validator/rest/v1/model/SclValidateResponseTest.java index 29e0781..eb992e1 100644 --- a/app/src/test/java/org/lfenergy/compas/scl/validator/rest/v1/model/SclValidateResponseTest.java +++ b/app/src/test/java/org/lfenergy/compas/scl/validator/rest/v1/model/SclValidateResponseTest.java @@ -10,4 +10,4 @@ class SclValidateResponseTest extends AbstractPojoTester { protected Class getClassToBeTested() { return SclValidateResponse.class; } -} \ No newline at end of file +} diff --git a/app/src/test/resources/scl/scl-1.scd b/app/src/test/resources/scl/scl-1.scd index de559b7..24acf04 100644 --- a/app/src/test/resources/scl/scl-1.scd +++ b/app/src/test/resources/scl/scl-1.scd @@ -1,5 +1,5 @@ - + diff --git a/riseclipse/validator-riseclipse/pom.xml b/riseclipse/validator-riseclipse/pom.xml index 6f92e11..6d82bbb 100644 --- a/riseclipse/validator-riseclipse/pom.xml +++ b/riseclipse/validator-riseclipse/pom.xml @@ -65,6 +65,13 @@ SPDX-License-Identifier: Apache-2.0 + + org.lfenergy.compas.scl.validator + validator + test-jar + test + + org.mockito mockito-junit-jupiter diff --git a/riseclipse/validator-riseclipse/src/test/resources/scl/example.scd b/riseclipse/validator-riseclipse/src/test/resources/scl/example.scd index 4dc2b38..943b374 100644 --- a/riseclipse/validator-riseclipse/src/test/resources/scl/example.scd +++ b/riseclipse/validator-riseclipse/src/test/resources/scl/example.scd @@ -1,9 +1,9 @@ - + - +
diff --git a/riseclipse/validator-riseclipse/src/test/resources/scl/invalid.scd b/riseclipse/validator-riseclipse/src/test/resources/scl/invalid.scd index 61fba55..5e2ab08 100644 --- a/riseclipse/validator-riseclipse/src/test/resources/scl/invalid.scd +++ b/riseclipse/validator-riseclipse/src/test/resources/scl/invalid.scd @@ -1,5 +1,5 @@ - + diff --git a/service/pom.xml b/service/pom.xml index f957aac..ae3f6e9 100644 --- a/service/pom.xml +++ b/service/pom.xml @@ -37,6 +37,11 @@ SPDX-License-Identifier: Apache-2.0 microprofile-openapi-api + + commons-codec + commons-codec + + org.slf4j slf4j-api diff --git a/service/src/main/java/org/lfenergy/compas/scl/validator/common/NsdocFinder.java b/service/src/main/java/org/lfenergy/compas/scl/validator/common/NsdocFinder.java new file mode 100644 index 0000000..a447790 --- /dev/null +++ b/service/src/main/java/org/lfenergy/compas/scl/validator/common/NsdocFinder.java @@ -0,0 +1,92 @@ +// SPDX-FileCopyrightText: 2022 Alliander N.V. +// +// SPDX-License-Identifier: Apache-2.0 +package org.lfenergy.compas.scl.validator.common; + +import org.apache.commons.codec.digest.DigestUtils; +import org.lfenergy.compas.scl.validator.exception.NsdocFileNotFoundException; +import org.lfenergy.compas.scl.validator.exception.SclValidatorException; +import org.lfenergy.compas.scl.validator.model.NsdocFile; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.nio.file.Files; +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; + +import static org.lfenergy.compas.scl.validator.exception.SclValidatorErrorCode.CALCULATING_CHECKSUM_FAILED; +import static org.lfenergy.compas.scl.validator.exception.SclValidatorErrorCode.LOADING_NSDOC_FILE_FAILED; + +public class NsdocFinder { + private static final Logger LOGGER = LoggerFactory.getLogger(NsdocFinder.class); + + private final String nsdocDirectory; + private final Map nsdocFiles; + + public NsdocFinder(String nsdocDirectory) { + this.nsdocDirectory = nsdocDirectory; + this.nsdocFiles = getFilesFromDirectory(nsdocDirectory); + } + + private Map getFilesFromDirectory(String directoryName) { + File directory = new File(directoryName); + if (directory.exists() && directory.isDirectory()) { + var files = directory.listFiles(); + if (files != null) { + return Arrays.stream(files) + .filter(File::isFile) + .map(this::convertToNsdocFile) + .filter(Objects::nonNull) + .collect(Collectors.toMap(NsdocFile::getId, Function.identity())); + } + } + return Collections.emptyMap(); + } + + private NsdocFile convertToNsdocFile(File file) { + try { + var nsdocInfo = new NsdocInfo(file); + var nsdocFile = new NsdocFile(); + nsdocFile.setId(UUID.randomUUID()); + nsdocFile.setNsdocId(nsdocInfo.getId()); + nsdocFile.setFilename(file.getName()); + nsdocFile.setChecksum(calculateChecksum(file)); + return nsdocFile; + } catch (Exception exp) { + LOGGER.warn("Error loading NSDoc File '" + file.getName() + "'. Skipping file.", exp); + return null; + } + } + + private String calculateChecksum(File file) { + try (var fis = new FileInputStream(file)) { + return DigestUtils.sha256Hex(fis); + } catch (IOException exp) { + throw new SclValidatorException(CALCULATING_CHECKSUM_FAILED, "Error calculating checksum for NSDoc File " + + file.getName() + "'.", exp); + } + } + + public Collection getNsdocFiles() { + return nsdocFiles.values() + .stream() + .sorted(Comparator.comparing(NsdocFile::getNsdocId)) + .collect(Collectors.toList()); + } + + public String getNsdocFile(UUID id) { + try { + if (nsdocFiles.containsKey(id)) { + var nsdocFile = nsdocFiles.get(id); + return Files.readString(new File(this.nsdocDirectory, nsdocFile.getFilename()).toPath()); + } + throw new NsdocFileNotFoundException("NSDoc File with ID '" + id + "' not found."); + } catch (IOException exp) { + throw new SclValidatorException(LOADING_NSDOC_FILE_FAILED, "Error loading NSDoc File with ID '" + id + "'", exp); + } + } +} diff --git a/service/src/main/java/org/lfenergy/compas/scl/validator/common/NsdocInfo.java b/service/src/main/java/org/lfenergy/compas/scl/validator/common/NsdocInfo.java new file mode 100644 index 0000000..b7908ee --- /dev/null +++ b/service/src/main/java/org/lfenergy/compas/scl/validator/common/NsdocInfo.java @@ -0,0 +1,61 @@ +// SPDX-FileCopyrightText: 2022 Alliander N.V. +// +// SPDX-License-Identifier: Apache-2.0 +package org.lfenergy.compas.scl.validator.common; + +import org.lfenergy.compas.scl.validator.exception.SclValidatorException; + +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.StartElement; +import javax.xml.stream.events.XMLEvent; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; + +import static org.lfenergy.compas.scl.validator.exception.SclValidatorErrorCode.DETERMINING_ID_FAILED; +import static org.lfenergy.compas.scl.validator.exception.SclValidatorErrorCode.LOADING_NSDOC_FILE_FAILED; +import static org.lfenergy.compas.scl.validator.util.StaxUtil.getAttributeValue; +import static org.lfenergy.compas.scl.validator.util.StaxUtil.isElement; + +public class NsdocInfo { + private static final String NSDOC_ELEMENT_NAME = "NSDoc"; + + private String id = null; + + public NsdocInfo(File file) { + try (var fis = new FileInputStream(file)) { + var factory = XMLInputFactory.newInstance(); + // Completely disable external entities declarations: + factory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, Boolean.FALSE); + + var reader = factory.createXMLEventReader(fis); + + while (id == null && reader.hasNext()) { + processEvent(reader.nextEvent()); + } + } catch (IOException | XMLStreamException exp) { + throw new SclValidatorException(LOADING_NSDOC_FILE_FAILED, "Error loading NSDoc File " + file.getName() + "'.", exp); + } + + if (id == null) { + throw new SclValidatorException(DETERMINING_ID_FAILED, "No ID found in NSDoc File '" + file.getName() + "'."); + } + } + + private void processEvent(XMLEvent nextEvent) { + if (nextEvent.isStartElement()) { + processStartElement(nextEvent.asStartElement()); + } + } + + private void processStartElement(StartElement element) { + if (isElement(element, NSDOC_ELEMENT_NAME)) { + id = getAttributeValue(element, "id"); + } + } + + public String getId() { + return id; + } +} diff --git a/service/src/main/java/org/lfenergy/compas/scl/validator/service/NsdocService.java b/service/src/main/java/org/lfenergy/compas/scl/validator/service/NsdocService.java new file mode 100644 index 0000000..82d2c99 --- /dev/null +++ b/service/src/main/java/org/lfenergy/compas/scl/validator/service/NsdocService.java @@ -0,0 +1,30 @@ +// SPDX-FileCopyrightText: 2022 Alliander N.V. +// +// SPDX-License-Identifier: Apache-2.0 +package org.lfenergy.compas.scl.validator.service; + +import org.lfenergy.compas.scl.validator.common.NsdocFinder; +import org.lfenergy.compas.scl.validator.model.NsdocFile; + +import javax.enterprise.context.ApplicationScoped; +import javax.inject.Inject; +import java.util.Collection; +import java.util.UUID; + +@ApplicationScoped +public class NsdocService { + private final NsdocFinder nsdocFinder; + + @Inject + public NsdocService(NsdocFinder nsdocFinder) { + this.nsdocFinder = nsdocFinder; + } + + public Collection list() { + return nsdocFinder.getNsdocFiles(); + } + + public String get(UUID id) { + return nsdocFinder.getNsdocFile(id); + } +} diff --git a/service/src/test/data/nsdoc/invalid.nsdoc b/service/src/test/data/nsdoc/invalid.nsdoc new file mode 100644 index 0000000..99f4ab6 --- /dev/null +++ b/service/src/test/data/nsdoc/invalid.nsdoc @@ -0,0 +1,7 @@ + + + + + + + diff --git a/service/src/test/data/nsdoc/testFile73.nsdoc b/service/src/test/data/nsdoc/testFile73.nsdoc new file mode 100644 index 0000000..12207b3 --- /dev/null +++ b/service/src/test/data/nsdoc/testFile73.nsdoc @@ -0,0 +1,13 @@ + + + + + + + + + diff --git a/service/src/test/data/nsdoc/testFile74.nsdoc b/service/src/test/data/nsdoc/testFile74.nsdoc new file mode 100644 index 0000000..84e699a --- /dev/null +++ b/service/src/test/data/nsdoc/testFile74.nsdoc @@ -0,0 +1,14 @@ + + + + + + + + + + diff --git a/service/src/test/java/org/lfenergy/compas/scl/validator/common/NsdocFinderTest.java b/service/src/test/java/org/lfenergy/compas/scl/validator/common/NsdocFinderTest.java new file mode 100644 index 0000000..7f270f8 --- /dev/null +++ b/service/src/test/java/org/lfenergy/compas/scl/validator/common/NsdocFinderTest.java @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: 2022 Alliander N.V. +// +// SPDX-License-Identifier: Apache-2.0 +package org.lfenergy.compas.scl.validator.common; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.lfenergy.compas.scl.validator.model.NsdocFile; + +import java.util.ArrayList; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +class NsdocFinderTest { + private NsdocFinder finder; + + @BeforeEach + void setup() { + finder = new NsdocFinder("./src/test/data/nsdoc"); + } + + @Test + void getNsdocFiles_WhenCalledWithConfiguredDirectory_ThenExpectCorrectNumberOfEntriesReturned() { + var files = finder.getNsdocFiles(); + + assertNotNull(files); + // 2 Files expected, because 1 file is invalid. + assertEquals(2, files.size()); + + var fileList = new ArrayList<>(files); + assertEquals("IEC 61850-7-3", fileList.get(0).getNsdocId()); + assertEquals("IEC 61850-7-4", fileList.get(1).getNsdocId()); + } + + @Test + void getNsdocFiles_WhenCalledWithNonExistingDirectory_ThenNoEntriesReturned() { + finder = new NsdocFinder("./src/text/data/non-existing"); + var files = finder.getNsdocFiles(); + + assertNotNull(files); + assertEquals(0, files.size()); + } + + @Test + void getNsdocFile_WhenUseTheIDsToRetrieveEntries_ThenContentIsReturned() { + var files = finder.getNsdocFiles(); + var content = files.stream() + .map(NsdocFile::getId) + .map(id -> finder.getNsdocFile(id)) + .findFirst() + .orElse(null); + + assertNotNull(content); + } +} diff --git a/service/src/test/java/org/lfenergy/compas/scl/validator/common/NsdocInfoTest.java b/service/src/test/java/org/lfenergy/compas/scl/validator/common/NsdocInfoTest.java new file mode 100644 index 0000000..cc022e1 --- /dev/null +++ b/service/src/test/java/org/lfenergy/compas/scl/validator/common/NsdocInfoTest.java @@ -0,0 +1,32 @@ +// SPDX-FileCopyrightText: 2022 Alliander N.V. +// +// SPDX-License-Identifier: Apache-2.0 +package org.lfenergy.compas.scl.validator.common; + +import org.junit.jupiter.api.Test; +import org.lfenergy.compas.scl.validator.exception.SclValidatorException; + +import java.io.File; + +import static org.junit.jupiter.api.Assertions.*; +import static org.lfenergy.compas.scl.validator.exception.SclValidatorErrorCode.DETERMINING_ID_FAILED; + +class NsdocInfoTest { + @Test + void getId_WhenCalledWithValidNsDocFile_ThenIdFromFileReturned() { + var nsdocFile = new File(getClass().getResource("/nsdoc/testFile74.nsdoc").getFile()); + + var nsdocInfo = new NsdocInfo(nsdocFile); + + assertNotNull(nsdocInfo.getId()); + assertEquals("IEC 61850-7-4", nsdocInfo.getId()); + } + + @Test + void getId_WhenCalledWithInvalidNsDocFile_ThenExceptionThrownDuringConstruction() { + var nsdocFile = new File(getClass().getResource("/nsdoc/invalid.nsdoc").getFile()); + + var exception = assertThrows(SclValidatorException.class, () -> new NsdocInfo(nsdocFile)); + assertNotNull(DETERMINING_ID_FAILED, exception.getErrorCode()); + } +} diff --git a/service/src/test/java/org/lfenergy/compas/scl/validator/service/NsdocServiceTest.java b/service/src/test/java/org/lfenergy/compas/scl/validator/service/NsdocServiceTest.java new file mode 100644 index 0000000..51e4bf5 --- /dev/null +++ b/service/src/test/java/org/lfenergy/compas/scl/validator/service/NsdocServiceTest.java @@ -0,0 +1,60 @@ +// SPDX-FileCopyrightText: 2022 Alliander N.V. +// +// SPDX-License-Identifier: Apache-2.0 +package org.lfenergy.compas.scl.validator.service; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.lfenergy.compas.scl.validator.common.NsdocFinder; +import org.lfenergy.compas.scl.validator.model.NsdocFile; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.List; +import java.util.UUID; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +class NsdocServiceTest { + + private NsdocService nsdocService; + + @Mock + private NsdocFinder nsdocFinder; + + @BeforeEach + void beforeEach() { + nsdocService = new NsdocService(nsdocFinder); + } + + @Test + void list_WhenCalled_ThenEmptyListReturned() { + when(nsdocFinder.getNsdocFiles()).thenReturn(List.of(new NsdocFile())); + + var result = nsdocService.list(); + + assertNotNull(result); + assertEquals(1, result.size()); + + verify(nsdocFinder, times(1)).getNsdocFiles(); + } + + @Test + void get_WhenCalled_ThenContentReturned() { + UUID id = UUID.randomUUID(); + String content = ""; + + when(nsdocFinder.getNsdocFile(id)).thenReturn(content); + + var result = nsdocService.get(id); + + assertNotNull(result); + assertEquals(content, result); + + verify(nsdocFinder, times(1)).getNsdocFile(id); + } +} \ No newline at end of file diff --git a/service/src/test/java/org/lfenergy/compas/scl/validator/service/SclValidatorServiceTest.java b/service/src/test/java/org/lfenergy/compas/scl/validator/service/SclValidatorServiceTest.java index 4c263c7..f7fdd95 100644 --- a/service/src/test/java/org/lfenergy/compas/scl/validator/service/SclValidatorServiceTest.java +++ b/service/src/test/java/org/lfenergy/compas/scl/validator/service/SclValidatorServiceTest.java @@ -8,10 +8,11 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.lfenergy.compas.scl.extensions.model.SclFileType; import org.lfenergy.compas.scl.validator.SclValidator; +import org.lfenergy.compas.scl.validator.model.ValidationError; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import java.util.Collections; +import java.util.List; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -31,16 +32,16 @@ void beforeEach() { } @Test - void validate_WhenCalled_ThenEmptyListReturned() { + void validate_WhenCalled_ThenExpectedListReturned() { var type = SclFileType.CID; var sclData = "Some String"; - when(sclValidator.validate(type, sclData)).thenReturn(Collections.emptyList()); + when(sclValidator.validate(type, sclData)).thenReturn(List.of(new ValidationError())); var result = sclValidatorService.validate(type, sclData); assertNotNull(result); - assertEquals(0, result.size()); + assertEquals(1, result.size()); verify(sclValidator, times(1)).validate(type, sclData); } diff --git a/service/src/test/resources/nsdoc/invalid.nsdoc b/service/src/test/resources/nsdoc/invalid.nsdoc new file mode 100644 index 0000000..99f4ab6 --- /dev/null +++ b/service/src/test/resources/nsdoc/invalid.nsdoc @@ -0,0 +1,7 @@ + + + + + + + diff --git a/service/src/test/resources/nsdoc/testFile74.nsdoc b/service/src/test/resources/nsdoc/testFile74.nsdoc new file mode 100644 index 0000000..84e699a --- /dev/null +++ b/service/src/test/resources/nsdoc/testFile74.nsdoc @@ -0,0 +1,14 @@ + + + + + + + + + + diff --git a/validator/src/main/java/org/lfenergy/compas/scl/validator/exception/NsdocFileNotFoundException.java b/validator/src/main/java/org/lfenergy/compas/scl/validator/exception/NsdocFileNotFoundException.java new file mode 100644 index 0000000..c4f17f0 --- /dev/null +++ b/validator/src/main/java/org/lfenergy/compas/scl/validator/exception/NsdocFileNotFoundException.java @@ -0,0 +1,12 @@ +// SPDX-FileCopyrightText: 2022 Alliander N.V. +// +// SPDX-License-Identifier: Apache-2.0 +package org.lfenergy.compas.scl.validator.exception; + +import static org.lfenergy.compas.scl.validator.exception.SclValidatorErrorCode.NSDOC_FILE_NOT_FOUND; + +public class NsdocFileNotFoundException extends SclValidatorException { + public NsdocFileNotFoundException(String message) { + super(NSDOC_FILE_NOT_FOUND, message); + } +} diff --git a/validator/src/main/java/org/lfenergy/compas/scl/validator/exception/SclValidatorErrorCode.java b/validator/src/main/java/org/lfenergy/compas/scl/validator/exception/SclValidatorErrorCode.java index 249706b..7d0e377 100644 --- a/validator/src/main/java/org/lfenergy/compas/scl/validator/exception/SclValidatorErrorCode.java +++ b/validator/src/main/java/org/lfenergy/compas/scl/validator/exception/SclValidatorErrorCode.java @@ -19,4 +19,9 @@ public class SclValidatorErrorCode { public static final String WRITE_TO_OCL_TEMP_FILES_FAILED = "SVS-2003"; public static final String OCL_MODEL_PACKAGE_NOT_FOUND = "SVS-2005"; public static final String NO_URI_PASSED = "SVS-2006"; + + public static final String CALCULATING_CHECKSUM_FAILED = "SVS-3001"; + public static final String DETERMINING_ID_FAILED = "SVS-3002"; + public static final String LOADING_NSDOC_FILE_FAILED = "SVS-3003"; + public static final String NSDOC_FILE_NOT_FOUND = "SVS-3004"; } diff --git a/validator/src/main/java/org/lfenergy/compas/scl/validator/model/NsdocFile.java b/validator/src/main/java/org/lfenergy/compas/scl/validator/model/NsdocFile.java new file mode 100644 index 0000000..8804f2b --- /dev/null +++ b/validator/src/main/java/org/lfenergy/compas/scl/validator/model/NsdocFile.java @@ -0,0 +1,81 @@ +// SPDX-FileCopyrightText: 2022 Alliander N.V. +// +// SPDX-License-Identifier: Apache-2.0 +package org.lfenergy.compas.scl.validator.model; + +import org.eclipse.microprofile.openapi.annotations.media.Schema; + +import javax.validation.constraints.NotBlank; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import java.util.UUID; + +import static org.lfenergy.compas.scl.validator.SclValidatorConstants.SCL_VALIDATOR_SERVICE_V1_NS_URI; + +@Schema(description = "Information about a single NSDoc file that is known by the service.") +@XmlAccessorType(XmlAccessType.FIELD) +public class NsdocFile { + @Schema(description = "The technical id of this NSDoc File.", + example = "123e4567-e89b-12d3-a456-426614174000") + @NotBlank + @XmlElement(name = "Id", + namespace = SCL_VALIDATOR_SERVICE_V1_NS_URI, + required = true) + private UUID id; + + @Schema(description = "The id of the NSDoc File.", + example = "IEC 61850-7-3") + @NotBlank + @XmlElement(name = "NsdocId", + namespace = SCL_VALIDATOR_SERVICE_V1_NS_URI, + required = true) + private String nsdocId; + + @Schema(description = "The name of the NSDoc File.", + example = "OfficialFile73.nsdoc") + @NotBlank + @XmlElement(name = "Filename", + namespace = SCL_VALIDATOR_SERVICE_V1_NS_URI, + required = true) + private String filename; + + @Schema(description = "The checksum of the NSDoc File.") + @NotBlank + @XmlElement(name = "Checksum", + namespace = SCL_VALIDATOR_SERVICE_V1_NS_URI, + required = true) + private String checksum; + + public UUID getId() { + return id; + } + + public void setId(UUID id) { + this.id = id; + } + + public String getNsdocId() { + return nsdocId; + } + + public void setNsdocId(String nsdocId) { + this.nsdocId = nsdocId; + } + + public String getFilename() { + return filename; + } + + public void setFilename(String filename) { + this.filename = filename; + } + + public String getChecksum() { + return checksum; + } + + public void setChecksum(String checksum) { + this.checksum = checksum; + } +} diff --git a/validator/src/main/java/org/lfenergy/compas/scl/validator/util/StaxUtil.java b/validator/src/main/java/org/lfenergy/compas/scl/validator/util/StaxUtil.java new file mode 100644 index 0000000..cc62091 --- /dev/null +++ b/validator/src/main/java/org/lfenergy/compas/scl/validator/util/StaxUtil.java @@ -0,0 +1,26 @@ +// SPDX-FileCopyrightText: 2022 Alliander N.V. +// +// SPDX-License-Identifier: Apache-2.0 +package org.lfenergy.compas.scl.validator.util; + +import javax.xml.namespace.QName; +import javax.xml.stream.events.Attribute; +import javax.xml.stream.events.StartElement; + +public class StaxUtil { + StaxUtil() { + throw new UnsupportedOperationException("StaxUtil class"); + } + + public static boolean isElement(StartElement element, String elementName) { + return elementName.equals(element.getName().getLocalPart()); + } + + public static String getAttributeValue(StartElement element, String attributeName) { + Attribute attribute = element.getAttributeByName(new QName(attributeName)); + if (attribute != null) { + return attribute.getValue(); + } + return null; + } +} diff --git a/validator/src/test/java/org/lfenergy/compas/scl/validator/exception/NsdocFileNotFoundExceptionTest.java b/validator/src/test/java/org/lfenergy/compas/scl/validator/exception/NsdocFileNotFoundExceptionTest.java new file mode 100644 index 0000000..17983f4 --- /dev/null +++ b/validator/src/test/java/org/lfenergy/compas/scl/validator/exception/NsdocFileNotFoundExceptionTest.java @@ -0,0 +1,18 @@ +// SPDX-FileCopyrightText: 2022 Alliander N.V. +// +// SPDX-License-Identifier: Apache-2.0 +package org.lfenergy.compas.scl.validator.exception; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +class NsdocFileNotFoundExceptionTest { + @Test + void constructor_WhenCalledWithOnlyMessage_ThenMessageCanBeRetrieved() { + var expectedMessage = "The message"; + var exception = new NsdocFileNotFoundException(expectedMessage); + + Assertions.assertEquals(SclValidatorErrorCode.NSDOC_FILE_NOT_FOUND, exception.getErrorCode()); + Assertions.assertEquals(expectedMessage, exception.getMessage()); + } +} \ No newline at end of file diff --git a/validator/src/test/java/org/lfenergy/compas/scl/validator/model/NsdocFileTest.java b/validator/src/test/java/org/lfenergy/compas/scl/validator/model/NsdocFileTest.java new file mode 100644 index 0000000..a6d047a --- /dev/null +++ b/validator/src/test/java/org/lfenergy/compas/scl/validator/model/NsdocFileTest.java @@ -0,0 +1,11 @@ +// SPDX-FileCopyrightText: 2022 Alliander N.V. +// +// SPDX-License-Identifier: Apache-2.0 +package org.lfenergy.compas.scl.validator.model; + +class NsdocFileTest extends AbstractPojoTester { + @Override + protected Class getClassToBeTested() { + return NsdocFile.class; + } +} \ No newline at end of file diff --git a/validator/src/test/java/org/lfenergy/compas/scl/validator/util/StaxUtilTest.java b/validator/src/test/java/org/lfenergy/compas/scl/validator/util/StaxUtilTest.java new file mode 100644 index 0000000..23ecb9c --- /dev/null +++ b/validator/src/test/java/org/lfenergy/compas/scl/validator/util/StaxUtilTest.java @@ -0,0 +1,81 @@ +// SPDX-FileCopyrightText: 2022 Alliander N.V. +// +// SPDX-License-Identifier: Apache-2.0 +package org.lfenergy.compas.scl.validator.util; + +import org.junit.jupiter.api.Test; + +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.StartElement; +import java.io.IOException; + +import static org.junit.jupiter.api.Assertions.*; +import static org.lfenergy.compas.scl.validator.util.StaxUtil.getAttributeValue; +import static org.lfenergy.compas.scl.validator.util.StaxUtil.isElement; + +class StaxUtilTest { + @Test + void constructor_WhenConstructorCalled_ThenShouldThrowExceptionCauseForbidden() { + assertThrows(UnsupportedOperationException.class, StaxUtil::new); + } + + @Test + void isElement_WhenCalledWithExpectedElementName_ThenFirstElementHasCorrectElementName() throws XMLStreamException, IOException { + var element = getFirstElement(); + if (element != null) { + var result = isElement(element, "NSDoc"); + assertTrue(result, "No NSDoc Element Found"); + } else { + fail("XML File couldn't be read."); + } + } + + @Test + void isElement_WhenCalledWithUnknownElementName_ThenFirstElementHasIncorrectElementName() throws XMLStreamException, IOException { + var element = getFirstElement(); + if (element != null) { + var result = isElement(element, "Unknown"); + assertFalse(result, "Unknown Element shouldn't be Found"); + } else { + fail("XML File couldn't be read."); + } + } + + @Test + void getAttributeValue_WhenCalledWithKnownAttribute_ThenAttributeValueReturned() throws XMLStreamException, IOException { + var element = getFirstElement(); + if (element != null) { + var result = getAttributeValue(element, "version"); + assertEquals("1010", result); + } else { + fail("XML File couldn't be read."); + } + } + + @Test + void getAttributeValue_WhenCalledWithUnknownAttribute_ThenNullReturned() throws XMLStreamException, IOException { + var element = getFirstElement(); + if (element != null) { + var result = getAttributeValue(element, "unknown"); + assertNull(result); + } else { + fail("XML File couldn't be read."); + } + } + + private StartElement getFirstElement() throws XMLStreamException, IOException { + try (var inputStream = getClass().getResourceAsStream("/testFile74.nsdoc")) { + var xmlInputFactory = XMLInputFactory.newInstance(); + var reader = xmlInputFactory.createXMLEventReader(inputStream); + + while (reader.hasNext()) { + var nextEvent = reader.nextEvent(); + if (nextEvent.isStartElement()) { + return nextEvent.asStartElement(); + } + } + return null; + } + } +} diff --git a/riseclipse/validator-riseclipse/src/test/java/org/lfenergy/compas/scl/validator/util/TestSupportUtil.java b/validator/src/test/java/org/lfenergy/compas/scl/validator/util/TestSupportUtil.java similarity index 79% rename from riseclipse/validator-riseclipse/src/test/java/org/lfenergy/compas/scl/validator/util/TestSupportUtil.java rename to validator/src/test/java/org/lfenergy/compas/scl/validator/util/TestSupportUtil.java index 0db7f6b..6cc144a 100644 --- a/riseclipse/validator-riseclipse/src/test/java/org/lfenergy/compas/scl/validator/util/TestSupportUtil.java +++ b/validator/src/test/java/org/lfenergy/compas/scl/validator/util/TestSupportUtil.java @@ -11,7 +11,11 @@ public final class TestSupportUtil { } public static String readSCL(String filename) throws IOException { - var inputStream = TestSupportUtil.class.getResourceAsStream("/scl/" + filename); + return readFile("/scl/" + filename); + } + + public static String readFile(String filename) throws IOException { + var inputStream = TestSupportUtil.class.getResourceAsStream(filename); assert inputStream != null; return new String(inputStream.readAllBytes()); diff --git a/validator/src/test/resources/testFile74.nsdoc b/validator/src/test/resources/testFile74.nsdoc new file mode 100644 index 0000000..8895653 --- /dev/null +++ b/validator/src/test/resources/testFile74.nsdoc @@ -0,0 +1,14 @@ + + + + + + + + + +