diff --git a/cqf-fhir-cr-hapi/src/main/java/org/opencds/cqf/fhir/cr/hapi/repository/ClinicalIntelligenceBundleProviderUtil.java b/cqf-fhir-cr-hapi/src/main/java/org/opencds/cqf/fhir/cr/hapi/repository/ClinicalIntelligenceBundleProviderUtil.java index e04b52de8c..60e6357db2 100644 --- a/cqf-fhir-cr-hapi/src/main/java/org/opencds/cqf/fhir/cr/hapi/repository/ClinicalIntelligenceBundleProviderUtil.java +++ b/cqf-fhir-cr-hapi/src/main/java/org/opencds/cqf/fhir/cr/hapi/repository/ClinicalIntelligenceBundleProviderUtil.java @@ -53,7 +53,7 @@ private int offsetOrZero() { } private int limitOrZero() { - return defaultZeroIfNull(offset); + return defaultZeroIfNull(limit); } private int defaultZeroIfNull(Integer value) { @@ -124,7 +124,7 @@ private static BundleLinks buildLinks( request.getParameters())); } if (isNotBlank(result.getPreviousPageId())) { - links.setNext(RestfulServerUtils.createOffsetPagingLink( + links.setPrev(RestfulServerUtils.createOffsetPagingLink( links, request.getRequestPath(), request.getTenantId(), diff --git a/cqf-fhir-cr-hapi/src/test/java/org/opencds/cqf/fhir/cr/hapi/repository/ClinicalIntelligenceBundleProviderUtilTest.java b/cqf-fhir-cr-hapi/src/test/java/org/opencds/cqf/fhir/cr/hapi/repository/ClinicalIntelligenceBundleProviderUtilTest.java new file mode 100644 index 0000000000..b7d474f762 --- /dev/null +++ b/cqf-fhir-cr-hapi/src/test/java/org/opencds/cqf/fhir/cr/hapi/repository/ClinicalIntelligenceBundleProviderUtilTest.java @@ -0,0 +1,505 @@ +package org.opencds.cqf.fhir.cr.hapi.repository; + +import static org.apache.commons.lang3.StringUtils.isEmpty; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.lenient; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.model.valueset.BundleTypeEnum; +import ca.uhn.fhir.rest.api.Constants; +import ca.uhn.fhir.rest.api.RestOperationTypeEnum; +import ca.uhn.fhir.rest.api.server.IBundleProvider; +import ca.uhn.fhir.rest.api.server.IRestfulServer; +import ca.uhn.fhir.rest.api.server.RequestDetails; +import ca.uhn.fhir.rest.api.server.SystemRequestDetails; +import ca.uhn.fhir.rest.server.IPagingProvider; +import ca.uhn.fhir.rest.server.SimpleBundleProvider; +import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; +import ca.uhn.fhir.util.BundleUtil; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import org.hl7.fhir.instance.model.api.IBaseResource; +import org.hl7.fhir.r4.model.Bundle; +import org.hl7.fhir.r4.model.Bundle.BundleLinkComponent; +import org.hl7.fhir.r4.model.IdType; +import org.hl7.fhir.r4.model.Library; +import org.hl7.fhir.r4.model.Measure; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import org.junit.jupiter.params.provider.EnumSource; +import org.junit.jupiter.params.provider.NullSource; +import org.junit.jupiter.params.provider.ValueSource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ClinicalIntelligenceBundleProviderUtilTest { + + public enum PagingStyle { + OFFSET, + PAGE_ID, + SEARCH_ID + } + + private static final Logger log = LoggerFactory.getLogger(ClinicalIntelligenceBundleProviderUtilTest.class); + // fhir context does not matter for this test; but a fhircontext is required + private final FhirContext context = FhirContext.forR4Cached(); + + private RequestDetails reqDetails; + + private IRestfulServer restfulServer; + + private IBundleProvider bundleProvider; + + @BeforeEach + public void before() { + reqDetails = new SystemRequestDetails(); + reqDetails.setFhirServerBase("http://localhost:8000/"); + + restfulServer = mock(IRestfulServer.class); + + bundleProvider = mock(IBundleProvider.class); + + // probably always needed + lenient().when(restfulServer.getFhirContext()).thenReturn(context); + } + + @ParameterizedTest + @CsvSource( + textBlock = + // limit, linkSelf, offset, bundleType, searchId, offset source + """ + null, null, TRANSACTION, null + null, null, TRANSACTION, searchID + null, http://root.com/self, TRANSACTION, null + 2, null, TRANSACTION, null + 2, http://root.com/self, TRANSACTION, null + 2, null, TRANSACTION, searchID + null, http://root.com/self, TRANSACTION, searchID + 2, http://root.com.self, TRANSACTION, searchID + """, + nullValues = "null") + public void createBundleFromBundleProvider_basicParametersCoverageTest( + Integer limit, String linkSelf, BundleTypeEnum bundleType, String searchId) { + // setup + int pagesize = 2; + int offset = 0; + int count = 3; + List libraries = new ArrayList<>(); + for (int i = 0; i < count; i++) { + Library library = new Library(); + library.setId("Library/123"); + + libraries.add(library); + } + bundleProvider = new SimpleBundleProvider(libraries); + + IPagingProvider pagingProvider = mock(IPagingProvider.class); + + // when + when(restfulServer.getDefaultPageSize()).thenReturn(pagesize); + when(restfulServer.getPagingProvider()).thenReturn(pagingProvider); + + // test + IBaseResource resource = ClinicalIntelligenceBundleProviderUtil.createBundleFromBundleProvider( + restfulServer, reqDetails, limit, linkSelf, Set.of(), bundleProvider, offset, bundleType, searchId); + + // verify + assertNotNull(resource); + assertInstanceOf(Bundle.class, resource); + Bundle bundle = (Bundle) resource; + List resources = BundleUtil.toListOfResources(context, bundle); + + if (limit != null && !isEmpty(searchId)) { + assertNotNull(bundle.getLink("next")); + } + + if (limit == null) { + assertEquals(pagesize, resources.size()); + } else { + assertEquals(limit, resources.size()); + } + + // if there's a self link, it should be provided + if (!isEmpty(linkSelf)) { + assertNotNull(bundle.getLink("self")); + } + } + + @Test + public void createBundleFromBundleProvider_nullEntries_coverageTest() { + // setup + int count = 2; + List libraries = new ArrayList<>(); + for (int i = 0; i < count; i++) { + Library library = new Library(); + library.setId("Library/123"); + + libraries.add(library); + } + libraries.add(null); + bundleProvider = new SimpleBundleProvider(libraries); + + ((SimpleBundleProvider) bundleProvider).setCurrentPageOffset(0); + ((SimpleBundleProvider) bundleProvider).setCurrentPageSize(count + 1); // +1 to get that null entry + + // test + IBaseResource resource = ClinicalIntelligenceBundleProviderUtil.createBundleFromBundleProvider( + restfulServer, + reqDetails, + null, // limit + null, // link self + Set.of(), // includes + bundleProvider, + 0, // offset + BundleTypeEnum.TRANSACTION, + null // searchId + ); + + // validate + assertNotNull(resource); + assertInstanceOf(Bundle.class, resource); // because we're using R4 + Bundle bundle = (Bundle) resource; + // no null value + assertEquals(count, bundle.getTotal()); + } + + @ParameterizedTest + @EnumSource(value = BundleTypeEnum.class) + public void createBundleFromBundleProvider_allBundleTypes_coverageTest(BundleTypeEnum bundleType) { + // setup + int count = 3; + List libraries = new ArrayList<>(); + for (int i = 0; i < count; i++) { + Library lib = new Library(); + lib.setId("Library/1"); + + libraries.add(lib); + } + + bundleProvider = new SimpleBundleProvider(libraries); + + // test + IBaseResource resource = ClinicalIntelligenceBundleProviderUtil.createBundleFromBundleProvider( + restfulServer, + reqDetails, + null, // limit + null, // link self + Set.of(), // includes + bundleProvider, + 0, // offset + bundleType, + null // searchId + ); + + // validate + assertNotNull(resource); + assertInstanceOf(Bundle.class, resource); // because we're using R4 + Bundle bundle = (Bundle) resource; + assertEquals(count, bundle.getTotal()); + assertEquals(bundleType.getCode(), bundle.getType().toCode()); + } + + @ParameterizedTest + @ValueSource(ints = 0) + @NullSource + public void createBundleFromBundleProvider_emptyResults_coverageTest(Integer size) { + // setup + bundleProvider = new SimpleBundleProvider(List.of()); + + // some providers return null, some return 0 + ((SimpleBundleProvider) bundleProvider).setSize(size); + + // test + IBaseResource resource = ClinicalIntelligenceBundleProviderUtil.createBundleFromBundleProvider( + restfulServer, + reqDetails, + null, // limit + null, // link self + Set.of(), // includes + bundleProvider, + 0, // offset + BundleTypeEnum.TRANSACTION, + null // searchId + ); + + // validate + assertNotNull(resource); + assertInstanceOf(Bundle.class, resource); + Bundle bundle = (Bundle) resource; + assertEquals(0, bundle.getEntry().size()); + assertNull(bundle.getLink("next")); + } + + @Test + public void createBundleFromBundleProvider_withNextPageOfset_hasCorrectPageLinkOffsets() { + // setup + int offset = 10; + int limit = 5; + List measures = new ArrayList<>(); + for (int i = 0; i < 5; i++) { + Measure measure = new Measure(); + measure.setId(new IdType("Measure/" + i)); + measure.setUrl("http://something.com/" + i); + measure.setName("measure" + i); + + measures.add(measure); + } + + bundleProvider = mock(IBundleProvider.class); + when(bundleProvider.getCurrentPageOffset()).thenReturn(offset); + when(bundleProvider.getCurrentPageSize()).thenReturn(limit); + when(bundleProvider.getNextPageId()).thenReturn("next"); + when(bundleProvider.getPreviousPageId()).thenReturn("prev"); + when(bundleProvider.getResources(anyInt(), anyInt())).thenReturn(measures); + + // test + IBaseResource baseResource = ClinicalIntelligenceBundleProviderUtil.createBundleFromBundleProvider( + restfulServer, + reqDetails, + null, + null, + Set.of(), + bundleProvider, + offset, + BundleTypeEnum.SEARCHSET, + null); + + // verify + assertNotNull(baseResource); + assertInstanceOf(Bundle.class, baseResource); + Bundle bundle = (Bundle) baseResource; + BundleLinkComponent nextLink = bundle.getLink("next"); + BundleLinkComponent prevLink = bundle.getLink("previous"); + assertNotNull(nextLink); + assertNotNull(prevLink); + // offset should be 15 = offset + limit + assertTrue(nextLink.getUrl().contains(String.format("%s=%d", Constants.PARAM_OFFSET, 15)), nextLink.getUrl()); + // offset should be 5 = offset - limit + assertTrue(prevLink.getUrl().contains(String.format("%s=%d", Constants.PARAM_OFFSET, 5)), prevLink.getUrl()); + } + + @ParameterizedTest + @EnumSource(PagingStyle.class) + public void createBundleFromBundleProvider_secondPage_coverageTest(PagingStyle style) { + // setup + int offset = 1; + String searchId = null; + int count = 4; + List libraries = new ArrayList<>(); + for (int i = 0; i < count; i++) { + Library lib = new Library(); + lib.setId("Library/1"); + + libraries.add(lib); + } + + bundleProvider = mock(IBundleProvider.class); + + // mock + when(bundleProvider.getNextPageId()).thenReturn("nextId"); + when(bundleProvider.getPreviousPageId()).thenReturn("previousId"); + when(bundleProvider.getResources(anyInt(), anyInt())).thenReturn(libraries); + + switch (style) { + case OFFSET -> { + when(bundleProvider.getCurrentPageOffset()).thenReturn(1); + } + case PAGE_ID -> { + IPagingProvider pagingProvider = mock(IPagingProvider.class); + when(restfulServer.getPagingProvider()).thenReturn(pagingProvider); + + when(bundleProvider.getCurrentPageOffset()).thenReturn(null); + when(restfulServer.canStoreSearchResults()).thenReturn(true); + when(bundleProvider.getCurrentPageId()).thenReturn("current"); + when(pagingProvider.getDefaultPageSize()).thenReturn(count); // just to get everything + } + case SEARCH_ID -> { + searchId = "searchId"; + IPagingProvider pagingProvider = mock(IPagingProvider.class); + when(restfulServer.getPagingProvider()).thenReturn(pagingProvider); + + when(bundleProvider.size()).thenReturn(count + offset + 1); // +1 so there's thought to be a "next" + + when(bundleProvider.getCurrentPageOffset()).thenReturn(null); + when(restfulServer.canStoreSearchResults()).thenReturn(true); + + when(bundleProvider.getUuid()).thenReturn("SearchIdGuid"); + } + } + + // test + IBaseResource resource = ClinicalIntelligenceBundleProviderUtil.createBundleFromBundleProvider( + restfulServer, + reqDetails, + count, // limit + null, // link self + Set.of(), // includes + bundleProvider, + offset, // offset + BundleTypeEnum.TRANSACTION, + searchId // searchId + ); + + // validate + assertNotNull(resource); + assertInstanceOf(Bundle.class, resource); + Bundle bundle = (Bundle) resource; + assertEquals(count, bundle.getEntry().size()); + // make sure links exist + assertNotNull(bundle.getLink("next")); + assertNotNull(bundle.getLink("previous")); + } + + @ParameterizedTest + @ValueSource(ints = {0, 1}) + public void createBundleFromBundleProvider_pageOffset_coverageTest(int offset) { + // setup + Integer pageSize = null; + int count = 4; + List libraries = new ArrayList<>(); + for (int i = 0; i < count; i++) { + Library lib = new Library(); + lib.setId("Library/1"); + + libraries.add(lib); + } + + bundleProvider = new SimpleBundleProvider(libraries); + + // mock + when(restfulServer.canStoreSearchResults()).thenReturn(true); + { + IPagingProvider provider = mock(IPagingProvider.class); + when(restfulServer.getPagingProvider()).thenReturn(provider); + pageSize = 2; + when(provider.getDefaultPageSize()).thenReturn(pageSize); + + if (offset > 0) { + SimpleBundleProvider sp = (SimpleBundleProvider) bundleProvider; + sp.setCurrentPageOffset(offset); + sp.setCurrentPageSize(pageSize); + + /* + * If we provide a default page size and it's not + * the first page (ie, offset > 0), then we + * will later ignore the pagesize and just return + * "everything that was passed back". + * + * But, we still require the defaultpagesize (even though it'll be ignored) + * so it's just the test that needs to ignore this later + */ + pageSize = null; + } + } + + // test + IBaseResource resource = ClinicalIntelligenceBundleProviderUtil.createBundleFromBundleProvider( + restfulServer, + reqDetails, + pageSize, // limit + null, // link self + Set.of(), // includes + bundleProvider, + offset, // offset + BundleTypeEnum.TRANSACTION, + null // searchId + ); + + // validate + assertNotNull(resource); + assertInstanceOf(Bundle.class, resource); + Bundle bundle = (Bundle) resource; + int usedPageSize = pageSize != null ? pageSize : 0; + assertEquals(count - usedPageSize, bundle.getEntry().size()); + } + + @ParameterizedTest + @ValueSource(booleans = {true, false}) + public void createBundleFromBundleProvider_invalidResourceList_coverageTest(boolean hasId) { + // setup + int count = 1; + List libraries = new ArrayList<>(); + for (int i = 0; i < count; i++) { + Library lib = new Library(); + if (hasId) { + // has id == empty id + lib.setId(""); + } + + libraries.add(lib); + } + + bundleProvider = new SimpleBundleProvider(libraries); + + // test + try { + ClinicalIntelligenceBundleProviderUtil.createBundleFromBundleProvider( + restfulServer, + reqDetails, + count, // limit + null, // link self + Set.of(), // includes + bundleProvider, + 0, // offset + BundleTypeEnum.TRANSACTION, + null // searchId + ); + fail(); + } catch (InternalErrorException ex) { + assertTrue( + ex.getLocalizedMessage().contains("Server method returned resource of type"), + ex.getLocalizedMessage()); + } + } + + @ParameterizedTest + @EnumSource( + value = RestOperationTypeEnum.class, + names = {"EXTENDED_OPERATION_TYPE", "EXTENDED_OPERATION_INSTANCE"}) + public void createBundleFromBundleProvider_everythingOp_coverageTest(RestOperationTypeEnum opType) { + // setup + int count = 1; + List libraries = new ArrayList<>(); + for (int i = 0; i < count; i++) { + Library lib = new Library(); + lib.setId("Library/1"); + + libraries.add(lib); + } + + bundleProvider = new SimpleBundleProvider(libraries); + + reqDetails.setRestOperationType(opType); + reqDetails.setOperation("$everything"); + + // test + IBaseResource resource = ClinicalIntelligenceBundleProviderUtil.createBundleFromBundleProvider( + restfulServer, + reqDetails, + count, // limit + null, // link self + Set.of(), // includes + bundleProvider, + 0, // offset + BundleTypeEnum.TRANSACTION, + null // searchId + ); + + // validate + assertNotNull(resource); + assertInstanceOf(Bundle.class, resource); + Bundle bundle = (Bundle) resource; + assertEquals(count, bundle.getEntry().size()); + } +} diff --git a/cqf-fhir-cr/src/main/java/org/opencds/cqf/fhir/cr/visitor/dstu3/ReleaseVisitor.java b/cqf-fhir-cr/src/main/java/org/opencds/cqf/fhir/cr/visitor/dstu3/ReleaseVisitor.java index adb438704f..f3dca053c0 100644 --- a/cqf-fhir-cr/src/main/java/org/opencds/cqf/fhir/cr/visitor/dstu3/ReleaseVisitor.java +++ b/cqf-fhir-cr/src/main/java/org/opencds/cqf/fhir/cr/visitor/dstu3/ReleaseVisitor.java @@ -98,7 +98,7 @@ public static void updateReleaseLabel(MetadataResource artifact, String releaseL public static Bundle searchArtifactAssessmentForArtifact(IIdType reference, IRepository repository) { Map> searchParams = new HashMap<>(); List urlList = new ArrayList<>(); - urlList.add(new ReferenceParam(reference)); + urlList.add(new ReferenceParam(reference.getResourceType() + "/" + reference.getIdPart())); searchParams.put("artifact", urlList); return repository.search(Bundle.class, Basic.class, searchParams); } diff --git a/cqf-fhir-cr/src/main/java/org/opencds/cqf/fhir/cr/visitor/r5/ReleaseVisitor.java b/cqf-fhir-cr/src/main/java/org/opencds/cqf/fhir/cr/visitor/r5/ReleaseVisitor.java index a261c9d5df..c68d9330d7 100644 --- a/cqf-fhir-cr/src/main/java/org/opencds/cqf/fhir/cr/visitor/r5/ReleaseVisitor.java +++ b/cqf-fhir-cr/src/main/java/org/opencds/cqf/fhir/cr/visitor/r5/ReleaseVisitor.java @@ -14,7 +14,7 @@ import org.hl7.fhir.instance.model.api.IBaseParameters; import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.instance.model.api.IPrimitiveType; -import org.hl7.fhir.r5.model.ArtifactAssessment; +import org.hl7.fhir.r5.model.Basic; import org.hl7.fhir.r5.model.Bundle; import org.hl7.fhir.r5.model.Bundle.BundleEntryComponent; import org.hl7.fhir.r5.model.CanonicalType; @@ -27,7 +27,6 @@ import org.hl7.fhir.r5.model.Parameters; import org.hl7.fhir.r5.model.Period; import org.hl7.fhir.r5.model.Reference; -import org.hl7.fhir.r5.model.RelatedArtifact.RelatedArtifactType; import org.hl7.fhir.r5.model.ResourceType; import org.hl7.fhir.r5.model.StringType; import org.hl7.fhir.r5.model.ValueSet; @@ -37,6 +36,7 @@ import org.opencds.cqf.fhir.utility.PackageHelper; import org.opencds.cqf.fhir.utility.SearchHelper; import org.opencds.cqf.fhir.utility.adapter.IKnowledgeArtifactAdapter; +import org.opencds.cqf.fhir.utility.r5.ArtifactAssessment; import org.slf4j.Logger; public class ReleaseVisitor { @@ -102,9 +102,10 @@ public static void updateReleaseLabel(MetadataResource artifact, String releaseL public static Bundle searchArtifactAssessmentForArtifact(IIdType reference, IRepository repository) { Map> searchParams = new HashMap<>(); List urlList = new ArrayList<>(); - urlList.add(new ReferenceParam(reference)); + + urlList.add(new ReferenceParam(reference.getResourceType() + "/" + reference.getIdPart())); searchParams.put("artifact", urlList); - return repository.search(Bundle.class, ArtifactAssessment.class, searchParams); + return repository.search(Bundle.class, Basic.class, searchParams); } public static Optional getReleaseVersion( @@ -140,15 +141,27 @@ public static Optional getReleaseVersion( public static List findArtifactCommentsToUpdate( MetadataResource rootArtifact, String releaseVersion, IRepository repository) { List returnEntries = new ArrayList<>(); - // find any artifact assessments and update those as part of the bundle searchArtifactAssessmentForArtifact(rootArtifact.getIdElement(), repository).getEntry().stream() - .map(entry -> (ArtifactAssessment) entry.getResource()) + // The search is on Basic resources only unless we can register the ArtifactAssessment class + .map(entry -> { + try { + return (Basic) entry.getResource(); + } catch (Exception e) { + return null; + } + }) .filter(entry -> entry != null) + // convert Basic to ArtifactAssessment by transferring the extensions + .map(basic -> { + ArtifactAssessment extensionsTransferred = new ArtifactAssessment(); + extensionsTransferred.setExtension(basic.getExtension()); + extensionsTransferred.setId(basic.getClass().getSimpleName() + "/" + basic.getIdPart()); + return extensionsTransferred; + }) .forEach(artifactComment -> { - var ra = artifactComment.getContentFirstRep().addRelatedArtifact(); - ra.setType(RelatedArtifactType.DERIVEDFROM) - .setResource("%s|%s".formatted(rootArtifact.getUrl(), releaseVersion)); - returnEntries.add((BundleEntryComponent) PackageHelper.createEntry(artifactComment, true)); + artifactComment.setDerivedFromContentRelatedArtifact( + "%s|%s".formatted(rootArtifact.getUrl(), releaseVersion)); + returnEntries.add((Bundle.BundleEntryComponent) PackageHelper.createEntry(artifactComment, true)); }); return returnEntries; } diff --git a/cqf-fhir-cr/src/test/java/org/opencds/cqf/fhir/cr/visitor/IWithdrawVisitorTest.java b/cqf-fhir-cr/src/test/java/org/opencds/cqf/fhir/cr/visitor/IWithdrawVisitorTest.java new file mode 100644 index 0000000000..29d4e4272a --- /dev/null +++ b/cqf-fhir-cr/src/test/java/org/opencds/cqf/fhir/cr/visitor/IWithdrawVisitorTest.java @@ -0,0 +1,110 @@ +package org.opencds.cqf.fhir.cr.visitor; + +import static org.junit.jupiter.api.Assertions.assertEquals; +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.PreconditionFailedException; +import ca.uhn.fhir.util.BundleUtil; +import ca.uhn.fhir.util.CanonicalBundleEntry; +import ca.uhn.fhir.util.bundle.BundleEntryParts; +import java.util.List; +import org.hl7.fhir.instance.model.api.IBaseBundle; +import org.hl7.fhir.instance.model.api.IBaseParameters; +import org.hl7.fhir.instance.model.api.IBaseResource; +import org.hl7.fhir.instance.model.api.IIdType; +import org.junit.jupiter.api.Test; +import org.opencds.cqf.fhir.utility.adapter.IAdapterFactory; +import org.opencds.cqf.fhir.utility.adapter.IKnowledgeArtifactVisitor; +import org.opencds.cqf.fhir.utility.adapter.ILibraryAdapter; + +public interface IWithdrawVisitorTest { + + FhirContext fhirContext(); + + IRepository getRepo(); + + T createFromResourceLocation(String resourceLocation); + + Class libraryClass(); + + IAdapterFactory getAdapterFactory(); + + IBaseParameters createParametersForWithdrawVisitor(String version); + + // this test largely tests BaseKnowledgeArtifactVisitor... + @Test + default void library_withdraw_test() { + // setup + IBaseBundle bundle = createFromResourceLocation("Bundle-small-draft.json"); + + IBaseBundle tsBundle = getRepo().transaction(bundle); + IIdType id; + { + List entries = BundleUtil.toListOfCanonicalBundleEntries(fhirContext(), tsBundle); + id = fhirContext().getVersion().newIdType().setValue(entries.get(0).getResponseLocation()); + } + + String version = "1.2.3-draft"; + var library = getRepo().read(libraryClass(), id); + + ILibraryAdapter libraryAdapter = getAdapterFactory().createLibrary(library); + + IKnowledgeArtifactVisitor withdrawVisitor = new WithdrawVisitor(getRepo()); + var params = createParametersForWithdrawVisitor(version); + + // test + IBaseBundle returnedBundle = (IBaseBundle) libraryAdapter.accept(withdrawVisitor, params); + + // verify + List entries = BundleUtil.toListOfEntries(fhirContext(), returnedBundle); + + assertEquals(4, entries.size()); + } + + @Test + default void library_withdraw_with_approval_test() { + IBaseBundle bundle = createFromResourceLocation("Bundle-small-approved-draft.json"); + IBaseResource sp = createFromResourceLocation("SearchParameter-artifactAssessment.json"); + + IBaseBundle tsBundle = getRepo().transaction(bundle); + getRepo().update(sp); + + IIdType id; + { + List entries = BundleUtil.toListOfCanonicalBundleEntries(fhirContext(), tsBundle); + id = fhirContext().getVersion().newIdType().setValue(entries.get(0).getResponseLocation()); + } + String version = "1.2.3-draft"; + IBaseResource library = getRepo().read(libraryClass(), id); + ILibraryAdapter libraryAdapter = getAdapterFactory().createLibrary(library); + IKnowledgeArtifactVisitor withdrawVisitor = new WithdrawVisitor(getRepo()); + var params = createParametersForWithdrawVisitor(version); + + // test + IBaseBundle returnedBundle = (IBaseBundle) libraryAdapter.accept(withdrawVisitor, params); + + // verify + List entries = BundleUtil.toListOfEntries(fhirContext(), returnedBundle); + assertEquals(5, entries.size()); + } + + @Test + default void library_withdraw_No_draft_test() { + IBaseBundle bundle = createFromResourceLocation("Bundle-ersd-small-active.json"); + IBaseBundle bundlets = getRepo().transaction(bundle); + String version = "1.2.3"; + IIdType id = fhirContext().getVersion().newIdType().setValue("Library/SpecificationLibrary"); + IBaseResource library = getRepo().read(libraryClass(), id); + + ILibraryAdapter libraryAdapter = getAdapterFactory().createLibrary(library); + IKnowledgeArtifactVisitor withdrawVisitor = new WithdrawVisitor(getRepo()); + var params = createParametersForWithdrawVisitor(version); + + var exception = + assertThrows(PreconditionFailedException.class, () -> libraryAdapter.accept(withdrawVisitor, params)); + assertTrue(exception.getMessage().contains("Cannot withdraw an artifact that is not in draft status")); + } +} diff --git a/cqf-fhir-cr/src/test/java/org/opencds/cqf/fhir/cr/visitor/dstu3/WithdrawVisitorTest.java b/cqf-fhir-cr/src/test/java/org/opencds/cqf/fhir/cr/visitor/dstu3/WithdrawVisitorTest.java new file mode 100644 index 0000000000..58aaff89d7 --- /dev/null +++ b/cqf-fhir-cr/src/test/java/org/opencds/cqf/fhir/cr/visitor/dstu3/WithdrawVisitorTest.java @@ -0,0 +1,66 @@ +package org.opencds.cqf.fhir.cr.visitor.dstu3; + +import static org.opencds.cqf.fhir.utility.dstu3.Parameters.parameters; +import static org.opencds.cqf.fhir.utility.dstu3.Parameters.part; + +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.parser.IParser; +import ca.uhn.fhir.repository.IRepository; +import org.hl7.fhir.dstu3.model.Library; +import org.hl7.fhir.dstu3.model.SearchParameter; +import org.hl7.fhir.instance.model.api.IBaseParameters; +import org.hl7.fhir.instance.model.api.IBaseResource; +import org.junit.jupiter.api.BeforeEach; +import org.opencds.cqf.fhir.cr.visitor.IWithdrawVisitorTest; +import org.opencds.cqf.fhir.utility.adapter.IAdapterFactory; +import org.opencds.cqf.fhir.utility.adapter.dstu3.AdapterFactory; +import org.opencds.cqf.fhir.utility.repository.InMemoryFhirRepository; + +public class WithdrawVisitorTest implements IWithdrawVisitorTest { + + private final FhirContext fhirContext = FhirContext.forDstu3Cached(); + + private final AdapterFactory factory = new AdapterFactory(); + private IRepository repo; + + private final IParser jsonParser = fhirContext.newJsonParser(); + + @BeforeEach + public void setup() { + SearchParameter sp = (SearchParameter) + jsonParser.parseResource(getClass().getResourceAsStream("SearchParameter-artifactAssessment.json")); + repo = new InMemoryFhirRepository(fhirContext); + repo.update(sp); + } + + @Override + public FhirContext fhirContext() { + return fhirContext; + } + + @Override + public IRepository getRepo() { + return repo; + } + + @Override + @SuppressWarnings("unchecked") + public T createFromResourceLocation(String resourceLocation) { + return (T) jsonParser.parseResource(getClass().getResourceAsStream(resourceLocation)); + } + + @Override + public Class libraryClass() { + return Library.class; + } + + @Override + public IAdapterFactory getAdapterFactory() { + return factory; + } + + @Override + public IBaseParameters createParametersForWithdrawVisitor(String version) { + return parameters(part("version", version)); + } +} diff --git a/cqf-fhir-cr/src/test/java/org/opencds/cqf/fhir/cr/visitor/r4/WithdrawVisitorTests.java b/cqf-fhir-cr/src/test/java/org/opencds/cqf/fhir/cr/visitor/r4/WithdrawVisitorTests.java index f2e1e2bfae..b2b192e660 100644 --- a/cqf-fhir-cr/src/test/java/org/opencds/cqf/fhir/cr/visitor/r4/WithdrawVisitorTests.java +++ b/cqf-fhir-cr/src/test/java/org/opencds/cqf/fhir/cr/visitor/r4/WithdrawVisitorTests.java @@ -1,94 +1,63 @@ package org.opencds.cqf.fhir.cr.visitor.r4; -import static org.junit.jupiter.api.Assertions.*; import static org.opencds.cqf.fhir.utility.r4.Parameters.parameters; import static org.opencds.cqf.fhir.utility.r4.Parameters.part; import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.parser.IParser; import ca.uhn.fhir.repository.IRepository; -import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException; -import org.hl7.fhir.r4.model.Bundle; -import org.hl7.fhir.r4.model.IdType; +import org.hl7.fhir.instance.model.api.IBaseParameters; +import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.r4.model.Library; -import org.hl7.fhir.r4.model.Parameters; import org.hl7.fhir.r4.model.SearchParameter; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.opencds.cqf.fhir.cr.visitor.WithdrawVisitor; -import org.opencds.cqf.fhir.utility.adapter.IKnowledgeArtifactVisitor; -import org.opencds.cqf.fhir.utility.adapter.ILibraryAdapter; +import org.opencds.cqf.fhir.cr.visitor.IWithdrawVisitorTest; +import org.opencds.cqf.fhir.utility.adapter.IAdapterFactory; import org.opencds.cqf.fhir.utility.adapter.r4.AdapterFactory; import org.opencds.cqf.fhir.utility.repository.InMemoryFhirRepository; -class WithdrawVisitorTests { +class WithdrawVisitorTests implements IWithdrawVisitorTest { private final FhirContext fhirContext = FhirContext.forR4Cached(); private IRepository repo; private final IParser jsonParser = fhirContext.newJsonParser(); + private final AdapterFactory factory = new AdapterFactory(); @BeforeEach void setup() { - SearchParameter sp = (SearchParameter) jsonParser.parseResource( - ReleaseVisitorTests.class.getResourceAsStream("SearchParameter-artifactAssessment.json")); + SearchParameter sp = (SearchParameter) + jsonParser.parseResource(getClass().getResourceAsStream("SearchParameter-artifactAssessment.json")); repo = new InMemoryFhirRepository(fhirContext); repo.update(sp); } - @Test - void library_withdraw_test() { - Bundle bundle = (Bundle) - jsonParser.parseResource(WithdrawVisitorTests.class.getResourceAsStream("Bundle-small-draft.json")); - Bundle tsBundle = repo.transaction(bundle); - // InMemoryFhirRepository bug - need to get id like this - String id = tsBundle.getEntry().get(0).getResponse().getLocation(); - String version = "1.2.3-draft"; - Library library = repo.read(Library.class, new IdType(id)).copy(); - ILibraryAdapter libraryAdapter = new AdapterFactory().createLibrary(library); - IKnowledgeArtifactVisitor withdrawVisitor = new WithdrawVisitor(repo); - Parameters params = parameters(part("version", version)); - Bundle returnedBundle = (Bundle) libraryAdapter.accept(withdrawVisitor, params); - - var res = returnedBundle.getEntry(); - - assertEquals(4, res.size()); + @Override + public FhirContext fhirContext() { + return fhirContext; } - @Test - void library_withdraw_with_approval_test() throws Exception { - Bundle bundle = (Bundle) jsonParser.parseResource( - WithdrawVisitorTests.class.getResourceAsStream("Bundle-small-approved-draft.json")); - SearchParameter sp = (SearchParameter) jsonParser.parseResource( - ReleaseVisitorTests.class.getResourceAsStream("SearchParameter-artifactAssessment.json")); - Bundle tsBundle = repo.transaction(bundle); - repo.update(sp); - // Resource is uploaded using POST - need to get id like this - String id = tsBundle.getEntry().get(0).getResponse().getLocation(); - String version = "1.2.3-draft"; - Library library = repo.read(Library.class, new IdType(id)).copy(); - ILibraryAdapter libraryAdapter = new AdapterFactory().createLibrary(library); - IKnowledgeArtifactVisitor withdrawVisitor = new WithdrawVisitor(repo); - Parameters params = parameters(part("version", version)); - Bundle returnedBundle = (Bundle) libraryAdapter.accept(withdrawVisitor, params); + @Override + public IRepository getRepo() { + return repo; + } - var res = returnedBundle.getEntry(); + @Override + @SuppressWarnings("unchecked") + public T createFromResourceLocation(String resourceLocation) { + return (T) jsonParser.parseResource(getClass().getResourceAsStream(resourceLocation)); + } - assertEquals(5, res.size()); + @Override + public Class libraryClass() { + return Library.class; } - @Test - void library_withdraw_No_draft_test() { - Bundle bundle = (Bundle) jsonParser.parseResource( - WithdrawVisitorTests.class.getResourceAsStream("Bundle-ersd-small-active.json")); - repo.transaction(bundle); - String version = "1.2.3"; - Library library = repo.read(Library.class, new IdType("Library/SpecificationLibrary")) - .copy(); - ILibraryAdapter libraryAdapter = new AdapterFactory().createLibrary(library); - IKnowledgeArtifactVisitor withdrawVisitor = new WithdrawVisitor(repo); - Parameters params = parameters(part("version", version)); + @Override + public IAdapterFactory getAdapterFactory() { + return factory; + } - var exception = - assertThrows(PreconditionFailedException.class, () -> libraryAdapter.accept(withdrawVisitor, params)); - assertTrue(exception.getMessage().contains("Cannot withdraw an artifact that is not in draft status")); + @Override + public IBaseParameters createParametersForWithdrawVisitor(String version) { + return parameters(part("version", version)); } } diff --git a/cqf-fhir-cr/src/test/java/org/opencds/cqf/fhir/cr/visitor/r5/WithdrawVisitorTest.java b/cqf-fhir-cr/src/test/java/org/opencds/cqf/fhir/cr/visitor/r5/WithdrawVisitorTest.java new file mode 100644 index 0000000000..6b412671b4 --- /dev/null +++ b/cqf-fhir-cr/src/test/java/org/opencds/cqf/fhir/cr/visitor/r5/WithdrawVisitorTest.java @@ -0,0 +1,69 @@ +package org.opencds.cqf.fhir.cr.visitor.r5; + +import static org.opencds.cqf.fhir.utility.r5.Parameters.parameters; +import static org.opencds.cqf.fhir.utility.r5.Parameters.part; + +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.parser.IParser; +import ca.uhn.fhir.repository.IRepository; +import org.hl7.fhir.instance.model.api.IBaseParameters; +import org.hl7.fhir.instance.model.api.IBaseResource; +import org.hl7.fhir.r5.model.Library; +import org.hl7.fhir.r5.model.SearchParameter; +import org.junit.jupiter.api.BeforeEach; +import org.opencds.cqf.fhir.cr.visitor.IWithdrawVisitorTest; +import org.opencds.cqf.fhir.utility.adapter.IAdapterFactory; +import org.opencds.cqf.fhir.utility.adapter.r5.AdapterFactory; +import org.opencds.cqf.fhir.utility.repository.InMemoryFhirRepository; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class WithdrawVisitorTest implements IWithdrawVisitorTest { + + private static final Logger log = LoggerFactory.getLogger(WithdrawVisitorTest.class); + private final FhirContext fhirContext = FhirContext.forR5Cached(); + + private final AdapterFactory factory = new AdapterFactory(); + private IRepository repo; + + private final IParser jsonParser = fhirContext.newJsonParser(); + + @BeforeEach + void setup() { + SearchParameter sp = (SearchParameter) + jsonParser.parseResource(getClass().getResourceAsStream("SearchParameter-artifactAssessment.json")); + repo = new InMemoryFhirRepository(fhirContext); + repo.update(sp); + } + + @Override + public FhirContext fhirContext() { + return fhirContext; + } + + @Override + public IRepository getRepo() { + return repo; + } + + @Override + @SuppressWarnings("unchecked") + public T createFromResourceLocation(String resourceLocation) { + return (T) jsonParser.parseResource(getClass().getResourceAsStream(resourceLocation)); + } + + @Override + public Class libraryClass() { + return Library.class; + } + + @Override + public IAdapterFactory getAdapterFactory() { + return factory; + } + + @Override + public IBaseParameters createParametersForWithdrawVisitor(String version) { + return parameters(part("version", version)); + } +} diff --git a/cqf-fhir-cr/src/test/resources/org/opencds/cqf/fhir/cr/visitor/dstu3/Bundle-small-approved-draft.json b/cqf-fhir-cr/src/test/resources/org/opencds/cqf/fhir/cr/visitor/dstu3/Bundle-small-approved-draft.json index 2d04308bed..68829df575 100644 --- a/cqf-fhir-cr/src/test/resources/org/opencds/cqf/fhir/cr/visitor/dstu3/Bundle-small-approved-draft.json +++ b/cqf-fhir-cr/src/test/resources/org/opencds/cqf/fhir/cr/visitor/dstu3/Bundle-small-approved-draft.json @@ -95,7 +95,7 @@ "relatedArtifact": [ { "type": "depends-on", - "label": "RCTC Value Set Library of Trigger Codes", + "display": "RCTC Value Set Library of Trigger Codes", "resource": { "reference": "http://ersd.aimsplatform.org/fhir/Library/rctc|1.2.3-draft" } @@ -308,7 +308,6 @@ ] }, "expansion": { - "timestamp": "2022-10-21T15:18:29-04:00", "contains": [ { "system": "http://snomed.info/sct", @@ -332,6 +331,73 @@ "method": "PUT", "url": "ValueSet/2.16.840.1.113762.1.4.1146.6" } + }, + { + "fullUrl": "http://localhost:8082/fhir/Basic/approval1428", + "resource": { + "resourceType": "Basic", + "id": "approval1428", + "meta": { + "versionId": "1", + "lastUpdated": "2024-09-17T15:47:39.304+00:00", + "profile": [ + "http://hl7.org/fhir/uv/crmi/StructureDefinition/crmi-artifactAssessment" + ] + }, + "extension": [ + { + "url": "http://hl7.org/fhir/uv/crmi/StructureDefinition/crmi-artifactAssessmentArtifact", + "valueReference": { + "reference": "Library/SpecificationLibrary" + } + }, + { + "url": "http://hl7.org/fhir/uv/crmi/StructureDefinition/crmi-artifactAssessmentContent", + "extension": [ + { + "url": "informationType", + "valueCode": "comment" + }, + { + "url": "summary", + "valueMarkdown": "test comment text" + }, + { + "url": "relatedArtifact", + "valueRelatedArtifact": { + "type": "citation", + "resource": { + "reference": "test program reference text" + } + } + }, + { + "url": "author", + "valueReference": { + "reference": "test user text" + } + }, + { + "url": "relatedArtifact", + "valueRelatedArtifact": { + "type": "derived-from", + "resource": { + "reference": "http://ersd.aimsplatform.org/fhir/Library/SpecificationLibrary|1.2.3" + } + } + } + ] + }, + { + "url": "http://hl7.org/fhir/uv/crmi/StructureDefinition/crmi-artifactAssessmentDate", + "valueDateTime": "2023-08-08T01:11:33+00:00" + } + ] + }, + "request": { + "method": "POST", + "url": "Basic" } + } ] } \ No newline at end of file diff --git a/cqf-fhir-cr/src/test/resources/org/opencds/cqf/fhir/cr/visitor/dstu3/Bundle-small-draft.json b/cqf-fhir-cr/src/test/resources/org/opencds/cqf/fhir/cr/visitor/dstu3/Bundle-small-draft.json new file mode 100644 index 0000000000..a3bed47197 --- /dev/null +++ b/cqf-fhir-cr/src/test/resources/org/opencds/cqf/fhir/cr/visitor/dstu3/Bundle-small-draft.json @@ -0,0 +1,312 @@ +{ + "resourceType": "Bundle", + "id": "rctc-release-2022-10-19-Bundle-rctc", + "type": "transaction", + "entry": [ + { + "fullUrl": "http://ersd.aimsplatform.org/fhir/Library/SpecificationLibrary", + "resource": { + "resourceType": "Library", + "id": "SpecificationLibrary", + "url": "http://ersd.aimsplatform.org/fhir/Library/SpecificationLibrary", + "version": "1.2.3-draft", + "status": "draft", + "date": "2023-06-30", + "relatedArtifact": [ + { + "type": "composed-of", + "resource": { + "reference": "http://ersd.aimsplatform.org/fhir/PlanDefinition/us-ecr-specification|1.2.3-draft" + }, + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/artifact-isOwned", + "valueBoolean": true + } + ] + }, + { + "type": "composed-of", + "resource": { + "reference": "http://ersd.aimsplatform.org/fhir/Library/rctc|1.2.3-draft" + }, + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/artifact-isOwned", + "valueBoolean": true + } + ] + }, + { + "extension": [ + { + "url": "http://aphl.org/fhir/vsm/StructureDefinition/vsm-valueset-priority", + "valueCodeableConcept": { + "coding": [ + { + "system": "http://hl7.org/fhir/us/ecr/CodeSystem/us-ph-usage-context", + "code": "emergent" + } + ], + "text": "Emergent" + } + }, + { + "url": "http://aphl.org/fhir/vsm/StructureDefinition/vsm-valueset-condition", + "valueCodeableConcept": { + "coding": [ + { + "system": "http://snomed.info/sct", + "code": "49649001" + } + ], + "text": "Infection caused by Acanthamoeba (disorder)" + } + } + ], + "type": "depends-on", + "resource": "http://cts.nlm.nih.gov/fhir/ValueSet/2.16.840.1.113762.1.4.1146.6|20210526" + } + ] + }, + "request": { + "method": "PUT", + "url": "Library/SpecificationLibrary" + } + }, + { + "fullUrl": "http://ersd.aimsplatform.org/fhir/PlanDefinition/us-ecr-specification", + "resource": { + "resourceType": "PlanDefinition", + "id": "us-ecr-specification", + "url": "http://ersd.aimsplatform.org/fhir/PlanDefinition/us-ecr-specification", + "version": "1.2.3-draft", + "status": "draft", + "relatedArtifact": [ + { + "type": "depends-on", + "display": "RCTC Value Set Library of Trigger Codes", + "resource": { + "reference": "http://ersd.aimsplatform.org/fhir/Library/rctc|1.2.3-draft" + } + } + ] + }, + "request": { + "method": "PUT", + "url": "PlanDefinition/us-ecr-specification" + } + }, + { + "fullUrl": "http://ersd.aimsplatform.org/fhir/Library/rctc", + "resource": { + "resourceType": "Library", + "id": "rctc", + "url": "http://ersd.aimsplatform.org/fhir/Library/rctc", + "version": "1.2.3-draft", + "status": "draft", + "relatedArtifact": [ + { + "type": "composed-of", + "resource": { + "reference": "http://ersd.aimsplatform.org/fhir/ValueSet/dxtc|1.2.3-draft" + }, + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/artifact-isOwned", + "valueBoolean": true + } + ] + } + ] + }, + "request": { + "method": "PUT", + "url": "Library/rctc" + } + }, + { + "fullUrl": "http://ersd.aimsplatform.org/fhir/ValueSet/dxtc", + "resource": { + "resourceType": "ValueSet", + "id": "dxtc", + "url": "http://ersd.aimsplatform.org/fhir/ValueSet/dxtc", + "version": "1.2.3-draft", + "status": "draft", + "compose": { + "include": [ + { + "valueSet": [ + "http://cts.nlm.nih.gov/fhir/ValueSet/2.16.840.1.113762.1.4.1146.6|20210526" + ] + } + ] + }, + "expansion": { + "contains": [ + { + "system": "http://hl7.org/fhir/sid/icd-10-cm", + "version": "Provisional_2022-01-12", + "code": "T40.0X1A" + }, + { + "system": "http://hl7.org/fhir/sid/icd-10-cm", + "version": "Provisional_2022-01-12", + "code": "T40.0X2A" + }, + { + "system": "http://hl7.org/fhir/sid/icd-10-cm", + "version": "Provisional_2022-01-12", + "code": "T40.0X3A" + } + ] + } + }, + "request": { + "method": "PUT", + "url": "ValueSet/dxtc" + } + }, + { + "fullUrl": "http://cts.nlm.nih.gov/fhir/ValueSet/2.16.840.1.113762.1.4.1146.6", + "resource": { + "resourceType": "ValueSet", + "id": "2.16.840.1.113762.1.4.1146.6", + "url": "http://cts.nlm.nih.gov/fhir/ValueSet/2.16.840.1.113762.1.4.1146.6", + "identifier": [ + { + "system": "urn:ietf:rfc:3986", + "value": "urn:oid:2.16.840.1.113762.1.4.1146.6" + } + ], + "version": "20210526", + "status": "active", + "compose": { + "include": [ + { + "system": "http://snomed.info/sct", + "version": "Provisional_2022-04-25", + "concept": [ + { + "code": "1086051000119107", + "display": "Cardiomyopathy due to diphtheria (disorder)" + }, + { + "code": "1086061000119109", + "display": "Diphtheria radiculomyelitis (disorder)" + }, + { + "code": "1086071000119103", + "display": "Diphtheria tubulointerstitial nephropathy (disorder)" + }, + { + "code": "1090211000119102", + "display": "Pharyngeal diphtheria (disorder)" + }, + { + "code": "129667001", + "display": "Diphtheritic peripheral neuritis (disorder)" + }, + { + "code": "13596001", + "display": "Diphtheritic peritonitis (disorder)" + }, + { + "code": "15682004", + "display": "Anterior nasal diphtheria (disorder)" + }, + { + "code": "186347006", + "display": "Diphtheria of penis (disorder)" + }, + { + "code": "18901009", + "display": "Cutaneous diphtheria (disorder)" + }, + { + "code": "194945009", + "display": "Acute myocarditis - diphtheritic (disorder)" + }, + { + "code": "230596007", + "display": "Diphtheritic neuropathy (disorder)" + }, + { + "code": "240422004", + "display": "Tracheobronchial diphtheria (disorder)" + }, + { + "code": "26117009", + "display": "Diphtheritic myocarditis (disorder)" + }, + { + "code": "276197005", + "display": "Infection caused by Corynebacterium diphtheriae (disorder)" + }, + { + "code": "3419005", + "display": "Faucial diphtheria (disorder)" + }, + { + "code": "397428000", + "display": "Diphtheria (disorder)" + }, + { + "code": "397430003", + "display": "Diphtheria caused by Corynebacterium diphtheriae (disorder)" + }, + { + "code": "48278001", + "display": "Diphtheritic cystitis (disorder)" + }, + { + "code": "50215002", + "display": "Laryngeal diphtheria (disorder)" + }, + { + "code": "715659006", + "display": "Diphtheria of respiratory system (disorder)" + }, + { + "code": "75589004", + "display": "Nasopharyngeal diphtheria (disorder)" + }, + { + "code": "7773002", + "display": "Conjunctival diphtheria (disorder)" + }, + { + "code": "789005009", + "display": "Paralysis of uvula after diphtheria (disorder)" + } + ] + } + ] + }, + "expansion": { + "contains": [ + { + "system": "http://snomed.info/sct", + "version": "Provisional_2022-04-25", + "code": "1086051000119107" + }, + { + "system": "http://snomed.info/sct", + "version": "Provisional_2022-04-25", + "code": "1086061000119109" + }, + { + "system": "http://snomed.info/sct", + "version": "Provisional_2022-04-25", + "code": "1086071000119103" + } + ] + } + }, + "request": { + "method": "PUT", + "url": "ValueSet/2.16.840.1.113762.1.4.1146.6" + } + } + ] +} diff --git a/cqf-fhir-cr/src/test/resources/org/opencds/cqf/fhir/cr/visitor/r5/Bundle-small-approved-draft.json b/cqf-fhir-cr/src/test/resources/org/opencds/cqf/fhir/cr/visitor/r5/Bundle-small-approved-draft.json index 523d9a594a..44975b34fd 100644 --- a/cqf-fhir-cr/src/test/resources/org/opencds/cqf/fhir/cr/visitor/r5/Bundle-small-approved-draft.json +++ b/cqf-fhir-cr/src/test/resources/org/opencds/cqf/fhir/cr/visitor/r5/Bundle-small-approved-draft.json @@ -320,6 +320,70 @@ "method": "PUT", "url": "ValueSet/2.16.840.1.113762.1.4.1146.6" } + }, + { + "fullUrl": "http://localhost:8082/fhir/Basic/approval1428", + "resource": { + "resourceType": "Basic", + "id": "approval1428", + "meta": { + "versionId": "1", + "lastUpdated": "2024-09-17T15:47:39.304+00:00", + "source": "#CxIqmz1z5zi7bitc", + "profile": [ + "http://hl7.org/fhir/uv/crmi/StructureDefinition/crmi-artifactAssessment" + ] + }, + "extension": [ + { + "url": "http://hl7.org/fhir/uv/crmi/StructureDefinition/crmi-artifactAssessmentArtifact", + "valueReference": { + "reference": "Library/SpecificationLibrary" + } + }, + { + "url": "http://hl7.org/fhir/uv/crmi/StructureDefinition/crmi-artifactAssessmentContent", + "extension": [ + { + "url": "informationType", + "valueCode": "comment" + }, + { + "url": "summary", + "valueMarkdown": "test comment text" + }, + { + "url": "relatedArtifact", + "valueRelatedArtifact": { + "type": "citation", + "resource": "test program reference text" + } + }, + { + "url": "author", + "valueReference": { + "reference": "test user text" + } + }, + { + "url": "relatedArtifact", + "valueRelatedArtifact": { + "type": "derived-from", + "resource": "http://ersd.aimsplatform.org/fhir/Library/SpecificationLibrary|1.2.3" + } + } + ] + }, + { + "url": "http://hl7.org/fhir/uv/crmi/StructureDefinition/crmi-artifactAssessmentDate", + "valueDateTime": "2023-08-08T01:11:33+00:00" + } + ] + }, + "request": { + "method": "POST", + "url": "Basic" + } } ] } diff --git a/cqf-fhir-cr/src/test/resources/org/opencds/cqf/fhir/cr/visitor/r5/Bundle-small-draft.json b/cqf-fhir-cr/src/test/resources/org/opencds/cqf/fhir/cr/visitor/r5/Bundle-small-draft.json new file mode 100644 index 0000000000..cc4ddb84ea --- /dev/null +++ b/cqf-fhir-cr/src/test/resources/org/opencds/cqf/fhir/cr/visitor/r5/Bundle-small-draft.json @@ -0,0 +1,307 @@ +{ + "resourceType": "Bundle", + "id": "rctc-release-2022-10-19-Bundle-rctc", + "type": "transaction", + "timestamp": "2022-10-21T15:18:28.504-04:00", + "entry": [ + { + "fullUrl": "http://ersd.aimsplatform.org/fhir/Library/SpecificationLibrary", + "resource": { + "resourceType": "Library", + "id": "SpecificationLibrary", + "url": "http://ersd.aimsplatform.org/fhir/Library/SpecificationLibrary", + "version": "1.2.3-draft", + "status": "draft", + "date": "2023-06-30", + "relatedArtifact": [ + { + "type": "composed-of", + "resource": "http://ersd.aimsplatform.org/fhir/PlanDefinition/us-ecr-specification|1.2.3-draft", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/artifact-isOwned", + "valueBoolean": true + } + ] + }, + { + "type": "composed-of", + "resource": "http://ersd.aimsplatform.org/fhir/Library/rctc|1.2.3-draft", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/artifact-isOwned", + "valueBoolean": true + } + ] + }, + { + "extension": [ + { + "url": "http://aphl.org/fhir/vsm/StructureDefinition/vsm-valueset-priority", + "valueCodeableConcept": { + "coding": [ + { + "system": "http://hl7.org/fhir/us/ecr/CodeSystem/us-ph-usage-context", + "code": "emergent" + } + ], + "text": "Emergent" + } + }, + { + "url": "http://aphl.org/fhir/vsm/StructureDefinition/vsm-valueset-condition", + "valueCodeableConcept": { + "coding": [ + { + "system": "http://snomed.info/sct", + "code": "49649001" + } + ], + "text": "Infection caused by Acanthamoeba (disorder)" + } + } + ], + "type": "depends-on", + "resource": "http://cts.nlm.nih.gov/fhir/ValueSet/2.16.840.1.113762.1.4.1146.6|20210526" + } + ] + }, + "request": { + "method": "PUT", + "url": "Library/SpecificationLibrary" + } + }, + { + "fullUrl": "http://ersd.aimsplatform.org/fhir/PlanDefinition/us-ecr-specification", + "resource": { + "resourceType": "PlanDefinition", + "id": "us-ecr-specification", + "url": "http://ersd.aimsplatform.org/fhir/PlanDefinition/us-ecr-specification", + "version": "1.2.3-draft", + "status": "draft", + "relatedArtifact": [ + { + "type": "depends-on", + "label": "RCTC Value Set Library of Trigger Codes", + "resource": "http://ersd.aimsplatform.org/fhir/Library/rctc|1.2.3-draft" + } + ] + }, + "request": { + "method": "PUT", + "url": "PlanDefinition/us-ecr-specification" + } + }, + { + "fullUrl": "http://ersd.aimsplatform.org/fhir/Library/rctc", + "resource": { + "resourceType": "Library", + "id": "rctc", + "url": "http://ersd.aimsplatform.org/fhir/Library/rctc", + "version": "1.2.3-draft", + "status": "draft", + "relatedArtifact": [ + { + "type": "composed-of", + "resource": "http://ersd.aimsplatform.org/fhir/ValueSet/dxtc|1.2.3-draft", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/artifact-isOwned", + "valueBoolean": true + } + ] + } + ] + }, + "request": { + "method": "PUT", + "url": "Library/rctc" + } + }, + { + "fullUrl": "http://ersd.aimsplatform.org/fhir/ValueSet/dxtc", + "resource": { + "resourceType": "ValueSet", + "id": "dxtc", + "url": "http://ersd.aimsplatform.org/fhir/ValueSet/dxtc", + "version": "1.2.3-draft", + "status": "draft", + "compose": { + "include": [ + { + "valueSet": [ + "http://cts.nlm.nih.gov/fhir/ValueSet/2.16.840.1.113762.1.4.1146.6|20210526" + ] + } + ] + }, + "expansion": { + "timestamp": "2022-10-21T15:18:29-04:00", + "contains": [ + { + "system": "http://hl7.org/fhir/sid/icd-10-cm", + "version": "Provisional_2022-01-12", + "code": "T40.0X1A" + }, + { + "system": "http://hl7.org/fhir/sid/icd-10-cm", + "version": "Provisional_2022-01-12", + "code": "T40.0X2A" + }, + { + "system": "http://hl7.org/fhir/sid/icd-10-cm", + "version": "Provisional_2022-01-12", + "code": "T40.0X3A" + } + ] + } + }, + "request": { + "method": "PUT", + "url": "ValueSet/dxtc" + } + }, + { + "fullUrl": "http://cts.nlm.nih.gov/fhir/ValueSet/2.16.840.1.113762.1.4.1146.6", + "resource": { + "resourceType": "ValueSet", + "id": "2.16.840.1.113762.1.4.1146.6", + "url": "http://cts.nlm.nih.gov/fhir/ValueSet/2.16.840.1.113762.1.4.1146.6", + "identifier": [ + { + "system": "urn:ietf:rfc:3986", + "value": "urn:oid:2.16.840.1.113762.1.4.1146.6" + } + ], + "version": "20210526", + "status": "active", + "compose": { + "include": [ + { + "system": "http://snomed.info/sct", + "version": "Provisional_2022-04-25", + "concept": [ + { + "code": "1086051000119107", + "display": "Cardiomyopathy due to diphtheria (disorder)" + }, + { + "code": "1086061000119109", + "display": "Diphtheria radiculomyelitis (disorder)" + }, + { + "code": "1086071000119103", + "display": "Diphtheria tubulointerstitial nephropathy (disorder)" + }, + { + "code": "1090211000119102", + "display": "Pharyngeal diphtheria (disorder)" + }, + { + "code": "129667001", + "display": "Diphtheritic peripheral neuritis (disorder)" + }, + { + "code": "13596001", + "display": "Diphtheritic peritonitis (disorder)" + }, + { + "code": "15682004", + "display": "Anterior nasal diphtheria (disorder)" + }, + { + "code": "186347006", + "display": "Diphtheria of penis (disorder)" + }, + { + "code": "18901009", + "display": "Cutaneous diphtheria (disorder)" + }, + { + "code": "194945009", + "display": "Acute myocarditis - diphtheritic (disorder)" + }, + { + "code": "230596007", + "display": "Diphtheritic neuropathy (disorder)" + }, + { + "code": "240422004", + "display": "Tracheobronchial diphtheria (disorder)" + }, + { + "code": "26117009", + "display": "Diphtheritic myocarditis (disorder)" + }, + { + "code": "276197005", + "display": "Infection caused by Corynebacterium diphtheriae (disorder)" + }, + { + "code": "3419005", + "display": "Faucial diphtheria (disorder)" + }, + { + "code": "397428000", + "display": "Diphtheria (disorder)" + }, + { + "code": "397430003", + "display": "Diphtheria caused by Corynebacterium diphtheriae (disorder)" + }, + { + "code": "48278001", + "display": "Diphtheritic cystitis (disorder)" + }, + { + "code": "50215002", + "display": "Laryngeal diphtheria (disorder)" + }, + { + "code": "715659006", + "display": "Diphtheria of respiratory system (disorder)" + }, + { + "code": "75589004", + "display": "Nasopharyngeal diphtheria (disorder)" + }, + { + "code": "7773002", + "display": "Conjunctival diphtheria (disorder)" + }, + { + "code": "789005009", + "display": "Paralysis of uvula after diphtheria (disorder)" + } + ] + } + ] + }, + "expansion": { + "timestamp": "2022-10-21T15:18:29-04:00", + "contains": [ + { + "system": "http://snomed.info/sct", + "version": "Provisional_2022-04-25", + "code": "1086051000119107" + }, + { + "system": "http://snomed.info/sct", + "version": "Provisional_2022-04-25", + "code": "1086061000119109" + }, + { + "system": "http://snomed.info/sct", + "version": "Provisional_2022-04-25", + "code": "1086071000119103" + } + ] + } + }, + "request": { + "method": "PUT", + "url": "ValueSet/2.16.840.1.113762.1.4.1146.6" + } + } + ] +} diff --git a/cqf-fhir-utility/src/main/java/org/opencds/cqf/fhir/utility/r5/ArtifactAssessment.java b/cqf-fhir-utility/src/main/java/org/opencds/cqf/fhir/utility/r5/ArtifactAssessment.java new file mode 100644 index 0000000000..a07eb170bf --- /dev/null +++ b/cqf-fhir-utility/src/main/java/org/opencds/cqf/fhir/utility/r5/ArtifactAssessment.java @@ -0,0 +1,1669 @@ +package org.opencds.cqf.fhir.utility.r5; + +import ca.uhn.fhir.model.api.annotation.DatatypeDef; +import ca.uhn.fhir.model.api.annotation.ResourceDef; +import java.util.Date; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; +import org.apache.commons.lang3.StringUtils; +import org.hl7.fhir.exceptions.FHIRException; +import org.hl7.fhir.r5.model.Base; +import org.hl7.fhir.r5.model.Basic; +import org.hl7.fhir.r5.model.BooleanType; +import org.hl7.fhir.r5.model.CanonicalType; +import org.hl7.fhir.r5.model.CodeType; +import org.hl7.fhir.r5.model.CodeableConcept; +import org.hl7.fhir.r5.model.Configuration; +import org.hl7.fhir.r5.model.DataType; +import org.hl7.fhir.r5.model.DateTimeType; +import org.hl7.fhir.r5.model.DateType; +import org.hl7.fhir.r5.model.EnumFactory; +import org.hl7.fhir.r5.model.Enumeration; +import org.hl7.fhir.r5.model.Extension; +import org.hl7.fhir.r5.model.MarkdownType; +import org.hl7.fhir.r5.model.PrimitiveType; +import org.hl7.fhir.r5.model.Quantity; +import org.hl7.fhir.r5.model.Reference; +import org.hl7.fhir.r5.model.RelatedArtifact; +import org.hl7.fhir.r5.model.RelatedArtifact.RelatedArtifactType; +import org.hl7.fhir.r5.model.StringType; +import org.hl7.fhir.r5.model.UriType; + +@ResourceDef( + id = "ArtifactAssessment", + profile = "http://hl7.org/fhir/uv/crmi/StructureDefinition/crmi-artifactAssessment") +public class ArtifactAssessment extends Basic { + public enum ArtifactAssessmentContentInformationType { + /** + * A comment on the artifact + */ + COMMENT, + /** + * A classifier of the artifact + */ + CLASSIFIER, + /** + * A rating of the artifact + */ + RATING, + /** + * A container for multiple components + */ + CONTAINER, + /** + * A response to a comment + */ + RESPONSE, + /** + * A change request for the artifact + */ + CHANGEREQUEST, + /** + * added to help the parsers with the generic types + */ + NULL; + + public static ArtifactAssessment.ArtifactAssessmentContentInformationType fromCode(String codeString) + throws FHIRException { + if (StringUtils.isBlank(codeString)) { + return null; + } + switch (codeString) { + case "comment": + return COMMENT; + case "classifier": + return CLASSIFIER; + case "rating": + return RATING; + case "container": + return CONTAINER; + case "response": + return RESPONSE; + case "change-request": + return CHANGEREQUEST; + + default: + if (Configuration.isAcceptInvalidEnums()) { + return null; + } else { + throw new FHIRException("Unknown ArtifactAssessment '" + codeString + "'"); + } + } + } + + public String toCode() { + switch (this) { + case COMMENT: + return "comment"; + case CLASSIFIER: + return "classifier"; + case RATING: + return "rating"; + case CONTAINER: + return "container"; + case RESPONSE: + return "response"; + case CHANGEREQUEST: + return "change-request"; + case NULL: + return null; + default: + return "?"; + } + } + + public String getSystem() { + switch (this) { + case COMMENT, CLASSIFIER, RATING, CONTAINER, RESPONSE, CHANGEREQUEST: + return "http://hl7.org/fhir/ValueSet/artifactassessment-information-type"; + case NULL: + return null; + default: + return "?"; + } + } + + public String getDefinition() { + switch (this) { + case COMMENT: + return "A comment on the artifact."; + case CLASSIFIER: + return "A classifier of the artifact."; + case RATING: + return "A rating of the artifact."; + case CONTAINER: + return "A container for multiple components."; + case RESPONSE: + return "A response to a comment."; + case CHANGEREQUEST: + return "A change request for the artifact."; + case NULL: + return null; + default: + return "?"; + } + } + + public String getDisplay() { + switch (this) { + case COMMENT: + return "Comment"; + case CLASSIFIER: + return "Classifier"; + case RATING: + return "Rating"; + case CONTAINER: + return "Container"; + case RESPONSE: + return "Response"; + case CHANGEREQUEST: + return "Change Request"; + case NULL: + return null; + default: + return "?"; + } + } + } + + public static class ArtifactAssessmentContentInformationTypeEnumFactory + implements EnumFactory { + public ArtifactAssessment.ArtifactAssessmentContentInformationType fromCode(String codeString) + throws IllegalArgumentException { + return ArtifactAssessment.ArtifactAssessmentContentInformationType.fromCode(codeString); + } + + public Enumeration fromType(Base code) + throws FHIRException { + if (code == null) return null; + if (code.isEmpty()) return new Enumeration<>(this); + return new Enumeration<>( + this, + ArtifactAssessment.ArtifactAssessmentContentInformationType.fromCode( + ((PrimitiveType) code).asStringValue())); + } + + public String toCode(ArtifactAssessment.ArtifactAssessmentContentInformationType code) { + return code.toCode(); + } + + public String toSystem(ArtifactAssessment.ArtifactAssessmentContentInformationType code) { + return code.getSystem(); + } + } + + public enum ArtifactAssessmentContentClassifier { + /** + * High quality evidence. + */ + HIGH, + /** + * Moderate quality evidence. + */ + MODERATE, + /** + * Low quality evidence. + */ + LOW, + /** + * Very low quality evidence + */ + VERY_LOW, + /** + * No serious concern. + */ + NO_CONCERN, + /** + * Serious concern. + */ + SERIOUS_CONCERN, + /** + * Very serious concern. + */ + VERY_SERIOUS_CONCERN, + /** + * Extremely serious concern. + */ + EXTREMELY_SERIOUS_CONCERN, + /** + * Possible reason for increasing quality rating was checked and found to be present. + */ + PRESENT, + /** + * Possible reason for increasing quality rating was checked and found to be absent. + */ + ABSENT, + /** + * No change to quality rating. + */ + NO_CHANGE, + /** + * Reduce quality rating by 1. + */ + DOWNCODE1, + /** + * Reduce quality rating by 2. + */ + DOWNCODE2, + /** + * Reduce quality rating by 3. + */ + DOWNCODE3, + /** + * Increase quality rating by 1. + */ + UPCODE1, + /** + * Increase quality rating by 2 + */ + UPCODE2, + /** + * added to help the parsers with the generic types + */ + NULL; + + public static ArtifactAssessment.ArtifactAssessmentContentClassifier fromCode(String codeString) + throws FHIRException { + if (StringUtils.isBlank(codeString)) { + return null; + } + switch (codeString) { + case "high": + return HIGH; + case "moderate": + return MODERATE; + case "low": + return LOW; + case "very-low": + return VERY_LOW; + case "no-concern": + return NO_CONCERN; + case "serious-concern": + return SERIOUS_CONCERN; + case "very-serious-concern": + return VERY_SERIOUS_CONCERN; + case "extremely-serious-concern": + return EXTREMELY_SERIOUS_CONCERN; + case "present": + return PRESENT; + case "absent": + return ABSENT; + case "no-change": + return NO_CHANGE; + case "downcode1": + return DOWNCODE1; + case "downcode2": + return DOWNCODE2; + case "downcode3": + return DOWNCODE3; + case "upcode1": + return UPCODE1; + case "upcode2": + return UPCODE2; + default: + if (Configuration.isAcceptInvalidEnums()) { + return null; + } else { + throw new FHIRException("Unknown ArtifactAssessment '" + codeString + "'"); + } + } + } + + public String toCode() { + switch (this) { + case HIGH: + return "high"; + case MODERATE: + return "moderate"; + case LOW: + return "low"; + case VERY_LOW: + return "very-low"; + case NO_CONCERN: + return "no-concern"; + case SERIOUS_CONCERN: + return "serious-concern"; + case VERY_SERIOUS_CONCERN: + return "very-serious-concern"; + case EXTREMELY_SERIOUS_CONCERN: + return "extremely-serious-concern"; + case PRESENT: + return "present"; + case ABSENT: + return "absent"; + case NO_CHANGE: + return "no-change"; + case DOWNCODE1: + return "downcode1"; + case DOWNCODE2: + return "downcode2"; + case DOWNCODE3: + return "downcode3"; + case UPCODE1: + return "upcode1"; + case UPCODE2: + return "upcode2"; + case NULL: + return null; + default: + return "?"; + } + } + + public String getSystem() { + switch (this) { + case HIGH, + MODERATE, + LOW, + VERY_LOW, + NO_CONCERN, + SERIOUS_CONCERN, + VERY_SERIOUS_CONCERN, + EXTREMELY_SERIOUS_CONCERN, + PRESENT, + ABSENT, + NO_CHANGE, + DOWNCODE1, + DOWNCODE2, + DOWNCODE3, + UPCODE1, + UPCODE2: + return "http://terminology.hl7.org/CodeSystem/certainty-rating"; + case NULL: + return null; + default: + return "?"; + } + } + + public String getDefinition() { + switch (this) { + case HIGH: + return "High quality evidence."; + case MODERATE: + return "Moderate quality evidence."; + case LOW: + return "Low quality evidence."; + case VERY_LOW: + return "Very low quality evidence."; + case NO_CONCERN: + return "No serious concern."; + case SERIOUS_CONCERN: + return "Serious concern."; + case VERY_SERIOUS_CONCERN: + return "Very serious concern."; + case EXTREMELY_SERIOUS_CONCERN: + return "Extremely serious concern."; + case PRESENT: + return "Possible reason for increasing quality rating was checked and found to be present."; + case ABSENT: + return "Possible reason for increasing quality rating was checked and found to be absent."; + case NO_CHANGE: + return "No change to quality rating."; + case DOWNCODE1: + return "Reduce quality rating by 1."; + case DOWNCODE2: + return "Reduce quality rating by 2."; + case DOWNCODE3: + return "Reduce quality rating by 3."; + case UPCODE1: + return "Increase quality rating by 1."; + case UPCODE2: + return "Increase quality rating by 2."; + case NULL: + return null; + default: + return "?"; + } + } + + public String getDisplay() { + switch (this) { + case HIGH: + return "High quality"; + case MODERATE: + return "Moderate quality"; + case LOW: + return "Low quality"; + case VERY_LOW: + return "Very low quality"; + case NO_CONCERN: + return "No serious concern"; + case SERIOUS_CONCERN: + return "Serious concern"; + case VERY_SERIOUS_CONCERN: + return "Very serious concern"; + case EXTREMELY_SERIOUS_CONCERN: + return "Extremely serious concern"; + case PRESENT: + return "Present"; + case ABSENT: + return "Absent"; + case NO_CHANGE: + return "No change to rating"; + case DOWNCODE1: + return "Reduce rating: -1"; + case DOWNCODE2: + return "Reduce rating: -2"; + case DOWNCODE3: + return "Reduce rating: -3"; + case UPCODE1: + return "Increase rating: +1"; + case UPCODE2: + return "Increase rating: +2"; + case NULL: + return null; + default: + return "?"; + } + } + } + + public static class ArtifactAssessmentContentClassifierEnumFactory + implements EnumFactory { + public ArtifactAssessment.ArtifactAssessmentContentClassifier fromCode(String codeString) + throws IllegalArgumentException { + return ArtifactAssessment.ArtifactAssessmentContentClassifier.fromCode(codeString); + } + + public Enumeration fromType(Base code) + throws FHIRException { + if (code == null) { + return null; + } + if (code.isEmpty()) { + return new Enumeration<>(this); + } + return new Enumeration<>( + this, + ArtifactAssessment.ArtifactAssessmentContentClassifier.fromCode( + ((PrimitiveType) code).asStringValue())); + } + + public String toCode(ArtifactAssessment.ArtifactAssessmentContentClassifier code) { + return code.toCode(); + } + + public String toSystem(ArtifactAssessment.ArtifactAssessmentContentClassifier code) { + return code.getSystem(); + } + } + + public enum ArtifactAssessmentContentType {} + + public enum ArtifactAssessmentWorkflowStatus { + /** + * The comment has been submitted, but the responsible party has not yet been determined, or the responsible party has not yet determined the next steps to be taken. + */ + SUBMITTED, + /** + * The comment has been triaged, meaning the responsible party has been determined and next steps have been identified to address the comment. + */ + TRIAGED, + /** + * The comment is waiting for input from a specific party before next steps can be taken. + */ + WAITINGFORINPUT, + /** + * The comment has been resolved and no changes resulted from the resolution + */ + RESOLVEDNOCHANGE, + /** + * The comment has been resolved and changes are required to address the comment + */ + RESOLVEDCHANGEREQUIRED, + /** + * The comment is acceptable, but resolution of the comment and application of any associated changes have been deferred + */ + DEFERRED, + /** + * The comment is a duplicate of another comment already received + */ + DUPLICATE, + /** + * The comment is resolved and any necessary changes have been applied + */ + APPLIED, + /** + * The necessary changes to the artifact have been published in a new version of the artifact + */ + PUBLISHED, + /** + * added to help the parsers with the generic types + */ + NULL; + + public static ArtifactAssessment.ArtifactAssessmentWorkflowStatus fromCode(String codeString) + throws FHIRException { + if (StringUtils.isBlank(codeString)) { + return null; + } + switch (codeString) { + case "submitted": + return SUBMITTED; + case "triaged": + return TRIAGED; + case "waiting-for-input": + return WAITINGFORINPUT; + case "resolved-no-change": + return RESOLVEDNOCHANGE; + case "resolved-change-required": + return RESOLVEDCHANGEREQUIRED; + case "deferred": + return DEFERRED; + case "duplicate": + return DUPLICATE; + case "applied": + return APPLIED; + case "published": + return PUBLISHED; + + default: + if (Configuration.isAcceptInvalidEnums()) { + return null; + } else { + throw new FHIRException("Unknown ArtifactAssessmentWorkflowStatus code '" + codeString + "'"); + } + } + } + + public String toCode() { + switch (this) { + case SUBMITTED: + return "submitted"; + case TRIAGED: + return "triaged"; + case WAITINGFORINPUT: + return "waiting-for-input"; + case RESOLVEDNOCHANGE: + return "resolved-no-change"; + case RESOLVEDCHANGEREQUIRED: + return "resolved-change-required"; + case DEFERRED: + return "deferred"; + case DUPLICATE: + return "duplicate"; + case APPLIED: + return "applied"; + case PUBLISHED: + return "published"; + default: + return "?"; + } + } + + public String getSystem() { + if (this.equals(NULL)) { + return "?"; + } else { + return "http://hl7.org/fhir/artifactassessment-workflow-status"; + } + } + + public String getDefinition() { + switch (this) { + case SUBMITTED: + return "The comment has been submitted, but the responsible party has not yet been determined, or the responsible party has not yet determined the next steps to be taken."; + case TRIAGED: + return "The comment has been triaged, meaning the responsible party has been determined and next steps have been identified to address the comment."; + case WAITINGFORINPUT: + return "The comment is waiting for input from a specific party before next steps can be taken."; + case RESOLVEDNOCHANGE: + return "The comment has been resolved and no changes resulted from the resolution"; + case RESOLVEDCHANGEREQUIRED: + return "The comment has been resolved and changes are required to address the comment"; + case DEFERRED: + return "The comment is acceptable, but resolution of the comment and application of any associated changes have been deferred"; + case DUPLICATE: + return "The comment is a duplicate of another comment already received"; + case APPLIED: + return "The comment is resolved and any necessary changes have been applied"; + case PUBLISHED: + return "The necessary changes to the artifact have been published in a new version of the artifact"; + default: + return "?"; + } + } + + public String getDisplay() { + switch (this) { + case SUBMITTED: + return "Submitted"; + case TRIAGED: + return "Triaged"; + case WAITINGFORINPUT: + return "Waiting for Input"; + case RESOLVEDNOCHANGE: + return "Resolved - No Change"; + case RESOLVEDCHANGEREQUIRED: + return "Resolved - Change Required"; + case DEFERRED: + return "Deferred"; + case DUPLICATE: + return "Duplicate"; + case APPLIED: + return "Applied"; + case PUBLISHED: + return "Published"; + default: + return "?"; + } + } + } + + public static class ArtifactAssessmentWorkflowStatusEnumFactory + implements EnumFactory { + public ArtifactAssessment.ArtifactAssessmentWorkflowStatus fromCode(String codeString) + throws IllegalArgumentException { + return ArtifactAssessment.ArtifactAssessmentWorkflowStatus.fromCode(codeString); + } + + public Enumeration fromType(Base code) + throws FHIRException { + if (code == null) { + return null; + } + if (code.isEmpty()) { + return new Enumeration<>(this); + } + return new Enumeration<>( + this, + ArtifactAssessment.ArtifactAssessmentWorkflowStatus.fromCode( + ((PrimitiveType) code).asStringValue())); + } + + public String toCode(ArtifactAssessment.ArtifactAssessmentWorkflowStatus code) { + return code.toCode(); + } + + public String toSystem(ArtifactAssessment.ArtifactAssessmentWorkflowStatus code) { + return code.getSystem(); + } + } + + public enum ArtifactAssessmentDisposition { + /** + * The comment is unresolved + */ + UNRESOLVED, + /** + * The comment is not persuasive (rejected in full) + */ + NOTPERSUASIVE, + /** + * The comment is persuasive (accepted in full) + */ + PERSUASIVE, + /** + * The comment is persuasive with modification (partially accepted) + */ + PERSUASIVEWITHMODIFICATION, + /** + * The comment is not persuasive with modification (partially rejected) + */ + NOTPERSUASIVEWITHMODIFICATION, + /** + * added to help the parsers with the generic types + */ + NULL; + + public static ArtifactAssessment.ArtifactAssessmentDisposition fromCode(String codeString) + throws FHIRException { + if (StringUtils.isBlank(codeString)) { + return null; + } + switch (codeString) { + case "unresolved": + return UNRESOLVED; + case "not-persuasive": + return NOTPERSUASIVE; + case "persuasive": + return PERSUASIVE; + case "persuasive-with-modification": + return PERSUASIVEWITHMODIFICATION; + case "not-persuasive-with-modification": + return NOTPERSUASIVEWITHMODIFICATION; + + default: + if (Configuration.isAcceptInvalidEnums()) { + return null; + } else { + throw new FHIRException("Unknown ArtifactAssessmentDisposition code '" + codeString + "'"); + } + } + } + + public String toCode() { + switch (this) { + case UNRESOLVED: + return "unresolved"; + case NOTPERSUASIVE: + return "not-persuasive"; + case PERSUASIVE: + return "persuasive"; + case PERSUASIVEWITHMODIFICATION: + return "persuasive-with-modification"; + case NOTPERSUASIVEWITHMODIFICATION: + return "not-persuasive-with-modification"; + default: + return "?"; + } + } + + public String getSystem() { + if (this.equals(NULL)) { + return "?"; + } else { + return "http://hl7.org/fhir/artifactassessment-disposition"; + } + } + + public String getDefinition() { + switch (this) { + case UNRESOLVED: + return "The comment is unresolved"; + case NOTPERSUASIVE: + return "The comment is not persuasive (rejected in full)"; + case PERSUASIVE: + return "The comment is persuasive (accepted in full)"; + case PERSUASIVEWITHMODIFICATION: + return "The comment is persuasive with modification (partially accepted)"; + case NOTPERSUASIVEWITHMODIFICATION: + return "The comment is not persuasive with modification (partially rejected)"; + default: + return "?"; + } + } + + public String getDisplay() { + switch (this) { + case UNRESOLVED: + return "Unresolved"; + case NOTPERSUASIVE: + return "Not Persuasive"; + case PERSUASIVE: + return "Persuasive"; + case PERSUASIVEWITHMODIFICATION: + return "Persuasive with Modification"; + case NOTPERSUASIVEWITHMODIFICATION: + return "Not Persuasive with Modification"; + default: + return "?"; + } + } + } + + public static class ArtifactAssessmentDispositionEnumFactory + implements EnumFactory { + public ArtifactAssessment.ArtifactAssessmentDisposition fromCode(String codeString) + throws IllegalArgumentException { + return ArtifactAssessment.ArtifactAssessmentDisposition.fromCode(codeString); + } + + public Enumeration fromType(Base code) throws FHIRException { + if (code == null) { + return null; + } + if (code.isEmpty()) { + return new Enumeration<>(this); + } + return new Enumeration<>( + this, + ArtifactAssessment.ArtifactAssessmentDisposition.fromCode( + ((PrimitiveType) code).asStringValue())); + } + + public String toCode(ArtifactAssessment.ArtifactAssessmentDisposition code) { + return code.toCode(); + } + + public String toSystem(ArtifactAssessment.ArtifactAssessmentDisposition code) { + return code.getSystem(); + } + } + + public static final String ARTIFACT_COMMENT_EXTENSION_URL = + "http://hl7.org/fhir/us/cqfmeasures/StructureDefinition/cqfm-artifactComment"; + public static final String CONTENT = + "http://hl7.org/fhir/uv/crmi/StructureDefinition/crmi-artifactAssessmentContent"; + public static final String ARTIFACT = + "http://hl7.org/fhir/uv/crmi/StructureDefinition/crmi-artifactAssessmentArtifact"; + public static final String CITEAS = "http://hl7.org/fhir/uv/crmi/StructureDefinition/crmi-artifactAssessmentCiteAs"; + public static final String TITLE = "http://hl7.org/fhir/uv/crmi/StructureDefinition/crmi-artifactAssessmentTitle"; + public static final String DATE = "http://hl7.org/fhir/uv/crmi/StructureDefinition/crmi-artifactAssessmentDate"; + public static final String COPYRIGHT = + "http://hl7.org/fhir/uv/crmi/StructureDefinition/crmi-artifactAssessmentCopyright"; + public static final String APPROVAL_DATE = + "http://hl7.org/fhir/uv/crmi/StructureDefinition/crmi-artifactAssessmentApprovalDate"; + public static final String LAST_REVIEW_DATE = + "http://hl7.org/fhir/uv/crmi/StructureDefinition/crmi-artifactAssessmentLastReviewDate"; + public static final String WORKFLOW_STATUS = + "http://hl7.org/fhir/uv/crmi/StructureDefinition/crmi-artifactAssessmentWorkflowStatus"; + public static final String DISPOSITION = + "http://hl7.org/fhir/uv/crmi/StructureDefinition/crmi-artifactAssessmentDisposition"; + + public ArtifactAssessment() { + super(); + } + + public ArtifactAssessment(Reference artifact) { + super(); + this.setArtifactExtension(artifact); + } + + public ArtifactAssessment(CanonicalType artifact) { + super(); + this.setArtifactExtension(artifact); + } + + public ArtifactAssessment(UriType artifact) { + super(); + this.setArtifactExtension(artifact); + } + + public ArtifactAssessment createArtifactComment( + CodeType type, + Reference targetReference, + Optional derivedFromUri, + Optional text, + Optional reference, + Optional user) + throws FHIRException { + ArtifactAssessment.ArtifactAssessmentContentExtension content = + new ArtifactAssessment.ArtifactAssessmentContentExtension(); + if (type != null) { + content.setInfoType(type); + } + if (text.isPresent() && !StringUtils.isBlank(text.get().getValue())) { + content.setSummary(text.get()); + } + if (reference.isPresent() && !StringUtils.isBlank(reference.get().getValue())) { + content.addRelatedArtifact(reference.get(), RelatedArtifactType.CITATION); + } + if (user.isPresent() && !StringUtils.isBlank(user.get().getReference())) { + content.setAuthorExtension(user.get()); + } + if (derivedFromUri.isPresent() + && !StringUtils.isBlank(derivedFromUri.get().getValue())) { + content.addRelatedArtifact(derivedFromUri.get(), RelatedArtifactType.DERIVEDFROM); + } + this.addExtension(content); + setDateExtension(new DateTimeType(new Date())); + if (targetReference != null && !StringUtils.isBlank(targetReference.getReference())) { + this.setArtifactExtension(targetReference); + } + return this; + } + + public ArtifactAssessment createArtifactComment( + CodeType type, + CanonicalType targetReference, + Optional derivedFromUri, + Optional text, + Optional reference, + Optional user) + throws FHIRException { + ArtifactAssessment.ArtifactAssessmentContentExtension content = + new ArtifactAssessment.ArtifactAssessmentContentExtension(); + if (type != null) { + content.setInfoType(type); + } + if (text.isPresent() && !StringUtils.isBlank(text.get().getValue())) { + content.setSummary(text.get()); + } + if (reference.isPresent() && !StringUtils.isBlank(reference.get().getValue())) { + content.addRelatedArtifact(reference.get(), RelatedArtifactType.CITATION); + } + if (user.isPresent() && !StringUtils.isBlank(user.get().getReference())) { + content.setAuthorExtension(user.get()); + } + if (derivedFromUri.isPresent() + && !StringUtils.isBlank(derivedFromUri.get().getValue())) { + content.addRelatedArtifact(derivedFromUri.get(), RelatedArtifactType.DERIVEDFROM); + } + this.addExtension(content); + setDateExtension(new DateTimeType(new Date())); + if (targetReference != null && !StringUtils.isBlank(targetReference.getValue())) { + this.setArtifactExtension(targetReference); + } + return this; + } + + public ArtifactAssessment createArtifactComment( + CodeType type, + UriType targetReference, + Optional derivedFromUri, + Optional text, + Optional reference, + Optional user) + throws FHIRException { + ArtifactAssessment.ArtifactAssessmentContentExtension content = + new ArtifactAssessment.ArtifactAssessmentContentExtension(); + if (type != null) { + content.setInfoType(type); + } + if (text.isPresent() && !StringUtils.isBlank(text.get().getValue())) { + content.setSummary(text.get()); + } + if (reference.isPresent() && !StringUtils.isBlank(reference.get().getValue())) { + content.addRelatedArtifact(reference.get(), RelatedArtifactType.CITATION); + } + if (user.isPresent() && !StringUtils.isBlank(user.get().getReference())) { + content.setAuthorExtension(user.get()); + } + if (derivedFromUri.isPresent() + && !StringUtils.isBlank(derivedFromUri.get().getValue())) { + content.addRelatedArtifact(derivedFromUri.get(), RelatedArtifactType.DERIVEDFROM); + } + this.addExtension(content); + setDateExtension(new DateTimeType(new Date())); + if (targetReference != null && !StringUtils.isBlank(targetReference.getValue())) { + this.setArtifactExtension(targetReference); + } + return this; + } + + public Optional getDerivedFromContentRelatedArtifact() { + Optional returnedRelatedArtifact = Optional.empty(); + Optional content = Optional.ofNullable(this.getExtensionByUrl(CONTENT)); + if (content.isPresent()) { + Optional maybeRelatedArtifact = content.get().getExtension().stream() + .filter(extension -> extension + .getUrl() + .equals(ArtifactAssessment.ArtifactAssessmentContentExtension.RELATEDARTIFACT) + && ((RelatedArtifact) extension.getValue()) + .getType() + .equals(RelatedArtifactType.DERIVEDFROM)) + .findFirst(); + if (maybeRelatedArtifact.isPresent()) { + RelatedArtifact derivedFromArtifact = + (RelatedArtifact) maybeRelatedArtifact.get().getValue(); + returnedRelatedArtifact = Optional.of(derivedFromArtifact); + } + } + return returnedRelatedArtifact; + } + + public ArtifactAssessment setDerivedFromContentRelatedArtifact(CanonicalType targetUri) { + Optional existingRelatedArtifact = this.getDerivedFromContentRelatedArtifact(); + if (existingRelatedArtifact.isPresent()) { + RelatedArtifact derivedFromArtifact = existingRelatedArtifact.get(); + derivedFromArtifact.setResourceElement(targetUri); + } else { + Extension content = this.getExtensionByUrl(CONTENT); + if (content == null) { + content = new Extension(CONTENT); + this.addExtension(content); + } + // this is duplicated from the addRelatedArtifact method + // since otherwise we get ClassCastExceptions when trying + // to Cast from Basic to ArtifactAssessment or its Extension subclasses + RelatedArtifact newRelatedArtifact = new RelatedArtifact(); + newRelatedArtifact.setType(RelatedArtifactType.DERIVEDFROM); + newRelatedArtifact.setResourceElement(targetUri); + content.addExtension( + ArtifactAssessment.ArtifactAssessmentContentExtension.RELATEDARTIFACT, newRelatedArtifact); + } + return this; + } + + public ArtifactAssessment setDerivedFromContentRelatedArtifact(String targetUri) { + return setDerivedFromContentRelatedArtifact(new CanonicalType(targetUri)); + } + + public boolean checkArtifactCommentParams( + String artifactAssessmentType, + String artifactAssessmentSummary, + String artifactAssessmentTargetReference, + String artifactAssessmentRelatedArtifact, + String derivedFromRelatedArtifactUrl, + String artifactAssessmentAuthor) { + var contentCorrect = false; + var artifactCorrect = false; + var contentIndex = findIndex(CONTENT, null, this.getExtension()); + if (contentIndex != -1) { + contentCorrect = checkContent( + contentIndex, + artifactAssessmentType, + artifactAssessmentSummary, + artifactAssessmentRelatedArtifact, + derivedFromRelatedArtifactUrl, + artifactAssessmentAuthor); + } + var artifactIndex = findIndex(ARTIFACT, null, this.getExtension()); + if (artifactIndex != -1) { + var artifactExt = this.getExtension().get(artifactIndex); + artifactCorrect = + ((Reference) artifactExt.getValue()).getReference().equals(artifactAssessmentTargetReference); + } + return contentCorrect && artifactCorrect; + } + + private boolean checkContent( + int contentIndex, + String artifactAssessmentType, + String artifactAssessmentSummary, + String artifactAssessmentRelatedArtifact, + String derivedFromRelatedArtifactUrl, + String artifactAssessmentAuthor) { + var infoTypeCorrect = false; + var summaryCorrect = false; + var citationRelatedArtifactCorrect = false; + var derivedFromRelatedArtifactCorrect = false; + var authorCorrect = false; + var contentExt = this.getExtension().get(contentIndex); + int infoTypeIndex = findIndex( + ArtifactAssessment.ArtifactAssessmentContentExtension.INFOTYPE, null, contentExt.getExtension()); + if (infoTypeIndex != -1) { + var infoTypeExt = contentExt.getExtension().get(infoTypeIndex); + infoTypeCorrect = ((CodeType) infoTypeExt.getValue()).getCode().equals(artifactAssessmentType); + } + var summaryIndex = findIndex( + ArtifactAssessment.ArtifactAssessmentContentExtension.SUMMARY, null, contentExt.getExtension()); + if (summaryIndex != -1) { + var summaryExt = contentExt.getExtension().get(summaryIndex); + summaryCorrect = ((StringType) summaryExt.getValue()).getValue().equals(artifactAssessmentSummary); + } + var relatedArtifactList = contentExt.getExtension().stream() + .filter(e -> e.getUrl().equals(ArtifactAssessment.ArtifactAssessmentContentExtension.RELATEDARTIFACT)) + .collect(Collectors.toList()); + if (!relatedArtifactList.isEmpty()) { + var maybeCitation = relatedArtifactList.stream() + .filter(ext -> ((RelatedArtifact) ext.getValue()).getType().equals(RelatedArtifactType.CITATION)) + .findAny(); + var maybeDerivedFrom = relatedArtifactList.stream() + .filter(ext -> ((RelatedArtifact) ext.getValue()).getType().equals(RelatedArtifactType.DERIVEDFROM)) + .findAny(); + if (maybeCitation.isPresent()) { + var citation = maybeCitation.get(); + citationRelatedArtifactCorrect = + ((RelatedArtifact) citation.getValue()).getResource().equals(artifactAssessmentRelatedArtifact); + } + if (maybeDerivedFrom.isPresent()) { + var derivedFrom = maybeDerivedFrom.get(); + derivedFromRelatedArtifactCorrect = + ((RelatedArtifact) derivedFrom.getValue()).getResource().equals(derivedFromRelatedArtifactUrl); + } + } + var authorIndex = findIndex( + ArtifactAssessment.ArtifactAssessmentContentExtension.AUTHOR, null, contentExt.getExtension()); + if (authorIndex != -1) { + var authorExt = contentExt.getExtension().get(authorIndex); + authorCorrect = ((Reference) authorExt.getValue()).getReference().equals(artifactAssessmentAuthor); + } + + return infoTypeCorrect + && summaryCorrect + && citationRelatedArtifactCorrect + && derivedFromRelatedArtifactCorrect + && authorCorrect; + } + + public boolean isValidArtifactComment() { + var infoTypeExists = false; + var summaryExists = false; + var relatedArtifactExists = false; + var authorExists = false; + var dateExists = findIndex(DATE, null, this.getExtension()) != -1; + var artifactExists = findIndex(ARTIFACT, null, this.getExtension()) != -1; + var contentIndex = findIndex(CONTENT, null, this.getExtension()); + if (contentIndex != -1) { + var content = this.getExtension().get(contentIndex); + infoTypeExists = findIndex( + ArtifactAssessment.ArtifactAssessmentContentExtension.INFOTYPE, + null, + content.getExtension()) + != -1; + summaryExists = findIndex( + ArtifactAssessment.ArtifactAssessmentContentExtension.SUMMARY, null, content.getExtension()) + != -1; + relatedArtifactExists = findIndex( + ArtifactAssessment.ArtifactAssessmentContentExtension.RELATEDARTIFACT, + null, + content.getExtension()) + != -1; + authorExists = findIndex( + ArtifactAssessment.ArtifactAssessmentContentExtension.AUTHOR, null, content.getExtension()) + != -1; + } + return (infoTypeExists || summaryExists || relatedArtifactExists || authorExists) + && dateExists + && artifactExists; + } + + List getContent() { + return this.getExtension().stream() + .filter(ext -> ext.getUrl().equals(CONTENT)) + .map(ArtifactAssessment.ArtifactAssessmentContentExtension.class::cast) + .collect(Collectors.toList()); + } + + public ArtifactAssessment setArtifactExtension(CanonicalType target) { + if (target != null && target.getValue() != null) { + int index = findIndex(ARTIFACT, null, this.getExtension()); + if (index != -1) { + this.extension.set(index, new ArtifactAssessment.ArtifactAssessmentArtifactExtension(target)); + } else { + this.addExtension(new ArtifactAssessment.ArtifactAssessmentArtifactExtension(target)); + } + } + return this; + } + + public ArtifactAssessment setArtifactExtension(Reference target) { + if (target != null && target.getReference() != null) { + int index = findIndex(ARTIFACT, null, this.getExtension()); + if (index != -1) { + this.extension.set(index, new ArtifactAssessment.ArtifactAssessmentArtifactExtension(target)); + } else { + this.addExtension(new ArtifactAssessment.ArtifactAssessmentArtifactExtension(target)); + } + } + return this; + } + + public ArtifactAssessment setArtifactExtension(UriType target) { + if (target != null && target.getValue() != null) { + int index = findIndex(ARTIFACT, null, this.getExtension()); + if (index != -1) { + this.extension.set(index, new ArtifactAssessment.ArtifactAssessmentArtifactExtension(target)); + } else { + this.addExtension(new ArtifactAssessment.ArtifactAssessmentArtifactExtension(target)); + } + } + return this; + } + + public ArtifactAssessment setDateExtension(DateTimeType date) { + if (date != null) { + int index = findIndex(DATE, null, this.getExtension()); + if (index != -1) { + this.extension.set(index, new ArtifactAssessment.ArtifactAssessmentDateExtension(date)); + } else { + this.addExtension(new ArtifactAssessment.ArtifactAssessmentDateExtension(date)); + } + } + return this; + } + + public ArtifactAssessment setLastReviewDateExtension(DateType reviewDate) { + if (reviewDate != null) { + int index = findIndex(LAST_REVIEW_DATE, null, this.getExtension()); + if (index != -1) { + this.extension.set(index, new ArtifactAssessment.ArtifactAssessmentLastReviewDateExtension(reviewDate)); + } else { + this.addExtension(new ArtifactAssessment.ArtifactAssessmentLastReviewDateExtension(reviewDate)); + } + } + return this; + } + + public ArtifactAssessment setApprovalDateExtension(DateType approvalDate) { + if (approvalDate != null) { + int index = findIndex(APPROVAL_DATE, null, this.getExtension()); + if (index != -1) { + this.extension.set(index, new ArtifactAssessment.ArtifactAssessmentApprovalDateExtension(approvalDate)); + } else { + this.addExtension(new ArtifactAssessment.ArtifactAssessmentApprovalDateExtension(approvalDate)); + } + } + return this; + } + + public ArtifactAssessment setTitleExtension(MarkdownType title) { + if (title != null) { + int index = findIndex(TITLE, null, this.getExtension()); + if (index != -1) { + this.extension.set(index, new ArtifactAssessment.ArtifactAssessmentTitleExtension(title)); + } else { + this.addExtension(new ArtifactAssessment.ArtifactAssessmentTitleExtension(title)); + } + } + return this; + } + + public ArtifactAssessment setCopyrightExtension(MarkdownType copyright) { + if (copyright != null) { + int index = findIndex(COPYRIGHT, null, this.getExtension()); + if (index != -1) { + this.extension.set(index, new ArtifactAssessment.ArtifactAssessmentCopyrightExtension(copyright)); + } else { + this.addExtension(new ArtifactAssessment.ArtifactAssessmentCopyrightExtension(copyright)); + } + } + return this; + } + + public ArtifactAssessment setCiteAsExtension(MarkdownType citeAs) { + if (citeAs != null) { + int index = findIndex(CITEAS, null, this.getExtension()); + if (index != -1) { + this.extension.set(index, new ArtifactAssessment.ArtifactAssessmentCiteAsExtension(citeAs)); + } else { + this.addExtension(new ArtifactAssessment.ArtifactAssessmentCiteAsExtension(citeAs)); + } + } + return this; + } + + public ArtifactAssessment setCiteAsExtension(Reference citeAs) { + if (citeAs != null) { + int index = findIndex(CITEAS, null, this.getExtension()); + if (index != -1) { + this.extension.set(index, new ArtifactAssessment.ArtifactAssessmentCiteAsExtension(citeAs)); + } else { + this.addExtension(new ArtifactAssessment.ArtifactAssessmentCiteAsExtension(citeAs)); + } + } + return this; + } + + public ArtifactAssessment setArtifactAssessmentWorkflowStatusExtension( + Enumeration status) { + if (status != null) { + int index = findIndex(WORKFLOW_STATUS, null, this.getExtension()); + if (index != -1) { + this.extension.set(index, new ArtifactAssessment.ArtifactAssessmentWorkflowStatusExtension(status)); + } else { + this.addExtension(new ArtifactAssessment.ArtifactAssessmentWorkflowStatusExtension(status)); + } + } + return this; + } + + public ArtifactAssessment setArtifactAssessmentDispositionExtension( + Enumeration status) { + if (status != null) { + int index = findIndex(DISPOSITION, null, this.getExtension()); + if (index != -1) { + this.extension.set(index, new ArtifactAssessment.ArtifactAssessmentDispositionExtension(status)); + } else { + this.addExtension(new ArtifactAssessment.ArtifactAssessmentDispositionExtension(status)); + } + } + return this; + } + + private int findIndex(String url, DataType value, List extensions) { + Optional existingExtension; + if (value != null) { + existingExtension = extensions.stream() + .filter(e -> e.getUrl().equals(url) && e.getValue().equals(value)) + .findAny(); + } else { + existingExtension = + extensions.stream().filter(e -> e.getUrl().equals(url)).findAny(); + } + if (existingExtension.isPresent()) { + return extensions.indexOf(existingExtension.get()); + } else { + return -1; + } + } + + @DatatypeDef(name = "ArtifactAssessmentContentExtension", isSpecialization = true, profileOf = Extension.class) + public class ArtifactAssessmentContentExtension extends Extension { + public static final String INFOTYPE = "informationType"; + public static final String SUMMARY = "summary"; + public static final String TYPE = "type"; + public static final String CLASSIFIER = "classifier"; + public static final String QUANTITY = "quantity"; + public static final String AUTHOR = "author"; + public static final String PATH = "path"; + public static final String RELATEDARTIFACT = "relatedArtifact"; + public static final String FREETOSHARE = "freeToShare"; + public static final String COMPONENT = "component"; + + public ArtifactAssessmentContentExtension() throws FHIRException { + super(CONTENT); + } + + ArtifactAssessment.ArtifactAssessmentContentExtension setInfoType(CodeType infoType) throws FHIRException { + if (infoType != null) { + int index = findIndex(INFOTYPE, null, this.getExtension()); + if (index != -1) { + this.extension.set( + index, + new ArtifactAssessment.ArtifactAssessmentContentExtension + .ArtifactAssessmentContentInformationTypeExtension(infoType)); + } else { + this.addExtension( + new ArtifactAssessment.ArtifactAssessmentContentExtension + .ArtifactAssessmentContentInformationTypeExtension(infoType)); + } + } + return this; + } + + ArtifactAssessment.ArtifactAssessmentContentExtension setSummary(MarkdownType summary) { + if (summary != null) { + int index = findIndex(SUMMARY, null, this.getExtension()); + if (index != -1) { + this.extension.set( + index, + new ArtifactAssessment.ArtifactAssessmentContentExtension + .ArtifactAssessmentContentSummaryExtension(summary)); + } else { + this.addExtension( + new ArtifactAssessment.ArtifactAssessmentContentExtension + .ArtifactAssessmentContentSummaryExtension(summary)); + } + } + return this; + } + + ArtifactAssessment.ArtifactAssessmentContentExtension addRelatedArtifact( + CanonicalType reference, RelatedArtifactType type) { + if (reference != null) { + RelatedArtifact newRelatedArtifact = new RelatedArtifact(); + newRelatedArtifact.setType(type); + newRelatedArtifact.setResourceElement(reference); + int index = findIndex(RELATEDARTIFACT, newRelatedArtifact, this.getExtension()); + if (index == -1) { + this.addExtension( + new ArtifactAssessment.ArtifactAssessmentContentExtension + .ArtifactAssessmentContentRelatedArtifactExtension(newRelatedArtifact)); + } + } + return this; + } + + ArtifactAssessment.ArtifactAssessmentContentExtension addComponent( + ArtifactAssessment.ArtifactAssessmentContentExtension component) { + if (component != null) { + this.addExtension( + new ArtifactAssessment.ArtifactAssessmentContentExtension + .ArtifactAssessmentContentComponentExtension(component)); + } + return this; + } + + ArtifactAssessment.ArtifactAssessmentContentExtension setAuthorExtension(Reference author) { + if (author != null) { + int index = findIndex(AUTHOR, null, this.getExtension()); + if (index != -1) { + this.extension.set( + index, + new ArtifactAssessment.ArtifactAssessmentContentExtension + .ArtifactAssessmentContentAuthorExtension(author)); + } else { + this.addExtension( + new ArtifactAssessment.ArtifactAssessmentContentExtension + .ArtifactAssessmentContentAuthorExtension(author)); + } + } + return this; + } + + ArtifactAssessment.ArtifactAssessmentContentExtension setQuantityExtension(Quantity quantity) { + if (quantity != null) { + int index = findIndex(QUANTITY, null, this.getExtension()); + if (index != -1) { + this.extension.set( + index, + new ArtifactAssessment.ArtifactAssessmentContentExtension + .ArtifactAssessmentContentQuantityExtension(quantity)); + } else { + this.addExtension( + new ArtifactAssessment.ArtifactAssessmentContentExtension + .ArtifactAssessmentContentQuantityExtension(quantity)); + } + } + return this; + } + + ArtifactAssessment.ArtifactAssessmentContentExtension setTypeExtension(CodeableConcept type) { + if (type != null) { + int index = findIndex(TYPE, null, this.getExtension()); + if (index != -1) { + this.extension.set( + index, + new ArtifactAssessment.ArtifactAssessmentContentExtension + .ArtifactAssessmentContentTypeExtension(type)); + } else { + this.addExtension( + new ArtifactAssessment.ArtifactAssessmentContentExtension + .ArtifactAssessmentContentTypeExtension(type)); + } + } + return this; + } + + ArtifactAssessment.ArtifactAssessmentContentExtension setFreeToShareExtension(BooleanType freeToShare) { + if (freeToShare != null) { + int index = findIndex(FREETOSHARE, null, this.getExtension()); + if (index != -1) { + this.extension.set( + index, + new ArtifactAssessment.ArtifactAssessmentContentExtension + .ArtifactAssessmentContentFreeToShareExtension(freeToShare)); + } else { + this.addExtension( + new ArtifactAssessment.ArtifactAssessmentContentExtension + .ArtifactAssessmentContentFreeToShareExtension(freeToShare)); + } + } + return this; + } + + ArtifactAssessment.ArtifactAssessmentContentExtension addClassifierExtension(CodeableConcept classifier) { + if (classifier != null) { + int index = findIndex(CLASSIFIER, classifier, this.getExtension()); + if (index == -1) { + this.addExtension( + new ArtifactAssessment.ArtifactAssessmentContentExtension + .ArtifactAssessmentContentClassifierExtension(classifier)); + } + } + return this; + } + + ArtifactAssessment.ArtifactAssessmentContentExtension addPathExtension(UriType path) { + if (path != null) { + int index = findIndex(PATH, path, this.getExtension()); + if (index == -1) { + this.addExtension( + new ArtifactAssessment.ArtifactAssessmentContentExtension + .ArtifactAssessmentContentPathExtension(path)); + } + } + return this; + } + + @DatatypeDef( + name = "ArtifactAssessmentContentInformationTypeExtension", + isSpecialization = true, + profileOf = Extension.class) + private class ArtifactAssessmentContentInformationTypeExtension extends Extension { + public ArtifactAssessmentContentInformationTypeExtension(CodeType informationTypeCode) { + super(INFOTYPE); + // validate code + ArtifactAssessment.ArtifactAssessmentContentInformationType.fromCode(informationTypeCode.getValue()); + this.setValue(informationTypeCode); + } + } + + @DatatypeDef( + name = "ArtifactAssessmentContentSummaryExtension", + isSpecialization = true, + profileOf = Extension.class) + private class ArtifactAssessmentContentSummaryExtension extends Extension { + public ArtifactAssessmentContentSummaryExtension(MarkdownType summary) { + super(SUMMARY, summary); + } + } + + @SuppressWarnings("squid:S2387") + @DatatypeDef( + name = "ArtifactAssessmentContentTypeExtension", + isSpecialization = true, + profileOf = Extension.class) + private class ArtifactAssessmentContentTypeExtension extends Extension { + @ca.uhn.fhir.model.api.annotation.Binding(valueSet = "http://hl7.org/fhir/ValueSet/certainty-type") + protected CodeableConcept value; + + public ArtifactAssessmentContentTypeExtension(CodeableConcept typeConcept) { + super(TYPE, typeConcept); + } + } + + @SuppressWarnings("squid:S2387") + @DatatypeDef( + name = "ArtifactAssessmentContentClassifierExtension", + isSpecialization = true, + profileOf = Extension.class) + private class ArtifactAssessmentContentClassifierExtension extends Extension { + @ca.uhn.fhir.model.api.annotation.Binding(valueSet = "http://hl7.org/fhir/ValueSet/certainty-rating") + protected CodeableConcept value; + + public ArtifactAssessmentContentClassifierExtension(CodeableConcept classifierConcept) { + super(CLASSIFIER, classifierConcept); + } + } + + @DatatypeDef( + name = "ArtifactAssessmentContentQuantityExtension", + isSpecialization = true, + profileOf = Extension.class) + private class ArtifactAssessmentContentQuantityExtension extends Extension { + public ArtifactAssessmentContentQuantityExtension(Quantity quantity) { + super(QUANTITY, quantity); + } + } + + @DatatypeDef( + name = "ArtifactAssessmentContentAuthorExtension", + isSpecialization = true, + profileOf = Extension.class) + private class ArtifactAssessmentContentAuthorExtension extends Extension { + public ArtifactAssessmentContentAuthorExtension(Reference author) { + super(AUTHOR, author); + } + } + + @DatatypeDef( + name = "ArtifactAssessmentContentPathExtension", + isSpecialization = true, + profileOf = Extension.class) + private class ArtifactAssessmentContentPathExtension extends Extension { + public ArtifactAssessmentContentPathExtension(UriType path) { + super(PATH, path); + } + } + + @DatatypeDef( + name = "ArtifactAssessmentContentRelatedArtifactExtension", + isSpecialization = true, + profileOf = Extension.class) + private class ArtifactAssessmentContentRelatedArtifactExtension extends Extension { + public ArtifactAssessmentContentRelatedArtifactExtension(RelatedArtifact relatedArtifact) { + super(RELATEDARTIFACT, relatedArtifact); + } + } + + @DatatypeDef( + name = "ArtifactAssessmentContentFreeToShareExtension", + isSpecialization = true, + profileOf = Extension.class) + private class ArtifactAssessmentContentFreeToShareExtension extends Extension { + public ArtifactAssessmentContentFreeToShareExtension(BooleanType freeToShare) { + super(FREETOSHARE, freeToShare); + } + } + + @DatatypeDef( + name = "ArtifactAssessmentContentComponentExtension", + isSpecialization = true, + profileOf = Extension.class) + private class ArtifactAssessmentContentComponentExtension extends Extension { + public ArtifactAssessmentContentComponentExtension( + ArtifactAssessment.ArtifactAssessmentContentExtension contentExtension) { + super(COMPONENT, contentExtension); + } + } + } + + @DatatypeDef(name = "ArtifactAssessmentArtifactExtension", isSpecialization = true, profileOf = Extension.class) + private class ArtifactAssessmentArtifactExtension extends Extension { + public ArtifactAssessmentArtifactExtension(CanonicalType target) { + super(ARTIFACT, target); + } + + public ArtifactAssessmentArtifactExtension(Reference target) { + super(ARTIFACT, target); + } + + public ArtifactAssessmentArtifactExtension(UriType target) { + super(ARTIFACT, target); + } + } + + @DatatypeDef( + name = "ArtifactAssessmentWorkflowStatusExtension", + isSpecialization = true, + profileOf = Extension.class) + private class ArtifactAssessmentWorkflowStatusExtension extends Extension { + public ArtifactAssessmentWorkflowStatusExtension( + Enumeration status) { + super(WORKFLOW_STATUS, status); + } + } + + @DatatypeDef(name = "ArtifactAssessmentDispositionExtension", isSpecialization = true, profileOf = Extension.class) + private class ArtifactAssessmentDispositionExtension extends Extension { + public ArtifactAssessmentDispositionExtension( + Enumeration disposition) { + super(DISPOSITION, disposition); + } + } + + @DatatypeDef( + name = "ArtifactAssessmentLastReviewDateExtension", + isSpecialization = true, + profileOf = Extension.class) + private class ArtifactAssessmentLastReviewDateExtension extends Extension { + public ArtifactAssessmentLastReviewDateExtension(DateType lastReviewDate) { + super(LAST_REVIEW_DATE, lastReviewDate); + } + } + + @DatatypeDef(name = "ArtifactAssessmentApprovalDateExtension", isSpecialization = true, profileOf = Extension.class) + private class ArtifactAssessmentApprovalDateExtension extends Extension { + public ArtifactAssessmentApprovalDateExtension(DateType approvalDate) { + super(APPROVAL_DATE, approvalDate); + } + } + + @DatatypeDef(name = "ArtifactAssessmentCopyrightExtension", isSpecialization = true, profileOf = Extension.class) + private class ArtifactAssessmentCopyrightExtension extends Extension { + public ArtifactAssessmentCopyrightExtension(MarkdownType copyright) { + super(COPYRIGHT, copyright); + } + } + + @DatatypeDef(name = "ArtifactAssessmentDateExtension", isSpecialization = true, profileOf = Extension.class) + private class ArtifactAssessmentDateExtension extends Extension { + public ArtifactAssessmentDateExtension(DateTimeType date) { + super(DATE, date); + } + } + + @DatatypeDef(name = "ArtifactAssessmentTitleExtension", isSpecialization = true, profileOf = Extension.class) + private class ArtifactAssessmentTitleExtension extends Extension { + public ArtifactAssessmentTitleExtension(StringType title) { + super(TITLE, title); + } + } + + @DatatypeDef(name = "ArtifactAssessmentCiteAsExtension", isSpecialization = true, profileOf = Extension.class) + private class ArtifactAssessmentCiteAsExtension extends Extension { + public ArtifactAssessmentCiteAsExtension(Reference citation) { + super(CITEAS, citation); + } + + public ArtifactAssessmentCiteAsExtension(MarkdownType citation) { + super(CITEAS, citation); + } + } +}