Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions docs/changelog.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
2025 Release 4.0.16
2026/01/08 Release 4.0.16

- adapt test and map for (440)
- adapt test and map for (#440)
- update org.hl7.fhir.core 6.7.10 (#448)
- support validating CodeableConcept in internal tx (448)
- support validating CodeableConcept in internal tx (#448)
- FHIR R4 validation error with R5 extension (#424)
- Fix THO loading: Unknown code '26' in the CodeSystem 'http://terminology.hl7.org/CodeSystem/object-role' version '4.0.1' (#452)
- Remove auto install ig's (did not handle -ballot versions)
- Use hl7.terminology#7.0.1 as FHIR Java validator 6.7.10 is doing (#452)

NOTE: Remove in your installation existing classpath entries for hl7.terminology#x.x.x in application.yaml

2025/11/03 Release 4.0.15

Expand Down
2 changes: 1 addition & 1 deletion jmeter/test.http
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ Content-Type: application/fhir+json
{
"attachment" : {
"language" : "de-CH"
^ }
}
}
]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,10 @@
public class MatchboxEngine extends ValidationEngine {

// Current packages that are provided with Matchbox Engine
public static final String PACKAGE_R4_TERMINOLOGY = "hl7.terminology.r4#6.3.0";
public static final String PACKAGE_R5_TERMINOLOGY = "hl7.terminology.r5#6.3.0";
public static final String PACKAGE_R4_TERMINOLOGY = "hl7.terminology.r4#7.0.1";
public static final String PACKAGE_R5_TERMINOLOGY = "hl7.terminology.r5#7.0.1";
public static final String PACKAGE_R4_TERMINOLOGY63 = "hl7.terminology.r4#6.3.0";
public static final String PACKAGE_R5_TERMINOLOGY63 = "hl7.terminology.r5#6.3.0";
public static final String PACKAGE_R4_TERMINOLOGY65 = "hl7.terminology.r4#6.5.0";
public static final String PACKAGE_R5_TERMINOLOGY65 = "hl7.terminology.r5#6.5.0";
public static final String PACKAGE_R4_UV_EXTENSIONS = "hl7.fhir.uv.extensions.r4#5.2.0";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,9 @@ public int compare(T arg1, T arg2) {
protected ContextUtilities cutils;
private List<String> suppressedMappings;

// matchbox patch https://github.com/ahdis/matchbox/issues/425
private Locale locale;

protected BaseWorkerContext() throws FileNotFoundException, IOException, FHIRException {
setValidationMessageLanguage(getLocale());
clock = new TimeTracker();
Expand Down Expand Up @@ -437,6 +440,7 @@ protected void copy(BaseWorkerContext other) {
cachingAllowed = other.cachingAllowed;
suppressedMappings = other.suppressedMappings;
cutils.setSuppressedMappings(other.suppressedMappings);
locale = other.locale; // matchbox patch https://github.com/ahdis/matchbox/issues/425
}
}

Expand Down Expand Up @@ -613,18 +617,21 @@ public void cacheResourceFromPackage(Resource r, PackageInformation packageInfo)
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)
// matchbox patch for duplicate resources, see https://github.com/ahdis/matchbox/issues/227 and issues/452
CanonicalResource ex = fetchResourceWithException(m.fhirType(), url);
if (ex.getVersion() != null && m.getVersion() != null && laterVersion(m.getVersion(), ex.getVersion())) {
boolean forceDrop = false;
if (url.startsWith("http://terminology.hl7.org/") && ex.getVersion()!=null && ex.getSourcePackage()!=null && ex.getVersion().equals(ex.getSourcePackage().getVersion()) ) {
forceDrop = true;
}
if (forceDrop || (ex.getVersion() != null && m.getVersion() != null && laterVersion(m.getVersion(), ex.getVersion()))) {
logger.logDebugMessage(LogCategory.INIT,
"Note replacing old version: "
"Note replacing existing version (is older): "
+ formatMessage(I18nConstants.DUPLICATE_RESOURCE_, url,
m.getVersion(), ex.getVersion(), ex.fhirType()));
m.getVersion(), ex.getVersion(), ex.fhirType()) + (forceDrop ? "forced" : ""));
dropResource(ex);
} else {
logger.logDebugMessage(LogCategory.INIT,
"Note keeping newer version: "
"Note keeping existing version (is newer): "
+ formatMessage(I18nConstants.DUPLICATE_RESOURCE_,
url,
m.getVersion(),
Expand Down Expand Up @@ -3779,7 +3786,23 @@ public <T extends Resource> List<T> fetchResourceVersions(Class<T> class_, Strin
}

public void setLocale(Locale locale) {
super.setLocale(locale);
// matchbox patch https://github.com/ahdis/matchbox/issues/425
if (this.locale == null) {
this.locale = locale;
super.setLocale(locale);
} else {
if (!this.locale.equals(locale)) {
this.locale = locale;
super.setLocale(locale);
if (locale != null) {
log.info("changing locale to" + locale.toLanguageTag());
} else {
log.info("resetting locale");
}
}
}
// END matchbox patch

if (locale == null) {
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -360,9 +360,7 @@ protected InputStreamWithSrc loadFromPackageServer(String id, String version) {
String packageName = id + "#" + version;
switch (packageName) {
case MatchboxEngine.PACKAGE_R4_TERMINOLOGY:
case MatchboxEngine.PACKAGE_R4_TERMINOLOGY65:
case MatchboxEngine.PACKAGE_R5_TERMINOLOGY:
case MatchboxEngine.PACKAGE_R5_TERMINOLOGY65:
case MatchboxEngine.PACKAGE_R4_UV_EXTENSIONS:
case MatchboxEngine.PACKAGE_R5_UV_EXTENSIONS:
ourLog.info("loading from classpath "+id);
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -179,14 +179,19 @@ public void loadIg(List<ImplementationGuide> igs, Map<String, ByteProvider> bina

switch (FhirVersionEnum.forVersionString(this.getVersion())) {
case R4, R4B -> {
if (src.startsWith("hl7.terminology#6.5.0")) {
if (src.startsWith("hl7.terminology#7.0.1")) {
log.info("Requesting to load '{}', loading '{}' instead'", src, PACKAGE_R4_TERMINOLOGY);
loadIg(igs, binaries, PACKAGE_R4_TERMINOLOGY, recursive);
return;
}
if (src.startsWith("hl7.terminology#6.5.0")) {
log.info("Requesting to load '{}', loading '{}' instead'", src, PACKAGE_R4_TERMINOLOGY65);
loadIg(igs, binaries, PACKAGE_R4_TERMINOLOGY65, recursive);
return;
}
if (src.startsWith("hl7.terminology#6.3.0")) {
log.info("Requesting to load '{}', loading '{}' instead'", src, PACKAGE_R4_TERMINOLOGY);
loadIg(igs, binaries, PACKAGE_R4_TERMINOLOGY, recursive);
log.info("Requesting to load '{}', loading '{}' instead'", src, PACKAGE_R4_TERMINOLOGY63);
loadIg(igs, binaries, PACKAGE_R4_TERMINOLOGY63, recursive);
return;
}
if (src.startsWith("hl7.fhir.uv.extensions#5.2.0")) {
Expand All @@ -196,14 +201,19 @@ public void loadIg(List<ImplementationGuide> igs, Map<String, ByteProvider> bina
}
}
case R5 -> {
if (src.startsWith("hl7.terminology#7.0.1")) {
log.info("Requesting to load '{}', loading '{}' instead'", src, PACKAGE_R5_TERMINOLOGY);
loadIg(igs, binaries, PACKAGE_R5_TERMINOLOGY, recursive);
return;
}
if (src.startsWith("hl7.terminology#6.5.0")) {
log.info("Requesting to load '{}', loading from classpath '{}' instead'", src, PACKAGE_R5_TERMINOLOGY);
log.info("Requesting to load '{}', loading from classpath '{}' instead'", src, PACKAGE_R5_TERMINOLOGY65);
loadIg(igs, binaries, PACKAGE_R5_TERMINOLOGY65, recursive);
return;
}
if (src.startsWith("hl7.terminology#6.3.0")) {
log.info("Requesting to load '{}', loading from classpath '{}' instead'", src, PACKAGE_R5_TERMINOLOGY);
loadIg(igs, binaries, PACKAGE_R5_TERMINOLOGY, recursive);
log.info("Requesting to load '{}', loading from classpath '{}' instead'", src, PACKAGE_R5_TERMINOLOGY63);
loadIg(igs, binaries, PACKAGE_R5_TERMINOLOGY63, recursive);
return;
}
if (src.startsWith("hl7.fhir.uv.extensions#5.2.0")) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,11 +166,6 @@ public IBaseResource validate(final HttpServletRequest theRequest) {
}
}

// Check if the IG should be auto-installed
if (!cliContext.isHttpReadOnly()) {
this.ensureIgIsInstalled(theRequest.getParameter("ig"), theRequest.getParameter("profile"));
}

if (theRequest.getParameter("profile") == null) {
return this.getOoForError("The 'profile' parameter must be provided");
}
Expand Down Expand Up @@ -389,89 +384,6 @@ private IBaseResource getOoForError(final @NonNull String message) {
return VersionConvertorFactory_40_50.convertResource(oo);
}

private void ensureIgIsInstalled(@Nullable final String ig,
final String profile) {
if (ig != null) {
// Easy case, the IG is known
final var parts = ig.split("#");
if (!this.igProvider.has(parts[0], parts[1])) {
log.debug("Auto-installing the IG '{}' version '{}'", parts[0], parts[1]);
this.igProvider.installFromInternetRegistry(parts[0], parts[1]);
}
return;
}

if (profile.startsWith("http://hl7.org/fhir/")) {
log.debug("Profile '{}' is a core FHIR profile, no need to install an IG", profile);
return;
}

// Harder case, only the profile is known
final var parts = profile.split("\\|");
final String canonical;
final String version;
if (parts.length == 2) {
final Boolean found = new TransactionTemplate(this.myTxManager)
.execute(tx -> this.myPackageVersionResourceDao.getPackageVersionByCanonicalAndVersion(parts[0], parts[1]).isPresent());
if (found != null && found) {
// The profile was found in the database, the IG is installed
return;
}
canonical = parts[0];
version = parts[1];
} else {
canonical = profile;
version = null;
}

// The profile was not found in the database, we need to search for the IG that contains it
final var gson = new Gson();
final var igSearchUrl =
"https://packages.simplifier.net/catalog?canonical=%s&prerelease=false".formatted(URLEncoder.encode(canonical, StandardCharsets.UTF_8));
final SimplifierPackage[] packages;
try (final CloseableHttpClient httpclient = HttpClients.createDefault()) {
final var httpget = new HttpGet(igSearchUrl);
packages = httpclient.execute(httpget, response ->
gson.fromJson(new InputStreamReader(response.getEntity().getContent()), SimplifierPackage[].class));
} catch (final Exception e) {
log.error("Error while searching for IGs", e);
return;
}

if (packages == null || packages.length == 0) {
return;
}
log.debug("Found {} IGs for profile '{}', checking the first one ('{}')", packages.length, profile,
packages[0].getName());
if (version != null) {
// This might not be always true, but it's a good heuristic: let's use the profile version as the IG version
this.igProvider.installFromInternetRegistry(packages[0].getName(), version);
return;
}
// We have to search for the latest profile version
final var versionSearchUrl = "https://packages.simplifier.net/" + packages[0].getName();
final SimplifierPackageVersionsObject versionsObject;
try (final CloseableHttpClient httpclient = HttpClients.createDefault()) {
final var httpget = new HttpGet(versionSearchUrl);
versionsObject = httpclient.execute(httpget, response ->
gson.fromJson(new InputStreamReader(response.getEntity().getContent()), SimplifierPackageVersionsObject.class));
} catch (final Exception e) {
log.error("Error while searching for IG versions", e);
return;
}

if (versionsObject == null || versionsObject.getVersions() == null || versionsObject.getVersions().isEmpty()) {
return;
}

final var latestVersion = versionsObject.getVersions().keySet().toArray()[ versionsObject.getVersions().size()-1].toString();
try {
this.igProvider.installFromInternetRegistry(packages[0].getName(), latestVersion);
} catch (final Exception e) {
log.error("Error while installing IG version", e);
}
}

public static List<ValidationMessage> doValidate(final MatchboxEngine engine,
String content,
final EncodingEnum encoding,
Expand Down
8 changes: 0 additions & 8 deletions matchbox-server/src/main/resources/application.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -73,14 +73,6 @@ hapi:
# name: hl7.fhir.r4.core
# version: 4.0.1
# url: classpath:/hl7.fhir.r4.core.tgz
# fhir_extensions:
# name: hl7.fhir.uv.extensions.r4
# version: 5.2.0
# url: classpath:/hl7.fhir.uv.extensions.r4#5.2.0.tgz
# fhir_terminology:
# name: hl7.terminology.r4
# version: 6.3.0
# url: classpath:/hl7.terminology.r4#6.3.0.tgz
# ch-core:
# name: ch.fhir.ig.ch-core
# version: 4.0.0-ballot
Expand Down
8 changes: 0 additions & 8 deletions matchbox-server/src/test/resources/application-test-r4.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,6 @@ hapi:
name: hl7.fhir.r4.core
version: 4.0.1
url: classpath:/hl7.fhir.r4.core.tgz
fhir_extensions:
name: hl7.fhir.uv.extensions.r4
version: 5.2.0
url: classpath:/hl7.fhir.uv.extensions.r4#5.2.0.tgz
fhir_terminology:
name: hl7.terminology.r4
version: 6.5.0
url: classpath:/hl7.terminology.r4#6.5.0.tgz
matchbox_health_test_ig_r4:
name: matchbox.health.test.ig.r4
version: 0.2.0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,6 @@ hapi:
name: hl7.fhir.r4.core
version: 4.0.1
url: classpath:/hl7.fhir.r4.core.tgz
fhir_extensions:
name: hl7.fhir.uv.extensions.r4
version: 5.2.0
url: classpath:/hl7.fhir.uv.extensions.r4#5.2.0.tgz
fhir_terminology:
name: hl7.terminology.r4
version: 6.5.0
url: classpath:/hl7.terminology.r4#6.5.0.tgz
fhir_r5_core:
name: hl7.fhir.r5.core
version: 5.0.0
Expand Down
8 changes: 0 additions & 8 deletions matchbox-server/with-alis/application.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,6 @@ hapi:
name: hl7.fhir.r4.core
version: 4.0.1
url: classpath:/hl7.fhir.r4.core.tgz
fhir_extensions:
name: hl7.fhir.uv.extensions.r4
version: 5.2.0
url: classpath:/hl7.fhir.uv.extensions.r4#5.2.0.tgz
fhir_terminology:
name: hl7.terminology.r4
version: 6.3.0
url: classpath:/hl7.terminology.r4#6.3.0.tgz
hl7_fhir_uv_ips:
name: ch.fhir.ig.ch-alis
version: 0.3.0-draft
Expand Down
8 changes: 0 additions & 8 deletions matchbox-server/with-ans/application.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,6 @@ hapi:
name: hl7.fhir.r4.core
version: 4.0.1
url: classpath:/hl7.fhir.r4.core.tgz
fhir_extensions:
name: hl7.fhir.uv.extensions.r4
version: 5.2.0
url: classpath:/hl7.fhir.uv.extensions.r4#5.2.0.tgz
fhir_terminology:
name: hl7.terminology.r4
version: 6.3.0
url: classpath:/hl7.terminology.r4#6.3.0.tgz
ans_fr_tddui:
name: ans.fhir.fr.tddui
version: 2.1.0-ballot
Expand Down
8 changes: 0 additions & 8 deletions matchbox-server/with-ca/application.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,6 @@ hapi:
name: hl7.fhir.r4.core
version: 4.0.1
url: classpath:/hl7.fhir.r4.core.tgz
fhir_extensions:
name: hl7.fhir.uv.extensions.r4
version: 5.2.0
url: classpath:/hl7.fhir.uv.extensions.r4#5.2.0.tgz
fhir_terminology:
name: hl7.terminology.r4
version: 6.3.0
url: classpath:/hl7.terminology.r4#6.3.0.tgz
cda:
name: ca.infoway.io.psca
version: 2.0.0-DFT-Ballot
Expand Down
8 changes: 0 additions & 8 deletions matchbox-server/with-cda-r5/application.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,6 @@ hapi:
name: hl7.fhir.r5.core
version: 5.0.0
url: classpath:/hl7.fhir.r5.core.tgz
fhir_extensions:
name: hl7.fhir.uv.extensions.r5
version: 5.2.0
url: classpath:/hl7.fhir.uv.extensions.r5#5.2.0.tgz
fhir_terminology:
name: hl7.terminology.r5
version: 6.3.0
url: classpath:/hl7.terminology.r5#6.3.0.tgz
cda:
name: hl7.cda.uv.core
version: 2.0.1-sd-202510-matchbox-patch
Expand Down
8 changes: 0 additions & 8 deletions matchbox-server/with-cda/application.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,6 @@ hapi:
name: hl7.fhir.r4.core
version: 4.0.1
url: classpath:/hl7.fhir.r4.core.tgz
fhir_extensions:
name: hl7.fhir.uv.extensions.r4
version: 5.2.0
url: classpath:/hl7.fhir.uv.extensions.r4#5.2.0.tgz
fhir_terminology:
name: hl7.terminology.r4
version: 6.3.0
url: classpath:/hl7.terminology.r4#6.3.0.tgz
cda:
name: hl7.cda.uv.core
version: 2.0.1-sd-202510-matchbox-patch
Expand Down
4 changes: 3 additions & 1 deletion matchbox-server/with-ch/application.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ hapi:
ch-core:
name: ch.fhir.ig.ch-core
version: 6.0.0
url: https://fhir.ch/ig/ch-core/package.tgz
ch-epr-fhir:
name: ch.fhir.ig.ch-epr-fhir
version: 5.0.0
matchbox:
fhir:
context:
Expand Down
Loading
Loading