001package ca.uhn.fhir.jpa.mdm.svc.candidate; 002 003/*- 004 * #%L 005 * HAPI FHIR JPA Server - Master Data Management 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.mdm.rules.json.MdmResourceSearchParamJson; 024import ca.uhn.fhir.mdm.svc.MdmSearchParamSvc; 025import ca.uhn.fhir.util.UrlUtil; 026import org.hl7.fhir.instance.model.api.IAnyResource; 027import org.springframework.beans.factory.annotation.Autowired; 028import org.springframework.stereotype.Service; 029 030import javax.annotation.Nonnull; 031import javax.annotation.Nullable; 032import java.util.ArrayList; 033import java.util.List; 034import java.util.Optional; 035import java.util.stream.Collectors; 036 037@Service 038public class MdmCandidateSearchCriteriaBuilderSvc { 039 040 @Autowired 041 private MdmSearchParamSvc myMdmSearchParamSvc; 042 043 /* 044 * Given a list of criteria upon which to block, a resource search parameter, and a list of values for that given search parameter, 045 * build a query url. e.g. 046 * 047 * Patient?active=true&name.given=Gary,Grant&name.family=Graham 048 */ 049 @Nonnull 050 public Optional<String> buildResourceQueryString(String theResourceType, IAnyResource theResource, List<String> theFilterCriteria, @Nullable MdmResourceSearchParamJson resourceSearchParam) { 051 List<String> criteria = new ArrayList<>(); 052 053 // If there are candidate search params, then make use of them, otherwise, search with only the filters. 054 if (resourceSearchParam != null) { 055 resourceSearchParam.iterator().forEachRemaining(searchParam -> { 056 //to compare it to all known GOLDEN_RESOURCE objects, using the overlapping search parameters that they have. 057 List<String> valuesFromResourceForSearchParam = myMdmSearchParamSvc.getValueFromResourceForSearchParam(theResource, searchParam); 058 if (!valuesFromResourceForSearchParam.isEmpty()) { 059 criteria.add(buildResourceMatchQuery(searchParam, valuesFromResourceForSearchParam)); 060 } 061 }); 062 if (criteria.isEmpty()) { 063 //TODO GGG/KHS, re-evaluate whether we should early drop here. 064 return Optional.empty(); 065 } 066 } 067 068 criteria.addAll(theFilterCriteria); 069 return Optional.of(theResourceType + "?" + String.join("&", criteria)); 070 } 071 072 private String buildResourceMatchQuery(String theSearchParamName, List<String> theResourceValues) { 073 String nameValueOrList = theResourceValues.stream() 074 .map(UrlUtil::escapeUrlParam) 075 .collect(Collectors.joining(",")); 076 return theSearchParamName + "=" + nameValueOrList; 077 } 078}