Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updated the Cql FhirDal to implement Translator FhirDal and introduce… #683

Merged
merged 2 commits into from
Dec 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 41 additions & 14 deletions plugin/cql/src/main/java/org/opencds/cqf/ruler/cql/JpaFhirDal.java
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
package org.opencds.cqf.ruler.cql;

import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.opencds.cqf.cql.evaluator.fhir.dal.FhirDal;

import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.model.api.IQueryParameterType;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.param.UriParam;
import org.cqframework.fhir.api.FhirDal;
import org.hl7.fhir.instance.model.api.IBase;
import org.hl7.fhir.instance.model.api.IBaseBundle;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.UUID;

@SuppressWarnings("unchecked")
public class JpaFhirDal implements FhirDal {
Expand Down Expand Up @@ -45,16 +51,37 @@ public void delete(IIdType theId) {

}

// TODO: the search interfaces need some work
@Override
public Iterable<IBaseResource> search(String theResourceType) {
return this.daoRegistry.getResourceDao(theResourceType).search(SearchParameterMap.newSynchronous())
.getAllResources();
}
public IBaseBundle search(String theResourceType, Map<String, List<List<IQueryParameterType>>> theSearchParameters) {
SearchParameterMap searchParameterMap = new SearchParameterMap();
for(Map.Entry<String, List<List<IQueryParameterType>>> entry : theSearchParameters.entrySet()) {
String keyValue = entry.getKey();

@Override
public Iterable<IBaseResource> searchByUrl(String theResourceType, String theUrl) {
return this.daoRegistry.getResourceDao(theResourceType)
.search(SearchParameterMap.newSynchronous().add("url", new UriParam(theUrl))).getAllResources();
for(List<IQueryParameterType> value : entry.getValue()) {
for (IQueryParameterType query : value) {
searchParameterMap.add(keyValue, query);
}
}
}

List<IBaseResource> searchResults = this.daoRegistry.getResourceDao(theResourceType).search(searchParameterMap).getAllResources();

ca.uhn.fhir.util.BundleBuilder builder = new ca.uhn.fhir.util.BundleBuilder(daoRegistry.getSystemDao().getContext());
builder
.setBundleField("type", "searchset")
.setBundleField("id", UUID.randomUUID().toString())
.setMetaField("lastUpdated", builder.newPrimitive("instant", new java.util.Date()));

for (var resource : searchResults) {
IBase entry = builder.addEntry();
builder.addToEntry(entry, "resource", resource);

// Add search results
IBase search = builder.addSearch(entry);
builder.setSearchField(search, "mode", "match");
builder.setSearchField(search, "score", builder.newPrimitive("decimal", BigDecimal.ONE));
}

return builder.getBundle();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package org.opencds.cqf.ruler.cql;

import ca.uhn.fhir.model.api.IQueryParameterType;
import ca.uhn.fhir.rest.param.UriParam;
import org.hl7.fhir.instance.model.api.IBaseBundle;
import org.hl7.fhir.r4.model.Bundle;
import org.hl7.fhir.r4.model.Library;
import org.junit.jupiter.api.Test;
import org.opencds.cqf.cql.evaluator.fhir.util.Canonicals;
import org.opencds.cqf.ruler.test.DaoIntegrationTest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
classes = { JpaFhirDalIT.class, CqlConfig.class }, properties = { "hapi.fhir.fhir_version=r4" })
public class JpaFhirDalIT extends DaoIntegrationTest {

@Autowired
private JpaFhirDalFactory fhirDalFactory;

@Test
void testFhirDalSearch() throws Exception {
JpaFhirDal fhirDal = new JpaFhirDal(this.getDaoRegistry());

String url = "http://somewhere.org/fhir/Library/SpecificationLibrary";
this.update(newResource(Library.class, "A123").setUrl(url));
this.update(newResource(Library.class, "A234").setUrl(url));

Map<String, List<List<IQueryParameterType>>> searchParams = new HashMap<>();

List<IQueryParameterType> urlList = new ArrayList<>();
urlList.add(new UriParam(Canonicals.getUrl(url)));
searchParams.put("url", List.of(urlList));

IBaseBundle searchResultsBundle = (IBaseBundle)fhirDal.search(Canonicals.getResourceType(url), searchParams);

assertNotNull(searchResultsBundle);
assertTrue(((Bundle)searchResultsBundle).getEntry().size() == 2);
assertTrue(((Bundle)searchResultsBundle).getType() == Bundle.BundleType.SEARCHSET);
assertTrue(((Library)((Bundle)searchResultsBundle).getEntryFirstRep().getResource()).getUrl().equals(url));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import java.util.function.Function;

import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
import org.opencds.cqf.cql.engine.fhir.searchparam.SearchParameterResolver;
import org.opencds.cqf.cql.evaluator.measure.MeasureEvaluationOptions;
import org.opencds.cqf.external.annotations.OnDSTU3Condition;
Expand Down Expand Up @@ -36,6 +37,11 @@ SearchParameterResolver searchParameterResolver(FhirContext fhirContext) {
return new SearchParameterResolver(fhirContext);
}

@Bean
JpaCRFhirDalFactory jpaCRFhirDalFactory(DaoRegistry daoRegistry) {
return rd -> new JpaCRFhirDal(daoRegistry, rd);
}

@Bean
@Conditional(OnDSTU3Condition.class)
public org.opencds.cqf.ruler.cr.dstu3.provider.ActivityDefinitionApplyProvider dstu3ActivityDefinitionApplyProvider() {
Expand Down
60 changes: 60 additions & 0 deletions plugin/cr/src/main/java/org/opencds/cqf/ruler/cr/JpaCRFhirDal.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package org.opencds.cqf.ruler.cr;

import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.opencds.cqf.cql.evaluator.fhir.dal.FhirDal;

import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.param.UriParam;

@SuppressWarnings("unchecked")
public class JpaCRFhirDal implements FhirDal {

protected final DaoRegistry daoRegistry;
protected final RequestDetails requestDetails;

public JpaCRFhirDal(DaoRegistry daoRegistry) {
this(daoRegistry, null);
}

public JpaCRFhirDal(DaoRegistry daoRegistry, RequestDetails requestDetails) {
this.daoRegistry = daoRegistry;
this.requestDetails = requestDetails;
}

@Override
public void create(IBaseResource theResource) {
this.daoRegistry.getResourceDao(theResource.fhirType()).create(theResource, requestDetails);
}

@Override
public IBaseResource read(IIdType theId) {
return this.daoRegistry.getResourceDao(theId.getResourceType()).read(theId, requestDetails);
}

@Override
public void update(IBaseResource theResource) {
this.daoRegistry.getResourceDao(theResource.fhirType()).update(theResource, requestDetails);
}

@Override
public void delete(IIdType theId) {
this.daoRegistry.getResourceDao(theId.getResourceType()).delete(theId, requestDetails);

}

// TODO: the search interfaces need some work
@Override
public Iterable<IBaseResource> search(String theResourceType) {
return this.daoRegistry.getResourceDao(theResourceType).search(SearchParameterMap.newSynchronous())
.getAllResources();
}

@Override
public Iterable<IBaseResource> searchByUrl(String theResourceType, String theUrl) {
return this.daoRegistry.getResourceDao(theResourceType)
.search(SearchParameterMap.newSynchronous().add("url", new UriParam(theUrl))).getAllResources();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package org.opencds.cqf.ruler.cr;

import ca.uhn.fhir.rest.api.server.RequestDetails;

public interface JpaCRFhirDalFactory {
JpaCRFhirDal create(RequestDetails requestDetails);
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@
import org.opencds.cqf.cql.evaluator.cql2elm.content.InMemoryLibrarySourceProvider;
import org.opencds.cqf.ruler.cql.CqlProperties;
import org.opencds.cqf.ruler.cql.JpaDataProviderFactory;
import org.opencds.cqf.ruler.cql.JpaFhirDal;
import org.opencds.cqf.ruler.cql.JpaFhirDalFactory;
import org.opencds.cqf.ruler.cr.JpaCRFhirDal;
import org.opencds.cqf.ruler.cr.JpaCRFhirDalFactory;
import org.opencds.cqf.ruler.cql.JpaLibrarySourceProviderFactory;
import org.opencds.cqf.ruler.cql.JpaTerminologyProviderFactory;
import org.opencds.cqf.ruler.cql.LibraryLoaderFactory;
Expand All @@ -47,7 +47,7 @@ public class ExpressionEvaluation {
@Autowired
private JpaTerminologyProviderFactory jpaTerminologyProviderFactory;
@Autowired
private JpaFhirDalFactory jpaFhirDalFactory;
private JpaCRFhirDalFactory jpaCRFhirDalFactory;
@Autowired
private CqlProperties cqlProperties;
@Autowired
Expand All @@ -60,8 +60,8 @@ public class ExpressionEvaluation {
*/
public Object evaluateInContext(DomainResource instance, String cql, Boolean aliasedExpression, String patientId,
RequestDetails theRequest) {
JpaFhirDal jpaFhirDal = jpaFhirDalFactory.create(theRequest);
List<Reference> libraries = getLibraryReferences(instance, jpaFhirDal, theRequest);
JpaCRFhirDal jpaCRFhirDal = jpaCRFhirDalFactory.create(theRequest);
List<Reference> libraries = getLibraryReferences(instance, jpaCRFhirDal, theRequest);
// String fhirVersion =
// this.context.getVersion().getVersion().getFhirVersionString();
String fhirVersion = "3.0.0";
Expand Down Expand Up @@ -90,7 +90,7 @@ public Object evaluateInContext(DomainResource instance, String cql, Boolean ali
// log error
}
if (executionLibrary == null) {
Library library = (Library) jpaFhirDal.read(new IdType("Library", vi.getId()));
Library library = (Library) jpaCRFhirDal.read(new IdType("Library", vi.getId()));
vi.setId(library.getName());
if (library.getVersion() != null) {
vi.setVersion(library.getVersion());
Expand All @@ -104,7 +104,7 @@ public Object evaluateInContext(DomainResource instance, String cql, Boolean ali
"library LocalLibrary using FHIR version '" + fhirVersion + "' include FHIRHelpers version '"
+ fhirVersion
+ "' called FHIRHelpers %s parameter %s %s parameter \"%%context\" %s define Expression: %s",
buildIncludes(tempLibraryLoader, jpaFhirDal, libraries), instance.fhirType(), instance.fhirType(),
buildIncludes(tempLibraryLoader, jpaCRFhirDal, libraries), instance.fhirType(), instance.fhirType(),
instance.fhirType(), vi.getId() + ".\"" + cql + "\"");
// String source = String.format("library LocalLibrary using FHIR version '1.8'
// include FHIRHelpers version '1.8' called FHIRHelpers %s parameter %s %s
Expand All @@ -120,7 +120,7 @@ public Object evaluateInContext(DomainResource instance, String cql, Boolean ali
"library LocalLibrary using FHIR version '" + fhirVersion + "' include FHIRHelpers version '"
+ fhirVersion
+ "' called FHIRHelpers %s parameter %s %s parameter \"%%context\" %s define Expression: %s",
buildIncludes(tempLibraryLoader, jpaFhirDal, libraries), instance.fhirType(), instance.fhirType(),
buildIncludes(tempLibraryLoader, jpaCRFhirDal, libraries), instance.fhirType(), instance.fhirType(),
instance.fhirType(), cql);
}

Expand Down Expand Up @@ -149,15 +149,15 @@ public Object evaluateInContext(DomainResource instance, String cql, Boolean ali
return context.resolveExpressionRef("Expression").evaluate(context);
}

private List<Reference> getLibraryReferences(DomainResource instance, JpaFhirDal jpaFhirDal,
private List<Reference> getLibraryReferences(DomainResource instance, JpaCRFhirDal jpaCRFhirDal,
RequestDetails theRequest) {
List<Reference> references = new ArrayList<>();

if (instance.hasContained()) {
for (Resource resource : instance.getContained()) {
if (resource instanceof Library) {
resource.setId(resource.getIdElement().getIdPart().replace("#", ""));
jpaFhirDal.update((Library) resource);
jpaCRFhirDal.update((Library) resource);
// getLibraryLoader().putLibrary(resource.getIdElement().getIdPart(),
// getLibraryLoader().toElmLibrary((Library) resource));
}
Expand Down Expand Up @@ -192,7 +192,7 @@ else if (instance instanceof Measure) {
return cleanReferences(references);
}

private String buildIncludes(LibraryLoader libraryLoader, JpaFhirDal jpaFhirDal, Iterable<Reference> references) {
private String buildIncludes(LibraryLoader libraryLoader, JpaCRFhirDal jpaCRFhirDal, Iterable<Reference> references) {
StringBuilder builder = new StringBuilder();
for (Reference reference : references) {
VersionedIdentifier vi = getVersionedIdentifierFromReference(reference);
Expand All @@ -212,7 +212,7 @@ private String buildIncludes(LibraryLoader libraryLoader, JpaFhirDal jpaFhirDal,
}
// else check local data for Library to get name and version from
else {
Library library = (Library) jpaFhirDal.read(reference.getReferenceElement());
Library library = (Library) jpaCRFhirDal.read(reference.getReferenceElement());
builder.append(buildLibraryIncludeString(reference, library.getName(), library.getVersion()));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import org.opencds.cqf.cql.evaluator.measure.MeasureEvaluationOptions;
import org.opencds.cqf.ruler.behavior.DaoRegistryUser;
import org.opencds.cqf.ruler.cql.JpaDataProviderFactory;
import org.opencds.cqf.ruler.cql.JpaFhirDalFactory;
import org.opencds.cqf.ruler.cr.JpaCRFhirDalFactory;
import org.opencds.cqf.ruler.cql.JpaLibrarySourceProviderFactory;
import org.opencds.cqf.ruler.cql.JpaTerminologyProviderFactory;
import org.springframework.beans.factory.annotation.Autowired;
Expand All @@ -44,7 +44,7 @@ public class MeasureService implements DaoRegistryUser {
private JpaLibrarySourceProviderFactory libraryContentProviderFactory;

@Autowired
private JpaFhirDalFactory fhirDalFactory;
private JpaCRFhirDalFactory fhirDalFactory;

@Autowired
private Map<org.cqframework.cql.elm.execution.VersionedIdentifier, org.cqframework.cql.elm.execution.Library> globalLibraryCache;
Expand Down
Loading