diff --git a/.vscode/launch.json b/.vscode/launch.json
index 9da8ef4d0c2..4d06bd3d9ea 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -84,6 +84,15 @@
"projectName": "matchbox-server",
"vmArgs": "-Dspring.config.additional-location=file:/Users/oegger/Documents/github/matchbox/matchbox-server/target/test-classes/application-test-r5onr4.yaml",
"cwd": "${workspaceFolder}/matchbox-server"
+ },
+ {
+ "type": "java",
+ "name": "Launch Matchbox-Server (alis)",
+ "request": "launch",
+ "mainClass": "ca.uhn.fhir.jpa.starter.Application",
+ "projectName": "matchbox-server",
+ "vmArgs": "-Dspring.config.additional-location=file:with-alis/application.yaml",
+ "cwd": "${workspaceFolder}/matchbox-server"
}, {
"type": "java",
"name": "Launch Matchbox-Server",
diff --git a/docs/changelog.md b/docs/changelog.md
index 4ce020f13e4..9e2ec9db7d6 100644
--- a/docs/changelog.md
+++ b/docs/changelog.md
@@ -1,7 +1,8 @@
-2024/04/xx Release 3.8.3
+2024/04/29 Release 3.8.3
- profile validation with different ig version issues, GUI & EVS Client [#225](https://github.com/ahdis/matchbox/issues/225)
- improved the profile selection in the validation GUI
+- FML: Side effect exception when updating a StructureMap [#227](https://github.com/ahdis/matchbox/issues/227)
2024/04/22 Release 3.8.2
diff --git a/matchbox-engine/pom.xml b/matchbox-engine/pom.xml
index 85740e686b1..5bec77cae43 100644
--- a/matchbox-engine/pom.xml
+++ b/matchbox-engine/pom.xml
@@ -6,7 +6,7 @@
matchbox
health.matchbox
- 3.8.2
+ 3.8.3
matchbox-engine
diff --git a/matchbox-engine/src/main/java/ch/ahdis/matchbox/engine/MatchboxEngine.java b/matchbox-engine/src/main/java/ch/ahdis/matchbox/engine/MatchboxEngine.java
index c7b103d6671..4d6ac33c7c8 100644
--- a/matchbox-engine/src/main/java/ch/ahdis/matchbox/engine/MatchboxEngine.java
+++ b/matchbox-engine/src/main/java/ch/ahdis/matchbox/engine/MatchboxEngine.java
@@ -254,6 +254,7 @@ public MatchboxEngine getEngine() throws MatchboxEngineCreationException {
try { engine = new MatchboxEngine(this.fromNothing()); }
catch (final IOException e) { throw new MatchboxEngineCreationException(e); }
engine.setVersion(this.fhirVersion.toCode());
+ engine.getContext().setAllowLoadingDuplicates(false);
if (this.txServer == null) {
engine.getContext().setCanRunWithoutTerminology(true);
engine.getContext().setNoTerminologyServer(true);
diff --git a/matchbox-engine/src/main/java/org/hl7/fhir/r5/context/BaseWorkerContext.java b/matchbox-engine/src/main/java/org/hl7/fhir/r5/context/BaseWorkerContext.java
index 0cf36a66298..abd689b449b 100644
--- a/matchbox-engine/src/main/java/org/hl7/fhir/r5/context/BaseWorkerContext.java
+++ b/matchbox-engine/src/main/java/org/hl7/fhir/r5/context/BaseWorkerContext.java
@@ -56,6 +56,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWIS
import org.hl7.fhir.exceptions.DefinitionException;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.exceptions.TerminologyServiceException;
+import org.hl7.fhir.r5.comparison.VersionComparisonAnnotation;
import org.hl7.fhir.r5.conformance.profile.ProfileUtilities;
import org.hl7.fhir.r5.context.CanonicalResourceManager.CanonicalResourceProxy;
import org.hl7.fhir.r5.context.ILoggingService.LogCategory;
@@ -383,9 +384,16 @@ public void registerResourceFromPackage(CanonicalResourceProxy r, PackageInforma
if (Utilities.existsInList(url, "http://hl7.org/fhir/SearchParameter/example")) {
return;
}
+ // matchbox patch for duplicate resources, see https://github.com/ahdis/matchbox/issues/227
+ // org.hl7.fhir.r5.conformance.R5ExtensionsLoader.loadR5SpecialTypes(R5ExtensionsLoader.java:141)
CanonicalResource ex = fetchResourceWithException(r.getType(), url);
- throw new DefinitionException(formatMessage(I18nConstants.DUPLICATE_RESOURCE_, url, r.getVersion(), ex.getVersion(),
- ex.fhirType()));
+ if (laterVersion(r.getVersion(), ex.getVersion())) {
+ logger.logMessage("Note replacing old version: " + formatMessage(I18nConstants.DUPLICATE_RESOURCE_, url, r.getVersion(), ex.getVersion(), ex.fhirType()));
+ dropResource(ex);
+ } else {
+ logger.logMessage("Note keeping newer version: " + formatMessage(I18nConstants.DUPLICATE_RESOURCE_, url, r.getVersion(), ex.getVersion(), ex.fhirType()));
+ return;
+ }
}
switch(r.getType()) {
case "StructureDefinition":
@@ -508,9 +516,16 @@ public void cacheResourceFromPackage(Resource r, PackageInformation packageInfo)
if (Utilities.existsInList(url, "http://hl7.org/fhir/SearchParameter/example")) {
return;
}
- CanonicalResource ex = (CanonicalResource) fetchResourceWithException(r.getClass(), url);
- throw new DefinitionException(formatMessage(I18nConstants.DUPLICATE_RESOURCE_, url, ((CanonicalResource) r).getVersion(), ex.getVersion(),
- ex.fhirType()));
+ // matchbox patch for duplicate resources, see https://github.com/ahdis/matchbox/issues/227
+ // org.hl7.fhir.r5.conformance.R5ExtensionsLoader.loadR5SpecialTypes(R5ExtensionsLoader.java:141)
+ CanonicalResource ex = fetchResourceWithException(m.fhirType(), url);
+ if (laterVersion(m.getVersion(), ex.getVersion())) {
+ logger.logMessage("Note replacing old version: " + formatMessage(I18nConstants.DUPLICATE_RESOURCE_, url, m.getVersion(), ex.getVersion(), ex.fhirType()));
+ dropResource(ex);
+ } else {
+ logger.logMessage("Note keeping newer version: " + formatMessage(I18nConstants.DUPLICATE_RESOURCE_, url, m.getVersion(), ex.getVersion(), ex.fhirType()));
+ return;
+ }
}
if (r instanceof StructureDefinition) {
StructureDefinition sd = (StructureDefinition) m;
diff --git a/matchbox-frontend/package.json b/matchbox-frontend/package.json
index ce00e5e8bf7..e496aaf3763 100644
--- a/matchbox-frontend/package.json
+++ b/matchbox-frontend/package.json
@@ -1,6 +1,6 @@
{
"name": "matchbox",
- "version": "3.8.2",
+ "version": "3.8.3",
"license": "MIT",
"scripts": {
"ng": "ng",
diff --git a/matchbox-server/pom.xml b/matchbox-server/pom.xml
index 3f797a454f3..deedfb8dbc3 100644
--- a/matchbox-server/pom.xml
+++ b/matchbox-server/pom.xml
@@ -5,7 +5,7 @@
matchbox
health.matchbox
- 3.8.2
+ 3.8.3
matchbox-server
diff --git a/matchbox-server/src/main/java/ch/ahdis/matchbox/ConformancePackageResourceProvider.java b/matchbox-server/src/main/java/ch/ahdis/matchbox/ConformancePackageResourceProvider.java
index 7a6b2a40d2b..22073f05a73 100644
--- a/matchbox-server/src/main/java/ch/ahdis/matchbox/ConformancePackageResourceProvider.java
+++ b/matchbox-server/src/main/java/ch/ahdis/matchbox/ConformancePackageResourceProvider.java
@@ -179,10 +179,12 @@ public ca.uhn.fhir.rest.api.server.IBundleProvider search(jakarta.servlet.http.H
if (theUrl != null) {
String url = theUrl.getValuesAsQueryTokens().get(0).getValuesAsQueryTokens().get(0).getValue();
R5 r = matchboxEngine.getContext().fetchResource(classR5,url);
- resources.add(r);
+ if (r != null)
+ resources.add(r);
} else {
resources.addAll(matchboxEngine.getContext().fetchResourcesByType(classR5));
}
+
switch (getFhirVersion(this.cliContext.getFhirVersion())) {
case "4.0.1": return new SimpleBundleProvider(
resources.stream().map(VersionConvertorFactory_40_50::convertResource).collect(Collectors.toList()));
diff --git a/matchbox-server/src/main/java/ch/ahdis/matchbox/IgLoaderFromJpaPackageCache.java b/matchbox-server/src/main/java/ch/ahdis/matchbox/IgLoaderFromJpaPackageCache.java
index 6592521dddc..aff4746495c 100644
--- a/matchbox-server/src/main/java/ch/ahdis/matchbox/IgLoaderFromJpaPackageCache.java
+++ b/matchbox-server/src/main/java/ch/ahdis/matchbox/IgLoaderFromJpaPackageCache.java
@@ -34,9 +34,11 @@
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_30_50;
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_40_50;
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_43_50;
+import org.hl7.fhir.r4.model.ConceptMap.ConceptMapGroupComponent;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.instance.model.api.IBaseBinary;
import org.hl7.fhir.r5.context.SimpleWorkerContext;
+import org.hl7.fhir.r5.model.CanonicalResource;
import org.hl7.fhir.r5.model.ImplementationGuide;
import org.hl7.fhir.r5.model.Resource;
import org.hl7.fhir.utilities.ByteProvider;
@@ -104,6 +106,42 @@ public FhirContext getFhirContext(FhirVersionEnum theFhirVersion) {
return myVersionToContext.computeIfAbsent(theFhirVersion, v -> new FhirContext(v));
}
+ private void cleanModifierExtensions(org.hl7.fhir.r5.model.ConceptMap r) {
+ for ( org.hl7.fhir.r5.model.ConceptMap.ConceptMapGroupComponent group :r.getGroup()) {
+ group.getElement().forEach(element -> {
+ element.getTarget().forEach(target -> {
+ target.getModifierExtension().clear();
+ });
+ });
+ }
+ }
+
+ private void cleanModifierExtensions(org.hl7.fhir.r5.model.StructureMap r) {
+ r.getContained().forEach(c -> {
+ if (c instanceof org.hl7.fhir.r5.model.ConceptMap) {
+ cleanModifierExtensions((org.hl7.fhir.r5.model.ConceptMap) c);
+ }
+ });
+ }
+
+ private void cleanModifierExtensions(org.hl7.fhir.r4.model.ConceptMap r) {
+ for ( ConceptMapGroupComponent group :r.getGroup()) {
+ group.getElement().forEach(element -> {
+ element.getTarget().forEach(target -> {
+ target.getModifierExtension().clear();
+ });
+ });
+ }
+ }
+
+ private void cleanModifierExtensions(org.hl7.fhir.r4.model.StructureMap r) {
+ r.getContained().forEach(c -> {
+ if (c instanceof org.hl7.fhir.r4.model.ConceptMap) {
+ cleanModifierExtensions((org.hl7.fhir.r4.model.ConceptMap) c);
+ }
+ });
+ }
+
private org.hl7.fhir.r5.model.Resource loadPackageEntity(NpmPackageVersionResourceEntity contents) {
try {
final var binary = MatchboxServerUtils.getBinaryFromId(contents.getResourceBinary().getId(), myDaoRegistry);
@@ -115,8 +153,12 @@ private org.hl7.fhir.r5.model.Resource loadPackageEntity(NpmPackageVersionResour
return VersionConvertorFactory_30_50
.convertResource(new org.hl7.fhir.dstu3.formats.JsonParser().parse(resourceContents));
case R4:
+ org.hl7.fhir.r4.model.Resource r = new org.hl7.fhir.r4.formats.JsonParser().parse(resourceContents);
+ if (r instanceof org.hl7.fhir.r4.model.StructureMap ) {
+ cleanModifierExtensions((org.hl7.fhir.r4.model.StructureMap) r);
+ }
return VersionConvertorFactory_40_50
- .convertResource(new org.hl7.fhir.r4.formats.JsonParser().parse(resourceContents));
+ .convertResource(r);
case R4B:
return VersionConvertorFactory_43_50
.convertResource(new org.hl7.fhir.r4b.formats.JsonParser().parse(resourceContents));
@@ -224,7 +266,24 @@ public void loadIg(List igs, Map bina
Resource r = null;
try {
r = loadResourceByVersion(npm.fhirVersion(), TextFile.streamToBytes(pi.load("package", s)), s);
- this.getContext().cacheResource(r);
+ // https://github.com/ahdis/matchbox/issues/227
+ if (r instanceof org.hl7.fhir.r5.model.StructureMap ) {
+ cleanModifierExtensions((org.hl7.fhir.r5.model.StructureMap) r);
+ }
+ if (r instanceof org.hl7.fhir.r5.model.ConceptMap ) {
+ cleanModifierExtensions((org.hl7.fhir.r5.model.ConceptMap) r);
+ }
+ if (r instanceof CanonicalResource) {
+ CanonicalResource m = (CanonicalResource) r;
+ String url = m.getUrl();
+ if (this.getContext().hasResource(r.getClass(), url)) {
+ log.error("Duplicate canonical resource: " + r.getClass().getName() + " from package " +pi.name() + "#" + pi.version() + " with url " + url);
+ } else {
+ this.getContext().cacheResource(r);
+ }
+ } else {
+ log.error("Resource is not a CanonicalResource: " + r.getClass().getName() + " from package " +pi.name() + "#" + pi.version());
+ }
} catch (FHIRException e) {
log.error(s, e);
} catch (IOException e) {
diff --git a/matchbox-server/with-alis/application.yaml b/matchbox-server/with-alis/application.yaml
new file mode 100644
index 00000000000..4cef2515f1d
--- /dev/null
+++ b/matchbox-server/with-alis/application.yaml
@@ -0,0 +1,33 @@
+server:
+ servlet:
+ context-path: /matchboxv3
+hapi:
+ fhir:
+ server_address: http://localhost:8080/matchboxv3/fhir
+ implementationguides:
+ fhir_r4_core:
+ name: hl7.fhir.r4.core
+ version: 4.0.1
+ url: classpath:/hl7.fhir.r4.core.tgz
+ fhir_terminology:
+ name: hl7.terminology
+ version: 5.4.0
+ url: classpath:/hl7.terminology#5.4.0.tgz
+ fhir_extensions:
+ name: hl7.fhir.uv.extensions.r4
+ version: 1.0.0
+ url: classpath:/hl7.fhir.uv.extensions.r4#1.0.0.tgz
+ hl7_fhir_uv_ips:
+ name: ch.fhir.ig.ch-alis
+ version: 0.2.0
+ url: file:/Users/oegger/Documents/github/ch-alis/output/package.tgz
+ staticLocation: file:/apps/
+matchbox:
+ fhir:
+ context:
+ fhirVersion: 4.0.1
+ txServer: http://tx.fhir.org
+ onlyOneEngine: true
+spring:
+ datasource:
+ url: "jdbc:h2:mem:test"
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 2dcd1e3fd85..014dc1548b1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -9,7 +9,7 @@
health.matchbox
matchbox
- 3.8.2
+ 3.8.3
pom
matchbox
An open-source implementation to support testing and implementation of FHIR based solutions and map or