001package ca.uhn.fhir.rest.param; 002 003/* 004 * #%L 005 * HAPI FHIR - Core Library 006 * %% 007 * Copyright (C) 2014 - 2017 University Health Network 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 java.util.ArrayList; 024import java.util.Collections; 025import java.util.HashSet; 026import java.util.List; 027import java.util.Set; 028 029import ca.uhn.fhir.model.primitive.IntegerDt; 030import ca.uhn.fhir.util.UrlUtil; 031 032public class ParameterUtil { 033 034 private static final Set<Class<?>> BINDABLE_INTEGER_TYPES; 035 036 static { 037 HashSet<Class<?>> intTypes = new HashSet<Class<?>>(); 038 intTypes.add(IntegerDt.class); 039 intTypes.add(Integer.class); 040 BINDABLE_INTEGER_TYPES = Collections.unmodifiableSet(intTypes); 041 042 } 043 044 // public static Integer findSinceParameterIndex(Method theMethod) { 045 // return findParamIndex(theMethod, Since.class); 046 // } 047 048 public static int nonEscapedIndexOf(String theString, char theCharacter) { 049 for (int i = 0; i < theString.length(); i++) { 050 if (theString.charAt(i) == theCharacter) { 051 if (i == 0 || theString.charAt(i - 1) != '\\') { 052 return i; 053 } 054 } 055 } 056 return -1; 057 } 058 059 060 public static Object fromInteger(Class<?> theType, IntegerDt theArgument) { 061 if (theType.equals(IntegerDt.class)) { 062 if (theArgument == null) { 063 return null; 064 } 065 return theArgument; 066 } 067 if (theType.equals(Integer.class)) { 068 if (theArgument == null) { 069 return null; 070 } 071 return theArgument.getValue(); 072 } 073 throw new IllegalArgumentException("Invalid Integer type:" + theType); 074 } 075 076 public static Set<Class<?>> getBindableIntegerTypes() { 077 return BINDABLE_INTEGER_TYPES; 078 } 079 080 081 public static IntegerDt toInteger(Object theArgument) { 082 if (theArgument instanceof IntegerDt) { 083 return (IntegerDt) theArgument; 084 } 085 if (theArgument instanceof Integer) { 086 return new IntegerDt((Integer) theArgument); 087 } 088 return null; 089 } 090 091 static List<String> splitParameterString(String theInput, boolean theUnescapeComponents) { 092 return splitParameterString(theInput, ',', theUnescapeComponents); 093 } 094 095 static List<String> splitParameterString(String theInput, char theDelimiter, boolean theUnescapeComponents) { 096 ArrayList<String> retVal = new ArrayList<String>(); 097 if (theInput != null) { 098 StringBuilder b = new StringBuilder(); 099 for (int i = 0; i < theInput.length(); i++) { 100 char next = theInput.charAt(i); 101 if (next == theDelimiter) { 102 if (i == 0) { 103 b.append(next); 104 } else { 105 char prevChar = theInput.charAt(i - 1); 106 if (prevChar == '\\') { 107 b.append(next); 108 } else { 109 if (b.length() > 0) { 110 retVal.add(b.toString()); 111 } else { 112 retVal.add(null); 113 } 114 b.setLength(0); 115 } 116 } 117 } else { 118 b.append(next); 119 } 120 } 121 if (b.length() > 0) { 122 retVal.add(b.toString()); 123 } 124 } 125 126 if (theUnescapeComponents) { 127 for (int i = 0; i < retVal.size(); i++) { 128 retVal.set(i, unescape(retVal.get(i))); 129 } 130 } 131 132 return retVal; 133 } 134 135 /** 136 * Escapes a string according to the rules for parameter escaping specified in the <a href="http://www.hl7.org/implement/standards/fhir/search.html#escaping">FHIR Specification Escaping 137 * Section</a> 138 */ 139 public static String escapeWithDefault(Object theValue) { 140 if (theValue == null) { 141 return ""; 142 } 143 return escape(theValue.toString()); 144 } 145 146 /** 147 * Escapes a string according to the rules for parameter escaping specified in the <a href="http://www.hl7.org/implement/standards/fhir/search.html#escaping">FHIR Specification Escaping 148 * Section</a> 149 */ 150 public static String escape(String theValue) { 151 if (theValue == null) { 152 return null; 153 } 154 StringBuilder b = new StringBuilder(); 155 156 for (int i = 0; i < theValue.length(); i++) { 157 char next = theValue.charAt(i); 158 switch (next) { 159 case '$': 160 case ',': 161 case '|': 162 case '\\': 163 b.append('\\'); 164 break; 165 default: 166 break; 167 } 168 b.append(next); 169 } 170 171 return b.toString(); 172 } 173 174 /** 175 * Escapes a string according to the rules for parameter escaping specified in the <a href="http://www.hl7.org/implement/standards/fhir/search.html#escaping">FHIR Specification Escaping 176 * Section</a> 177 */ 178 public static String escapeAndUrlEncode(String theValue) { 179 if (theValue == null) { 180 return null; 181 } 182 183 String escaped = escape(theValue); 184 return UrlUtil.escape(escaped); 185 } 186 187 /** 188 * Unescapes a string according to the rules for parameter escaping specified in the <a href="http://www.hl7.org/implement/standards/fhir/search.html#escaping">FHIR Specification Escaping 189 * Section</a> 190 */ 191 public static String unescape(String theValue) { 192 if (theValue == null) { 193 return theValue; 194 } 195 if (theValue.indexOf('\\') == -1) { 196 return theValue; 197 } 198 199 StringBuilder b = new StringBuilder(); 200 201 for (int i = 0; i < theValue.length(); i++) { 202 char next = theValue.charAt(i); 203 if (next == '\\') { 204 if (i == theValue.length() - 1) { 205 b.append(next); 206 } else { 207 switch (theValue.charAt(i + 1)) { 208 case '$': 209 case ',': 210 case '|': 211 case '\\': 212 continue; 213 default: 214 b.append(next); 215 } 216 } 217 } else { 218 b.append(next); 219 } 220 } 221 222 return b.toString(); 223 } 224 225}