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