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}