The type of the resource returned by the operation.
+ * @param The type of the parameters for the operation.
+ * @param The type of the resource on which the operation is
+ * invoked.
+ * @param resourceType The class representing the FHIR resource type.
+ * @param name The name of the operation.
+ * @param parameters The operation parameters.
+ * @param returnType The expected return type.
+ * @param headers Additional headers (not used in this implementation).
+ * @return The result of the operation.
+ */
+ @Override
+ public R invoke(
+ Class resourceType, String name, P parameters, Class returnType, Map headers) {
+ return invokeOperation(null, resourceType.getSimpleName(), name, parameters);
+ }
+
+ /**
+ * Invokes a FHIR operation on a specific resource instance.
+ *
+ * @param The type of the resource returned by the operation.
+ * @param The type of the parameters for the operation.
+ * @param The type of the resource identifier.
+ * @param id The identifier of the resource.
+ * @param name The name of the operation.
+ * @param parameters The operation parameters.
+ * @param returnType The expected return type.
+ * @param headers Additional headers (not used in this implementation).
+ * @return The result of the operation.
+ */
+ @Override
+ public R invoke(
+ I id, String name, P parameters, Class returnType, Map headers) {
+ return invokeOperation(id, id.getResourceType(), name, parameters);
+ }
+
+ protected R invokeOperation(
+ IIdType id, String resourceType, String operationName, IBaseParameters parameters) {
+ if (operationProvider == null) {
+ throw new IllegalArgumentException("No operation provider found. Unable to invoke operations.");
+ }
+ return operationProvider.invokeOperation(this, id, resourceType, operationName, parameters);
+ }
+
+ protected IgStandardRepositoryCompartment compartmentFrom(Map headers) {
+ if (headers == null) {
+ return new IgStandardRepositoryCompartment();
+ }
+
+ var compartmentHeader = headers.get(FHIR_COMPARTMENT_HEADER);
+ return compartmentHeader == null
+ ? new IgStandardRepositoryCompartment()
+ : new IgStandardRepositoryCompartment(compartmentHeader);
+ }
+
+ protected String pathForCompartment(IgStandardRepositoryCompartment igStandardRepositoryCompartment) {
+ if (igStandardRepositoryCompartment.isEmpty()) {
+ return "";
+ }
+ // The compartment path is typically ResourceType/Id (e.g., Patient/123)
+ // This is used as a directory name.
+ return igStandardRepositoryCompartment.getType() + "/" + igStandardRepositoryCompartment.getId();
+ }
+}
diff --git a/ls/server/src/main/java/org/opencds/cqf/cql/ls/server/repository/ig/standard/IgStandardRepositoryCompartment.java b/ls/server/src/main/java/org/opencds/cqf/cql/ls/server/repository/ig/standard/IgStandardRepositoryCompartment.java
new file mode 100644
index 00000000..d7875f18
--- /dev/null
+++ b/ls/server/src/main/java/org/opencds/cqf/cql/ls/server/repository/ig/standard/IgStandardRepositoryCompartment.java
@@ -0,0 +1,84 @@
+package org.opencds.cqf.cql.ls.server.repository.ig.standard;
+
+import static java.util.Objects.requireNonNull;
+
+import java.util.Objects;
+import java.util.StringJoiner;
+import org.opencds.cqf.fhir.utility.repository.ig.IgRepository;
+
+/**
+ * Class that represents the compartment context for a given request within {@link IgRepository} only.
+ */
+public class IgStandardRepositoryCompartment {
+
+ private final String type;
+ private final String id;
+
+ private static String typeOfContext(String context) {
+ return context.split("/")[0];
+ }
+
+ private static String idOfContext(String context) {
+ return context.split("/")[1];
+ }
+
+ // Empty context (i.e. no compartment context)
+ public IgStandardRepositoryCompartment() {
+ this.type = null;
+ this.id = null;
+ }
+
+ // Context in the format ResourceType/Id
+ public IgStandardRepositoryCompartment(String context) {
+ this(typeOfContext(context), idOfContext(context));
+ }
+
+ // Context in the format type and id
+ public IgStandardRepositoryCompartment(String type, String id) {
+ // Make this lowercase so the path will resolve on Linux (FYI: macOS is case-insensitive)
+ this.type = requireNonNullOrEmpty("type", type).toLowerCase();
+ this.id = requireNonNullOrEmpty("id", id);
+ }
+
+ public String getType() {
+ return this.type;
+ }
+
+ public String getId() {
+ return this.id;
+ }
+
+ public boolean isEmpty() {
+ return this.type == null || this.id == null;
+ }
+
+ private static String requireNonNullOrEmpty(String name, String value) {
+ requireNonNull(name, "name cannot be null");
+ if (value == null || value.isEmpty()) {
+ throw new IllegalArgumentException(name + " cannot be null or empty");
+ }
+ return value;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ IgStandardRepositoryCompartment that = (IgStandardRepositoryCompartment) o;
+ return Objects.equals(type, that.type) && Objects.equals(id, that.id);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type, id);
+ }
+
+ @Override
+ public String toString() {
+ return new StringJoiner(", ", IgStandardRepositoryCompartment.class.getSimpleName() + "[", "]")
+ .add("type='" + type + "'")
+ .add("id='" + id + "'")
+ .toString();
+ }
+}
diff --git a/ls/server/src/main/java/org/opencds/cqf/cql/ls/server/repository/ig/standard/IgStandardResourceCategory.java b/ls/server/src/main/java/org/opencds/cqf/cql/ls/server/repository/ig/standard/IgStandardResourceCategory.java
new file mode 100644
index 00000000..f7439fe4
--- /dev/null
+++ b/ls/server/src/main/java/org/opencds/cqf/cql/ls/server/repository/ig/standard/IgStandardResourceCategory.java
@@ -0,0 +1,24 @@
+package org.opencds.cqf.cql.ls.server.repository.ig.standard;
+
+import com.google.common.collect.Sets;
+import java.util.Set;
+
+enum IgStandardResourceCategory {
+ DATA,
+ TERMINOLOGY,
+ CONTENT;
+
+ private static final Set TERMINOLOGY_RESOURCES = Sets.newHashSet("ValueSet", "CodeSystem");
+ private static final Set CONTENT_RESOURCES = Sets.newHashSet(
+ "Library", "Questionnaire", "Measure", "PlanDefinition", "StructureDefinition", "ActivityDefinition");
+
+ static IgStandardResourceCategory forType(String resourceType) {
+ if (TERMINOLOGY_RESOURCES.contains(resourceType)) {
+ return TERMINOLOGY;
+ } else if (CONTENT_RESOURCES.contains(resourceType)) {
+ return CONTENT;
+ }
+
+ return DATA;
+ }
+}
diff --git a/ls/server/src/main/java/org/opencds/cqf/cql/ls/server/visitor/ExpressionTrackBackVisitor.java b/ls/server/src/main/java/org/opencds/cqf/cql/ls/server/visitor/ExpressionTrackBackVisitor.java
index 7beb41ef..5fbd0f5d 100644
--- a/ls/server/src/main/java/org/opencds/cqf/cql/ls/server/visitor/ExpressionTrackBackVisitor.java
+++ b/ls/server/src/main/java/org/opencds/cqf/cql/ls/server/visitor/ExpressionTrackBackVisitor.java
@@ -1,10 +1,12 @@
package org.opencds.cqf.cql.ls.server.visitor;
-import org.cqframework.cql.elm.tracking.TrackBack;
+import org.cqframework.cql.cql2elm.tracking.TrackBack;
+import org.cqframework.cql.cql2elm.tracking.Trackable;
import org.cqframework.cql.elm.visiting.BaseElmLibraryVisitor;
import org.hl7.elm.r1.Element;
import org.hl7.elm.r1.ExpressionDef;
import org.hl7.elm.r1.Retrieve;
+import org.jetbrains.annotations.NotNull;
public class ExpressionTrackBackVisitor extends BaseElmLibraryVisitor {
@@ -35,7 +37,7 @@ public Element visitRetrieve(Retrieve retrieve, TrackBack context) {
}
protected boolean elementCoversTrackBack(Element elm, TrackBack context) {
- for (TrackBack tb : elm.getTrackbacks()) {
+ for (TrackBack tb : Trackable.INSTANCE.getTrackbacks(elm)) {
if (startsOnOrBefore(tb, context) && endsOnOrAfter(tb, context)) {
return true;
}
@@ -69,4 +71,9 @@ protected boolean endsOnOrAfter(TrackBack left, TrackBack right) {
// Same line
return left.getEndChar() >= right.getEndChar();
}
+
+ @Override
+ protected Element defaultResult(@NotNull Element element, TrackBack trackBack) {
+ return null;
+ }
}
diff --git a/ls/server/src/test/java/org/opencds/cqf/cql/ls/server/provider/ContentServiceProviderTest.java b/ls/server/src/test/java/org/opencds/cqf/cql/ls/server/provider/ContentServiceProviderTest.java
new file mode 100644
index 00000000..612be057
--- /dev/null
+++ b/ls/server/src/test/java/org/opencds/cqf/cql/ls/server/provider/ContentServiceProviderTest.java
@@ -0,0 +1,31 @@
+package org.opencds.cqf.cql.ls.server.provider;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.net.URI;
+import java.util.Set;
+import org.hl7.elm.r1.VersionedIdentifier;
+import org.junit.jupiter.api.Test;
+import org.opencds.cqf.cql.ls.core.ContentService;
+import org.opencds.cqf.cql.ls.core.utility.Uris;
+
+public class ContentServiceProviderTest {
+
+ @Test
+ void should_throwException_when_gettingLibrary() throws Exception {
+ VersionedIdentifier versionedIdentifier = new VersionedIdentifier();
+ versionedIdentifier.withVersion("1.0.0");
+
+ ContentServiceSourceProvider contentServiceSourceProvider = new ContentServiceSourceProvider(
+ Uris.parseOrNull("/provider/content/sample-library-1.0.0.json"), new ContentService() {
+ @Override
+ public Set locate(URI root, VersionedIdentifier identifier) {
+ throw new UncheckedIOException(new IOException());
+ }
+ });
+
+ assertThrows(RuntimeException.class, () -> contentServiceSourceProvider.getLibrarySource(versionedIdentifier));
+ }
+}
diff --git a/ls/server/src/test/java/org/opencds/cqf/cql/ls/server/repository/ig/standard/BadDataTest.java b/ls/server/src/test/java/org/opencds/cqf/cql/ls/server/repository/ig/standard/BadDataTest.java
new file mode 100644
index 00000000..fab426ac
--- /dev/null
+++ b/ls/server/src/test/java/org/opencds/cqf/cql/ls/server/repository/ig/standard/BadDataTest.java
@@ -0,0 +1,70 @@
+package org.opencds.cqf.cql.ls.server.repository.ig.standard;
+
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.repository.IRepository;
+import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.nio.file.Path;
+import java.util.stream.Stream;
+import org.hl7.fhir.instance.model.api.IIdType;
+import org.hl7.fhir.r4.model.Bundle;
+import org.hl7.fhir.r4.model.IdType;
+import org.hl7.fhir.r4.model.Patient;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+import org.opencds.cqf.fhir.test.Resources;
+import org.opencds.cqf.fhir.utility.search.Searches;
+
+class BadDataTest {
+
+ private static IRepository repository;
+
+ @TempDir
+ static Path tempDir;
+
+ @BeforeAll
+ static void setup() throws URISyntaxException, IOException, ClassNotFoundException {
+ // This copies the sample IG to a temporary directory so that
+ // we can test against an actual filesystem
+ Resources.copyFromJar("/sampleIgs/ig/standard/badData", tempDir);
+ repository = new IgStandardRepository(FhirContext.forR4Cached(), tempDir);
+ }
+
+ @ParameterizedTest
+ @MethodSource("invalidContentTestData")
+ void readInvalidContentThrowsException(IIdType id, String errorMessage) {
+ var e = assertThrows(ResourceNotFoundException.class, () -> repository.read(Patient.class, id));
+ assertTrue(e.getMessage().contains(errorMessage));
+ }
+
+ @Test
+ void nonFhirFilesAreIgnored() {
+ var id = new IdType("Patient/NotAFhirFile");
+ assertThrows(ResourceNotFoundException.class, () -> repository.read(Patient.class, id));
+ }
+
+ @Test
+ void searchThrowsBecauseOfInvalidContent() {
+ // If there's any invalid content in the directory, the search will fail
+ assertThrows(
+ ResourceNotFoundException.class, () -> repository.search(Bundle.class, Patient.class, Searches.ALL));
+ }
+
+ private static Stream invalidContentTestData() {
+ return Stream.of(
+ Arguments.of(new IdType("Patient/InvalidContent"), "Found empty or invalid content"),
+ Arguments.of(new IdType("Patient/MissingId"), "Found resource without an id"),
+ Arguments.of(new IdType("Patient/NoContent"), "Found empty or invalid content"),
+ Arguments.of(new IdType("Patient/WrongId"), "Found resource with an id DoesntMatchFilename"),
+ Arguments.of(new IdType("Patient/WrongResourceType"), "Found resource with type Encounter"),
+ Arguments.of(new IdType("Patient/WrongVersion").withVersion("1"), "Found resource with version 2"));
+ }
+}
diff --git a/ls/server/src/test/java/org/opencds/cqf/cql/ls/server/repository/ig/standard/CompartmentTest.java b/ls/server/src/test/java/org/opencds/cqf/cql/ls/server/repository/ig/standard/CompartmentTest.java
new file mode 100644
index 00000000..7379058a
--- /dev/null
+++ b/ls/server/src/test/java/org/opencds/cqf/cql/ls/server/repository/ig/standard/CompartmentTest.java
@@ -0,0 +1,243 @@
+package org.opencds.cqf.cql.ls.server.repository.ig.standard;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.repository.IRepository;
+import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Map;
+import org.hl7.fhir.r4.model.*;
+import org.junit.jupiter.api.*;
+import org.junit.jupiter.api.io.TempDir;
+import org.opencds.cqf.fhir.test.Resources;
+import org.opencds.cqf.fhir.utility.Ids;
+import org.opencds.cqf.fhir.utility.search.Searches;
+
+@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
+class CompartmentTest {
+
+ private static IRepository repository;
+
+ @TempDir
+ static Path tempDir;
+
+ @BeforeAll
+ static void setup() throws URISyntaxException, IOException, ClassNotFoundException {
+ // This copies the sample IG to a temporary directory so that
+ // we can test against an actual filesystem
+ Resources.copyFromJar("/sampleIgs/ig/standard/compartment", tempDir);
+ repository = new IgStandardRepository(FhirContext.forR4Cached(), tempDir);
+ }
+
+ @Test
+ void readLibrary() {
+ var id = Ids.newId(Library.class, "123");
+ var lib = repository.read(Library.class, id);
+ assertNotNull(lib);
+ assertEquals(id.getIdPart(), lib.getIdElement().getIdPart());
+ }
+
+ @Test
+ void readLibraryNotExists() {
+ var id = Ids.newId(Library.class, "DoesNotExist");
+ assertThrows(ResourceNotFoundException.class, () -> repository.read(Library.class, id));
+ }
+
+ @Test
+ void searchLibrary() {
+ var libs = repository.search(Bundle.class, Library.class, Searches.ALL);
+
+ assertNotNull(libs);
+ assertEquals(2, libs.getEntry().size());
+ }
+
+ @Test
+ void searchLibraryNotExists() {
+ var libs = repository.search(Bundle.class, Library.class, Searches.byUrl("not-exists"));
+ assertNotNull(libs);
+ assertEquals(0, libs.getEntry().size());
+ }
+
+ @Test
+ void readPatientNoCompartment() {
+ var id = Ids.newId(Patient.class, "123");
+ assertThrows(ResourceNotFoundException.class, () -> repository.read(Patient.class, id));
+ }
+
+ @Test
+ void readPatient() {
+ var id = Ids.newId(Patient.class, "123");
+ var p = repository.read(Patient.class, id, Map.of(IgStandardRepository.FHIR_COMPARTMENT_HEADER, "Patient/123"));
+
+ assertNotNull(p);
+ assertEquals(id.getIdPart(), p.getIdElement().getIdPart());
+ }
+
+ @Test
+ void searchEncounterNoCompartment() {
+ var encounters = repository.search(Bundle.class, Encounter.class, Searches.ALL);
+ assertNotNull(encounters);
+ assertEquals(0, encounters.getEntry().size());
+ }
+
+ @Test
+ void searchEncounter() {
+ var encounters = repository.search(
+ Bundle.class,
+ Encounter.class,
+ Searches.ALL,
+ Map.of(IgStandardRepository.FHIR_COMPARTMENT_HEADER, "Patient/123"));
+ assertNotNull(encounters);
+ assertEquals(1, encounters.getEntry().size());
+ }
+
+ @Test
+ void readValueSetNoCompartment() {
+ var id = Ids.newId(ValueSet.class, "456");
+ var vs = repository.read(ValueSet.class, id);
+
+ assertNotNull(vs);
+ assertEquals(vs.getIdPart(), vs.getIdElement().getIdPart());
+ }
+
+ // Terminology resources are not in compartments
+ @Test
+ void readValueSet() {
+ var id = Ids.newId(ValueSet.class, "456");
+ var vs = repository.read(
+ ValueSet.class, id, Map.of(IgStandardRepository.FHIR_COMPARTMENT_HEADER, "Patient/123"));
+
+ assertNotNull(vs);
+ assertEquals(vs.getIdPart(), vs.getIdElement().getIdPart());
+ }
+
+ @Test
+ void searchValueSet() {
+ var sets = repository.search(Bundle.class, ValueSet.class, Searches.byUrl("example.com/ValueSet/456"));
+ assertNotNull(sets);
+ assertEquals(1, sets.getEntry().size());
+ }
+
+ @Test
+ void createAndDeleteLibrary() {
+ var lib = new Library();
+ lib.setId("new-library");
+ var o = repository.create(lib);
+ var created = repository.read(Library.class, o.getId());
+ assertNotNull(created);
+
+ var loc = tempDir.resolve("resources/library/new-library.json");
+ assertTrue(Files.exists(loc));
+
+ repository.delete(Library.class, created.getIdElement());
+ assertFalse(Files.exists(loc));
+ }
+
+ @Test
+ void createAndDeletePatient() {
+ var p = new Patient();
+ p.setId("new-patient");
+ var header = Map.of(IgStandardRepository.FHIR_COMPARTMENT_HEADER, "Patient/new-patient");
+ var o = repository.create(p, header);
+ var created = repository.read(Patient.class, o.getId(), header);
+ assertNotNull(created);
+
+ var loc = tempDir.resolve("tests/patient/new-patient/patient/new-patient.json");
+ assertTrue(Files.exists(loc));
+
+ repository.delete(Patient.class, created.getIdElement(), header);
+ assertFalse(Files.exists(loc));
+ }
+
+ @Test
+ void createAndDeleteValueSet() {
+ var v = new ValueSet();
+ v.setId("new-valueset");
+ var o = repository.create(v);
+ var created = repository.read(ValueSet.class, o.getId());
+ assertNotNull(created);
+
+ var loc = tempDir.resolve("vocabulary/valueset/new-valueset.json");
+ assertTrue(Files.exists(loc));
+
+ repository.delete(ValueSet.class, created.getIdElement());
+ assertFalse(Files.exists(loc));
+ }
+
+ @Test
+ void updatePatient() {
+ var id = Ids.newId(Patient.class, "123");
+ var p = repository.read(Patient.class, id, Map.of(IgStandardRepository.FHIR_COMPARTMENT_HEADER, "Patient/123"));
+ assertFalse(p.hasActive());
+
+ p.setActive(true);
+ repository.update(p);
+
+ var updated =
+ repository.read(Patient.class, id, Map.of(IgStandardRepository.FHIR_COMPARTMENT_HEADER, "Patient/123"));
+ assertTrue(updated.hasActive());
+ assertTrue(updated.getActive());
+ }
+
+ @Test
+ void deleteNonExistentPatient() {
+ var id = Ids.newId(Patient.class, "DoesNotExist");
+ assertThrows(ResourceNotFoundException.class, () -> repository.delete(Patient.class, id));
+ }
+
+ @Test
+ void searchNonExistentType() {
+ var results = repository.search(Bundle.class, Encounter.class, Searches.ALL);
+ assertNotNull(results);
+ assertEquals(0, results.getEntry().size());
+ }
+
+ @Test
+ void searchById() {
+ var bundle = repository.search(Bundle.class, Library.class, Searches.byId("123"));
+ assertNotNull(bundle);
+ assertEquals(1, bundle.getEntry().size());
+ }
+
+ @Test
+ void searchByIdNotFound() {
+ var bundle = repository.search(Bundle.class, Library.class, Searches.byId("DoesNotExist"));
+ assertNotNull(bundle);
+ assertEquals(0, bundle.getEntry().size());
+ }
+
+ @Test
+ @Order(1) // Do this test first because it puts the filesystem (temporarily) in an invalid state
+ void resourceMissingWhenCacheCleared() throws IOException {
+ var id = new IdType("Library", "ToDelete");
+ var lib = new Library().setIdElement(id);
+ var path = tempDir.resolve("resources/library/ToDelete.json");
+
+ repository.create(lib);
+ assertTrue(path.toFile().exists());
+
+ // Read back, should exist
+ lib = repository.read(Library.class, id);
+ assertNotNull(lib);
+
+ // Overwrite the file on disk.
+ Files.writeString(path, "");
+
+ // Read from cache, repo doesn't know the content is gone.
+ lib = repository.read(Library.class, id);
+ assertNotNull(lib);
+ assertEquals("ToDelete", lib.getIdElement().getIdPart());
+
+ ((IgStandardRepository) repository).clearCache();
+
+ // Try to read again, should be gone because it's not in the cache and the content is gone.
+ assertThrows(ResourceNotFoundException.class, () -> repository.read(Library.class, id));
+
+ // Clean up so that we don't affect other tests
+ path.toFile().delete();
+ }
+}
diff --git a/ls/server/src/test/java/org/opencds/cqf/cql/ls/server/repository/ig/standard/ConventionsTest.java b/ls/server/src/test/java/org/opencds/cqf/cql/ls/server/repository/ig/standard/ConventionsTest.java
new file mode 100644
index 00000000..aa6e14b3
--- /dev/null
+++ b/ls/server/src/test/java/org/opencds/cqf/cql/ls/server/repository/ig/standard/ConventionsTest.java
@@ -0,0 +1,88 @@
+package org.opencds.cqf.cql.ls.server.repository.ig.standard;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.nio.file.Path;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+import org.opencds.cqf.fhir.test.Resources;
+
+class ConventionsTest {
+
+ @TempDir
+ static Path tempDir;
+
+ @BeforeAll
+ static void setup() throws URISyntaxException, IOException, ClassNotFoundException {
+ // This copies the sample IG to a temporary directory so that
+ // we can test against an actual filesystem
+ Resources.copyFromJar("/sampleIgs/ig/standard", tempDir);
+ }
+
+ @Test
+ void autoDetectDefault() {
+ assertEquals(IgStandardConventions.STANDARD, IgStandardConventions.autoDetect(null));
+ assertEquals(
+ IgStandardConventions.STANDARD, IgStandardConventions.autoDetect(tempDir.resolve("does_not_exist")));
+ }
+
+ @Test
+ void autoDetectStandard() {
+ assertEquals(
+ IgStandardConventions.STANDARD,
+ IgStandardConventions.autoDetect(tempDir.resolve("directoryPerType/standard")));
+ }
+
+ @Test
+ void autoDetectPrefix() {
+ var config = IgStandardConventions.autoDetect(tempDir.resolve("directoryPerType/prefixed"));
+ assertEquals(IgStandardConventions.FilenameMode.TYPE_AND_ID, config.filenameMode());
+ assertEquals(IgStandardConventions.CategoryLayout.DIRECTORY_PER_CATEGORY, config.categoryLayout());
+ assertEquals(IgStandardConventions.CompartmentLayout.FLAT, config.compartmentLayout());
+ assertEquals(IgStandardConventions.FhirTypeLayout.DIRECTORY_PER_TYPE, config.typeLayout());
+ }
+
+ @Test
+ void autoDetectFlat() {
+ assertEquals(IgStandardConventions.FLAT, IgStandardConventions.autoDetect(tempDir.resolve("flat")));
+ }
+
+ @Test
+ void autoDetectFlatNoTypeNames() {
+ var config = IgStandardConventions.autoDetect(tempDir.resolve("flatNoTypeNames"));
+ assertEquals(IgStandardConventions.FilenameMode.ID_ONLY, config.filenameMode());
+ assertEquals(IgStandardConventions.CategoryLayout.FLAT, config.categoryLayout());
+ assertEquals(IgStandardConventions.CompartmentLayout.FLAT, config.compartmentLayout());
+ assertEquals(IgStandardConventions.FhirTypeLayout.FLAT, config.typeLayout());
+ }
+
+ @Test
+ void autoDetectWithMisleadingFileName() {
+ assertEquals(
+ IgStandardConventions.STANDARD,
+ IgStandardConventions.autoDetect(tempDir.resolve("misleadingFileName")));
+ }
+
+ @Test
+ void autoDetectWithEmptyContent() {
+ assertEquals(IgStandardConventions.STANDARD, IgStandardConventions.autoDetect(tempDir.resolve("emptyContent")));
+ }
+
+ @Test
+ void autoDetectWithNonFhirFilename() {
+ assertEquals(
+ IgStandardConventions.STANDARD, IgStandardConventions.autoDetect(tempDir.resolve("nonFhirFilename")));
+ }
+
+ @Test
+ void autoDetectWitCompartments() {
+ var config = IgStandardConventions.autoDetect(tempDir.resolve("compartment"));
+ assertEquals(IgStandardConventions.FilenameMode.ID_ONLY, config.filenameMode());
+ assertEquals(IgStandardConventions.CategoryLayout.DIRECTORY_PER_CATEGORY, config.categoryLayout());
+ assertEquals(IgStandardConventions.CompartmentLayout.DIRECTORY_PER_COMPARTMENT, config.compartmentLayout());
+ assertEquals(IgStandardConventions.FhirTypeLayout.DIRECTORY_PER_TYPE, config.typeLayout());
+ }
+}
diff --git a/ls/server/src/test/java/org/opencds/cqf/cql/ls/server/repository/ig/standard/CqlContentTest.java b/ls/server/src/test/java/org/opencds/cqf/cql/ls/server/repository/ig/standard/CqlContentTest.java
new file mode 100644
index 00000000..004af4a6
--- /dev/null
+++ b/ls/server/src/test/java/org/opencds/cqf/cql/ls/server/repository/ig/standard/CqlContentTest.java
@@ -0,0 +1,84 @@
+package org.opencds.cqf.cql.ls.server.repository.ig.standard;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.nio.file.Path;
+import org.hl7.fhir.dstu2.model.ValueSet;
+import org.hl7.fhir.dstu3.model.Library;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+import org.opencds.cqf.fhir.test.Resources;
+
+class CqlContentTest {
+
+ @TempDir
+ static Path tempDir;
+
+ @BeforeAll
+ static void setup() throws ClassNotFoundException, URISyntaxException, IOException {
+ // This copies the sample IG to a temporary directory so that
+ // we can test against an actual filesystem
+ Resources.copyFromJar("/sampleIgs/ig/standard/cqlContent", tempDir);
+ }
+
+ @Test
+ void loadCqlContentDstu3() {
+ var lib = new Library();
+ lib.addContent().setContentType("text/cql").setUrl("cql/Test.cql");
+ IgStandardCqlContent.loadCqlContent(lib, tempDir);
+ assertNotNull(lib.getContentFirstRep().getData());
+ }
+
+ @Test
+ void loadCqlContentR4() {
+ var lib = new org.hl7.fhir.r4.model.Library();
+ lib.addContent().setContentType("text/cql").setUrl("cql/Test.cql");
+ IgStandardCqlContent.loadCqlContent(lib, tempDir);
+ assertNotNull(lib.getContentFirstRep().getData());
+ }
+
+ @Test
+ void loadCqlContentR5() {
+ var lib = new org.hl7.fhir.r5.model.Library();
+ lib.addContent().setContentType("text/cql").setUrl("cql/Test.cql");
+ IgStandardCqlContent.loadCqlContent(lib, tempDir);
+ assertNotNull(lib.getContentFirstRep().getData());
+ }
+
+ @Test
+ void emptyLibraryDoesNothing() {
+ var lib = new Library();
+ IgStandardCqlContent.loadCqlContent(lib, tempDir);
+ assertEquals(0, lib.getContent().size());
+ }
+
+ @Test
+ void nonLibraryResourceDoesNotThrow() {
+ assertDoesNotThrow(() -> IgStandardCqlContent.loadCqlContent(new ValueSet(), tempDir));
+ }
+
+ @Test
+ void invalidFhirVersionThrows() {
+ var lib = new org.hl7.fhir.r4b.model.Library();
+ assertThrows(IllegalArgumentException.class, () -> IgStandardCqlContent.loadCqlContent(lib, tempDir));
+ }
+
+ @Test
+ void invalidPathThrows() {
+ var lib = new org.hl7.fhir.r4.model.Library();
+ lib.addContent().setContentType("text/cql").setUrl("not-a-real-path/Test.cql");
+ assertThrows(ResourceNotFoundException.class, () -> IgStandardCqlContent.loadCqlContent(lib, tempDir));
+ }
+
+ @Test
+ void nullThrows() {
+ assertThrows(NullPointerException.class, () -> IgStandardCqlContent.loadCqlContent(null, tempDir));
+
+ var lib = new Library();
+ assertThrows(NullPointerException.class, () -> IgStandardCqlContent.loadCqlContent(lib, null));
+ }
+}
diff --git a/ls/server/src/test/java/org/opencds/cqf/cql/ls/server/repository/ig/standard/DirectoryTest.java b/ls/server/src/test/java/org/opencds/cqf/cql/ls/server/repository/ig/standard/DirectoryTest.java
new file mode 100644
index 00000000..443d0ba1
--- /dev/null
+++ b/ls/server/src/test/java/org/opencds/cqf/cql/ls/server/repository/ig/standard/DirectoryTest.java
@@ -0,0 +1,176 @@
+package org.opencds.cqf.cql.ls.server.repository.ig.standard;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.repository.IRepository;
+import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import org.hl7.fhir.r4.model.*;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+import org.opencds.cqf.fhir.test.Resources;
+import org.opencds.cqf.fhir.utility.Ids;
+import org.opencds.cqf.fhir.utility.search.Searches;
+
+class DirectoryTest {
+
+ private static IRepository repository;
+
+ @TempDir
+ static Path tempDir;
+
+ @BeforeAll
+ static void setup() throws URISyntaxException, IOException, ClassNotFoundException {
+ // This copies the sample IG to a temporary directory so that
+ // we can test against an actual filesystem
+ Resources.copyFromJar("/sampleIgs/ig/standard/directoryPerType/standard", tempDir);
+ repository = new IgStandardRepository(FhirContext.forR4Cached(), tempDir);
+ }
+
+ @Test
+ void readLibrary() {
+ var id = Ids.newId(Library.class, "123");
+ var lib = repository.read(Library.class, id);
+ assertNotNull(lib);
+ assertEquals(id.getIdPart(), lib.getIdElement().getIdPart());
+ }
+
+ @Test
+ void readLibraryNotExists() {
+ var id = Ids.newId(Library.class, "DoesNotExist");
+ assertThrows(ResourceNotFoundException.class, () -> repository.read(Library.class, id));
+ }
+
+ @Test
+ void searchLibrary() {
+ var libs = repository.search(Bundle.class, Library.class, Searches.ALL);
+
+ assertNotNull(libs);
+ assertEquals(2, libs.getEntry().size());
+ }
+
+ @Test
+ void searchLibraryWithFilter() {
+ var libs = repository.search(Bundle.class, Library.class, Searches.byUrl("http://example.com/Library/Test"));
+
+ assertNotNull(libs);
+ assertEquals(1, libs.getEntry().size());
+ }
+
+ @Test
+ void searchLibraryNotExists() {
+ var libs = repository.search(Bundle.class, Library.class, Searches.byUrl("not-exists"));
+ assertNotNull(libs);
+ assertEquals(0, libs.getEntry().size());
+ }
+
+ @Test
+ void readPatient() {
+ var id = Ids.newId(Patient.class, "ABC");
+ var cond = repository.read(Patient.class, id);
+
+ assertNotNull(cond);
+ assertEquals(id.getIdPart(), cond.getIdElement().getIdPart());
+ }
+
+ @Test
+ void searchCondition() {
+ var cons = repository.search(
+ Bundle.class, Condition.class, Searches.byCodeAndSystem("12345", "example.com/codesystem"));
+ assertNotNull(cons);
+ assertEquals(2, cons.getEntry().size());
+ }
+
+ @Test
+ void readValueSet() {
+ var id = Ids.newId(ValueSet.class, "456");
+ var vs = repository.read(ValueSet.class, id);
+
+ assertNotNull(vs);
+ assertEquals(vs.getIdPart(), vs.getIdElement().getIdPart());
+ }
+
+ @Test
+ void searchValueSet() {
+ var sets = repository.search(Bundle.class, ValueSet.class, Searches.byUrl("example.com/ValueSet/456"));
+ assertNotNull(sets);
+ assertEquals(1, sets.getEntry().size());
+ }
+
+ @Test
+ void createAndDeleteLibrary() {
+ var lib = new Library();
+ lib.setId("new-library");
+ var o = repository.create(lib);
+ var created = repository.read(Library.class, o.getId());
+ assertNotNull(created);
+
+ var loc = tempDir.resolve("resources/library/new-library.json");
+ assertTrue(Files.exists(loc));
+
+ repository.delete(Library.class, created.getIdElement());
+ assertFalse(Files.exists(loc));
+ }
+
+ @Test
+ void createAndDeletePatient() {
+ var p = new Patient();
+ p.setId("new-patient");
+ var o = repository.create(p);
+ var created = repository.read(Patient.class, o.getId());
+ assertNotNull(created);
+
+ var loc = tempDir.resolve("tests/patient/new-patient.json");
+ assertTrue(Files.exists(loc));
+
+ repository.delete(Patient.class, created.getIdElement());
+ assertFalse(Files.exists(loc));
+ }
+
+ @Test
+ void createAndDeleteValueSet() {
+ var v = new ValueSet();
+ v.setId("new-valueset");
+ var o = repository.create(v);
+ var created = repository.read(ValueSet.class, o.getId());
+ assertNotNull(created);
+
+ var loc = tempDir.resolve("vocabulary/valueset/new-valueset.json");
+ assertTrue(Files.exists(loc));
+
+ repository.delete(ValueSet.class, created.getIdElement());
+ assertFalse(Files.exists(loc));
+ }
+
+ @Test
+ void updatePatient() {
+ var id = Ids.newId(Patient.class, "ABC");
+ var p = repository.read(Patient.class, id);
+ assertFalse(p.hasActive());
+
+ p.setActive(true);
+ repository.update(p);
+
+ var updated = repository.read(Patient.class, id);
+ assertTrue(updated.hasActive());
+ assertTrue(updated.getActive());
+ }
+
+ @Test
+ void deleteNonExistentPatient() {
+ var id = Ids.newId(Patient.class, "DoesNotExist");
+ assertThrows(ResourceNotFoundException.class, () -> repository.delete(Patient.class, id));
+ }
+
+ @Test
+ void searchNonExistentType() {
+ var results = repository.search(Bundle.class, Encounter.class, Searches.ALL);
+ assertNotNull(results);
+ assertEquals(0, results.getEntry().size());
+ }
+}
diff --git a/ls/server/src/test/java/org/opencds/cqf/cql/ls/server/repository/ig/standard/ExternalTest.java b/ls/server/src/test/java/org/opencds/cqf/cql/ls/server/repository/ig/standard/ExternalTest.java
new file mode 100644
index 00000000..39d9da8a
--- /dev/null
+++ b/ls/server/src/test/java/org/opencds/cqf/cql/ls/server/repository/ig/standard/ExternalTest.java
@@ -0,0 +1,87 @@
+package org.opencds.cqf.cql.ls.server.repository.ig.standard;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.repository.IRepository;
+import ca.uhn.fhir.rest.server.exceptions.ForbiddenOperationException;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import org.hl7.fhir.r4.model.Bundle;
+import org.hl7.fhir.r4.model.ValueSet;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+import org.opencds.cqf.fhir.test.Resources;
+import org.opencds.cqf.fhir.utility.Ids;
+import org.opencds.cqf.fhir.utility.search.Searches;
+
+class ExternalTest {
+
+ private static IRepository repository;
+
+ @TempDir
+ static Path tempDir;
+
+ @BeforeAll
+ static void setup() throws URISyntaxException, IOException, ClassNotFoundException {
+ // This copies the sample IG to a temporary directory so that
+ // we can test against an actual filesystem
+ Resources.copyFromJar("/sampleIgs/ig/standard/externalResource", tempDir);
+ repository = new IgStandardRepository(FhirContext.forR4Cached(), tempDir);
+ }
+
+ @Test
+ void readValueSet() {
+ var id = Ids.newId(ValueSet.class, "456");
+ var vs = repository.read(ValueSet.class, id);
+
+ assertNotNull(vs);
+ assertEquals(vs.getIdPart(), vs.getIdElement().getIdPart());
+ }
+
+ @Test
+ void createAndDeleteValueSet() {
+ var v = new ValueSet();
+ v.setId("new-valueset");
+ var o = repository.create(v);
+ var created = repository.read(ValueSet.class, o.getId());
+ assertNotNull(created);
+
+ var loc = tempDir.resolve("vocabulary/valueset/new-valueset.json");
+ assertTrue(Files.exists(loc));
+
+ repository.delete(ValueSet.class, created.getIdElement());
+ assertFalse(Files.exists(loc));
+ }
+
+ @Test
+ void readExternalValueSet() {
+ var id = Ids.newId(ValueSet.class, "789");
+ var vs = repository.read(ValueSet.class, id);
+ assertNotNull(vs);
+ assertEquals(vs.getIdPart(), vs.getIdElement().getIdPart());
+
+ // Should be tagged with its source path
+ var path = (Path) vs.getUserData(IgStandardRepository.SOURCE_PATH_TAG);
+ assertNotNull(path);
+ assertTrue(path.toFile().exists());
+ assertTrue(path.toString().contains("external"));
+ }
+
+ @Test
+ void searchExternalValueSet() {
+ var sets = repository.search(Bundle.class, ValueSet.class, Searches.byUrl("example.com/ValueSet/789"));
+ assertNotNull(sets);
+ assertEquals(1, sets.getEntry().size());
+ }
+
+ @Test
+ void updateExternalValueSetFails() {
+ var id = Ids.newId(ValueSet.class, "789");
+ var vs = repository.read(ValueSet.class, id);
+ assertThrows(ForbiddenOperationException.class, () -> repository.update(vs));
+ }
+}
diff --git a/ls/server/src/test/java/org/opencds/cqf/cql/ls/server/repository/ig/standard/FlatNoTypeNamesTest.java b/ls/server/src/test/java/org/opencds/cqf/cql/ls/server/repository/ig/standard/FlatNoTypeNamesTest.java
new file mode 100644
index 00000000..42c5289e
--- /dev/null
+++ b/ls/server/src/test/java/org/opencds/cqf/cql/ls/server/repository/ig/standard/FlatNoTypeNamesTest.java
@@ -0,0 +1,176 @@
+package org.opencds.cqf.cql.ls.server.repository.ig.standard;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.repository.IRepository;
+import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import org.hl7.fhir.r4.model.*;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+import org.opencds.cqf.fhir.test.Resources;
+import org.opencds.cqf.fhir.utility.Ids;
+import org.opencds.cqf.fhir.utility.search.Searches;
+
+class FlatNoTypeNamesTest {
+
+ private static IRepository repository;
+
+ @TempDir
+ static Path tempDir;
+
+ @BeforeAll
+ static void setup() throws URISyntaxException, IOException, ClassNotFoundException {
+ // This copies the sample IG to a temporary directory so that
+ // we can test against an actual filesystem
+ Resources.copyFromJar("/sampleIgs/ig/standard/flatNoTypeNames", tempDir);
+ repository = new IgStandardRepository(FhirContext.forR4Cached(), tempDir);
+ }
+
+ @Test
+ void readLibrary() {
+ var id = Ids.newId(Library.class, "123");
+ var lib = repository.read(Library.class, id);
+ assertNotNull(lib);
+ assertEquals(id.getIdPart(), lib.getIdElement().getIdPart());
+ }
+
+ @Test
+ void readLibraryNotExists() {
+ var id = Ids.newId(Library.class, "DoesNotExist");
+ assertThrows(ResourceNotFoundException.class, () -> repository.read(Library.class, id));
+ }
+
+ @Test
+ void searchLibrary() {
+ var libs = repository.search(Bundle.class, Library.class, Searches.ALL);
+
+ assertNotNull(libs);
+ assertEquals(2, libs.getEntry().size());
+ }
+
+ @Test
+ void searchLibraryWithFilter() {
+ var libs = repository.search(Bundle.class, Library.class, Searches.byUrl("http://example.com/Library/Test"));
+
+ assertNotNull(libs);
+ assertEquals(1, libs.getEntry().size());
+ }
+
+ @Test
+ void searchLibraryNotExists() {
+ var libs = repository.search(Bundle.class, Library.class, Searches.byUrl("not-exists"));
+ assertNotNull(libs);
+ assertEquals(0, libs.getEntry().size());
+ }
+
+ @Test
+ void readPatient() {
+ var id = Ids.newId(Patient.class, "ABC");
+ var cond = repository.read(Patient.class, id);
+
+ assertNotNull(cond);
+ assertEquals(id.getIdPart(), cond.getIdElement().getIdPart());
+ }
+
+ @Test
+ void searchCondition() {
+ var cons = repository.search(
+ Bundle.class, Condition.class, Searches.byCodeAndSystem("12345", "example.com/codesystem"));
+ assertNotNull(cons);
+ assertEquals(2, cons.getEntry().size());
+ }
+
+ @Test
+ void readValueSet() {
+ var id = Ids.newId(ValueSet.class, "789");
+ var vs = repository.read(ValueSet.class, id);
+
+ assertNotNull(vs);
+ assertEquals(vs.getIdPart(), vs.getIdElement().getIdPart());
+ }
+
+ @Test
+ void searchValueSet() {
+ var sets = repository.search(Bundle.class, ValueSet.class, Searches.byUrl("example.com/ValueSet/789"));
+ assertNotNull(sets);
+ assertEquals(1, sets.getEntry().size());
+ }
+
+ @Test
+ void createAndDeleteLibrary() {
+ var lib = new Library();
+ lib.setId("new-library");
+ var o = repository.create(lib);
+ var created = repository.read(Library.class, o.getId());
+ assertNotNull(created);
+
+ var loc = tempDir.resolve("new-library.json");
+ assertTrue(Files.exists(loc));
+
+ repository.delete(Library.class, created.getIdElement());
+ assertFalse(Files.exists(loc));
+ }
+
+ @Test
+ void createAndDeletePatient() {
+ var p = new Patient();
+ p.setId("new-patient");
+ var o = repository.create(p);
+ var created = repository.read(Patient.class, o.getId());
+ assertNotNull(created);
+
+ var loc = tempDir.resolve("new-patient.json");
+ assertTrue(Files.exists(loc));
+
+ repository.delete(Patient.class, created.getIdElement());
+ assertFalse(Files.exists(loc));
+ }
+
+ @Test
+ void createAndDeleteValueSet() {
+ var v = new ValueSet();
+ v.setId("new-valueset");
+ var o = repository.create(v);
+ var created = repository.read(ValueSet.class, o.getId());
+ assertNotNull(created);
+
+ var loc = tempDir.resolve("new-valueset.json");
+ assertTrue(Files.exists(loc));
+
+ repository.delete(ValueSet.class, created.getIdElement());
+ assertFalse(Files.exists(loc));
+ }
+
+ @Test
+ void updatePatient() {
+ var id = Ids.newId(Patient.class, "ABC");
+ var p = repository.read(Patient.class, id);
+ assertFalse(p.hasActive());
+
+ p.setActive(true);
+ repository.update(p);
+
+ var updated = repository.read(Patient.class, id);
+ assertTrue(updated.hasActive());
+ assertTrue(updated.getActive());
+ }
+
+ @Test
+ void deleteNonExistentPatient() {
+ var id = Ids.newId(Patient.class, "DoesNotExist");
+ assertThrows(ResourceNotFoundException.class, () -> repository.delete(Patient.class, id));
+ }
+
+ @Test
+ void searchNonExistentType() {
+ var results = repository.search(Bundle.class, Encounter.class, Searches.ALL);
+ assertNotNull(results);
+ assertEquals(0, results.getEntry().size());
+ }
+}
diff --git a/ls/server/src/test/java/org/opencds/cqf/cql/ls/server/repository/ig/standard/FlatTest.java b/ls/server/src/test/java/org/opencds/cqf/cql/ls/server/repository/ig/standard/FlatTest.java
new file mode 100644
index 00000000..eb7d0b85
--- /dev/null
+++ b/ls/server/src/test/java/org/opencds/cqf/cql/ls/server/repository/ig/standard/FlatTest.java
@@ -0,0 +1,176 @@
+package org.opencds.cqf.cql.ls.server.repository.ig.standard;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.repository.IRepository;
+import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import org.hl7.fhir.r4.model.*;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+import org.opencds.cqf.fhir.test.Resources;
+import org.opencds.cqf.fhir.utility.Ids;
+import org.opencds.cqf.fhir.utility.search.Searches;
+
+class FlatTest {
+
+ private static IRepository repository;
+
+ @TempDir
+ static Path tempDir;
+
+ @BeforeAll
+ static void setup() throws URISyntaxException, IOException, ClassNotFoundException {
+ // This copies the sample IG to a temporary directory so that
+ // we can test against an actual filesystem
+ Resources.copyFromJar("/sampleIgs/ig/standard/flat", tempDir);
+ repository = new IgStandardRepository(FhirContext.forR4Cached(), tempDir);
+ }
+
+ @Test
+ void readLibrary() {
+ var id = Ids.newId(Library.class, "123");
+ var lib = repository.read(Library.class, id);
+ assertNotNull(lib);
+ assertEquals(id.getIdPart(), lib.getIdElement().getIdPart());
+ }
+
+ @Test
+ void readLibraryNotExists() {
+ var id = Ids.newId(Library.class, "DoesNotExist");
+ assertThrows(ResourceNotFoundException.class, () -> repository.read(Library.class, id));
+ }
+
+ @Test
+ void searchLibrary() {
+ var libs = repository.search(Bundle.class, Library.class, Searches.ALL);
+
+ assertNotNull(libs);
+ assertEquals(2, libs.getEntry().size());
+ }
+
+ @Test
+ void searchLibraryWithFilter() {
+ var libs = repository.search(Bundle.class, Library.class, Searches.byUrl("http://example.com/Library/Test"));
+
+ assertNotNull(libs);
+ assertEquals(1, libs.getEntry().size());
+ }
+
+ @Test
+ void searchLibraryNotExists() {
+ var libs = repository.search(Bundle.class, Library.class, Searches.byUrl("not-exists"));
+ assertNotNull(libs);
+ assertEquals(0, libs.getEntry().size());
+ }
+
+ @Test
+ void readPatient() {
+ var id = Ids.newId(Patient.class, "ABC");
+ var cond = repository.read(Patient.class, id);
+
+ assertNotNull(cond);
+ assertEquals(id.getIdPart(), cond.getIdElement().getIdPart());
+ }
+
+ @Test
+ void searchCondition() {
+ var cons = repository.search(
+ Bundle.class, Condition.class, Searches.byCodeAndSystem("12345", "example.com/codesystem"));
+ assertNotNull(cons);
+ assertEquals(2, cons.getEntry().size());
+ }
+
+ @Test
+ void readValueSet() {
+ var id = Ids.newId(ValueSet.class, "456");
+ var vs = repository.read(ValueSet.class, id);
+
+ assertNotNull(vs);
+ assertEquals(vs.getIdPart(), vs.getIdElement().getIdPart());
+ }
+
+ @Test
+ void searchValueSet() {
+ var sets = repository.search(Bundle.class, ValueSet.class, Searches.byUrl("example.com/ValueSet/456"));
+ assertNotNull(sets);
+ assertEquals(1, sets.getEntry().size());
+ }
+
+ @Test
+ void createAndDeleteLibrary() {
+ var lib = new Library();
+ lib.setId("new-library");
+ var o = repository.create(lib);
+ var created = repository.read(Library.class, o.getId());
+ assertNotNull(created);
+
+ var loc = tempDir.resolve("Library-new-library.json");
+ assertTrue(Files.exists(loc));
+
+ repository.delete(Library.class, created.getIdElement());
+ assertFalse(Files.exists(loc));
+ }
+
+ @Test
+ void createAndDeletePatient() {
+ var p = new Patient();
+ p.setId("new-patient");
+ var o = repository.create(p);
+ var created = repository.read(Patient.class, o.getId());
+ assertNotNull(created);
+
+ var loc = tempDir.resolve("Patient-new-patient.json");
+ assertTrue(Files.exists(loc));
+
+ repository.delete(Patient.class, created.getIdElement());
+ assertFalse(Files.exists(loc));
+ }
+
+ @Test
+ void createAndDeleteValueSet() {
+ var v = new ValueSet();
+ v.setId("new-valueset");
+ var o = repository.create(v);
+ var created = repository.read(ValueSet.class, o.getId());
+ assertNotNull(created);
+
+ var loc = tempDir.resolve("ValueSet-new-valueset.json");
+ assertTrue(Files.exists(loc));
+
+ repository.delete(ValueSet.class, created.getIdElement());
+ assertFalse(Files.exists(loc));
+ }
+
+ @Test
+ void updatePatient() {
+ var id = Ids.newId(Patient.class, "ABC");
+ var p = repository.read(Patient.class, id);
+ assertFalse(p.hasActive());
+
+ p.setActive(true);
+ repository.update(p);
+
+ var updated = repository.read(Patient.class, id);
+ assertTrue(updated.hasActive());
+ assertTrue(updated.getActive());
+ }
+
+ @Test
+ void deleteNonExistentPatient() {
+ var id = Ids.newId(Patient.class, "DoesNotExist");
+ assertThrows(ResourceNotFoundException.class, () -> repository.delete(Patient.class, id));
+ }
+
+ @Test
+ void searchNonExistentType() {
+ var results = repository.search(Bundle.class, Encounter.class, Searches.ALL);
+ assertNotNull(results);
+ assertEquals(0, results.getEntry().size());
+ }
+}
diff --git a/ls/server/src/test/java/org/opencds/cqf/cql/ls/server/repository/ig/standard/MixedEncodingTest.java b/ls/server/src/test/java/org/opencds/cqf/cql/ls/server/repository/ig/standard/MixedEncodingTest.java
new file mode 100644
index 00000000..fd6be6d5
--- /dev/null
+++ b/ls/server/src/test/java/org/opencds/cqf/cql/ls/server/repository/ig/standard/MixedEncodingTest.java
@@ -0,0 +1,181 @@
+package org.opencds.cqf.cql.ls.server.repository.ig.standard;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.repository.IRepository;
+import ca.uhn.fhir.rest.server.exceptions.ForbiddenOperationException;
+import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import org.hl7.fhir.r4.model.*;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+import org.opencds.cqf.fhir.test.Resources;
+import org.opencds.cqf.fhir.utility.Ids;
+import org.opencds.cqf.fhir.utility.search.Searches;
+
+class MixedEncodingTest {
+
+ private static IRepository repository;
+
+ @TempDir
+ static Path tempDir;
+
+ @BeforeAll
+ static void setup() throws URISyntaxException, IOException, ClassNotFoundException {
+ // This copies the sample IG to a temporary directory so that
+ // we can test against an actual filesystem
+ Resources.copyFromJar("/sampleIgs/ig/standard/mixedEncoding", tempDir);
+ repository = new IgStandardRepository(FhirContext.forR4Cached(), tempDir);
+ }
+
+ @Test
+ void readLibrary() {
+ var id = Ids.newId(Library.class, "123");
+ var lib = repository.read(Library.class, id);
+ assertNotNull(lib);
+ assertEquals(id.getIdPart(), lib.getIdElement().getIdPart());
+ }
+
+ @Test
+ void readLibraryNotExists() {
+ var id = Ids.newId(Library.class, "DoesNotExist");
+ assertThrows(ResourceNotFoundException.class, () -> repository.read(Library.class, id));
+ }
+
+ @Test
+ void searchLibrary() {
+ var libs = repository.search(Bundle.class, Library.class, Searches.ALL);
+
+ assertNotNull(libs);
+ assertEquals(1, libs.getEntry().size());
+ }
+
+ @Test
+ void searchLibraryWithFilter() {
+ var libs = repository.search(Bundle.class, Library.class, Searches.byUrl("http://example.com/Library/123"));
+
+ assertNotNull(libs);
+ assertEquals(1, libs.getEntry().size());
+ }
+
+ @Test
+ void searchLibraryNotExists() {
+ var libs = repository.search(Bundle.class, Library.class, Searches.byUrl("not-exists"));
+ assertNotNull(libs);
+ assertEquals(0, libs.getEntry().size());
+ }
+
+ @Test
+ void readValueSet() {
+ var id = Ids.newId(ValueSet.class, "456");
+ var vs = repository.read(ValueSet.class, id);
+
+ assertNotNull(vs);
+ assertEquals(vs.getIdPart(), vs.getIdElement().getIdPart());
+ }
+
+ @Test
+ void searchValueSet() {
+ var sets = repository.search(Bundle.class, ValueSet.class, Searches.byUrl("example.com/ValueSet/456"));
+ assertNotNull(sets);
+ assertEquals(1, sets.getEntry().size());
+ }
+
+ @Test
+ void searchWithExternalValueSet() {
+ var sets = repository.search(Bundle.class, ValueSet.class, Searches.ALL);
+ assertNotNull(sets);
+ assertEquals(2, sets.getEntry().size());
+ }
+
+ @Test
+ void createAndDeleteLibrary() {
+ var lib = new Library();
+ lib.setId("new-library");
+ var o = repository.create(lib);
+ var created = repository.read(Library.class, o.getId());
+ assertNotNull(created);
+
+ var loc = tempDir.resolve("resources/library/new-library.json");
+ assertTrue(Files.exists(loc));
+
+ repository.delete(Library.class, created.getIdElement());
+ assertFalse(Files.exists(loc));
+ }
+
+ @Test
+ void createAndDeletePatient() {
+ var p = new Patient();
+ p.setId("new-patient");
+ var o = repository.create(p);
+ var created = repository.read(Patient.class, o.getId());
+ assertNotNull(created);
+
+ var loc = tempDir.resolve("tests/patient/new-patient.json");
+ assertTrue(Files.exists(loc));
+
+ repository.delete(Patient.class, created.getIdElement());
+ assertFalse(Files.exists(loc));
+ }
+
+ @Test
+ void createAndDeleteValueSet() {
+ var v = new ValueSet();
+ v.setId("new-valueset");
+ var o = repository.create(v);
+ var created = repository.read(ValueSet.class, o.getId());
+ assertNotNull(created);
+
+ var loc = tempDir.resolve("vocabulary/valueset/new-valueset.json");
+ assertTrue(Files.exists(loc));
+
+ repository.delete(ValueSet.class, created.getIdElement());
+ assertFalse(Files.exists(loc));
+ }
+
+ @Test
+ void deleteNonExistentPatient() {
+ var id = Ids.newId(Patient.class, "DoesNotExist");
+ assertThrows(ResourceNotFoundException.class, () -> repository.delete(Patient.class, id));
+ }
+
+ @Test
+ void searchNonExistentType() {
+ var results = repository.search(Bundle.class, Encounter.class, Searches.ALL);
+ assertNotNull(results);
+ assertEquals(0, results.getEntry().size());
+ }
+
+ @Test
+ void readExternalValueSet() {
+ var id = Ids.newId(ValueSet.class, "789");
+ var vs = repository.read(ValueSet.class, id);
+ assertNotNull(vs);
+ assertEquals(vs.getIdPart(), vs.getIdElement().getIdPart());
+
+ // Should be tagged with its source path
+ var path = (Path) vs.getUserData(IgStandardRepository.SOURCE_PATH_TAG);
+ assertNotNull(path);
+ assertTrue(path.toFile().exists());
+ assertTrue(path.toString().contains("external"));
+ }
+
+ @Test
+ void searchExternalValueSet() {
+ var sets = repository.search(Bundle.class, ValueSet.class, Searches.byUrl("example.com/ValueSet/789"));
+ assertNotNull(sets);
+ assertEquals(1, sets.getEntry().size());
+ }
+
+ @Test
+ void updateExternalValueSetFails() {
+ var id = Ids.newId(ValueSet.class, "789");
+ var vs = repository.read(ValueSet.class, id);
+ assertThrows(ForbiddenOperationException.class, () -> repository.update(vs));
+ }
+}
diff --git a/ls/server/src/test/java/org/opencds/cqf/cql/ls/server/repository/ig/standard/MultiMeasureTest.java b/ls/server/src/test/java/org/opencds/cqf/cql/ls/server/repository/ig/standard/MultiMeasureTest.java
new file mode 100644
index 00000000..e1c5fdc7
--- /dev/null
+++ b/ls/server/src/test/java/org/opencds/cqf/cql/ls/server/repository/ig/standard/MultiMeasureTest.java
@@ -0,0 +1,117 @@
+package org.opencds.cqf.cql.ls.server.repository.ig.standard;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.repository.IRepository;
+import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import org.hl7.fhir.r4.model.Library;
+import org.hl7.fhir.r4.model.Patient;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+import org.opencds.cqf.fhir.test.Resources;
+import org.opencds.cqf.fhir.utility.Ids;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MultiMeasureTest {
+ private static final Logger log = LoggerFactory.getLogger(MultiMeasureTest.class);
+
+ private static final String rootDir = "/sampleIgs/ig/standard/cqlMeasures/multiMeasure";
+ private static final String modelPathMeasure100TestCase1111 = "input/tests/measure/measure100/1111";
+ private static final String modelPathMeasure100TestCase2222 = "input/tests/measure/measure100/2222";
+ private static final String modelPathMeasure200TestCase1111 = "input/tests/measure/measure200/1111";
+ private static final String terminologyPath = "input/vocabulary/valueset";
+
+ @TempDir
+ static Path tempDir;
+
+ @TempDir
+ static Path pathModelPathMeasure100TestCase1111;
+
+ @TempDir
+ static Path pathModelPathMeasure100TestCase2222;
+
+ @TempDir
+ static Path pathModelPathMeasure200TestCase1111;
+
+ @TempDir
+ static Path pathTerminology;
+
+ static IRepository model1111Measure100Repo;
+ static IRepository model2222Measure100Repo;
+ static IRepository model1111Measure200Repo;
+ static IRepository terminologyRepo;
+
+ static void listFiles(Path path) {
+ var pathExists = path.toFile().exists();
+ log.info("path[{}] exists: {}", path, pathExists);
+ if (pathExists)
+ try (Stream stream = Files.walk(path)) {
+ String fileNames = stream.map(Path::toString).collect(Collectors.joining("\n "));
+
+ log.info("resources: \n {}", fileNames);
+ } catch (IOException e) {
+ log.error("Exception while capturing filenames. {}", e.getMessage());
+ }
+ }
+
+ @BeforeAll
+ static void setup() throws URISyntaxException, IOException, ClassNotFoundException {
+ // This copies the sample IG to a temporary directory so that
+ // we can test against an actual filesystem
+ Resources.copyFromJar(rootDir, tempDir);
+
+ pathModelPathMeasure100TestCase1111 = tempDir.resolve(modelPathMeasure100TestCase1111);
+ pathModelPathMeasure100TestCase2222 = tempDir.resolve(modelPathMeasure100TestCase2222);
+ pathModelPathMeasure200TestCase1111 = tempDir.resolve(modelPathMeasure200TestCase1111);
+ pathTerminology = tempDir.resolve(terminologyPath);
+
+ model1111Measure100Repo =
+ new IgStandardRepository(FhirContext.forR4Cached(), pathModelPathMeasure100TestCase1111);
+ model2222Measure100Repo =
+ new IgStandardRepository(FhirContext.forR4Cached(), pathModelPathMeasure100TestCase2222);
+ model1111Measure200Repo =
+ new IgStandardRepository(FhirContext.forR4Cached(), pathModelPathMeasure200TestCase1111);
+ terminologyRepo = new IgStandardRepository(FhirContext.forR4Cached(), pathTerminology);
+
+ listFiles(tempDir);
+ listFiles(pathModelPathMeasure100TestCase1111);
+ listFiles(pathModelPathMeasure100TestCase2222);
+ listFiles(pathModelPathMeasure200TestCase1111);
+ listFiles(pathTerminology);
+ }
+
+ @Test
+ void should_throwException_when_libraryDoesNotExist() {
+ var id = Ids.newId(Library.class, "DoesNotExist");
+ assertThrows(ResourceNotFoundException.class, () -> model1111Measure100Repo.read(Library.class, id));
+ assertThrows(ResourceNotFoundException.class, () -> model2222Measure100Repo.read(Library.class, id));
+ assertThrows(ResourceNotFoundException.class, () -> model1111Measure200Repo.read(Library.class, id));
+ assertThrows(ResourceNotFoundException.class, () -> terminologyRepo.read(Library.class, id));
+ }
+
+ // Test works locally but doesn't work on GitHub
+ // @Disabled("Disabled until issue with running test on github is resolved.")
+ @Test
+ void should_findResourceInCorrectRepo_when_resourcesIsolatedByRepo() {
+ var id = Ids.newId(Patient.class, "1111");
+ var patientFrommModel1111Measure100Repo = model1111Measure100Repo.read(Patient.class, id);
+ var patientFrommModel1111Measure200Repo = model1111Measure200Repo.read(Patient.class, id);
+
+ assertEquals(
+ id.getIdPart(),
+ patientFrommModel1111Measure100Repo.getIdElement().getIdPart());
+ assertEquals(
+ id.getIdPart(),
+ patientFrommModel1111Measure200Repo.getIdElement().getIdPart());
+ assertNotEquals(patientFrommModel1111Measure100Repo.getName(), patientFrommModel1111Measure200Repo.getName());
+ }
+}
diff --git a/ls/server/src/test/java/org/opencds/cqf/cql/ls/server/repository/ig/standard/NoTestDataTest.java b/ls/server/src/test/java/org/opencds/cqf/cql/ls/server/repository/ig/standard/NoTestDataTest.java
new file mode 100644
index 00000000..39e4e96d
--- /dev/null
+++ b/ls/server/src/test/java/org/opencds/cqf/cql/ls/server/repository/ig/standard/NoTestDataTest.java
@@ -0,0 +1,141 @@
+package org.opencds.cqf.cql.ls.server.repository.ig.standard;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.repository.IRepository;
+import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import org.hl7.fhir.r4.model.*;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+import org.opencds.cqf.fhir.test.Resources;
+import org.opencds.cqf.fhir.utility.Ids;
+import org.opencds.cqf.fhir.utility.search.Searches;
+
+/**
+ * This set of tests ensures that we can create new directories as needed if
+ * they don't exist ahead of time
+ */
+class NoTestDataTest {
+
+ private static IRepository repository;
+
+ @TempDir
+ static Path tempDir;
+
+ @BeforeAll
+ static void setup() throws URISyntaxException, IOException, ClassNotFoundException {
+ // This copies the sample IG to a temporary directory so that
+ // we can test against an actual filesystem
+ Resources.copyFromJar("/sampleIgs/ig/standard/noTestData", tempDir);
+ repository = new IgStandardRepository(FhirContext.forR4Cached(), tempDir);
+ }
+
+ @Test
+ void createAndDeleteLibrary() {
+ var lib = new Library();
+ lib.setId("new-library");
+ var o = repository.create(lib);
+ var created = repository.read(Library.class, o.getId());
+ assertNotNull(created);
+
+ var loc = tempDir.resolve("resources/library/new-library.json");
+ assertTrue(Files.exists(loc));
+
+ repository.delete(Library.class, created.getIdElement());
+ assertFalse(Files.exists(loc));
+ }
+
+ @Test
+ void createAndDeleteMeasure() {
+ var measure = new Measure();
+ measure.setId("new-measure");
+ var o = repository.create(measure);
+ var created = repository.read(Measure.class, o.getId());
+ assertNotNull(created);
+
+ var loc = tempDir.resolve("resources/measure/new-measure.json");
+ assertTrue(Files.exists(loc));
+
+ repository.delete(Measure.class, created.getIdElement());
+ assertFalse(Files.exists(loc));
+ }
+
+ @Test
+ void createAndDeletePatient() {
+ var p = new Patient();
+ p.setId("new-patient");
+ var o = repository.create(p);
+ var created = repository.read(Patient.class, o.getId());
+ assertNotNull(created);
+
+ var loc = tempDir.resolve("tests/patient/new-patient.json");
+ assertTrue(Files.exists(loc));
+
+ repository.delete(Patient.class, created.getIdElement());
+ assertFalse(Files.exists(loc));
+ }
+
+ @Test
+ void createAndDeleteCondition() {
+ var p = new Condition();
+ p.setId("new-condition");
+ var o = repository.create(p);
+ var created = repository.read(Condition.class, o.getId());
+ assertNotNull(created);
+
+ var loc = tempDir.resolve("tests/condition/new-condition.json");
+ assertTrue(Files.exists(loc));
+
+ repository.delete(Condition.class, created.getIdElement());
+ assertFalse(Files.exists(loc));
+ }
+
+ @Test
+ void createAndDeleteValueSet() {
+ var v = new ValueSet();
+ v.setId("new-valueset");
+ var o = repository.create(v);
+ var created = repository.read(ValueSet.class, o.getId());
+ assertNotNull(created);
+
+ var loc = tempDir.resolve("vocabulary/valueset/new-valueset.json");
+ assertTrue(Files.exists(loc));
+
+ repository.delete(ValueSet.class, created.getIdElement());
+ assertFalse(Files.exists(loc));
+ }
+
+ @Test
+ void createAndDeleteCodeSystem() {
+ var c = new CodeSystem();
+ c.setId("new-codesystem");
+ var o = repository.create(c);
+ var created = repository.read(CodeSystem.class, o.getId());
+ assertNotNull(created);
+
+ var loc = tempDir.resolve("vocabulary/codesystem/new-codesystem.json");
+ assertTrue(Files.exists(loc));
+
+ repository.delete(CodeSystem.class, created.getIdElement());
+ assertFalse(Files.exists(loc));
+ }
+
+ @Test
+ void deleteNonExistentPatient() {
+ var id = Ids.newId(Patient.class, "DoesNotExist");
+ assertThrows(ResourceNotFoundException.class, () -> repository.delete(Patient.class, id));
+ }
+
+ @Test
+ void searchNonExistentType() {
+ var results = repository.search(Bundle.class, Encounter.class, Searches.ALL);
+ assertNotNull(results);
+ assertEquals(0, results.getEntry().size());
+ }
+}
diff --git a/ls/server/src/test/java/org/opencds/cqf/cql/ls/server/repository/ig/standard/OverwriteEncodingTest.java b/ls/server/src/test/java/org/opencds/cqf/cql/ls/server/repository/ig/standard/OverwriteEncodingTest.java
new file mode 100644
index 00000000..a432871f
--- /dev/null
+++ b/ls/server/src/test/java/org/opencds/cqf/cql/ls/server/repository/ig/standard/OverwriteEncodingTest.java
@@ -0,0 +1,62 @@
+package org.opencds.cqf.cql.ls.server.repository.ig.standard;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.repository.IRepository;
+import ca.uhn.fhir.rest.api.EncodingEnum;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.nio.file.Path;
+import org.hl7.fhir.r4.model.Library;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+import org.opencds.cqf.fhir.test.Resources;
+import org.opencds.cqf.fhir.utility.Ids;
+
+class OverwriteEncodingTest {
+
+ private static IRepository repository;
+
+ @TempDir
+ static Path tempDir;
+
+ @BeforeAll
+ static void setup() throws URISyntaxException, IOException, ClassNotFoundException {
+ // This copies the sample IG to a temporary directory so that
+ // we can test against an actual filesystem
+ Resources.copyFromJar("/sampleIgs/ig/standard/mixedEncoding", tempDir);
+ var conventions = IgStandardConventions.autoDetect(tempDir);
+ repository = new IgStandardRepository(
+ FhirContext.forR4Cached(),
+ tempDir,
+ conventions,
+ new IgStandardEncodingBehavior(
+ EncodingEnum.XML,
+ IgStandardEncodingBehavior.PreserveEncoding.OVERWRITE_WITH_PREFERRED_ENCODING),
+ null);
+ }
+
+ @Test
+ void readLibrary() {
+ var id = Ids.newId(Library.class, "123");
+ var lib = repository.read(Library.class, id);
+ assertNotNull(lib);
+ assertEquals(id.getIdPart(), lib.getIdElement().getIdPart());
+ }
+
+ @Test
+ void updateLibrary() {
+ var id = Ids.newId(Library.class, "123");
+ var lib = repository.read(Library.class, id);
+ assertNotNull(lib);
+ assertEquals(id.getIdPart(), lib.getIdElement().getIdPart());
+
+ lib.addAuthor().setName("Test Author");
+
+ repository.update(lib);
+ assertFalse(tempDir.resolve("resources/library/123.json").toFile().exists());
+ assertTrue(tempDir.resolve("resources/library/123.xml").toFile().exists());
+ }
+}
diff --git a/ls/server/src/test/java/org/opencds/cqf/cql/ls/server/repository/ig/standard/PrefixTest.java b/ls/server/src/test/java/org/opencds/cqf/cql/ls/server/repository/ig/standard/PrefixTest.java
new file mode 100644
index 00000000..a2f6d9b2
--- /dev/null
+++ b/ls/server/src/test/java/org/opencds/cqf/cql/ls/server/repository/ig/standard/PrefixTest.java
@@ -0,0 +1,221 @@
+package org.opencds.cqf.cql.ls.server.repository.ig.standard;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.repository.IRepository;
+import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import org.hl7.fhir.r4.model.*;
+import org.junit.jupiter.api.*;
+import org.junit.jupiter.api.io.TempDir;
+import org.opencds.cqf.fhir.test.Resources;
+import org.opencds.cqf.fhir.utility.Ids;
+import org.opencds.cqf.fhir.utility.search.Searches;
+
+@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
+class PrefixTest {
+
+ private static IRepository repository;
+
+ @TempDir
+ static Path tempDir;
+
+ @BeforeAll
+ static void setup() throws URISyntaxException, IOException, ClassNotFoundException {
+ // This copies the sample IG to a temporary directory so that
+ // we can test against an actual filesystem
+ Resources.copyFromJar("/sampleIgs/ig/standard/directoryPerType/prefixed", tempDir);
+ repository = new IgStandardRepository(FhirContext.forR4Cached(), tempDir);
+ }
+
+ @Test
+ void readLibrary() {
+ var id = Ids.newId(Library.class, "123");
+ var lib = repository.read(Library.class, id);
+ assertNotNull(lib);
+ assertEquals(id.getIdPart(), lib.getIdElement().getIdPart());
+ }
+
+ @Test
+ void readLibraryNotExists() {
+ var id = Ids.newId(Library.class, "DoesNotExist");
+ assertThrows(ResourceNotFoundException.class, () -> repository.read(Library.class, id));
+ }
+
+ @Test
+ void searchLibrary() {
+ var libs = repository.search(Bundle.class, Library.class, Searches.ALL);
+
+ assertNotNull(libs);
+ assertEquals(2, libs.getEntry().size());
+ }
+
+ @Test
+ void searchLibraryWithFilter() {
+ var libs = repository.search(Bundle.class, Library.class, Searches.byUrl("http://example.com/Library/Test"));
+
+ assertNotNull(libs);
+ assertEquals(1, libs.getEntry().size());
+ }
+
+ @Test
+ void searchLibraryNotExists() {
+ var libs = repository.search(Bundle.class, Library.class, Searches.byUrl("not-exists"));
+ assertNotNull(libs);
+ assertEquals(0, libs.getEntry().size());
+ }
+
+ @Test
+ void readPatient() {
+ var id = Ids.newId(Patient.class, "ABC");
+ var cond = repository.read(Patient.class, id);
+
+ assertNotNull(cond);
+ assertEquals(id.getIdPart(), cond.getIdElement().getIdPart());
+ }
+
+ @Test
+ void searchCondition() {
+ var cons = repository.search(
+ Bundle.class, Condition.class, Searches.byCodeAndSystem("12345", "example.com/codesystem"));
+ assertNotNull(cons);
+ assertEquals(2, cons.getEntry().size());
+ }
+
+ @Test
+ void readValueSet() {
+ var id = Ids.newId(ValueSet.class, "456");
+ var vs = repository.read(ValueSet.class, id);
+
+ assertNotNull(vs);
+ assertEquals(vs.getIdPart(), vs.getIdElement().getIdPart());
+ }
+
+ @Test
+ void searchValueSet() {
+ var sets = repository.search(Bundle.class, ValueSet.class, Searches.byUrl("example.com/ValueSet/456"));
+ assertNotNull(sets);
+ assertEquals(1, sets.getEntry().size());
+ }
+
+ @Test
+ void createAndDeleteLibrary() {
+ var lib = new Library();
+ lib.setId("new-library");
+ var o = repository.create(lib);
+ var created = repository.read(Library.class, o.getId());
+ assertNotNull(created);
+
+ var loc = tempDir.resolve("resources/library/Library-new-library.json");
+ assertTrue(Files.exists(loc));
+
+ repository.delete(Library.class, created.getIdElement());
+ assertFalse(Files.exists(loc));
+ }
+
+ @Test
+ void createAndDeletePatient() {
+ var p = new Patient();
+ p.setId("new-patient");
+ var o = repository.create(p);
+ var created = repository.read(Patient.class, o.getId());
+ assertNotNull(created);
+
+ var loc = tempDir.resolve("tests/patient/Patient-new-patient.json");
+ assertTrue(Files.exists(loc));
+
+ repository.delete(Patient.class, created.getIdElement());
+ assertFalse(Files.exists(loc));
+ }
+
+ @Test
+ void createAndDeleteValueSet() {
+ var v = new ValueSet();
+ v.setId("new-valueset");
+ var o = repository.create(v);
+ var created = repository.read(ValueSet.class, o.getId());
+ assertNotNull(created);
+
+ var loc = tempDir.resolve("vocabulary/valueset/ValueSet-new-valueset.json");
+ assertTrue(Files.exists(loc));
+
+ repository.delete(ValueSet.class, created.getIdElement());
+ assertFalse(Files.exists(loc));
+ }
+
+ @Test
+ void updatePatient() {
+ var id = Ids.newId(Patient.class, "ABC");
+ var p = repository.read(Patient.class, id);
+ assertFalse(p.hasActive());
+
+ p.setActive(true);
+ repository.update(p);
+
+ var updated = repository.read(Patient.class, id);
+ assertTrue(updated.hasActive());
+ assertTrue(updated.getActive());
+ }
+
+ @Test
+ void deleteNonExistentPatient() {
+ var id = Ids.newId(Patient.class, "DoesNotExist");
+ assertThrows(ResourceNotFoundException.class, () -> repository.delete(Patient.class, id));
+ }
+
+ @Test
+ void searchNonExistentType() {
+ var results = repository.search(Bundle.class, Encounter.class, Searches.ALL);
+ assertNotNull(results);
+ assertEquals(0, results.getEntry().size());
+ }
+
+ @Test
+ void searchById() {
+ var bundle = repository.search(Bundle.class, Library.class, Searches.byId("123"));
+ assertNotNull(bundle);
+ assertEquals(1, bundle.getEntry().size());
+ }
+
+ @Test
+ void searchByIdNotFound() {
+ var bundle = repository.search(Bundle.class, Library.class, Searches.byId("DoesNotExist"));
+ assertNotNull(bundle);
+ assertEquals(0, bundle.getEntry().size());
+ }
+
+ @Test
+ @Order(1) // Do this test first because it puts the filesystem (temporarily) in an invalid state
+ void resourceMissingWhenCacheCleared() throws IOException {
+ var id = new IdType("Library", "ToDelete");
+ var lib = new Library().setIdElement(id);
+ var path = tempDir.resolve("resources/library/Library-ToDelete.json");
+
+ repository.create(lib);
+ assertTrue(path.toFile().exists());
+
+ // Read back, should exist
+ lib = repository.read(Library.class, id);
+ assertNotNull(lib);
+
+ // Overwrite the file on disk.
+ Files.writeString(path, "");
+
+ // Read from cache, repo doesn't know the content is gone.
+ lib = repository.read(Library.class, id);
+ assertNotNull(lib);
+ assertEquals("ToDelete", lib.getIdElement().getIdPart());
+
+ ((IgStandardRepository) repository).clearCache();
+
+ // Try to read again, should be gone because it's not in the cache and the content is gone.
+ assertThrows(ResourceNotFoundException.class, () -> repository.read(Library.class, id));
+
+ // Clean up so that we don't affect other tests
+ path.toFile().delete();
+ }
+}
diff --git a/ls/server/src/test/java/org/opencds/cqf/cql/ls/server/repository/ig/standard/XmlWriteTest.java b/ls/server/src/test/java/org/opencds/cqf/cql/ls/server/repository/ig/standard/XmlWriteTest.java
new file mode 100644
index 00000000..7821c83d
--- /dev/null
+++ b/ls/server/src/test/java/org/opencds/cqf/cql/ls/server/repository/ig/standard/XmlWriteTest.java
@@ -0,0 +1,95 @@
+package org.opencds.cqf.cql.ls.server.repository.ig.standard;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.repository.IRepository;
+import ca.uhn.fhir.rest.api.EncodingEnum;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import org.hl7.fhir.r4.model.Bundle;
+import org.hl7.fhir.r4.model.Library;
+import org.hl7.fhir.r4.model.Patient;
+import org.hl7.fhir.r4.model.ValueSet;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+import org.opencds.cqf.fhir.test.Resources;
+import org.opencds.cqf.fhir.utility.Ids;
+import org.opencds.cqf.fhir.utility.search.Searches;
+
+class XmlWriteTest {
+
+ private static IRepository repository;
+
+ @TempDir
+ static Path tempDir;
+
+ @BeforeAll
+ static void setup() throws URISyntaxException, IOException, ClassNotFoundException {
+ // This copies the sample IG to a temporary directory so that
+ // we can test against an actual filesystem
+ Resources.copyFromJar("/sampleIgs/ig/standard/mixedEncoding", tempDir);
+ var conventions = IgStandardConventions.autoDetect(tempDir);
+ repository = new IgStandardRepository(
+ FhirContext.forR4Cached(),
+ tempDir,
+ conventions,
+ new IgStandardEncodingBehavior(
+ EncodingEnum.XML, IgStandardEncodingBehavior.PreserveEncoding.PRESERVE_ORIGINAL_ENCODING),
+ null);
+ }
+
+ @Test
+ void createAndDeleteLibrary() {
+ var lib = new Library();
+ lib.setId("new-library");
+ var o = repository.create(lib);
+ var created = repository.read(Library.class, o.getId());
+ assertNotNull(created);
+
+ var loc = tempDir.resolve("resources/library/new-library.xml");
+ assertTrue(Files.exists(loc));
+
+ repository.delete(Library.class, created.getIdElement());
+ assertFalse(Files.exists(loc));
+ }
+
+ @Test
+ void createAndDeletePatient() {
+ var p = new Patient();
+ p.setId("new-patient");
+ var o = repository.create(p);
+ var created = repository.read(Patient.class, o.getId());
+ assertNotNull(created);
+
+ var loc = tempDir.resolve("tests/patient/new-patient.xml");
+ assertTrue(Files.exists(loc));
+
+ repository.delete(Patient.class, created.getIdElement());
+ assertFalse(Files.exists(loc));
+ }
+
+ @Test
+ void readExternalValueSet() {
+ var id = Ids.newId(ValueSet.class, "789");
+ var vs = repository.read(ValueSet.class, id);
+ assertNotNull(vs);
+ assertEquals(vs.getIdPart(), vs.getIdElement().getIdPart());
+
+ // Should be tagged with its source path
+ var path = (Path) vs.getUserData(IgStandardRepository.SOURCE_PATH_TAG);
+ assertNotNull(path);
+ assertTrue(path.toFile().exists());
+ assertTrue(path.toString().contains("external"));
+ }
+
+ @Test
+ void searchExternalValueSet() {
+ var sets = repository.search(Bundle.class, ValueSet.class, Searches.byUrl("example.com/ValueSet/789"));
+ assertNotNull(sets);
+ assertEquals(1, sets.getEntry().size());
+ }
+}
diff --git a/ls/server/src/test/java/org/opencds/cqf/cql/ls/server/visitor/ExpressionTrackBackVisitorTest.java b/ls/server/src/test/java/org/opencds/cqf/cql/ls/server/visitor/ExpressionTrackBackVisitorTest.java
index 78ebdc64..0b207429 100644
--- a/ls/server/src/test/java/org/opencds/cqf/cql/ls/server/visitor/ExpressionTrackBackVisitorTest.java
+++ b/ls/server/src/test/java/org/opencds/cqf/cql/ls/server/visitor/ExpressionTrackBackVisitorTest.java
@@ -5,7 +5,7 @@
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
-import org.cqframework.cql.elm.tracking.TrackBack;
+import org.cqframework.cql.cql2elm.tracking.TrackBack;
import org.hl7.elm.r1.Element;
import org.hl7.elm.r1.ExpressionDef;
import org.hl7.elm.r1.Library;
diff --git a/ls/server/src/test/resources/provider/content/sample-library-1.0.0.json b/ls/server/src/test/resources/provider/content/sample-library-1.0.0.json
new file mode 100644
index 00000000..1eb1024e
--- /dev/null
+++ b/ls/server/src/test/resources/provider/content/sample-library-1.0.0.json
@@ -0,0 +1,16 @@
+{
+ "resourceType": "Library",
+ "id": "sample-library",
+ "version" : "1.0.0",
+ "name" : "SampleLibrary",
+ "title" : "Sample Library",
+ "status" : "active",
+ "experimental" : true,
+ "type" : {
+ "coding" : [{
+ "system" : "http://terminology.hl7.org/CodeSystem/library-type",
+ "code" : "logic-library",
+ "display" : "Logic Library"
+ }]
+ }
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/provider/content/sample-library-2.0.0.json b/ls/server/src/test/resources/provider/content/sample-library-2.0.0.json
new file mode 100644
index 00000000..7d389ff8
--- /dev/null
+++ b/ls/server/src/test/resources/provider/content/sample-library-2.0.0.json
@@ -0,0 +1,16 @@
+{
+ "resourceType": "Library",
+ "id": "sample-library",
+ "version" : "2.0.0",
+ "name" : "SampleLibrary",
+ "title" : "Sample Library",
+ "status" : "active",
+ "experimental" : true,
+ "type" : {
+ "coding" : [{
+ "system" : "http://terminology.hl7.org/CodeSystem/library-type",
+ "code" : "logic-library",
+ "display" : "Logic Library"
+ }]
+ }
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/badData/tests/patient/InvalidContent.json b/ls/server/src/test/resources/sampleIgs/ig/standard/badData/tests/patient/InvalidContent.json
new file mode 100644
index 00000000..0c5f31f3
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/badData/tests/patient/InvalidContent.json
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/badData/tests/patient/MissingId.json b/ls/server/src/test/resources/sampleIgs/ig/standard/badData/tests/patient/MissingId.json
new file mode 100644
index 00000000..5dd7c706
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/badData/tests/patient/MissingId.json
@@ -0,0 +1,3 @@
+{
+ "resourceType": "Patient"
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/badData/tests/patient/NoContent.json b/ls/server/src/test/resources/sampleIgs/ig/standard/badData/tests/patient/NoContent.json
new file mode 100644
index 00000000..e69de29b
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/badData/tests/patient/NotAFhirFile b/ls/server/src/test/resources/sampleIgs/ig/standard/badData/tests/patient/NotAFhirFile
new file mode 100644
index 00000000..b75e5685
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/badData/tests/patient/NotAFhirFile
@@ -0,0 +1 @@
+// Intentionally empty file that tests to ensure we ignore non-FHIR files
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/badData/tests/patient/WrongId.json b/ls/server/src/test/resources/sampleIgs/ig/standard/badData/tests/patient/WrongId.json
new file mode 100644
index 00000000..f5620252
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/badData/tests/patient/WrongId.json
@@ -0,0 +1,4 @@
+{
+ "resourceType": "Patient",
+ "id": "DoesntMatchFilename"
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/badData/tests/patient/WrongResourceType.json b/ls/server/src/test/resources/sampleIgs/ig/standard/badData/tests/patient/WrongResourceType.json
new file mode 100644
index 00000000..a5f91d61
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/badData/tests/patient/WrongResourceType.json
@@ -0,0 +1,4 @@
+{
+ "resourceType": "Encounter",
+ "id": "WrongResourceType"
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/badData/tests/patient/WrongVersion.json b/ls/server/src/test/resources/sampleIgs/ig/standard/badData/tests/patient/WrongVersion.json
new file mode 100644
index 00000000..c37a88a8
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/badData/tests/patient/WrongVersion.json
@@ -0,0 +1,7 @@
+{
+ "resourceType": "Patient",
+ "id": "WrongVersion",
+ "meta": {
+ "versionId": "2"
+ }
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/compartment/resources/library/123.json b/ls/server/src/test/resources/sampleIgs/ig/standard/compartment/resources/library/123.json
new file mode 100644
index 00000000..b026b65f
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/compartment/resources/library/123.json
@@ -0,0 +1,4 @@
+{
+ "resourceType": "Library",
+ "id": "123"
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/compartment/resources/library/456.json b/ls/server/src/test/resources/sampleIgs/ig/standard/compartment/resources/library/456.json
new file mode 100644
index 00000000..7e88b654
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/compartment/resources/library/456.json
@@ -0,0 +1,4 @@
+{
+ "resourceType": "Library",
+ "id": "456"
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/compartment/tests/patient/123/encounter/ABC.json b/ls/server/src/test/resources/sampleIgs/ig/standard/compartment/tests/patient/123/encounter/ABC.json
new file mode 100644
index 00000000..881455a8
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/compartment/tests/patient/123/encounter/ABC.json
@@ -0,0 +1,7 @@
+{
+ "resourceType": "Encounter",
+ "id": "ABC",
+ "subject": {
+ "reference": "Patient/123"
+ }
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/compartment/tests/patient/123/patient/123.json b/ls/server/src/test/resources/sampleIgs/ig/standard/compartment/tests/patient/123/patient/123.json
new file mode 100644
index 00000000..7445fac0
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/compartment/tests/patient/123/patient/123.json
@@ -0,0 +1,4 @@
+{
+ "resourceType": "Patient",
+ "id": "123"
+}
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/compartment/tests/patient/456/encounter/DEF.json b/ls/server/src/test/resources/sampleIgs/ig/standard/compartment/tests/patient/456/encounter/DEF.json
new file mode 100644
index 00000000..5ef8a507
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/compartment/tests/patient/456/encounter/DEF.json
@@ -0,0 +1,7 @@
+{
+ "resourceType": "Encounter",
+ "id": "DEF",
+ "subject": {
+ "reference": "Patient/456"
+ }
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/compartment/tests/patient/456/patient/456.json b/ls/server/src/test/resources/sampleIgs/ig/standard/compartment/tests/patient/456/patient/456.json
new file mode 100644
index 00000000..4f8e71f5
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/compartment/tests/patient/456/patient/456.json
@@ -0,0 +1,4 @@
+{
+ "resourceType": "Patient",
+ "id": "456"
+}
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/compartment/vocabulary/valueset/456.json b/ls/server/src/test/resources/sampleIgs/ig/standard/compartment/vocabulary/valueset/456.json
new file mode 100644
index 00000000..3ad4292a
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/compartment/vocabulary/valueset/456.json
@@ -0,0 +1,5 @@
+{
+ "resourceType": "ValueSet",
+ "id": "456",
+ "url": "example.com/ValueSet/456"
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/cqlContent/cql/Test.cql b/ls/server/src/test/resources/sampleIgs/ig/standard/cqlContent/cql/Test.cql
new file mode 100644
index 00000000..aeed429d
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/cqlContent/cql/Test.cql
@@ -0,0 +1 @@
+library Test
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/cqlMeasures/multiMeasure/input/cql/measure100.cql b/ls/server/src/test/resources/sampleIgs/ig/standard/cqlMeasures/multiMeasure/input/cql/measure100.cql
new file mode 100644
index 00000000..e69de29b
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/cqlMeasures/multiMeasure/input/cql/measure200.cql b/ls/server/src/test/resources/sampleIgs/ig/standard/cqlMeasures/multiMeasure/input/cql/measure200.cql
new file mode 100644
index 00000000..e69de29b
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/cqlMeasures/multiMeasure/input/tests/measure/measure100/1111/Encounter-1234.json b/ls/server/src/test/resources/sampleIgs/ig/standard/cqlMeasures/multiMeasure/input/tests/measure/measure100/1111/Encounter-1234.json
new file mode 100644
index 00000000..327442f6
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/cqlMeasures/multiMeasure/input/tests/measure/measure100/1111/Encounter-1234.json
@@ -0,0 +1,4 @@
+{
+ "resourceType": "Encounter",
+ "id": "1234"
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/cqlMeasures/multiMeasure/input/tests/measure/measure100/1111/Patient-1111.json b/ls/server/src/test/resources/sampleIgs/ig/standard/cqlMeasures/multiMeasure/input/tests/measure/measure100/1111/Patient-1111.json
new file mode 100644
index 00000000..b6f0bb57
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/cqlMeasures/multiMeasure/input/tests/measure/measure100/1111/Patient-1111.json
@@ -0,0 +1,7 @@
+{
+ "resourceType": "Patient",
+ "id": "1111",
+ "name": [ {
+ "family": "measure100"
+ } ]
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/cqlMeasures/multiMeasure/input/tests/measure/measure100/2222/Encounter-5678.json b/ls/server/src/test/resources/sampleIgs/ig/standard/cqlMeasures/multiMeasure/input/tests/measure/measure100/2222/Encounter-5678.json
new file mode 100644
index 00000000..aebd3dcb
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/cqlMeasures/multiMeasure/input/tests/measure/measure100/2222/Encounter-5678.json
@@ -0,0 +1,4 @@
+{
+ "resourceType": "Encounter",
+ "id": "5678"
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/cqlMeasures/multiMeasure/input/tests/measure/measure100/2222/Patient-2222.json b/ls/server/src/test/resources/sampleIgs/ig/standard/cqlMeasures/multiMeasure/input/tests/measure/measure100/2222/Patient-2222.json
new file mode 100644
index 00000000..188b9756
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/cqlMeasures/multiMeasure/input/tests/measure/measure100/2222/Patient-2222.json
@@ -0,0 +1,7 @@
+{
+ "resourceType": "Patient",
+ "id": "2222",
+ "name": [ {
+ "family": "measure100"
+ } ]
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/cqlMeasures/multiMeasure/input/tests/measure/measure200/1111/Observation-1234.json b/ls/server/src/test/resources/sampleIgs/ig/standard/cqlMeasures/multiMeasure/input/tests/measure/measure200/1111/Observation-1234.json
new file mode 100644
index 00000000..7f69b186
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/cqlMeasures/multiMeasure/input/tests/measure/measure200/1111/Observation-1234.json
@@ -0,0 +1,4 @@
+{
+ "resourceType": "Observation",
+ "id": "1234"
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/cqlMeasures/multiMeasure/input/tests/measure/measure200/1111/Patient-1111.json b/ls/server/src/test/resources/sampleIgs/ig/standard/cqlMeasures/multiMeasure/input/tests/measure/measure200/1111/Patient-1111.json
new file mode 100644
index 00000000..e319db3b
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/cqlMeasures/multiMeasure/input/tests/measure/measure200/1111/Patient-1111.json
@@ -0,0 +1,7 @@
+{
+ "resourceType": "Patient",
+ "id": "1111",
+ "name": [ {
+ "family": "measure200"
+ } ]
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/cqlMeasures/multiMeasure/input/vocabulary/valueset/external/ValueSet-1234.json b/ls/server/src/test/resources/sampleIgs/ig/standard/cqlMeasures/multiMeasure/input/vocabulary/valueset/external/ValueSet-1234.json
new file mode 100644
index 00000000..b0f3f124
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/cqlMeasures/multiMeasure/input/vocabulary/valueset/external/ValueSet-1234.json
@@ -0,0 +1,5 @@
+{
+ "resourceType": "ValueSet",
+ "id": "1234",
+ "name": "ValueSet-1234"
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/cqlMeasures/multiMeasure/input/vocabulary/valueset/external/ValueSet-5678.json b/ls/server/src/test/resources/sampleIgs/ig/standard/cqlMeasures/multiMeasure/input/vocabulary/valueset/external/ValueSet-5678.json
new file mode 100644
index 00000000..cd993554
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/cqlMeasures/multiMeasure/input/vocabulary/valueset/external/ValueSet-5678.json
@@ -0,0 +1,5 @@
+{
+ "resourceType": "ValueSet",
+ "id": "5678",
+ "name": "ValueSet-5678"
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/directoryPerType/prefixed/cql/Example.cql b/ls/server/src/test/resources/sampleIgs/ig/standard/directoryPerType/prefixed/cql/Example.cql
new file mode 100644
index 00000000..aeed429d
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/directoryPerType/prefixed/cql/Example.cql
@@ -0,0 +1 @@
+library Test
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/directoryPerType/prefixed/resources/library/Library-123.json b/ls/server/src/test/resources/sampleIgs/ig/standard/directoryPerType/prefixed/resources/library/Library-123.json
new file mode 100644
index 00000000..1bfad9f5
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/directoryPerType/prefixed/resources/library/Library-123.json
@@ -0,0 +1,10 @@
+{
+ "resourceType": "Library",
+ "id": "123",
+ "name": "Test",
+ "url": "http://example.com/Library/Test",
+ "content": {
+ "contentType": "text/cql",
+ "url": "../../cql/Example.cql"
+ }
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/directoryPerType/prefixed/resources/library/Library-456.json b/ls/server/src/test/resources/sampleIgs/ig/standard/directoryPerType/prefixed/resources/library/Library-456.json
new file mode 100644
index 00000000..3adffbfd
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/directoryPerType/prefixed/resources/library/Library-456.json
@@ -0,0 +1,6 @@
+{
+ "resourceType": "Library",
+ "id": "456",
+ "name": "NotTest",
+ "url": "http://example.com/Library/NotTest"
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/directoryPerType/prefixed/resources/measure/Measure-XYZ.json b/ls/server/src/test/resources/sampleIgs/ig/standard/directoryPerType/prefixed/resources/measure/Measure-XYZ.json
new file mode 100644
index 00000000..e13b0247
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/directoryPerType/prefixed/resources/measure/Measure-XYZ.json
@@ -0,0 +1,4 @@
+{
+ "resourceType": "Measure",
+ "id": "XYZ"
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/directoryPerType/prefixed/tests/condition/Condition-DEF.json b/ls/server/src/test/resources/sampleIgs/ig/standard/directoryPerType/prefixed/tests/condition/Condition-DEF.json
new file mode 100644
index 00000000..65447c1d
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/directoryPerType/prefixed/tests/condition/Condition-DEF.json
@@ -0,0 +1,12 @@
+{
+ "resourceType": "Condition",
+ "id": "DEF",
+ "code": {
+ "coding": [
+ {
+ "system": "example.com/codesystem",
+ "code": "12345"
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/directoryPerType/prefixed/tests/condition/Condition-GHI.json b/ls/server/src/test/resources/sampleIgs/ig/standard/directoryPerType/prefixed/tests/condition/Condition-GHI.json
new file mode 100644
index 00000000..62aa77f7
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/directoryPerType/prefixed/tests/condition/Condition-GHI.json
@@ -0,0 +1,12 @@
+{
+ "resourceType": "Condition",
+ "id": "GHI",
+ "code": {
+ "coding": [
+ {
+ "system": "example.com/codesystem",
+ "code": "12345"
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/directoryPerType/prefixed/tests/condition/Condition-JKL.json b/ls/server/src/test/resources/sampleIgs/ig/standard/directoryPerType/prefixed/tests/condition/Condition-JKL.json
new file mode 100644
index 00000000..caecea4e
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/directoryPerType/prefixed/tests/condition/Condition-JKL.json
@@ -0,0 +1,12 @@
+{
+ "resourceType": "Condition",
+ "id": "JKL",
+ "code": {
+ "coding": [
+ {
+ "system": "example.com/codesystem",
+ "code": "000000"
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/directoryPerType/prefixed/tests/patient/Patient-ABC.json b/ls/server/src/test/resources/sampleIgs/ig/standard/directoryPerType/prefixed/tests/patient/Patient-ABC.json
new file mode 100644
index 00000000..30e01de9
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/directoryPerType/prefixed/tests/patient/Patient-ABC.json
@@ -0,0 +1,4 @@
+{
+ "resourceType": "Patient",
+ "id": "ABC"
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/directoryPerType/prefixed/vocabulary/valueset/ValueSet-456.json b/ls/server/src/test/resources/sampleIgs/ig/standard/directoryPerType/prefixed/vocabulary/valueset/ValueSet-456.json
new file mode 100644
index 00000000..3ad4292a
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/directoryPerType/prefixed/vocabulary/valueset/ValueSet-456.json
@@ -0,0 +1,5 @@
+{
+ "resourceType": "ValueSet",
+ "id": "456",
+ "url": "example.com/ValueSet/456"
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/directoryPerType/standard/cql/Example.cql b/ls/server/src/test/resources/sampleIgs/ig/standard/directoryPerType/standard/cql/Example.cql
new file mode 100644
index 00000000..aeed429d
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/directoryPerType/standard/cql/Example.cql
@@ -0,0 +1 @@
+library Test
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/directoryPerType/standard/resources/library/123.json b/ls/server/src/test/resources/sampleIgs/ig/standard/directoryPerType/standard/resources/library/123.json
new file mode 100644
index 00000000..1bfad9f5
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/directoryPerType/standard/resources/library/123.json
@@ -0,0 +1,10 @@
+{
+ "resourceType": "Library",
+ "id": "123",
+ "name": "Test",
+ "url": "http://example.com/Library/Test",
+ "content": {
+ "contentType": "text/cql",
+ "url": "../../cql/Example.cql"
+ }
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/directoryPerType/standard/resources/library/456.json b/ls/server/src/test/resources/sampleIgs/ig/standard/directoryPerType/standard/resources/library/456.json
new file mode 100644
index 00000000..3adffbfd
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/directoryPerType/standard/resources/library/456.json
@@ -0,0 +1,6 @@
+{
+ "resourceType": "Library",
+ "id": "456",
+ "name": "NotTest",
+ "url": "http://example.com/Library/NotTest"
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/directoryPerType/standard/resources/measure/XYZ.json b/ls/server/src/test/resources/sampleIgs/ig/standard/directoryPerType/standard/resources/measure/XYZ.json
new file mode 100644
index 00000000..e13b0247
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/directoryPerType/standard/resources/measure/XYZ.json
@@ -0,0 +1,4 @@
+{
+ "resourceType": "Measure",
+ "id": "XYZ"
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/directoryPerType/standard/tests/condition/DEF.json b/ls/server/src/test/resources/sampleIgs/ig/standard/directoryPerType/standard/tests/condition/DEF.json
new file mode 100644
index 00000000..65447c1d
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/directoryPerType/standard/tests/condition/DEF.json
@@ -0,0 +1,12 @@
+{
+ "resourceType": "Condition",
+ "id": "DEF",
+ "code": {
+ "coding": [
+ {
+ "system": "example.com/codesystem",
+ "code": "12345"
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/directoryPerType/standard/tests/condition/GHI.json b/ls/server/src/test/resources/sampleIgs/ig/standard/directoryPerType/standard/tests/condition/GHI.json
new file mode 100644
index 00000000..62aa77f7
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/directoryPerType/standard/tests/condition/GHI.json
@@ -0,0 +1,12 @@
+{
+ "resourceType": "Condition",
+ "id": "GHI",
+ "code": {
+ "coding": [
+ {
+ "system": "example.com/codesystem",
+ "code": "12345"
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/directoryPerType/standard/tests/condition/JKL.json b/ls/server/src/test/resources/sampleIgs/ig/standard/directoryPerType/standard/tests/condition/JKL.json
new file mode 100644
index 00000000..caecea4e
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/directoryPerType/standard/tests/condition/JKL.json
@@ -0,0 +1,12 @@
+{
+ "resourceType": "Condition",
+ "id": "JKL",
+ "code": {
+ "coding": [
+ {
+ "system": "example.com/codesystem",
+ "code": "000000"
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/directoryPerType/standard/tests/patient/ABC.json b/ls/server/src/test/resources/sampleIgs/ig/standard/directoryPerType/standard/tests/patient/ABC.json
new file mode 100644
index 00000000..30e01de9
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/directoryPerType/standard/tests/patient/ABC.json
@@ -0,0 +1,4 @@
+{
+ "resourceType": "Patient",
+ "id": "ABC"
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/directoryPerType/standard/vocabulary/valueset/456.json b/ls/server/src/test/resources/sampleIgs/ig/standard/directoryPerType/standard/vocabulary/valueset/456.json
new file mode 100644
index 00000000..3ad4292a
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/directoryPerType/standard/vocabulary/valueset/456.json
@@ -0,0 +1,5 @@
+{
+ "resourceType": "ValueSet",
+ "id": "456",
+ "url": "example.com/ValueSet/456"
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/emptyContent/resources/patient/patient-123.json b/ls/server/src/test/resources/sampleIgs/ig/standard/emptyContent/resources/patient/patient-123.json
new file mode 100644
index 00000000..e69de29b
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/externalResource/resources/library/123.json b/ls/server/src/test/resources/sampleIgs/ig/standard/externalResource/resources/library/123.json
new file mode 100644
index 00000000..28e42017
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/externalResource/resources/library/123.json
@@ -0,0 +1,6 @@
+{
+ "resourceType": "Library",
+ "id": "123",
+ "name": "123",
+ "url": "http://example.com/Library/123"
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/externalResource/vocabulary/codesystem/ABC.json b/ls/server/src/test/resources/sampleIgs/ig/standard/externalResource/vocabulary/codesystem/ABC.json
new file mode 100644
index 00000000..705973ab
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/externalResource/vocabulary/codesystem/ABC.json
@@ -0,0 +1,5 @@
+{
+ "resourceType": "CodeSystem",
+ "id": "ABC",
+ "url": "example.com/CodeSystem/ABC"
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/externalResource/vocabulary/codesystem/external/DEF.json b/ls/server/src/test/resources/sampleIgs/ig/standard/externalResource/vocabulary/codesystem/external/DEF.json
new file mode 100644
index 00000000..537f9630
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/externalResource/vocabulary/codesystem/external/DEF.json
@@ -0,0 +1,5 @@
+{
+ "resourceType": "CodeSystem",
+ "id": "DEF",
+ "url": "example.com/CodeSystem/DEF"
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/externalResource/vocabulary/valueset/456.json b/ls/server/src/test/resources/sampleIgs/ig/standard/externalResource/vocabulary/valueset/456.json
new file mode 100644
index 00000000..3ad4292a
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/externalResource/vocabulary/valueset/456.json
@@ -0,0 +1,5 @@
+{
+ "resourceType": "ValueSet",
+ "id": "456",
+ "url": "example.com/ValueSet/456"
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/externalResource/vocabulary/valueset/external/789.json b/ls/server/src/test/resources/sampleIgs/ig/standard/externalResource/vocabulary/valueset/external/789.json
new file mode 100644
index 00000000..19d67a74
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/externalResource/vocabulary/valueset/external/789.json
@@ -0,0 +1,5 @@
+{
+ "resourceType": "ValueSet",
+ "id": "789",
+ "url": "example.com/ValueSet/789"
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/flat/Condition-DEF.json b/ls/server/src/test/resources/sampleIgs/ig/standard/flat/Condition-DEF.json
new file mode 100644
index 00000000..65447c1d
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/flat/Condition-DEF.json
@@ -0,0 +1,12 @@
+{
+ "resourceType": "Condition",
+ "id": "DEF",
+ "code": {
+ "coding": [
+ {
+ "system": "example.com/codesystem",
+ "code": "12345"
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/flat/Condition-GHI.json b/ls/server/src/test/resources/sampleIgs/ig/standard/flat/Condition-GHI.json
new file mode 100644
index 00000000..62aa77f7
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/flat/Condition-GHI.json
@@ -0,0 +1,12 @@
+{
+ "resourceType": "Condition",
+ "id": "GHI",
+ "code": {
+ "coding": [
+ {
+ "system": "example.com/codesystem",
+ "code": "12345"
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/flat/Condition-JKL.json b/ls/server/src/test/resources/sampleIgs/ig/standard/flat/Condition-JKL.json
new file mode 100644
index 00000000..caecea4e
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/flat/Condition-JKL.json
@@ -0,0 +1,12 @@
+{
+ "resourceType": "Condition",
+ "id": "JKL",
+ "code": {
+ "coding": [
+ {
+ "system": "example.com/codesystem",
+ "code": "000000"
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/flat/Library-123.json b/ls/server/src/test/resources/sampleIgs/ig/standard/flat/Library-123.json
new file mode 100644
index 00000000..574a45c2
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/flat/Library-123.json
@@ -0,0 +1,6 @@
+{
+ "resourceType": "Library",
+ "id": "123",
+ "name": "Test",
+ "url": "http://example.com/Library/Test"
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/flat/Library-456.json b/ls/server/src/test/resources/sampleIgs/ig/standard/flat/Library-456.json
new file mode 100644
index 00000000..3adffbfd
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/flat/Library-456.json
@@ -0,0 +1,6 @@
+{
+ "resourceType": "Library",
+ "id": "456",
+ "name": "NotTest",
+ "url": "http://example.com/Library/NotTest"
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/flat/Measure-XYZ.json b/ls/server/src/test/resources/sampleIgs/ig/standard/flat/Measure-XYZ.json
new file mode 100644
index 00000000..e13b0247
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/flat/Measure-XYZ.json
@@ -0,0 +1,4 @@
+{
+ "resourceType": "Measure",
+ "id": "XYZ"
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/flat/Patient-ABC.json b/ls/server/src/test/resources/sampleIgs/ig/standard/flat/Patient-ABC.json
new file mode 100644
index 00000000..30e01de9
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/flat/Patient-ABC.json
@@ -0,0 +1,4 @@
+{
+ "resourceType": "Patient",
+ "id": "ABC"
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/flat/ValueSet-456.json b/ls/server/src/test/resources/sampleIgs/ig/standard/flat/ValueSet-456.json
new file mode 100644
index 00000000..3ad4292a
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/flat/ValueSet-456.json
@@ -0,0 +1,5 @@
+{
+ "resourceType": "ValueSet",
+ "id": "456",
+ "url": "example.com/ValueSet/456"
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/flatNoTypeNames/123.json b/ls/server/src/test/resources/sampleIgs/ig/standard/flatNoTypeNames/123.json
new file mode 100644
index 00000000..574a45c2
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/flatNoTypeNames/123.json
@@ -0,0 +1,6 @@
+{
+ "resourceType": "Library",
+ "id": "123",
+ "name": "Test",
+ "url": "http://example.com/Library/Test"
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/flatNoTypeNames/456.json b/ls/server/src/test/resources/sampleIgs/ig/standard/flatNoTypeNames/456.json
new file mode 100644
index 00000000..3adffbfd
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/flatNoTypeNames/456.json
@@ -0,0 +1,6 @@
+{
+ "resourceType": "Library",
+ "id": "456",
+ "name": "NotTest",
+ "url": "http://example.com/Library/NotTest"
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/flatNoTypeNames/789.json b/ls/server/src/test/resources/sampleIgs/ig/standard/flatNoTypeNames/789.json
new file mode 100644
index 00000000..19d67a74
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/flatNoTypeNames/789.json
@@ -0,0 +1,5 @@
+{
+ "resourceType": "ValueSet",
+ "id": "789",
+ "url": "example.com/ValueSet/789"
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/flatNoTypeNames/ABC.json b/ls/server/src/test/resources/sampleIgs/ig/standard/flatNoTypeNames/ABC.json
new file mode 100644
index 00000000..30e01de9
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/flatNoTypeNames/ABC.json
@@ -0,0 +1,4 @@
+{
+ "resourceType": "Patient",
+ "id": "ABC"
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/flatNoTypeNames/DEF.json b/ls/server/src/test/resources/sampleIgs/ig/standard/flatNoTypeNames/DEF.json
new file mode 100644
index 00000000..65447c1d
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/flatNoTypeNames/DEF.json
@@ -0,0 +1,12 @@
+{
+ "resourceType": "Condition",
+ "id": "DEF",
+ "code": {
+ "coding": [
+ {
+ "system": "example.com/codesystem",
+ "code": "12345"
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/flatNoTypeNames/GHI.json b/ls/server/src/test/resources/sampleIgs/ig/standard/flatNoTypeNames/GHI.json
new file mode 100644
index 00000000..62aa77f7
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/flatNoTypeNames/GHI.json
@@ -0,0 +1,12 @@
+{
+ "resourceType": "Condition",
+ "id": "GHI",
+ "code": {
+ "coding": [
+ {
+ "system": "example.com/codesystem",
+ "code": "12345"
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/flatNoTypeNames/JKL.json b/ls/server/src/test/resources/sampleIgs/ig/standard/flatNoTypeNames/JKL.json
new file mode 100644
index 00000000..caecea4e
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/flatNoTypeNames/JKL.json
@@ -0,0 +1,12 @@
+{
+ "resourceType": "Condition",
+ "id": "JKL",
+ "code": {
+ "coding": [
+ {
+ "system": "example.com/codesystem",
+ "code": "000000"
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/flatNoTypeNames/XYZ.json b/ls/server/src/test/resources/sampleIgs/ig/standard/flatNoTypeNames/XYZ.json
new file mode 100644
index 00000000..e13b0247
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/flatNoTypeNames/XYZ.json
@@ -0,0 +1,4 @@
+{
+ "resourceType": "Measure",
+ "id": "XYZ"
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/misleadingFileName/resources/patient/measure-strat1-denom.json b/ls/server/src/test/resources/sampleIgs/ig/standard/misleadingFileName/resources/patient/measure-strat1-denom.json
new file mode 100644
index 00000000..7d3de0bb
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/misleadingFileName/resources/patient/measure-strat1-denom.json
@@ -0,0 +1,4 @@
+{
+ "resourceType": "Patient",
+ "id": "measure-strat1-denom"
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/mixedEncoding/resources/library/123.json b/ls/server/src/test/resources/sampleIgs/ig/standard/mixedEncoding/resources/library/123.json
new file mode 100644
index 00000000..28e42017
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/mixedEncoding/resources/library/123.json
@@ -0,0 +1,6 @@
+{
+ "resourceType": "Library",
+ "id": "123",
+ "name": "123",
+ "url": "http://example.com/Library/123"
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/mixedEncoding/tests/patient/123.xml b/ls/server/src/test/resources/sampleIgs/ig/standard/mixedEncoding/tests/patient/123.xml
new file mode 100644
index 00000000..8aa711ab
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/mixedEncoding/tests/patient/123.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/mixedEncoding/vocabulary/codesystem/ABC.xml b/ls/server/src/test/resources/sampleIgs/ig/standard/mixedEncoding/vocabulary/codesystem/ABC.xml
new file mode 100644
index 00000000..54407d97
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/mixedEncoding/vocabulary/codesystem/ABC.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/mixedEncoding/vocabulary/codesystem/external/DEF.json b/ls/server/src/test/resources/sampleIgs/ig/standard/mixedEncoding/vocabulary/codesystem/external/DEF.json
new file mode 100644
index 00000000..537f9630
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/mixedEncoding/vocabulary/codesystem/external/DEF.json
@@ -0,0 +1,5 @@
+{
+ "resourceType": "CodeSystem",
+ "id": "DEF",
+ "url": "example.com/CodeSystem/DEF"
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/mixedEncoding/vocabulary/valueset/456.json b/ls/server/src/test/resources/sampleIgs/ig/standard/mixedEncoding/vocabulary/valueset/456.json
new file mode 100644
index 00000000..3ad4292a
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/mixedEncoding/vocabulary/valueset/456.json
@@ -0,0 +1,5 @@
+{
+ "resourceType": "ValueSet",
+ "id": "456",
+ "url": "example.com/ValueSet/456"
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/mixedEncoding/vocabulary/valueset/external/789.xml b/ls/server/src/test/resources/sampleIgs/ig/standard/mixedEncoding/vocabulary/valueset/external/789.xml
new file mode 100644
index 00000000..10f7c74b
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/mixedEncoding/vocabulary/valueset/external/789.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/noTestData/resources/library/123.json b/ls/server/src/test/resources/sampleIgs/ig/standard/noTestData/resources/library/123.json
new file mode 100644
index 00000000..28e42017
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/noTestData/resources/library/123.json
@@ -0,0 +1,6 @@
+{
+ "resourceType": "Library",
+ "id": "123",
+ "name": "123",
+ "url": "http://example.com/Library/123"
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/noTestData/vocabulary/codesystem/ABC.json b/ls/server/src/test/resources/sampleIgs/ig/standard/noTestData/vocabulary/codesystem/ABC.json
new file mode 100644
index 00000000..705973ab
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/noTestData/vocabulary/codesystem/ABC.json
@@ -0,0 +1,5 @@
+{
+ "resourceType": "CodeSystem",
+ "id": "ABC",
+ "url": "example.com/CodeSystem/ABC"
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/noTestData/vocabulary/valueset/456.json b/ls/server/src/test/resources/sampleIgs/ig/standard/noTestData/vocabulary/valueset/456.json
new file mode 100644
index 00000000..3ad4292a
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/noTestData/vocabulary/valueset/456.json
@@ -0,0 +1,5 @@
+{
+ "resourceType": "ValueSet",
+ "id": "456",
+ "url": "example.com/ValueSet/456"
+}
\ No newline at end of file
diff --git a/ls/server/src/test/resources/sampleIgs/ig/standard/nonFhirFileName/resources/patient/denom-patient-123.json b/ls/server/src/test/resources/sampleIgs/ig/standard/nonFhirFileName/resources/patient/denom-patient-123.json
new file mode 100644
index 00000000..b0422f26
--- /dev/null
+++ b/ls/server/src/test/resources/sampleIgs/ig/standard/nonFhirFileName/resources/patient/denom-patient-123.json
@@ -0,0 +1,4 @@
+{
+ "resourceType": "Patient",
+ "id": "denom-patient-123"
+}
\ No newline at end of file
diff --git a/ls/service/pom.xml b/ls/service/pom.xml
index fc15c444..7629bd30 100644
--- a/ls/service/pom.xml
+++ b/ls/service/pom.xml
@@ -2,7 +2,6 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
4.0.0
- org.opencds.cqf.cql.ls
cql-ls-service
jar
CQL Language Server Service
@@ -20,17 +19,15 @@
org.opencds.cqf.cql.ls
cql-ls-server
- 4.0.0-SNAPSHOT
+ ${project.version}
org.springframework.boot
spring-boot
- ${spring.boot.version}
org.springframework.boot
spring-boot-starter-logging
- ${spring.boot.version}
ch.qos.logback
diff --git a/plugin/debug/pom.xml b/plugin/debug/pom.xml
index c8336d06..2ebaf17c 100644
--- a/plugin/debug/pom.xml
+++ b/plugin/debug/pom.xml
@@ -2,7 +2,6 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
4.0.0
- org.opencds.cqf.cql.ls
cql-ls-plugin-debug
jar
CQL Language Server Debug Plugin
@@ -20,13 +19,13 @@
org.opencds.cqf.cql.ls
cql-ls-server
- 4.0.0-SNAPSHOT
+ ${project.version}
provided
org.opencds.cqf.cql.debug
cql-debug-server
- 4.0.0-SNAPSHOT
+ ${project.version}
org.eclipse.lsp4j
diff --git a/pom.xml b/pom.xml
index b7ce4cfd..7cede42f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -12,10 +12,16 @@
https://github.com/cqframework/cql-language-server/tree/master
+ 17
+ 17
+ 17
+
+ 2.2.0
+
UTF-8
UTF-8
- 11
- 3.23.0
+ 4.0.0
+ 4.2.0
1.1.1
1.7.36
2.7.18
@@ -78,6 +84,12 @@
+
+ org.jetbrains.kotlin
+ kotlin-stdlib
+ ${kotlin.version}
+
+
org.springframework.boot
@@ -87,6 +99,7 @@
import
+
org.opencds.cqf.fhir
cqf-fhir-bom
@@ -95,6 +108,15 @@
import
+
+
+ org.cqframework
+ cql-bom
+ ${cql.version}
+ pom
+ import
+
+
com.fasterxml.jackson
jackson-bom
@@ -127,15 +149,6 @@
${jackson.version}
-
-
-
-
- info.cqframework
- cql-formatter
- 3.27.0
-
-
org.eclipse.lsp4j
@@ -169,8 +182,7 @@
3.0.1
-
-
+
org.hamcrest
hamcrest-all
@@ -248,7 +260,7 @@
true
-XDcompilePolicy=simple
-
+
-Xplugin:ErrorProne -XepDisableAllWarnings
@@ -313,7 +325,6 @@
maven-javadoc-plugin
3.3.1
- 11
private
-missing