001/*- 002 * #%L 003 * HAPI FHIR JPA - Search Parameters 004 * %% 005 * Copyright (C) 2014 - 2024 Smile CDR, Inc. 006 * %% 007 * Licensed under the Apache License, Version 2.0 (the "License"); 008 * you may not use this file except in compliance with the License. 009 * You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, software 014 * distributed under the License is distributed on an "AS IS" BASIS, 015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 016 * See the License for the specific language governing permissions and 017 * limitations under the License. 018 * #L% 019 */ 020package ca.uhn.fhir.jpa.searchparam.nickname; 021 022import ca.uhn.fhir.interceptor.api.Hook; 023import ca.uhn.fhir.interceptor.api.Pointcut; 024import ca.uhn.fhir.jpa.nickname.INicknameSvc; 025import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; 026import ca.uhn.fhir.model.api.IQueryParameterType; 027import ca.uhn.fhir.rest.param.StringParam; 028import org.slf4j.Logger; 029import org.slf4j.LoggerFactory; 030 031import java.util.ArrayList; 032import java.util.Collection; 033import java.util.List; 034import java.util.Locale; 035import java.util.Map; 036 037public class NicknameInterceptor { 038 private static final Logger ourLog = LoggerFactory.getLogger(NicknameInterceptor.class); 039 040 private final INicknameSvc myNicknameSvc; 041 042 public NicknameInterceptor(INicknameSvc theNicknameSvc) { 043 myNicknameSvc = theNicknameSvc; 044 } 045 046 @Hook(Pointcut.STORAGE_PRESEARCH_REGISTERED) 047 public void expandNicknames(SearchParameterMap theSearchParameterMap) { 048 for (Map.Entry<String, List<List<IQueryParameterType>>> set : theSearchParameterMap.entrySet()) { 049 String paramName = set.getKey(); 050 List<List<IQueryParameterType>> andList = set.getValue(); 051 for (List<IQueryParameterType> orList : andList) { 052 // here we will know if it's an _id param or not 053 // from theSearchParameterMap.keySet() 054 expandAnyNicknameParameters(paramName, orList); 055 } 056 } 057 } 058 059 /** 060 * If a Parameter is a string parameter, and it has been set to expand Nicknames, perform the expansion. 061 */ 062 private void expandAnyNicknameParameters(String theParamName, List<IQueryParameterType> orList) { 063 List<IQueryParameterType> toAdd = new ArrayList<>(); 064 List<IQueryParameterType> toRemove = new ArrayList<>(); 065 for (IQueryParameterType iQueryParameterType : orList) { 066 if (iQueryParameterType instanceof StringParam) { 067 StringParam stringParam = (StringParam) iQueryParameterType; 068 if (stringParam.isNicknameExpand()) { 069 ourLog.debug("Found a nickname parameter to expand: {} {}", theParamName, stringParam); 070 toRemove.add(stringParam); 071 // First, attempt to expand as a formal name 072 String name = stringParam.getValue().toLowerCase(Locale.ROOT); 073 Collection<String> expansions = myNicknameSvc.getEquivalentNames(name); 074 if (expansions == null) { 075 continue; 076 } 077 ourLog.debug("Parameter has been expanded to: {} {}", theParamName, String.join(", ", expansions)); 078 expansions.stream().map(StringParam::new).forEach(toAdd::add); 079 } 080 } 081 } 082 orList.removeAll(toRemove); 083 orList.addAll(toAdd); 084 } 085}