Skip to content

Commit 9197f8b

Browse files
authored
Use operation outcome (#27)
## Summary - Routine Change ### Details - returns a FHIR operation outcome - refactor
1 parent 95731e4 commit 9197f8b

37 files changed

Lines changed: 4902 additions & 878 deletions

Makefile

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,10 @@ check-licenses-python:
3939
scripts/check_python_licenses.sh
4040

4141
check-licenses-java:
42-
mvn validate
42+
mvn validate
43+
44+
show-unused-dependencies:
45+
mvn dependency:analyze
4346

4447
# clean targets
4548
clean-packages:
@@ -101,4 +104,4 @@ aws-configure:
101104
aws configure sso --region eu-west-2
102105

103106
aws-login:
104-
aws sso login --sso-session sso-session
107+
aws sso login --sso-session sso-session

SAMtemplates/main_template.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ Resources:
5656
Properties:
5757
FunctionName: !Sub "${AWS::StackName}-FHIRValidator"
5858
CodeUri: ../
59-
Handler: software.nhs.FHIRValidator.HandlerStream::handleRequest
59+
Handler: software.nhs.fhirvalidator.handler.HandlerStream::handleRequest
6060
Role: !GetAtt FHIRValidatorResources.Outputs.LambdaRoleArn
6161
SnapStart:
6262
ApplyOn: PublishedVersions

pom.xml

Lines changed: 56 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
44
<modelVersion>4.0.0</modelVersion>
55

6-
<groupId>software.nhs.FHIRValidator</groupId>
6+
<groupId>software.nhs.fhirvalidator</groupId>
77
<artifactId>FHIRValidator</artifactId>
88
<packaging>jar</packaging>
99
<version>dev</version>
@@ -13,7 +13,7 @@
1313
<maven.compiler.source>1.8</maven.compiler.source>
1414
<maven.compiler.target>1.8</maven.compiler.target>
1515
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
16-
<fhir.version>5.5.0</fhir.version>
16+
<fhir.version>7.0.0</fhir.version>
1717
<log4j.version>2.23.0</log4j.version>
1818
<fasterxml.version>2.16.1</fasterxml.version>
1919
<sonar.organization>nhsdigital</sonar.organization>
@@ -31,7 +31,12 @@
3131
</dependencies>
3232
</dependencyManagement>
3333
<dependencies>
34-
34+
<dependency>
35+
<groupId>io.github.hakky54</groupId>
36+
<artifactId>logcaptor</artifactId>
37+
<version>2.9.2</version>
38+
<scope>test</scope>
39+
</dependency>
3540
<!--The
3641
following runtime dependencies are specific to a FHIR version-->
3742
<!--Enable
@@ -52,6 +57,26 @@
5257
<artifactId>hapi-fhir-validation</artifactId>
5358
<version>${fhir.version}</version>
5459
</dependency>
60+
<dependency>
61+
<groupId>ca.uhn.hapi.fhir</groupId>
62+
<artifactId>hapi-fhir-caching-caffeine</artifactId>
63+
<version>${fhir.version}</version>
64+
</dependency>
65+
<dependency>
66+
<groupId>ca.uhn.hapi.fhir</groupId>
67+
<artifactId>hapi-fhir-base</artifactId>
68+
<version>${fhir.version}</version>
69+
</dependency>
70+
<dependency>
71+
<groupId>ca.uhn.hapi.fhir</groupId>
72+
<artifactId>org.hl7.fhir.utilities</artifactId>
73+
<version>6.1.2.2</version>
74+
</dependency>
75+
<dependency>
76+
<groupId>ca.uhn.hapi.fhir</groupId>
77+
<artifactId>org.hl7.fhir.r4</artifactId>
78+
<version>6.1.2.2</version>
79+
</dependency>
5580
<dependency>
5681
<groupId>com.amazonaws</groupId>
5782
<artifactId>aws-lambda-java-core</artifactId>
@@ -84,8 +109,8 @@
84109
</dependency>
85110
<dependency>
86111
<groupId>org.apache.logging.log4j</groupId>
87-
<artifactId>log4j-slf4j18-impl</artifactId>
88-
<version>2.18.0</version>
112+
<artifactId>log4j-slf4j2-impl</artifactId>
113+
<version>${log4j.version}</version>
89114
</dependency>
90115
<dependency>
91116
<groupId>org.apache.logging.log4j</groupId>
@@ -97,12 +122,6 @@
97122
<artifactId>powertools-logging</artifactId>
98123
<version>1.18.0</version>
99124
</dependency>
100-
<dependency>
101-
<groupId>org.projectlombok</groupId>
102-
<artifactId>lombok</artifactId>
103-
<version>1.18.30</version>
104-
<scope>provided</scope>
105-
</dependency>
106125
<dependency>
107126
<groupId>org.aspectj</groupId>
108127
<artifactId>aspectjrt</artifactId>
@@ -129,7 +148,11 @@
129148
<artifactId>junit-jupiter</artifactId>
130149
<scope>test</scope>
131150
</dependency>
132-
151+
<dependency>
152+
<groupId>org.junit.jupiter</groupId>
153+
<artifactId>junit-jupiter-api</artifactId>
154+
<scope>test</scope>
155+
</dependency>
133156
</dependencies>
134157

135158
<build>
@@ -186,6 +209,27 @@
186209
</execution>
187210
</executions>
188211
</plugin>
212+
213+
<plugin>
214+
<groupId>org.jacoco</groupId>
215+
<artifactId>jacoco-maven-plugin</artifactId>
216+
<version>0.8.11</version>
217+
<executions>
218+
<execution>
219+
<goals>
220+
<goal>prepare-agent</goal>
221+
</goals>
222+
</execution>
223+
<!-- attached to Maven test phase -->
224+
<execution>
225+
<id>report</id>
226+
<phase>test</phase>
227+
<goals>
228+
<goal>report</goal>
229+
</goals>
230+
</execution>
231+
</executions>
232+
</plugin>
189233
<!--
190234
Using the Apache Maven Shade plugin to package the jar
191235

src/main/java/software/nhs/FHIRValidator/Utils.java

Lines changed: 0 additions & 30 deletions
This file was deleted.

src/main/java/software/nhs/FHIRValidator/ValidatorResponse.java

Lines changed: 0 additions & 20 deletions
This file was deleted.

src/main/java/software/nhs/FHIRValidator/Validator.java renamed to src/main/java/software/nhs/fhirvalidator/configuration/ValidatorConfiguration.java

Lines changed: 38 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
package software.nhs.FHIRValidator;
1+
package software.nhs.fhirvalidator.configuration;
22

33
import java.io.IOException;
4+
import java.io.InputStream;
5+
import java.util.ArrayList;
46
import java.util.List;
5-
import java.util.stream.Collectors;
67

7-
import com.google.common.collect.ImmutableList;
88
import com.google.gson.Gson;
9-
import com.google.gson.JsonSyntaxException;
109

10+
import org.hl7.fhir.common.hapi.validation.support.CachingValidationSupport;
1111
import org.hl7.fhir.common.hapi.validation.support.CommonCodeSystemsTerminologyService;
1212
import org.hl7.fhir.common.hapi.validation.support.InMemoryTerminologyServerValidationSupport;
1313
import org.hl7.fhir.common.hapi.validation.support.NpmPackageValidationSupport;
@@ -18,50 +18,57 @@
1818
import org.hl7.fhir.r4.model.CanonicalType;
1919
import org.hl7.fhir.r4.model.ElementDefinition;
2020
import org.hl7.fhir.r4.model.StructureDefinition;
21+
import org.hl7.fhir.utilities.npm.NpmPackage;
2122

2223
import ca.uhn.fhir.context.FhirContext;
2324
import ca.uhn.fhir.context.support.ConceptValidationOptions;
2425
import ca.uhn.fhir.context.support.DefaultProfileValidationSupport;
2526
import ca.uhn.fhir.context.support.IValidationSupport;
2627
import ca.uhn.fhir.context.support.ValidationSupportContext;
2728
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
28-
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
29+
import ca.uhn.fhir.util.ClasspathUtil;
2930
import ca.uhn.fhir.validation.FhirValidator;
30-
import ca.uhn.fhir.validation.ValidationResult;
31+
import software.nhs.fhirvalidator.models.SimplifierPackage;
32+
import software.nhs.fhirvalidator.util.ResourceUtils;
33+
3134
import org.apache.logging.log4j.LogManager;
3235
import org.apache.logging.log4j.Logger;
33-
import software.nhs.FHIRValidator.models.SimplifierPackage;
34-
import software.amazon.lambda.powertools.logging.Logging;
3536

3637
/**
3738
* This class is a wrapper around the HAPI FhirValidator.
3839
* The FhirValidator is built using default settings and the available
3940
* implementation guides are loaded into it.
4041
*/
4142

42-
public class Validator {
43-
private final FhirValidator validator;
43+
public class ValidatorConfiguration {
44+
public final FhirValidator validator;
45+
public final FhirContext fhirContext;
46+
public final List<NpmPackage> npmPackages = new ArrayList<>();
4447

45-
private final FhirContext ctx;
46-
Logger log = LogManager.getLogger(Validator.class);
48+
Logger log = LogManager.getLogger(ValidatorConfiguration.class);
4749

48-
public Validator() {
49-
ctx = FhirContext.forR4();
50+
public ValidatorConfiguration() {
51+
fhirContext = FhirContext.forR4();
5052

5153
// Create a chain that will hold our modules
5254
ValidationSupportChain supportChain = new ValidationSupportChain(
53-
new DefaultProfileValidationSupport(ctx),
54-
new CommonCodeSystemsTerminologyService(ctx),
55-
terminologyValidationSupport(ctx),
56-
new SnapshotGeneratingValidationSupport(ctx));
55+
new DefaultProfileValidationSupport(fhirContext),
56+
new CommonCodeSystemsTerminologyService(fhirContext),
57+
terminologyValidationSupport(fhirContext),
58+
new SnapshotGeneratingValidationSupport(fhirContext));
5759

58-
NpmPackageValidationSupport npmPackageSupport = new NpmPackageValidationSupport(ctx);
5960
SimplifierPackage[] packages = getPackages();
61+
NpmPackageValidationSupport npmPackageSupport = new NpmPackageValidationSupport(fhirContext);
62+
6063
try {
6164
for (SimplifierPackage individualPackage : packages) {
6265
String packagePath = String.format("classpath:package/%s-%s.tgz", individualPackage.packageName,
6366
individualPackage.version);
6467
npmPackageSupport.loadPackageFromClasspath(packagePath);
68+
try (InputStream is = ClasspathUtil.loadResourceAsStream(packagePath)) {
69+
NpmPackage pkg = NpmPackage.fromPackage(is);
70+
npmPackages.add(pkg);
71+
}
6572
}
6673
} catch (InternalErrorException | IOException ex) {
6774
log.error(ex.getMessage(), ex);
@@ -71,40 +78,11 @@ public Validator() {
7178
generateSnapshots(supportChain);
7279
supportChain.fetchCodeSystem("http://snomed.info/sct");
7380

74-
// Create a validator using the FhirInstanceValidator module.
75-
FhirInstanceValidator validatorModule = new FhirInstanceValidator(supportChain);
76-
validator = ctx.newValidator().registerValidatorModule(validatorModule);
77-
}
78-
79-
@Logging
80-
public ValidatorResponse validate(String resourceAsJsonText) {
81-
try {
82-
ValidationResult result = validator.validateWithResult(resourceAsJsonText);
83-
return toValidatorResponse(result);
84-
} catch (JsonSyntaxException | NullPointerException | IllegalArgumentException | InvalidRequestException e) {
85-
log.error(e.toString());
86-
return ValidatorResponse.builder()
87-
.isSuccessful(false)
88-
.errorMessages(ImmutableList.of(ValidatorErrorMessage.builder()
89-
.msg("Invalid JSON")
90-
.severity("error")
91-
.build()))
92-
.build();
93-
}
94-
}
81+
CachingValidationSupport validationSupport = new CachingValidationSupport(supportChain);
9582

96-
private ValidatorResponse toValidatorResponse(ValidationResult result) {
97-
return ValidatorResponse.builder()
98-
.isSuccessful(result.isSuccessful())
99-
.errorMessages(result.getMessages().stream()
100-
.map(singleValidationMessage -> ValidatorErrorMessage.builder()
101-
.severity(singleValidationMessage.getSeverity().getCode())
102-
.msg(singleValidationMessage.getLocationString() + " - "
103-
+ singleValidationMessage.getMessage())
104-
.build())
105-
106-
.collect(Collectors.toList()))
107-
.build();
83+
// Create a validator using the FhirInstanceValidator module.
84+
FhirInstanceValidator validatorModule = new FhirInstanceValidator(validationSupport);
85+
validator = fhirContext.newValidator().registerValidatorModule(validatorModule);
10886
}
10987

11088
private void generateSnapshots(IValidationSupport supportChain) {
@@ -121,7 +99,7 @@ private void generateSnapshots(IValidationSupport supportChain) {
12199
try {
122100
circularReferenceCheck(it, supportChain);
123101
} catch (Exception e) {
124-
log.error("Failed to generate snapshot for " + it, e);
102+
log.error(String.format("Failed to generate snapshot for %s", it), e);
125103
}
126104
});
127105

@@ -131,7 +109,7 @@ private void generateSnapshots(IValidationSupport supportChain) {
131109
try {
132110
supportChain.generateSnapshot(context, it, it.getUrl(), "https://fhir.nhs.uk/R4", it.getName());
133111
} catch (Exception e) {
134-
log.error("Failed to generate snapshot for " + it, e);
112+
log.error(String.format("Failed to generate snapshot for %s", it), e);
135113
}
136114
});
137115
}
@@ -144,7 +122,7 @@ private boolean shouldGenerateSnapshot(StructureDefinition structureDefinition)
144122
private StructureDefinition circularReferenceCheck(StructureDefinition structureDefinition,
145123
IValidationSupport supportChain) {
146124
if (structureDefinition.hasSnapshot()) {
147-
log.error(structureDefinition.getUrl() + " has snapshot!!");
125+
log.error(String.format("%s has snapshot!!", structureDefinition.getUrl()));
148126
}
149127

150128
for (ElementDefinition element : structureDefinition.getDifferential().getElement()) {
@@ -163,7 +141,8 @@ private StructureDefinition circularReferenceCheck(StructureDefinition structure
163141
element.getId().contains("Encounter.reasonReference") ||
164142
element.getId().contains("Encounter.appointment")) && element.hasType()) {
165143

166-
log.warn(structureDefinition.getUrl() + " has circular references (" + element.getId() + ")");
144+
log.warn(String.format("%s has circular references (%s)", structureDefinition.getUrl(),
145+
element.getId()));
167146

168147
for (ElementDefinition.TypeRefComponent typeRef : element.getType()) {
169148
if (typeRef.hasTargetProfile()) {
@@ -202,7 +181,7 @@ public IValidationSupport.CodeValidationResult validateCodeInValueSet(
202181
String theCode,
203182
String theDisplay,
204183
IBaseResource theValueSet) {
205-
String valueSetUrl = CommonCodeSystemsTerminologyService.getValueSetUrl(theValueSet);
184+
String valueSetUrl = CommonCodeSystemsTerminologyService.getValueSetUrl(fhirContext, theValueSet);
206185

207186
if ("https://fhir.nhs.uk/ValueSet/NHSDigital-MedicationRequest-Code".equals(valueSetUrl)
208187
|| "https://fhir.nhs.uk/ValueSet/NHSDigital-MedicationDispense-Code".equals(valueSetUrl)
@@ -224,8 +203,7 @@ public IValidationSupport.CodeValidationResult validateCodeInValueSet(
224203
}
225204

226205
private SimplifierPackage[] getPackages() {
227-
String manifestContent = Utils.getResourceContent("manifest.json");
228-
SimplifierPackage[] packages = new Gson().fromJson(manifestContent, SimplifierPackage[].class);
229-
return packages;
206+
String manifestContent = ResourceUtils.getResourceContent("manifest.json");
207+
return new Gson().fromJson(manifestContent, SimplifierPackage[].class);
230208
}
231209
}

0 commit comments

Comments
 (0)