Skip to content

Commit

Permalink
Implement the new Gazelle validation API
Browse files Browse the repository at this point in the history
Fixes #141
  • Loading branch information
qligier committed Feb 21, 2024
1 parent 29da3b9 commit 6763f75
Show file tree
Hide file tree
Showing 21 changed files with 2,272 additions and 37 deletions.
4 changes: 4 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
YYYY/MM/DD Release X.Y.Z

- Implement the new Gazelle validation API [#141](https://github.com/ahdis/matchbox/issues/141)

2024/01/31 Release 3.5.4

- `docker pull europe-west6-docker.pkg.dev/ahdis-ch/ahdis/matchbox:v3.5.4`
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package ca.uhn.fhir.jpa.starter;

import ch.ahdis.matchbox.spring.MatchboxEventListener;
import ch.ahdis.matchbox.gazelle.GazelleValidationWs;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.boot.SpringApplication;
Expand All @@ -26,7 +27,8 @@
MdmConfig.class,
MatchboxJpaConfig.class,
FhirServerConfigR4.class,
MatchboxEventListener.class})
MatchboxEventListener.class,
GazelleValidationWs.class})
public class Application extends SpringBootServletInitializer {

public static void main(String[] args) {
Expand All @@ -48,8 +50,8 @@ protected SpringApplicationBuilder configure(

@Bean
@Conditional(OnEitherVersion.class)
public ServletRegistrationBean hapiServletRegistration(RestfulServer restfulServer) {
ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean();
public ServletRegistrationBean<RestfulServer> hapiServletRegistration(RestfulServer restfulServer) {
ServletRegistrationBean<RestfulServer> servletRegistrationBean = new ServletRegistrationBean<>();
beanFactory.autowireBean(restfulServer);
servletRegistrationBean.setServlet(restfulServer);
servletRegistrationBean.addUrlMappings("/fhir/*");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
import org.hl7.fhir.r5.elementmodel.Manager.FhirFormat;
import org.hl7.fhir.r5.model.OperationOutcome;
import org.hl7.fhir.r5.model.StringType;
import org.hl7.fhir.r5.utils.EOperationOutcome;
import org.hl7.fhir.r5.utils.OperationOutcomeUtilities;
import org.hl7.fhir.r5.utils.ToolingExtensions;
import org.hl7.fhir.utilities.validation.ValidationMessage;
Expand Down Expand Up @@ -73,9 +74,6 @@ public class ValidationProvider {
@Autowired
private FhirContext myContext;

@Autowired
private INpmPackageVersionDao myPackageVersionDao;

// @Operation(name = "$canonical", manualRequest = true, idempotent = true, returnParameters = {
// @OperationParam(name = "return", type = IBase.class, min = 1, max = 1) })
// public IBaseResource canonical(HttpServletRequest theRequest) {
Expand Down Expand Up @@ -140,7 +138,13 @@ public IBaseResource validate(final HttpServletRequest theRequest) {
reload = theRequest.getParameter("reload").equals("true");
}

final String contentString = this.getContentString(theRequest, addedValidationMessages);
String contentString = "";
try {
contentString = new String(theRequest.getInputStream().readAllBytes(), StandardCharsets.UTF_8);
} catch (final Exception e) {
log.error(e.getMessage(), e);
}

if (contentString.isEmpty()) {
return this.getOoForError("No content provided in HTTP body");
} else {
Expand Down Expand Up @@ -172,10 +176,7 @@ public IBaseResource validate(final HttpServletRequest theRequest) {

final List<ValidationMessage> messages;
try {
final var format = encoding == EncodingEnum.XML ? FhirFormat.XML : FhirFormat.JSON;
final var stream = new ByteArrayInputStream(contentString.getBytes(StandardCharsets.UTF_8));
messages = engine.validate(format, stream, profile);

messages = doValidate(engine, contentString, encoding, profile);
} catch (final Exception e) {
sw.endCurrentTask();
log.debug("Validation time: {}", sw);
Expand All @@ -188,32 +189,6 @@ public IBaseResource validate(final HttpServletRequest theRequest) {
return this.getOperationOutcome(sha3Hex, messages, profile, engine, sw.formatTaskDurations(), cliContext);
}

private String getContentString(final HttpServletRequest theRequest,
final List<SingleValidationMessage> addedValidationMessages) {
byte[] bytes = null;
String contentString = "";
try {
bytes = IOUtils.toByteArray(theRequest.getInputStream());
if (bytes.length > 2 && bytes[0] == -17 && bytes[1] == -69 && bytes[2] == -65) {
byte[] dest = new byte[bytes.length - 3];
System.arraycopy(bytes, 3, dest, 0, bytes.length - 3);
bytes = dest;
if (addedValidationMessages != null) {
final var m = new SingleValidationMessage();
m.setSeverity(ResultSeverityEnum.WARNING);
m.setMessage(
"Resource content has a UTF-8 BOM marking, skipping BOM, see https://en.wikipedia.org/wiki/Byte_order_mark");
m.setLocationCol(0);
m.setLocationLine(0);
addedValidationMessages.add(m);
}
}
contentString = new String(bytes);
} catch (final IOException e) {
log.error(e.getMessage(), e);
}
return contentString;
}

private IBaseResource getOperationOutcome(final String id,
final List<ValidationMessage> messages,
Expand Down Expand Up @@ -295,4 +270,27 @@ private IBaseResource getOoForError(final @NonNull String message) {
issue.addExtension().setUrl(ToolingExtensions.EXT_ISSUE_SOURCE).setValue(new StringType("ValidationProvider"));
return VersionConvertorFactory_40_50.convertResource(oo);
}

public static List<ValidationMessage> doValidate(final MatchboxEngine engine,
String content,
final EncodingEnum encoding,
final String profile) throws EOperationOutcome, IOException {
final List<ValidationMessage> messages = new ArrayList<>();

if (content.startsWith("\uFEFF")) {
content = content.replace("\uFEFF", "");
final var m = new ValidationMessage();
m.setLevel(ValidationMessage.IssueSeverity.WARNING);
m.setMessage(
"Resource content has a UTF-8 BOM marking, skipping BOM, see https://en.wikipedia.org/wiki/Byte_order_mark");
m.setCol(0);
m.setLine(0);
messages.add(m);
}

final var format = encoding == EncodingEnum.XML ? FhirFormat.XML : FhirFormat.JSON;
final var stream = new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8));
messages.addAll(engine.validate(format, stream, profile));
return messages;
}
}
Loading

0 comments on commit 6763f75

Please sign in to comment.