Skip to content

Commit

Permalink
Versioning and NewRefreshIg Merge (#526)
Browse files Browse the repository at this point in the history
* Versioning and NewRefreshIg Merge

* Revert test

* Updating refresh TerserUtil usage to clear field before update

* Update

* Added test cases for external reference and Versioning

* Added test cases for external reference and Versioning 2

* Reduced test IG Size

* Reduced test IG Size and update location

* Removed use of Junit, replaced my TestNg Framework

* Using afterSuite instead of method

* Test update

* Fix paths

* Fix urls

---------

Co-authored-by: c-schuler <[email protected]>
Co-authored-by: JP <[email protected]>
  • Loading branch information
3 people authored May 3, 2024
1 parent 1f3a5c8 commit 2ca0172
Show file tree
Hide file tree
Showing 24 changed files with 4,869 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import org.hl7.fhir.utilities.npm.NpmPackage;
import org.opencds.cqf.tooling.npm.LibraryLoader;
import org.opencds.cqf.tooling.npm.NpmPackageManager;
import org.opencds.cqf.tooling.parameter.RefreshIGParameters;
import org.opencds.cqf.tooling.processor.CqlProcessor;
import org.opencds.cqf.tooling.utilities.CanonicalUtils;
import org.opencds.cqf.tooling.utilities.IOUtils;
Expand Down Expand Up @@ -48,9 +49,12 @@ public LibraryRefresh(IGInfo igInfo) {
Collections.singletonList(igInfo.getCqlBinaryPath()), libraryLoader, new IGLoggingService(logger), ucumService,
igInfo.getPackageId(), igInfo.getCanonical(), true);
}

@Override
public List<IBaseResource> refresh() {
return refresh(null);
}

public List<IBaseResource> refresh(RefreshIGParameters params) {
List<IBaseResource> refreshedLibraries = new ArrayList<>();
this.cqlProcessor.execute();
if (getIgInfo().isRefreshLibraries()) {
Expand All @@ -72,6 +76,7 @@ public List<IBaseResource> refresh() {
refreshDataRequirements(library, info);
refreshRelatedArtifacts(library, info);
refreshParameters(library, info);
refreshVersion(library, params);
refreshedLibraries.add(library);
this.libraryPackages.add(new LibraryPackage(library, getFhirContext(), info));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public void execute(String[] args) {
this.params = new RefreshIGArgumentProcessor().parseAndConvert(args);
IGInfo info = new IGInfo(null, params);
LibraryRefresh libraryRefresh = new LibraryRefresh(info);
publishLibraries(info, libraryRefresh.refresh());
publishLibraries(info, libraryRefresh.refresh(this.params));
PlanDefinitionRefresh planDefinitionRefresh = new PlanDefinitionRefresh(info, libraryRefresh.getCqlProcessor(), libraryRefresh.getLibraryPackages());
publishPlanDefinitions(info, planDefinitionRefresh.refresh());
if (!planDefinitionRefresh.getPlanDefinitionPackages().isEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import org.hl7.fhir.instance.model.api.IBaseBundle;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.r5.model.*;
import org.opencds.cqf.tooling.parameter.RefreshIGParameters;
import org.opencds.cqf.tooling.utilities.BundleUtils;
import org.opencds.cqf.tooling.utilities.constants.CqfmConstants;
import org.opencds.cqf.tooling.utilities.converters.ResourceAndTypeConverter;
Expand All @@ -29,10 +30,19 @@ public Refresh(IGInfo igInfo) {
public abstract List<IBaseResource> refresh();

public void refreshDate(IBaseResource resource) {
TerserUtil.clearField(getIgInfo().getFhirContext(), "date", resource);
TerserUtil.setField(getIgInfo().getFhirContext(), "date", resource,
ResourceAndTypeConverter.convertType(getFhirContext(), new DateTimeType(new Date())));
}

public void refreshVersion(IBaseResource resource, RefreshIGParameters params) {
if (params != null && params.updatedVersion != null && !params.updatedVersion.isEmpty()) {
TerserUtil.clearField(getIgInfo().getFhirContext(), "version", resource);
TerserUtil.setField(getIgInfo().getFhirContext(), "version", resource,
ResourceAndTypeConverter.convertType(getFhirContext(), new StringType(params.updatedVersion)));
}
}

public void validatePrimaryLibraryReference(IBaseResource resource) {
if ((resource instanceof PlanDefinition && !((PlanDefinition) resource).hasLibrary())
|| (resource instanceof Measure && !((Measure) resource).hasLibrary())) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,5 @@ public class RefreshIGParameters {
public String libraryOutputPath;
public String measureOutputPath;
public Boolean verboseMessaging;
public String updatedVersion;
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@


public class RefreshIGArgumentProcessor {
public static final String[] OPERATION_OPTIONS = {"RefreshIG"};
public static final String[] OPERATION_OPTIONS = {"RefreshIG", "NewRefreshIG"};
public static final String[] INI_OPTIONS = {"ini"};
public static final String[] ROOT_DIR_OPTIONS = {"root-dir", "rd"};
public static final String[] IG_PATH_OPTIONS = {"ip", "ig-path"};
Expand All @@ -28,6 +28,7 @@ public class RefreshIGArgumentProcessor {
public static final String[] INCLUDE_TERMINOLOGY_OPTIONS = {"t", "include-terminology"};
public static final String[] INCLUDE_PATIENT_SCENARIOS_OPTIONS = {"p", "include-patients"};
public static final String[] VERSIONED_OPTIONS = {"v", "versioned"};
public static final String[] UPDATED_VERSION_OPTIONS = {"uv", "updated-version"};
public static final String[] FHIR_URI_OPTIONS = {"fs", "fhir-uri"};
public static final String[] MEASURE_TO_REFRESH_PATH = {"mtrp", "measure-to-refresh-path"};
public static final String[] RESOURCE_PATH_OPTIONS = {"rp", "resourcepath"};
Expand All @@ -45,6 +46,7 @@ public OptionParser build() {

OptionSpecBuilder iniBuilder = parser.acceptsAll(asList(INI_OPTIONS), "Path to ig ini file");
OptionSpecBuilder rootDirBuilder = parser.acceptsAll(asList(ROOT_DIR_OPTIONS), "Root directory of the ig");
OptionSpecBuilder updatedVersionBuilder = parser.acceptsAll(asList(UPDATED_VERSION_OPTIONS), "Version for the new libraries");
OptionSpecBuilder igPathBuilder = parser.acceptsAll(asList(IG_PATH_OPTIONS),"Path to the IG, relative to the root directory");
OptionSpecBuilder resourcePathBuilder = parser.acceptsAll(asList(RESOURCE_PATH_OPTIONS),"Use multiple times to define multiple resource directories, relative to the root directory.");
OptionSpecBuilder libraryPathBuilder = parser.acceptsAll(asList(LIBRARY_PATH_OPTIONS), "Provide a single path, relative to the root directory, for library resources. The path will be added to the resource directories available to the refresh processing.");
Expand All @@ -58,6 +60,7 @@ public OptionParser build() {
OptionSpecBuilder shouldVerboseMessaging = parser.acceptsAll(asList(SHOULD_APPLY_SOFTWARE_SYSTEM_STAMP_OPTIONS),"Indicates that a complete list of errors during library, measure, and test case refresh are included upon failure.");

OptionSpec<String> ini = iniBuilder.withRequiredArg().describedAs("Path to the IG ini file");
OptionSpec<String> updatedVersion = updatedVersionBuilder.withOptionalArg().describedAs("Updated version of the IG");
OptionSpec<String> rootDir = rootDirBuilder.withOptionalArg().describedAs("Root directory of the IG");
OptionSpec<String> igPath = igPathBuilder.withRequiredArg().describedAs("Path to the IG, relative to the root directory");
OptionSpec<String> resourcePath = resourcePathBuilder.withOptionalArg().describedAs("directory of resources");
Expand Down Expand Up @@ -124,6 +127,11 @@ public RefreshIGParameters parseAndConvert(String[] args) {
String fhirUri = (String)options.valueOf(FHIR_URI_OPTIONS[0]);
String measureToRefreshPath = (String)options.valueOf(MEASURE_TO_REFRESH_PATH[0]);

String updatedVersion = (String)options.valueOf(UPDATED_VERSION_OPTIONS[0]);
if(updatedVersion == null) {
updatedVersion = "";
}

String libraryOutputPath = (String)options.valueOf(LIBRARY_OUTPUT_PATH_OPTIONS[0]);
if (libraryOutputPath == null) {
libraryOutputPath = "";
Expand Down Expand Up @@ -178,6 +186,7 @@ public RefreshIGParameters parseAndConvert(String[] args) {
ip.measureToRefreshPath = measureToRefreshPath;
ip.libraryOutputPath = libraryOutputPath;
ip.measureOutputPath = measureOutputPath;
ip.updatedVersion = updatedVersion;
ip.verboseMessaging = verboseMessaging;
return ip;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,7 @@ protected void copyResourcesToTargetDir(String targetDirectory, String resourceD
File outputDirectory = new File(targetDirectory);
outputDirectory.mkdirs();
URL url = RefreshTest.class.getResource(resourceDirectoryPath);
String path = url.getPath();
File resourceDirectory = new File(path);
File resourceDirectory = FileUtils.toFile(url);
FileUtils.copyDirectory(resourceDirectory, outputDirectory);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
import org.opencds.cqf.tooling.RefreshTest;
import org.opencds.cqf.tooling.parameter.RefreshIGParameters;
import org.opencds.cqf.tooling.processor.IGProcessor;
import org.opencds.cqf.tooling.processor.TestCaseProcessor;
import org.opencds.cqf.tooling.processor.argument.RefreshIGArgumentProcessor;
import org.opencds.cqf.tooling.utilities.IOUtils;
import org.opencds.cqf.tooling.utilities.ResourceUtils;
Expand All @@ -47,7 +46,6 @@

import static org.testng.Assert.*;
import org.hl7.fhir.r4.model.Group;
import org.hl7.fhir.r4.model.Reference;
public class RefreshIGOperationTest extends RefreshTest {
protected final Logger logger = LoggerFactory.getLogger(this.getClass());
public RefreshIGOperationTest() {
Expand All @@ -64,7 +62,7 @@ public RefreshIGOperationTest() {
private final String LIB_TYPE = "Library";
private final String MEASURE_TYPE = "Measure";

private final String INI_LOC = "target" + separator + "refreshIG" + separator + "ig.ini";
private final String INI_LOC = Path.of("target","refreshIG","ig.ini").toString();


// Store the original standard out before changing it.
Expand Down Expand Up @@ -147,7 +145,7 @@ public void testBundledFiles() throws IOException {
wireMockServer.stop();
}

// determine fhireContext for measure lookup
// determine fhirContext for measure lookup
FhirContext fhirContext = IGProcessor.getIgFhirContext(getFhirVersion(ini));

// get list of measures resulting from execution
Expand Down
4 changes: 4 additions & 0 deletions tooling/src/test/resources/NewRefreshIG/ig.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[IG]
ig = input/cqf-us.xml
template = cqf.fhir.template
usage-stats-opt-out = false
134 changes: 134 additions & 0 deletions tooling/src/test/resources/NewRefreshIG/input/cqf-us.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
<?xml version="1.0" encoding="UTF-8"?>
<ImplementationGuide xmlns="http://hl7.org/fhir" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://hl7.org/fhir ../input-cache/schemas/R5/fhir-single.xsd">
<id value="fhir.cqf.us.common"/>
<!-- <extension url="http://hl7.org/fhir/tools/StructureDefinition/igpublisher-spreadsheet">
<valueString value="resources-spreadsheet.xml"/>
</extension>-->
<url value="http://fhir.org/guides/cqf/us/common/ImplementationGuide/fhir.cqf.us.common"/>
<version value="0.1.0"/>
<name value="CQFUSCommon"/>
<title value="Clinical Quality Framework Common FHIR Assets (US-Based)"/>
<status value="draft"/>
<experimental value="false"/>
<publisher value="Clinical Quality Framework"/>
<contact>
<telecom>
<system value="url"/>
<value value="http://github.com/cqframework"/>
</telecom>
</contact>
<description value="This implementation guide contains common FHIR assets for use in US-based CQFramework content IGs, including the USCore-ModelInfo and USCommon libraries."/>
<jurisdiction>
<coding>
<system value="http://unstats.un.org/unsd/methods/m49/m49.htm"/>
<code value="840"/>
<display value="USA"/>
</coding>
</jurisdiction>
<packageId value="fhir.cqf.us.common"/>
<license value="CC0-1.0"/>
<fhirVersion value="4.0.1"/>
<!-- Do not declare this dependency, since we would like to use this IG to fix
the reference problems in CPG as well...
<dependsOn id="cpg">
<uri value="http://hl7.org/fhir/uv/cpg/ImplementationGuide/hl7.fhir.uv.cpg"/>
<packageId value="hl7.fhir.uv.cpg"/>
<version value="1.0.0"/>
</dependsOn>-->
<dependsOn id="cqf">
<uri value="http://fhir.org/guides/cqf/common/ImplementationGuide/fhir.cqf.common"/>
<packageId value="fhir.cqf.common"/>
<version value="4.0.1"/>
</dependsOn>
<dependsOn id="uscore">
<uri value="http://hl7.org/fhir/us/core/ImplementationGuide/hl7.fhir.us.core"/>
<packageId value="hl7.fhir.us.core"/>
<version value="3.1.1"/>
</dependsOn>
<definition>
<page>
<!-- The root will always be toc.html - the template will force it if you don't do it -->
<nameUrl value="toc.html"/>
<title value="Table of Contents"/>
<generation value="html"/>
<page>
<nameUrl value="index.html"/>
<title value="Home"/>
<generation value="html"/>
</page>
<page>
<nameUrl value="downloads.html"/>
<title value="Downloads"/>
<generation value="html"/>
</page>
<page>
<nameUrl value="license.html"/>
<title value="License"/>
<generation value="markdown"/>
</page>
</page>
<!-- copyright year is a mandatory parameter -->
<parameter>
<code value="copyrightyear"/>
<value value="2019+"/>
</parameter>
<!-- releaselabel should be the ballot status for HL7-published IGs. -->
<parameter>
<code value="releaselabel"/>
<value value="CI Build"/>
</parameter>
<parameter>
<code value="find-other-resources"/>
<value value="true"/>
</parameter>
<!-- This parameter indicates to the publisher that it should translate and package CQL libraries. See the example library resources for more -->
<!-- Disabling because the publisher tooling does not know how to deal with FHIRHelpers and FHIR-ModelInfo in this IG -->
<parameter>
<code value="path-binary"/>
<value value="input/cql"/>
</parameter>
<!-- <parameter>-->
<!-- <code value="path-resource"/>-->
<!-- <value value="input/resources/device"/>-->
<!-- </parameter>-->
<parameter>
<code value="path-resource"/>
<value value="input/resources/library"/>
</parameter>
<!-- <parameter>-->
<!-- <code value="path-resource"/>-->
<!-- <value value="input/resources/questionnaire"/>-->
<!-- </parameter>-->
<!-- <parameter>-->
<!-- <code value="path-liquid"/>-->
<!-- <value value="templates\liquid"/>-->
<!-- </parameter>-->
<!-- <parameter>-->
<!-- <code value="path-suppressed-warnings"/>-->
<!-- <value value="input/ignoreWarnings.txt"/>-->
<!-- </parameter>-->
<!-- &lt;!&ndash; Allow the domain CPG. This does prevent a few of the errors,-->
<!-- but the canonical URLs for extensions and profiles from this domain still result in errors... &ndash;&gt;-->
<!-- <parameter>-->
<!-- <code value="extension-domain"/>-->
<!-- <value value="http://hl7.org/fhir/uv/cpg"/>-->
<!-- </parameter>-->
<!-- Uncomment one or more of these if you want to limit which syntaxes are supported or want to disable the display of mappings
<parameter>
<code value="excludexml"/>
<value value="true"/>
</parameter>
<parameter>
<code value="excludejson"/>
<value value="true"/>
</parameter>
<parameter>
<code value="excludettl"/>
<value value="true"/>
</parameter>
<parameter>
<code value="excludemap"/>
<value value="true"/>
</parameter>-->
</definition>
</ImplementationGuide>
Loading

0 comments on commit 2ca0172

Please sign in to comment.