001/*- 002 * #%L 003 * HAPI FHIR - Server Framework 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.rest.server.util; 021 022import ca.uhn.fhir.context.RuntimeSearchParam; 023import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum; 024 025import java.util.Collection; 026import java.util.Collections; 027import java.util.HashMap; 028import java.util.LinkedHashMap; 029import java.util.Map; 030import java.util.Set; 031import java.util.stream.Stream; 032 033import static ca.uhn.fhir.rest.server.util.ISearchParamRegistry.isAllowedForContext; 034 035public class ResourceSearchParams { 036 private final String myResourceName; 037 private final Map<String, RuntimeSearchParam> myMap; 038 private final Map<ISearchParamRegistry.SearchParamLookupContextEnum, ResourceSearchParams> myContextToParams = 039 new HashMap<>(); 040 041 public ResourceSearchParams(String theResourceName) { 042 myResourceName = theResourceName; 043 myMap = new LinkedHashMap<>(); 044 } 045 046 private ResourceSearchParams(String theResourceName, Map<String, RuntimeSearchParam> theMap) { 047 myResourceName = theResourceName; 048 myMap = theMap; 049 } 050 051 public Collection<RuntimeSearchParam> values() { 052 return myMap.values(); 053 } 054 055 /** 056 * Returns a filtered view of this {@link ResourceSearchParams} instance if 057 * any parameters are not valid for the given {@literal theContext}. 058 */ 059 public ResourceSearchParams toFilteredForContext(ISearchParamRegistry.SearchParamLookupContextEnum theContext) { 060 if (theContext == null) { 061 return this; 062 } 063 synchronized (this) { 064 ResourceSearchParams retVal = myContextToParams.get(theContext); 065 if (retVal == null) { 066 Map<String, RuntimeSearchParam> filteredMap = new HashMap<>(myMap.size()); 067 for (var nextEntry : myMap.entrySet()) { 068 String key = nextEntry.getKey(); 069 RuntimeSearchParam nextParam = nextEntry.getValue(); 070 if (isAllowedForContext(nextParam, theContext)) { 071 filteredMap.put(key, nextParam); 072 } 073 } 074 retVal = new ResourceSearchParams(myResourceName, filteredMap); 075 myContextToParams.put(theContext, retVal); 076 } 077 return retVal; 078 } 079 } 080 081 public static ResourceSearchParams empty(String theResourceName) { 082 return new ResourceSearchParams(theResourceName, Collections.emptyMap()); 083 } 084 085 public ResourceSearchParams readOnly() { 086 return new ResourceSearchParams(myResourceName, Collections.unmodifiableMap(this.myMap)); 087 } 088 089 public void remove(String theName) { 090 myContextToParams.clear(); 091 myMap.remove(theName); 092 } 093 094 public int size() { 095 return myMap.size(); 096 } 097 098 public RuntimeSearchParam get(String theParamName) { 099 return myMap.get(theParamName); 100 } 101 102 public RuntimeSearchParam put(String theName, RuntimeSearchParam theSearchParam) { 103 myContextToParams.clear(); 104 return myMap.put(theName, theSearchParam); 105 } 106 107 public void addSearchParamIfAbsent(String theParamName, RuntimeSearchParam theRuntimeSearchParam) { 108 myContextToParams.clear(); 109 myMap.putIfAbsent(theParamName, theRuntimeSearchParam); 110 } 111 112 public Set<String> getSearchParamNames() { 113 return myMap.keySet(); 114 } 115 116 public boolean containsParamName(String theParamName) { 117 return myMap.containsKey(theParamName); 118 } 119 120 public void removeInactive() { 121 myMap.entrySet() 122 .removeIf(entry -> 123 entry.getValue().getStatus() != RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE); 124 } 125 126 public Stream<String> getReferenceSearchParamNames() { 127 return myMap.entrySet().stream() 128 .filter(entry -> entry.getValue().getParamType() == RestSearchParameterTypeEnum.REFERENCE) 129 .map(Map.Entry::getKey); 130 } 131 132 public ResourceSearchParams makeCopy() { 133 return new ResourceSearchParams(myResourceName, new HashMap<>(myMap)); 134 } 135}