From a783fd711fd2e4ba6b2d77ddd8d86a5743dbde67 Mon Sep 17 00:00:00 2001 From: c-schuler Date: Tue, 7 Apr 2026 09:10:26 -0600 Subject: [PATCH] Deduplicate logicDefinition extensions on the moduleDefinitionLibrary --- .../measure/MeasureRefreshProcessor.java | 26 +++++++++++++++++++ .../cqf/tooling/operation/ig/Refresh.java | 20 ++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/tooling/src/main/java/org/opencds/cqf/tooling/measure/MeasureRefreshProcessor.java b/tooling/src/main/java/org/opencds/cqf/tooling/measure/MeasureRefreshProcessor.java index d0b1e2ae8..64fd01920 100644 --- a/tooling/src/main/java/org/opencds/cqf/tooling/measure/MeasureRefreshProcessor.java +++ b/tooling/src/main/java/org/opencds/cqf/tooling/measure/MeasureRefreshProcessor.java @@ -20,6 +20,7 @@ import org.hl7.fhir.r5.model.RelatedArtifact; import org.hl7.fhir.r5.model.Resource; import org.hl7.fhir.r5.model.StringType; +import org.opencds.cqf.tooling.utilities.constants.CqfConstants; import org.opencds.cqf.tooling.utilities.constants.CrmiConstants; public class MeasureRefreshProcessor { @@ -39,6 +40,7 @@ public Measure refreshMeasure(Measure measureToUse, LibraryManager libraryManage Library moduleDefinitionLibrary = getModuleDefinitionLibrary(measureToUse, libraryManager, compiledLibrary, options); removeModelInfoDependencies(moduleDefinitionLibrary); + deduplicateLogicDefinitions(moduleDefinitionLibrary); measureToUse.setDate(new Date()); // http://hl7.org/fhir/us/cqfmeasures/StructureDefinition/measure-cqfm setMeta(measureToUse, moduleDefinitionLibrary); @@ -102,6 +104,30 @@ private Set getExpressions(Measure measureToUse) { return expressionSet; } + private void deduplicateLogicDefinitions(Library moduleDefinitionLibrary) { + Set seen = new HashSet<>(); + moduleDefinitionLibrary.getExtension().removeIf(ext -> { + if (ext.hasUrl() && ext.getUrl().equals(CqfConstants.LOGIC_DEFINITION_EXT_URL)) { + String key = getLogicDefinitionKey(ext); + return key != null && !seen.add(key); + } + return false; + }); + } + + private String getLogicDefinitionKey(Extension logicDefinition) { + String libraryName = null; + String name = null; + for (Extension sub : logicDefinition.getExtension()) { + if ("libraryName".equals(sub.getUrl()) && sub.hasValue()) { + libraryName = sub.getValue().primitiveValue(); + } else if ("name".equals(sub.getUrl()) && sub.hasValue()) { + name = sub.getValue().primitiveValue(); + } + } + return (libraryName != null && name != null) ? libraryName + "|" + name : null; + } + private void clearMeasureExtensions(Measure measure, String extensionUrl) { List extensionsToRemove = measure.getExtensionsByUrl(extensionUrl); measure.getExtension().removeAll(extensionsToRemove); diff --git a/tooling/src/main/java/org/opencds/cqf/tooling/operation/ig/Refresh.java b/tooling/src/main/java/org/opencds/cqf/tooling/operation/ig/Refresh.java index 74d75ce35..a0faf1f72 100644 --- a/tooling/src/main/java/org/opencds/cqf/tooling/operation/ig/Refresh.java +++ b/tooling/src/main/java/org/opencds/cqf/tooling/operation/ig/Refresh.java @@ -66,14 +66,34 @@ public void refreshCqfmExtensions(MetadataResource resource, Library moduleDefin resource.getExtension().removeAll(resource.getExtensionsByUrl(CqfmConstants.LOGIC_DEFINITION_EXT_URL)); resource.getExtension().removeAll(resource.getExtensionsByUrl(CqfmConstants.EFFECTIVE_DATA_REQS_EXT_URL)); + Set logicDefinitionKeys = new HashSet<>(); for (Extension extension : moduleDefinitionLibrary.getExtension()) { if (extension.hasUrl() && extension.getUrl().equals(CqfmConstants.DIRECT_REF_CODE_EXT_URL)) { continue; } + if (extension.hasUrl() && extension.getUrl().equals(CqfmConstants.LOGIC_DEFINITION_EXT_URL)) { + String key = getLogicDefinitionKey(extension); + if (key != null && !logicDefinitionKeys.add(key)) { + continue; + } + } resource.addExtension(extension); } } + private String getLogicDefinitionKey(Extension logicDefinition) { + String libraryName = null; + String name = null; + for (Extension sub : logicDefinition.getExtension()) { + if ("libraryName".equals(sub.getUrl()) && sub.hasValue()) { + libraryName = sub.getValue().primitiveValue(); + } else if ("name".equals(sub.getUrl()) && sub.hasValue()) { + name = sub.getValue().primitiveValue(); + } + } + return (libraryName != null && name != null) ? libraryName + "|" + name : null; + } + public void attachModuleDefinitionLibrary(MetadataResource resource, Library moduleDefinitionLibrary) { resource.getContained().removeIf(res -> res.getId() .equalsIgnoreCase("#" + CrmiConstants.EFFECTIVE_DATA_REQUIREMENTS_IDENTIFIER));