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