001package ca.uhn.fhir.cql.common.retrieve; 002 003/*- 004 * #%L 005 * HAPI FHIR JPA Server - Clinical Quality Language 006 * %% 007 * Copyright (C) 2014 - 2022 Smile CDR, Inc. 008 * %% 009 * Licensed under the Apache License, Version 2.0 (the "License"); 010 * you may not use this file except in compliance with the License. 011 * You may obtain a copy of the License at 012 * 013 * http://www.apache.org/licenses/LICENSE-2.0 014 * 015 * Unless required by applicable law or agreed to in writing, software 016 * distributed under the License is distributed on an "AS IS" BASIS, 017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 018 * See the License for the specific language governing permissions and 019 * limitations under the License. 020 * #L% 021 */ 022 023import ca.uhn.fhir.jpa.api.dao.DaoRegistry; 024import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao; 025import ca.uhn.fhir.model.api.IQueryParameterType; 026import ca.uhn.fhir.rest.api.server.IBundleProvider; 027import ca.uhn.fhir.rest.api.server.RequestDetails; 028import org.hl7.fhir.instance.model.api.IBaseResource; 029import org.opencds.cqf.cql.engine.fhir.retrieve.SearchParamFhirRetrieveProvider; 030import org.opencds.cqf.cql.engine.fhir.searchparam.SearchParameterMap; 031import org.opencds.cqf.cql.engine.fhir.searchparam.SearchParameterResolver; 032import org.slf4j.Logger; 033import org.slf4j.LoggerFactory; 034import org.springframework.beans.factory.annotation.Autowired; 035import org.springframework.stereotype.Component; 036 037import java.lang.reflect.Method; 038import java.util.ArrayList; 039import java.util.Arrays; 040import java.util.Collection; 041import java.util.Collections; 042import java.util.List; 043import java.util.Map; 044import java.util.stream.Collectors; 045 046@Component 047public class JpaFhirRetrieveProvider extends SearchParamFhirRetrieveProvider { 048 049 private static final Logger logger = LoggerFactory.getLogger(JpaFhirRetrieveProvider.class); 050 051 private final DaoRegistry registry; 052 private final RequestDetails myRequestDetails; 053 054 @Autowired 055 public JpaFhirRetrieveProvider(DaoRegistry registry, SearchParameterResolver searchParameterResolver, RequestDetails theRequestDetails) { 056 super(searchParameterResolver); 057 this.registry = registry; 058 myRequestDetails = theRequestDetails; 059 } 060 061 @Override 062 protected Iterable<Object> executeQueries(String dataType, List<SearchParameterMap> queries) { 063 if (queries == null || queries.isEmpty()) { 064 return Collections.emptyList(); 065 } 066 067 List<Object> objects = new ArrayList<>(); 068 for (SearchParameterMap map : queries) { 069 objects.addAll(executeQuery(dataType, map)); 070 } 071 072 return objects; 073 } 074 075 protected Collection<Object> executeQuery(String dataType, SearchParameterMap map) { 076 // TODO: Once HAPI breaks this out from the server dependencies 077 // we can include it on its own. 078 ca.uhn.fhir.jpa.searchparam.SearchParameterMap hapiMap = ca.uhn.fhir.jpa.searchparam.SearchParameterMap.newSynchronous(); 079 try { 080 081 Method[] methods = hapiMap.getClass().getDeclaredMethods(); 082 List<Method> methodList = Arrays.asList(methods); 083 List<Method> puts = methodList.stream().filter(x -> x.getName().equals("put")).collect(Collectors.toList()); 084 Method method = puts.get(0); 085 method.setAccessible(true); 086 087 for (Map.Entry<String, List<List<IQueryParameterType>>> entry : map.entrySet()) { 088 method.invoke(hapiMap, entry.getKey(), entry.getValue()); 089 } 090 091 } catch (Exception e) { 092 logger.warn("Error converting search parameter map", e); 093 } 094 095 IFhirResourceDao<?> dao = this.registry.getResourceDao(dataType); 096 097 IBundleProvider bundleProvider = dao.search(hapiMap, myRequestDetails); 098 if (bundleProvider.size() == null) { 099 return resolveResourceList(bundleProvider.getResources(0, 10000)); 100 } 101 List<IBaseResource> resourceList = bundleProvider.getAllResources(); 102 return resolveResourceList(resourceList); 103 } 104 105 public synchronized Collection<Object> resolveResourceList(List<IBaseResource> resourceList) { 106 List<Object> ret = new ArrayList<>(); 107 for (IBaseResource res : resourceList) { 108 Class<?> clazz = res.getClass(); 109 ret.add(clazz.cast(res)); 110 } 111 // ret.addAll(resourceList); 112 return ret; 113 } 114}