001package ca.uhn.fhir.jpa.subscription.match.matcher.subscriber;
002
003/*-
004 * #%L
005 * HAPI FHIR Subscription Server
006 * %%
007 * Copyright (C) 2014 - 2022 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 ca.uhn.fhir.jpa.searchparam.extractor.StringTrimmingTrimmerMatcher;
024import ca.uhn.fhir.rest.api.Constants;
025import com.google.common.collect.Sets;
026import org.apache.commons.lang3.builder.ToStringBuilder;
027import org.apache.commons.lang3.builder.ToStringStyle;
028import org.apache.commons.text.StringTokenizer;
029
030import javax.annotation.Nullable;
031import java.util.Collections;
032import java.util.List;
033import java.util.Set;
034
035import static org.apache.commons.lang3.StringUtils.isBlank;
036import static org.apache.commons.lang3.StringUtils.isNotBlank;
037import static org.apache.commons.lang3.StringUtils.trim;
038
039public enum SubscriptionCriteriaParser {
040        ;
041
042        public enum TypeEnum {
043
044                /**
045                 * Normal search URL expression
046                 */
047                SEARCH_EXPRESSION,
048
049                /**
050                 * Collection of resource types
051                 */
052                MULTITYPE_EXPRESSION,
053
054                /**
055                 * All types
056                 */
057                STARTYPE_EXPRESSION
058
059        }
060
061        public static class SubscriptionCriteria {
062
063                private final TypeEnum myType;
064                private final String myCriteria;
065                private final Set<String> myApplicableResourceTypes;
066
067                private SubscriptionCriteria(TypeEnum theType, String theCriteria, Set<String> theApplicableResourceTypes) {
068                        myType = theType;
069                        myCriteria = theCriteria;
070                        myApplicableResourceTypes = theApplicableResourceTypes;
071                }
072
073                @Override
074                public String toString() {
075                        ToStringBuilder retVal = new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE);
076                        retVal.append("type", myType);
077                        if (isNotBlank(myCriteria)) {
078                                retVal.append("criteria", myCriteria);
079                        }
080                        if (myApplicableResourceTypes != null) {
081                                retVal.append("applicableResourceTypes", myApplicableResourceTypes);
082                        }
083                        return retVal.toString();
084                }
085
086                public TypeEnum getType() {
087                        return myType;
088                }
089
090                public String getCriteria() {
091                        return myCriteria;
092                }
093
094                public Set<String> getApplicableResourceTypes() {
095                        return myApplicableResourceTypes;
096                }
097        }
098
099        @Nullable
100        public static SubscriptionCriteria parse(String theCriteria) {
101                String criteria = trim(theCriteria);
102                if (isBlank(criteria)) {
103                        return null;
104                }
105
106                if (criteria.startsWith(Constants.SUBSCRIPTION_MULTITYPE_PREFIX)) {
107                        if (criteria.endsWith(Constants.SUBSCRIPTION_MULTITYPE_SUFFIX)) {
108                                String multitypeExpression = criteria.substring(1, criteria.length() - 1);
109                                StringTokenizer tok = new StringTokenizer(multitypeExpression, ",");
110                                tok.setTrimmerMatcher(new StringTrimmingTrimmerMatcher());
111                                List<String> types = tok.getTokenList();
112                                if (types.isEmpty()) {
113                                        return null;
114                                }
115                                if (types.contains(Constants.SUBSCRIPTION_MULTITYPE_STAR)) {
116                                        return new SubscriptionCriteria(TypeEnum.STARTYPE_EXPRESSION, null, null);
117                                }
118                                Set<String> typesSet = Sets.newHashSet(types);
119                                return new SubscriptionCriteria(TypeEnum.MULTITYPE_EXPRESSION, null, typesSet);
120                        }
121                }
122
123                if (Character.isLetter(criteria.charAt(0))) {
124                        String criteriaType = criteria;
125                        int questionMarkIdx = criteriaType.indexOf('?');
126                        if (questionMarkIdx > 0) {
127                                criteriaType = criteriaType.substring(0, questionMarkIdx);
128                        }
129                        Set<String> types = Collections.singleton(criteriaType);
130                        return new SubscriptionCriteria(TypeEnum.SEARCH_EXPRESSION, criteria, types);
131                }
132
133                return null;
134        }
135
136
137}