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