Skip to content
This repository was archived by the owner on Oct 6, 2025. It is now read-only.

Commit be9b555

Browse files
committed
stand-alone validator working, workaround for icd10-gm, ops, pzn
Added a "code ok" validation support impl that assumes that codes from http://fhir.de/CodeSystem/bfarm/icd-10-gm, http://fhir.de/CodeSystem/dimdi/icd-10-gm, http://fhir.de/CodeSystem/bfarm/ops, http://fhir.de/CodeSystem/dimdi/ops, http://fhir.de/CodeSystem/ifa/pzn are always valid, this workaround is fine if the codes are later checked against an expanded ValueSet. Fixed copy-dependencies build step for stand-alone validator
1 parent 576ef36 commit be9b555

6 files changed

Lines changed: 136 additions & 27 deletions

File tree

codex-process-data-transfer/pom.xml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -178,10 +178,10 @@
178178
hapi-fhir-base,hapi-fhir-client,hapi-fhir-converter,hapi-fhir-structures-r4,hapi-fhir-structures-r5,hapi-fhir-validation,hapi-fhir-validation-resources-r4,
179179
hapi-fhir-validation-resources-r5,org.hl7.fhir.convertors,org.hl7.fhir.dstu2,org.hl7.fhir.dstu2016may,org.hl7.fhir.dstu3,org.hl7.fhir.r4,org.hl7.fhir.r5,org.hl7.fhir.utilities,
180180
org.hl7.fhir.validation,jackson-annotations,jackson-core,jackson-databind,jackson-module-jaxb-annotations,caffeine,guava,
181-
commons-codec,commons-io,crypto-utils,log4j2-utils,jakarta.activation,jakarta.annotation-api,jakarta.ws.rs-api,jakarta.xml.bind-api,commons-compress,commons-lang3,commons-text,
182-
httpclient,httpcore,log4j-api,log4j-core,log4j-slf4j-impl,bcpkix-jdk15on,bcprov-jdk15on,bcutil-jdk15on,ucum,hk2-api,hk2-locator,hk2-utils,osgi-resource-locator,
183-
aopalliance-repackaged,jakarta.inject,jersey-apache-connector,jersey-client,jersey-common,jersey-entity-filtering,jersey-hk2,jersey-media-jaxb,jersey-media-json-jackson,
184-
dsf-bpe-process-base,dsf-fhir-rest-adapter,dsf-fhir-validation,dsf-openehr-model,jcl-over-slf4j,
181+
commons-codec,commons-io,crypto-utils,jakarta.activation,jakarta.annotation-api,jakarta.ws.rs-api,jakarta.xml.bind-api,commons-compress,commons-lang3,commons-text,
182+
httpclient,httpcore,log4j-api,log4j-core,log4j-slf4j2-impl,bcpkix-jdk18on,bcprov-jdk18on,bcutil-jdk18on,ucum,hk2-api,hk2-locator,hk2-utils,osgi-resource-locator,
183+
aopalliance-repackaged,jakarta.inject-api,jersey-apache-connector,jersey-client,jersey-common,jersey-entity-filtering,jersey-hk2,jersey-media-jaxb,jersey-media-json-jackson,
184+
dsf-bpe-process-api-v1,dsf-fhir-auth,dsf-fhir-rest-adapter,dsf-fhir-validation,dsf-openehr-model,jcl-over-slf4j,
185185
slf4j-api,spring-aop,spring-beans,spring-context,spring-core,spring-expression,spring-jcl,thymeleaf,unbescape,xpp3,xpp3_xpath
186186
</includeArtifactIds>
187187
</configuration>

codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/spring/config/ValidationConfig.java

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
import org.springframework.context.annotation.Bean;
3030
import org.springframework.context.annotation.Configuration;
3131

32+
import com.fasterxml.jackson.databind.ObjectMapper;
33+
3234
import ca.uhn.fhir.context.FhirContext;
3335
import ca.uhn.fhir.context.support.IValidationSupport;
3436
import de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.validation.BundleValidatorFactory;
@@ -52,7 +54,6 @@
5254
import de.rwh.utils.crypto.CertificateHelper;
5355
import de.rwh.utils.crypto.io.CertificateReader;
5456
import de.rwh.utils.crypto.io.PemIo;
55-
import dev.dsf.bpe.v1.ProcessPluginApi;
5657
import dev.dsf.bpe.v1.documentation.ProcessDocumentation;
5758
import dev.dsf.fhir.validation.SnapshotGenerator;
5859
import dev.dsf.fhir.validation.ValueSetExpander;
@@ -218,8 +219,13 @@ public static enum TerminologyServerConnectionTestStatus
218219
@Value("${java.io.tmpdir}")
219220
private String systemTempFolder;
220221

222+
// not using process plugin api to enable reuse of this config class in stand-alone validator
223+
@Autowired
224+
private FhirContext fhirContext;
225+
226+
// not using process plugin api to enable reuse of this config class in stand-alone validator
221227
@Autowired
222-
private ProcessPluginApi api;
228+
private ObjectMapper objectMapper;
223229

224230

225231
@Bean
@@ -230,9 +236,9 @@ public ValidationPackageManager validationPackageManager()
230236
EnumSet<BindingStrength> bindingStrengths = EnumSet.copyOf(
231237
valueSetExpansionBindingStrengths.stream().map(BindingStrength::fromCode).collect(Collectors.toList()));
232238

233-
return new ValidationPackageManagerImpl(validationPackageClient(), valueSetExpansionClient(),
234-
api.getObjectMapper(), api.getFhirContext(), internalSnapshotGeneratorFactory(),
235-
internalValueSetExpanderFactory(), noDownload, bindingStrengths);
239+
return new ValidationPackageManagerImpl(validationPackageClient(), valueSetExpansionClient(), objectMapper,
240+
fhirContext, internalSnapshotGeneratorFactory(), internalValueSetExpanderFactory(), noDownload,
241+
bindingStrengths);
236242
}
237243

238244
private StructureDefinitionModifier createStructureDefinitionModifier(String className)
@@ -368,7 +374,7 @@ else if (clientCertificateFile == null && clientCertificatePrivateKeyFile == nul
368374
@Bean
369375
public ValidationPackageClient validationPackageClient()
370376
{
371-
return new ValidationPackageClientWithFileSystemCache(packageCacheFolder(), api.getObjectMapper(),
377+
return new ValidationPackageClientWithFileSystemCache(packageCacheFolder(), objectMapper,
372378
validationPackageClientJersey());
373379
}
374380

@@ -410,7 +416,7 @@ public ValueSetExpansionClient valueSetExpansionClient()
410416
List<ValueSetModifier> modifiers = valueSetModifierClasses.stream().map(this::createValueSetModifier)
411417
.collect(Collectors.toList());
412418

413-
return new ValueSetExpansionClientWithFileSystemCache(valueSetCacheFolder(), api.getFhirContext(),
419+
return new ValueSetExpansionClientWithFileSystemCache(valueSetCacheFolder(), fhirContext,
414420
new ValueSetExpansionClientWithModifiers(valueSetExpansionClientJersey(), modifiers));
415421
}
416422

@@ -464,8 +470,7 @@ private ValueSetExpansionClient valueSetExpansionClientJersey()
464470
valueSetExpansionClientBasicAuthUsername, valueSetExpansionClientBasicAuthPassword,
465471
valueSetExpansionClientProxySchemeHostPort, valueSetExpansionClientProxyUsername,
466472
valueSetExpansionClientProxyPassword, valueSetExpansionClientConnectTimeout,
467-
valueSetExpansionClientReadTimeout, valueSetExpansionClientVerbose, api.getObjectMapper(),
468-
api.getFhirContext());
473+
valueSetExpansionClientReadTimeout, valueSetExpansionClientVerbose, objectMapper, fhirContext);
469474
}
470475

471476
public TerminologyServerConnectionTestStatus testConnectionToTerminologyServer()
@@ -524,7 +529,8 @@ public BundleValidatorFactory bundleValidatorFactory()
524529
validationPackageIdentifiers());
525530
}
526531

527-
private List<ValidationPackageIdentifier> validationPackageIdentifiers()
532+
@Bean
533+
public List<ValidationPackageIdentifier> validationPackageIdentifiers()
528534
{
529535
if (validationPackages == null || validationPackages.isEmpty())
530536
throw new IllegalArgumentException("Validation packages not specified");
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package de.netzwerk_universitaetsmedizin.codex.processes.data_transfer.validation;
2+
3+
import java.util.ArrayList;
4+
import java.util.Arrays;
5+
import java.util.Collection;
6+
import java.util.List;
7+
8+
import org.slf4j.Logger;
9+
import org.slf4j.LoggerFactory;
10+
11+
import ca.uhn.fhir.context.FhirContext;
12+
import ca.uhn.fhir.context.support.ConceptValidationOptions;
13+
import ca.uhn.fhir.context.support.IValidationSupport;
14+
import ca.uhn.fhir.context.support.ValidationSupportContext;
15+
16+
public class NonValidatingValidationSupport implements IValidationSupport
17+
{
18+
private static final Logger logger = LoggerFactory.getLogger(NonValidatingValidationSupport.class);
19+
20+
private final FhirContext fhirContext;
21+
private final List<String> notValidatedCodeSystemSystems = new ArrayList<>();
22+
23+
public NonValidatingValidationSupport(FhirContext fhirContext, String... notValidatedCodeSystemSystems)
24+
{
25+
this(fhirContext, Arrays.asList(notValidatedCodeSystemSystems));
26+
}
27+
28+
public NonValidatingValidationSupport(FhirContext fhirContext, Collection<String> notValidatedCodeSystemSystems)
29+
{
30+
this.fhirContext = fhirContext;
31+
32+
if (notValidatedCodeSystemSystems != null)
33+
this.notValidatedCodeSystemSystems.addAll(notValidatedCodeSystemSystems);
34+
}
35+
36+
@Override
37+
public FhirContext getFhirContext()
38+
{
39+
return fhirContext;
40+
}
41+
42+
@Override
43+
public CodeValidationResult validateCode(ValidationSupportContext theValidationSupportContext,
44+
ConceptValidationOptions theOptions, String system, String code, String display, String valueSetUrl)
45+
{
46+
if (notValidatedCodeSystemSystems.contains(system))
47+
{
48+
logger.warn("Not validating code {} from system {} for valueSet {}", code, system, valueSetUrl);
49+
return new CodeValidationResult().setCode(code).setCodeSystemName(system).setDisplay(display);
50+
}
51+
52+
else
53+
return null;
54+
}
55+
56+
@Override
57+
public boolean isCodeSystemSupported(ValidationSupportContext theValidationSupportContext, String system)
58+
{
59+
return notValidatedCodeSystemSystems.contains(system);
60+
}
61+
}

codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/validation/ValidationMain.java

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
import java.io.InputStream;
44
import java.nio.file.Files;
55
import java.nio.file.Paths;
6+
import java.util.ArrayList;
67
import java.util.Arrays;
8+
import java.util.List;
79
import java.util.Locale;
810
import java.util.Objects;
911
import java.util.stream.Stream;
@@ -23,6 +25,11 @@
2325
import org.springframework.core.env.ConfigurableEnvironment;
2426
import org.springframework.core.env.EnumerablePropertySource;
2527

28+
import com.fasterxml.jackson.annotation.JsonInclude.Include;
29+
import com.fasterxml.jackson.databind.MapperFeature;
30+
import com.fasterxml.jackson.databind.ObjectMapper;
31+
import com.fasterxml.jackson.databind.json.JsonMapper;
32+
2633
import ca.uhn.fhir.context.FhirContext;
2734
import ca.uhn.fhir.i18n.HapiLocalizer;
2835
import ca.uhn.fhir.parser.IParser;
@@ -70,7 +77,7 @@ public static class TestConfig
7077
private ValidationPackageManager packageManager;
7178

7279
@Autowired
73-
private ValidationPackageIdentifier validationPackage;
80+
private List<ValidationPackageIdentifier> validationPackageIdentifiers;
7481

7582
@Autowired
7683
private ValueSetExpansionClient valueSetExpansionClient;
@@ -79,7 +86,15 @@ public static class TestConfig
7986
private ConfigurableEnvironment environment;
8087

8188
@Bean
82-
public FhirContext fhirContext()
89+
public ObjectMapper getObjectMapper()
90+
{
91+
return JsonMapper.builder().serializationInclusion(Include.NON_NULL)
92+
.serializationInclusion(Include.NON_EMPTY).disable(MapperFeature.AUTO_DETECT_CREATORS)
93+
.disable(MapperFeature.AUTO_DETECT_FIELDS).disable(MapperFeature.AUTO_DETECT_SETTERS).build();
94+
}
95+
96+
@Bean
97+
public FhirContext getFhirContext()
8398
{
8499
FhirContext context = FhirContext.forR4();
85100
HapiLocalizer localizer = new HapiLocalizer()
@@ -97,14 +112,15 @@ public Locale getLocale()
97112
@Bean
98113
public ValidationMain validatorMain()
99114
{
100-
return new ValidationMain(environment, fhirContext(), packageManager, validationPackage, output,
101-
outputPretty, valueSetExpansionClient);
115+
return new ValidationMain(environment, getFhirContext(), packageManager, validationPackageIdentifiers,
116+
output, outputPretty, valueSetExpansionClient);
102117
}
103118
}
104119

105120
public static enum Output
106121
{
107122
JSON, XML
123+
108124
}
109125

110126
public static void main(String[] args)
@@ -137,19 +153,20 @@ public static void main(String[] args)
137153
private final ConfigurableEnvironment environment;
138154
private final FhirContext fhirContext;
139155
private final ValidationPackageManager packageManager;
140-
private final ValidationPackageIdentifier validationPackage;
156+
private final List<ValidationPackageIdentifier> validationPackageIdentifiers = new ArrayList<>();
141157
private final Output output;
142158
private final boolean outputPretty;
143159
private final ValueSetExpansionClient valueSetExpansionClient;
144160

145161
public ValidationMain(ConfigurableEnvironment environment, FhirContext fhirContext,
146-
ValidationPackageManager packageManager, ValidationPackageIdentifier validationPackage, Output output,
147-
boolean outputPretty, ValueSetExpansionClient valueSetExpansionClient)
162+
ValidationPackageManager packageManager, List<ValidationPackageIdentifier> validationPackageIdentifiers,
163+
Output output, boolean outputPretty, ValueSetExpansionClient valueSetExpansionClient)
148164
{
149165
this.environment = environment;
150166
this.fhirContext = fhirContext;
151167
this.packageManager = packageManager;
152-
this.validationPackage = validationPackage;
168+
if (validationPackageIdentifiers != null)
169+
this.validationPackageIdentifiers.addAll(validationPackageIdentifiers);
153170
this.output = output;
154171
this.outputPretty = outputPretty;
155172
this.valueSetExpansionClient = valueSetExpansionClient;
@@ -161,18 +178,16 @@ public void afterPropertiesSet() throws Exception
161178
Objects.requireNonNull(environment, "environment");
162179
Objects.requireNonNull(fhirContext, "fhirContext");
163180
Objects.requireNonNull(packageManager, "packageManager");
164-
Objects.requireNonNull(validationPackage, "validationPackage");
165181
Objects.requireNonNull(output, "output");
166182
Objects.requireNonNull(valueSetExpansionClient, "valueSetExpansionClient");
167183
}
168184

169185
public void validate(String[] files)
170186
{
171-
logger.info("Using validation package {}", validationPackage);
187+
logger.info("Using validation packages {}", validationPackageIdentifiers);
172188
getAllNumProperties().forEach(c -> logger.debug("Config: {}", c));
173189

174-
BundleValidator validator = packageManager.createBundleValidator(validationPackage.getName(),
175-
validationPackage.getVersion());
190+
BundleValidator validator = packageManager.createBundleValidator(validationPackageIdentifiers);
176191

177192
Arrays.stream(files).map(this::read).filter(r -> r != null).forEach(r ->
178193
{

codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/validation/ValidationPackageManager.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,4 +148,16 @@ default BundleValidator createBundleValidator(String name, String version)
148148
* @return {@link BundleValidator} for the specified FHIR package
149149
*/
150150
BundleValidator createBundleValidator(ValidationPackageIdentifier identifier);
151+
152+
/**
153+
* Downloads the given FHIR packages and all its dependencies. Will try to generate snapshots for all
154+
* {@link StructureDefinition}s of the specified (root) package and its dependencies, will try to expand all
155+
* {@link ValueSet}s with binding strength {@link BindingStrength#EXTENSIBLE}, {@link BindingStrength#PREFERRED} or
156+
* {@link BindingStrength#REQUIRED} used by the {@link StructureDefinition} of the specified (root) package or their
157+
* dependencies, before returning a {@link IValidationSupport}.
158+
*
159+
* @param identifiers
160+
* @return {@link BundleValidator} for the specified FHIR packages
161+
*/
162+
BundleValidator createBundleValidator(List<ValidationPackageIdentifier> identifiers);
151163
}

codex-process-data-transfer/src/main/java/de/netzwerk_universitaetsmedizin/codex/processes/data_transfer/validation/ValidationPackageManagerImpl.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,17 @@ public BundleValidator createBundleValidator(IValidationSupport validationSuppor
170170
return validator;
171171
}
172172

173+
@Override
174+
public BundleValidator createBundleValidator(List<ValidationPackageIdentifier> identifiers)
175+
{
176+
Objects.requireNonNull(identifiers, "identifiers");
177+
178+
List<ValidationPackageWithDepedencies> packageWithDependencies = downloadPackagesWithDependencies(identifiers);
179+
IValidationSupport validationSupport = expandValueSetsAndGenerateStructureDefinitionSnapshots(
180+
packageWithDependencies);
181+
return createBundleValidator(validationSupport, packageWithDependencies);
182+
}
183+
173184
@Override
174185
public BundleValidator createBundleValidator(ValidationPackageIdentifier identifier)
175186
{
@@ -409,7 +420,11 @@ private ValidationSupportChain createSupportChain(FhirContext context,
409420
getAll(ValidationPackageWithDepedencies::getAllStructureDefinitions, packagesWithDependencies),
410421
getAll(ValidationPackageWithDepedencies::getAllCodeSystems, packagesWithDependencies),
411422
getAll(ValidationPackageWithDepedencies::getAllValueSets, packagesWithDependencies)),
412-
new DefaultProfileValidationSupport(context), new QuietCommonCodeSystemsTerminologyService(context));
423+
new DefaultProfileValidationSupport(context), new QuietCommonCodeSystemsTerminologyService(context),
424+
// TODO remove NonValidatingValidationSupport
425+
new NonValidatingValidationSupport(context, "http://fhir.de/CodeSystem/bfarm/icd-10-gm",
426+
"http://fhir.de/CodeSystem/dimdi/icd-10-gm", "http://fhir.de/CodeSystem/bfarm/ops",
427+
"http://fhir.de/CodeSystem/dimdi/ops", "http://fhir.de/CodeSystem/ifa/pzn"));
413428
}
414429

415430
private <V> List<V> getAll(Function<ValidationPackageWithDepedencies, List<V>> mapper,

0 commit comments

Comments
 (0)