
001/*- 002 * #%L 003 * HAPI FHIR - Core Library 004 * %% 005 * Copyright (C) 2014 - 2025 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.interceptor.api; 021 022import com.google.common.collect.ArrayListMultimap; 023import com.google.common.collect.ListMultimap; 024import com.google.common.collect.Multimaps; 025import jakarta.annotation.Nonnull; 026import org.apache.commons.lang3.Validate; 027import org.hl7.fhir.instance.model.api.IBaseResource; 028 029import java.util.Collection; 030import java.util.Collections; 031import java.util.List; 032import java.util.function.Supplier; 033import java.util.stream.Collectors; 034 035public class HookParams { 036 037 private ListMultimap<Class<?>, Object> myParams = ArrayListMultimap.create(); 038 039 /** 040 * Constructor 041 */ 042 public HookParams() {} 043 044 /** 045 * Constructor 046 */ 047 public HookParams(Object... theParams) { 048 for (Object next : theParams) { 049 add(next); 050 } 051 } 052 053 @SuppressWarnings("unchecked") 054 public <T> HookParams add(@Nonnull T theNext) { 055 Class<T> nextClass = (Class<T>) theNext.getClass(); 056 add(nextClass, theNext); 057 return this; 058 } 059 060 public <T> HookParams add(Class<T> theType, T theParam) { 061 return doAdd(theType, theParam); 062 } 063 064 // /** 065 // * This is useful for providing a lazy-loaded (generally expensive to create) 066 // * parameters 067 // */ 068 // public <T> HookParams addSupplier(Class<T> theType, Supplier<T> theParam) { 069 // return doAdd(theType, theParam); 070 // } 071 072 private <T> HookParams doAdd(Class<T> theType, Object theParam) { 073 Validate.isTrue(theType.equals(Supplier.class) == false, "Can not add parameters of type Supplier"); 074 myParams.put(theType, theParam); 075 return this; 076 } 077 078 public <T> T get(Class<T> theParamType) { 079 return get(theParamType, 0); 080 } 081 082 @SuppressWarnings("unchecked") 083 public <T> T get(Class<T> theParamType, int theIndex) { 084 List<Object> objects = myParams.get(theParamType); 085 Object retVal = null; 086 if (objects.size() > theIndex) { 087 retVal = objects.get(theIndex); 088 } 089 090 retVal = unwrapValue(retVal); 091 092 return (T) retVal; 093 } 094 095 private Object unwrapValue(Object theValue) { 096 if (theValue instanceof Supplier) { 097 theValue = ((Supplier) theValue).get(); 098 } 099 return theValue; 100 } 101 102 /** 103 * Returns an unmodifiable multimap of the params, where the 104 * key is the param type and the value is the actual instance 105 */ 106 public ListMultimap<Class<?>, Object> getParamsForType() { 107 ArrayListMultimap<Class<?>, Object> retVal = ArrayListMultimap.create(); 108 myParams.entries().forEach(entry -> retVal.put(entry.getKey(), unwrapValue(entry.getValue()))); 109 return Multimaps.unmodifiableListMultimap(retVal); 110 } 111 112 public Collection<Object> values() { 113 return Collections.unmodifiableCollection(myParams.values()).stream() 114 .map(t -> unwrapValue(t)) 115 .collect(Collectors.toList()); 116 } 117 118 @SuppressWarnings("unchecked") 119 public <T> HookParams addIfMatchesType(Class<T> theType, Object theParam) { 120 if (theParam == null) { 121 add(theType, null); 122 } else { 123 if (theType.isAssignableFrom(theParam.getClass())) { 124 T param = (T) theParam; 125 add(theType, param); 126 } else { 127 add(theType, null); 128 } 129 } 130 return this; 131 } 132 133 @Override 134 public String toString() { 135 StringBuilder b = new StringBuilder(); 136 myParams.forEach((key, value) -> { 137 b.append(" ") 138 .append(key.getSimpleName()) 139 .append(": ") 140 .append(valueAsStringForLog(value)) 141 .append("\n"); 142 }); 143 return b.toString(); 144 } 145 146 private static String valueAsStringForLog(Object theValue) { 147 if (theValue instanceof IBaseResource) { 148 return ((IBaseResource) theValue).getIdElement().toString(); 149 } 150 return theValue.toString(); 151 } 152}