001package ca.uhn.fhir.context;
002
003import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum;
004import org.apache.commons.lang3.builder.EqualsBuilder;
005import org.apache.commons.lang3.builder.HashCodeBuilder;
006import org.apache.commons.lang3.builder.ToStringBuilder;
007import org.apache.commons.lang3.builder.ToStringStyle;
008import org.hl7.fhir.instance.model.api.IBaseDatatype;
009import org.hl7.fhir.instance.model.api.IBaseExtension;
010import org.hl7.fhir.instance.model.api.IIdType;
011
012import javax.annotation.Nonnull;
013import java.util.ArrayList;
014import java.util.Collection;
015import java.util.Collections;
016import java.util.HashMap;
017import java.util.HashSet;
018import java.util.List;
019import java.util.Map;
020import java.util.Set;
021import java.util.StringTokenizer;
022
023import static org.apache.commons.lang3.StringUtils.isNotBlank;
024import static org.apache.commons.lang3.StringUtils.trim;
025
026/*
027 * #%L
028 * HAPI FHIR - Core Library
029 * %%
030 * Copyright (C) 2014 - 2020 University Health Network
031 * %%
032 * Licensed under the Apache License, Version 2.0 (the "License");
033 * you may not use this file except in compliance with the License.
034 * You may obtain a copy of the License at
035 *
036 *      http://www.apache.org/licenses/LICENSE-2.0
037 *
038 * Unless required by applicable law or agreed to in writing, software
039 * distributed under the License is distributed on an "AS IS" BASIS,
040 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
041 * See the License for the specific language governing permissions and
042 * limitations under the License.
043 * #L%
044 */
045
046public class RuntimeSearchParam {
047        private final IIdType myId;
048        private final Set<String> myBase;
049        private final List<RuntimeSearchParam> myCompositeOf;
050        private final String myDescription;
051        private final String myName;
052        private final RestSearchParameterTypeEnum myParamType;
053        private final String myPath;
054        private final Set<String> myTargets;
055        private final Set<String> myProvidesMembershipInCompartments;
056        private final RuntimeSearchParamStatusEnum myStatus;
057        private final String myUri;
058        private final Map<String, List<IBaseExtension<?, ?>>> myExtensions = new HashMap<>();
059
060        /**
061         * Constructor
062         */
063        public RuntimeSearchParam(IIdType theId, String theUri, String theName, String theDescription, String thePath, RestSearchParameterTypeEnum theParamType, List<RuntimeSearchParam> theCompositeOf,
064                                                                          Set<String> theProvidesMembershipInCompartments, Set<String> theTargets, RuntimeSearchParamStatusEnum theStatus) {
065                this(theId, theUri, theName, theDescription, thePath, theParamType, theCompositeOf, theProvidesMembershipInCompartments, theTargets, theStatus, null);
066        }
067
068        /**
069         * Constructor
070         */
071        public RuntimeSearchParam(IIdType theId, String theUri, String theName, String theDescription, String thePath, RestSearchParameterTypeEnum theParamType, List<RuntimeSearchParam> theCompositeOf,
072                                                                          Set<String> theProvidesMembershipInCompartments, Set<String> theTargets, RuntimeSearchParamStatusEnum theStatus, Collection<String> theBase) {
073                super();
074
075                myId = theId;
076                myUri = theUri;
077                myName = theName;
078                myDescription = theDescription;
079                myPath = thePath;
080                myParamType = theParamType;
081                myCompositeOf = theCompositeOf;
082                myStatus = theStatus;
083                if (theProvidesMembershipInCompartments != null && !theProvidesMembershipInCompartments.isEmpty()) {
084                        myProvidesMembershipInCompartments = Collections.unmodifiableSet(theProvidesMembershipInCompartments);
085                } else {
086                        myProvidesMembershipInCompartments = null;
087                }
088                if (theTargets != null && theTargets.isEmpty() == false) {
089                        myTargets = Collections.unmodifiableSet(theTargets);
090                } else {
091                        myTargets = Collections.emptySet();
092                }
093
094                if (theBase == null || theBase.isEmpty()) {
095                        HashSet<String> base = new HashSet<>();
096                        if (isNotBlank(thePath)) {
097                                int indexOf = thePath.indexOf('.');
098                                if (indexOf != -1) {
099                                        base.add(trim(thePath.substring(0, indexOf)));
100                                }
101                        }
102                        myBase = Collections.unmodifiableSet(base);
103                } else {
104                        myBase = Collections.unmodifiableSet(new HashSet<>(theBase));
105                }
106        }
107
108        public RuntimeSearchParam(String theName, String theDescription, String thePath, RestSearchParameterTypeEnum theParamType, Set<String> theProvidesMembershipInCompartments, Set<String> theTargets, RuntimeSearchParamStatusEnum theStatus) {
109                this(null, null, theName, theDescription, thePath, theParamType, null, theProvidesMembershipInCompartments, theTargets, theStatus);
110        }
111
112        /**
113         * Retrieve user data - This can be used to store any application-specific data
114         *
115         * @return
116         */
117        public List<IBaseExtension<?, ?>> getExtensions(String theKey) {
118                List<IBaseExtension<?, ?>> retVal = myExtensions.get(theKey);
119                if (retVal != null) {
120                        retVal = Collections.unmodifiableList(retVal);
121                }
122                return retVal;
123        }
124
125        /**
126         * Sets user data - This can be used to store any application-specific data
127         */
128        public RuntimeSearchParam addExtension(String theKey, IBaseExtension theValue) {
129                List<IBaseExtension<?, ?>> valuesList = myExtensions.computeIfAbsent(theKey, k -> new ArrayList<>());
130                valuesList.add(theValue);
131                return this;
132        }
133
134        @Override
135        public String toString() {
136                return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
137                        .append("base", myBase)
138                        .append("name", myName)
139                        .append("path", myPath)
140                        .append("id", myId)
141                        .append("uri", myUri)
142                        .toString();
143        }
144
145        public IIdType getId() {
146                return myId;
147        }
148
149        public String getUri() {
150                return myUri;
151        }
152
153        @Override
154        public boolean equals(Object theO) {
155                if (this == theO) return true;
156
157                if (theO == null || getClass() != theO.getClass()) return false;
158
159                RuntimeSearchParam that = (RuntimeSearchParam) theO;
160
161                return new EqualsBuilder()
162                        .append(getId(), that.getId())
163                        .append(getName(), that.getName())
164                        .append(getPath(), that.getPath())
165                        .append(getUri(), that.getUri())
166                        .isEquals();
167        }
168
169        @Override
170        public int hashCode() {
171                return new HashCodeBuilder(17, 37)
172                        .append(getId())
173                        .append(getName())
174                        .append(getPath())
175                        .append(getUri())
176                        .toHashCode();
177        }
178
179        public Set<String> getBase() {
180                return myBase;
181        }
182
183        @Nonnull
184        public Set<String> getTargets() {
185                return myTargets;
186        }
187
188        public boolean hasTargets() {
189                return !myTargets.isEmpty();
190        }
191
192        public RuntimeSearchParamStatusEnum getStatus() {
193                return myStatus;
194        }
195
196        public List<RuntimeSearchParam> getCompositeOf() {
197                return myCompositeOf;
198        }
199
200        public String getDescription() {
201                return myDescription;
202        }
203
204        public String getName() {
205                return myName;
206        }
207
208        public RestSearchParameterTypeEnum getParamType() {
209                return myParamType;
210        }
211
212        public String getPath() {
213                return myPath;
214        }
215
216        public List<String> getPathsSplit() {
217                String path = getPath();
218                if (path.indexOf('|') == -1) {
219                        return Collections.singletonList(path);
220                }
221
222                List<String> retVal = new ArrayList<>();
223                StringTokenizer tok = new StringTokenizer(path, "|");
224                while (tok.hasMoreElements()) {
225                        String nextPath = tok.nextToken().trim();
226                        retVal.add(nextPath.trim());
227                }
228                return retVal;
229        }
230
231        /**
232         * Can return null
233         */
234        public Set<String> getProvidesMembershipInCompartments() {
235                return myProvidesMembershipInCompartments;
236        }
237
238
239        public enum RuntimeSearchParamStatusEnum {
240                ACTIVE,
241                DRAFT,
242                RETIRED,
243                UNKNOWN
244        }
245
246}