001// *************************************************************************************************************************** 002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * 003// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * 004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * 005// * with the License. You may obtain a copy of the License at * 006// * * 007// * http://www.apache.org/licenses/LICENSE-2.0 * 008// * * 009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * 010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * 011// * specific language governing permissions and limitations under the License. * 012// *************************************************************************************************************************** 013package org.apache.juneau.rest; 014 015import static org.apache.juneau.internal.StringUtils.*; 016 017import java.lang.reflect.*; 018import java.util.*; 019 020import org.apache.juneau.*; 021import org.apache.juneau.httppart.*; 022import org.apache.juneau.parser.*; 023 024/** 025 * @deprecated Unused. 026 */ 027@Deprecated 028@SuppressWarnings("unchecked") 029public class RequestPathMatch extends TreeMap<String,String> { 030 private static final long serialVersionUID = 1L; 031 032 private HttpPartParser parser; 033 private BeanSession beanSession; 034 private String remainder, pattern; 035 036 RequestPathMatch() { 037 super(String.CASE_INSENSITIVE_ORDER); 038 } 039 040 RequestPathMatch parser(HttpPartParser parser) { 041 this.parser = parser; 042 return this; 043 } 044 045 RequestPathMatch beanSession(BeanSession beanSession) { 046 this.beanSession = beanSession; 047 return this; 048 } 049 050 RequestPathMatch remainder(String remainder) { 051 this.remainder = remainder; 052 return this; 053 } 054 055 RequestPathMatch pattern(String pattern) { 056 this.pattern = pattern; 057 return this; 058 } 059 060 /** 061 * Sets a request query parameter value. 062 * 063 * @param name The parameter name. 064 * @param value The parameter value. 065 */ 066 public void put(String name, Object value) { 067 super.put(name, value.toString()); 068 } 069 070 /** 071 * Returns the specified path parameter converted to a String. 072 * 073 * @param name The path variable name. 074 * @return The parameter value. 075 * @throws ParseException 076 */ 077 public String getString(String name) throws ParseException { 078 return parse(parser, name, beanSession.string()); 079 } 080 081 /** 082 * Returns the specified path parameter converted to an integer. 083 * 084 * @param name The path variable name. 085 * @return The parameter value. 086 * @throws ParseException 087 */ 088 public int getInt(String name) throws ParseException { 089 return parse(parser, name, beanSession.getClassMeta(int.class)); 090 } 091 092 /** 093 * Returns the specified path parameter converted to a boolean. 094 * 095 * @param name The path variable name. 096 * @return The parameter value. 097 * @throws ParseException 098 */ 099 public boolean getBoolean(String name) throws ParseException { 100 return parse(parser, name, beanSession.getClassMeta(boolean.class)); 101 } 102 103 /** 104 * Returns the specified path parameter value converted to a POJO using the {@link HttpPartParser} registered with the resource. 105 * 106 * <h5 class='section'>Examples:</h5> 107 * <p class='bcode'> 108 * <jc>// Parse into an integer.</jc> 109 * <jk>int</jk> myparam = path.get(<js>"myparam"</js>, <jk>int</jk>.<jk>class</jk>); 110 * 111 * <jc>// Parse into an int array.</jc> 112 * <jk>int</jk>[] myparam = path.get(<js>"myparam"</js>, <jk>int</jk>[].<jk>class</jk>); 113 114 * <jc>// Parse into a bean.</jc> 115 * MyBean myparam = path.get(<js>"myparam"</js>, MyBean.<jk>class</jk>); 116 * 117 * <jc>// Parse into a linked-list of objects.</jc> 118 * List myparam = path.get(<js>"myparam"</js>, LinkedList.<jk>class</jk>); 119 * 120 * <jc>// Parse into a map of object keys/values.</jc> 121 * Map myparam = path.get(<js>"myparam"</js>, TreeMap.<jk>class</jk>); 122 * </p> 123 * 124 * <h5 class='section'>See Also:</h5> 125 * <ul> 126 * <li class='jf'>{@link RestContext#REST_partParser} 127 * </ul> 128 * 129 * @param name The attribute name. 130 * @param type The class type to convert the attribute value to. 131 * @param <T> The class type to convert the attribute value to. 132 * @return The attribute value converted to the specified class type. 133 * @throws ParseException 134 */ 135 public <T> T get(String name, Class<T> type) throws ParseException { 136 return get(parser, name, type); 137 } 138 139 /** 140 * Same as {@link #get(String, Class)} but allows you to override the part parser. 141 * 142 * @param parser 143 * The parser to use for parsing the string value. 144 * <br>If <jk>null</jk>, uses the part parser defined on the resource/method. 145 * @param name The attribute name. 146 * @param type The class type to convert the attribute value to. 147 * @param <T> The class type to convert the attribute value to. 148 * @return The attribute value converted to the specified class type. 149 * @throws ParseException 150 */ 151 public <T> T get(HttpPartParser parser, String name, Class<T> type) throws ParseException { 152 return parse(parser, name, beanSession.getClassMeta(type)); 153 } 154 155 /** 156 * Returns the specified query parameter value converted to a POJO using the {@link HttpPartParser} registered with the resource. 157 * 158 * <p> 159 * Similar to {@link #get(String,Class)} but allows for complex collections of POJOs to be created. 160 * 161 * <p> 162 * Use this method if you want to parse into a parameterized <code>Map</code>/<code>Collection</code> object. 163 * 164 * <h5 class='section'>Examples:</h5> 165 * <p class='bcode'> 166 * <jc>// Parse into a linked-list of strings.</jc> 167 * List<String> myparam = req.getPathParameter(<js>"myparam"</js>, LinkedList.<jk>class</jk>, String.<jk>class</jk>); 168 * 169 * <jc>// Parse into a linked-list of linked-lists of strings.</jc> 170 * List<List<String>> myparam = req.getPathParameter(<js>"myparam"</js>, LinkedList.<jk>class</jk>, LinkedList.<jk>class</jk>, String.<jk>class</jk>); 171 * 172 * <jc>// Parse into a map of string keys/values.</jc> 173 * Map<String,String> myparam = req.getPathParameter(<js>"myparam"</js>, TreeMap.<jk>class</jk>, String.<jk>class</jk>, String.<jk>class</jk>); 174 * 175 * <jc>// Parse into a map containing string keys and values of lists containing beans.</jc> 176 * Map<String,List<MyBean>> myparam = req.getPathParameter(<js>"myparam"</js>, TreeMap.<jk>class</jk>, String.<jk>class</jk>, List.<jk>class</jk>, MyBean.<jk>class</jk>); 177 * </p> 178 * 179 * <h5 class='section'>Notes:</h5> 180 * <ul class='spaced-list'> 181 * <li> 182 * <code>Collections</code> must be followed by zero or one parameter representing the value type. 183 * <li> 184 * <code>Maps</code> must be followed by zero or two parameters representing the key and value types. 185 * </ul> 186 * 187 * <h5 class='section'>See Also:</h5> 188 * <ul> 189 * <li class='jf'>{@link RestContext#REST_partParser} 190 * </ul> 191 * 192 * @param name The attribute name. 193 * @param type 194 * The type of object to create. 195 * <br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType} 196 * @param args 197 * The type arguments of the class if it's a collection or map. 198 * <br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType} 199 * <br>Ignored if the main type is not a map or collection. 200 * @param <T> The class type to convert the attribute value to. 201 * @return The attribute value converted to the specified class type. 202 * @throws ParseException 203 */ 204 public <T> T get(String name, Type type, Type...args) throws ParseException { 205 return get(parser, name, type, args); 206 } 207 208 /** 209 * Same as {@link #get(String, Type, Type...)} but allows you to override the part parser. 210 * 211 * @param parser 212 * The parser to use for parsing the string value. 213 * <br>If <jk>null</jk>, uses the part parser defined on the resource/method. 214 * @param name The attribute name. 215 * @param type 216 * The type of object to create. 217 * <br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType} 218 * @param args 219 * The type arguments of the class if it's a collection or map. 220 * <br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType} 221 * <br>Ignored if the main type is not a map or collection. 222 * @param <T> The class type to convert the attribute value to. 223 * @return The attribute value converted to the specified class type. 224 * @throws ParseException 225 */ 226 public <T> T get(HttpPartParser parser, String name, Type type, Type...args) throws ParseException { 227 return (T)parse(parser, name, beanSession.getClassMeta(type, args)); 228 } 229 230 231 /* Workhorse method */ 232 <T> T parse(HttpPartParser parser, String name, ClassMeta<T> cm) throws ParseException { 233 if (parser == null) 234 parser = this.parser; 235 Object attr = get(name); 236 T t = null; 237 if (attr != null) 238 t = parser.parse(HttpPartType.PATH, attr.toString(), cm); 239 if (t == null && cm.isPrimitive()) 240 return cm.getPrimitiveDefault(); 241 return t; 242 } 243 244 /** 245 * Returns the decoded remainder of the URL following any path pattern matches. 246 * 247 * <p> 248 * The behavior of path remainder is shown below given the path pattern "/foo/*": 249 * <table class='styled'> 250 * <tr> 251 * <th>URL</th> 252 * <th>Path Remainder</th> 253 * </tr> 254 * <tr> 255 * <td><code>/foo</code></td> 256 * <td><jk>null</jk></td> 257 * </tr> 258 * <tr> 259 * <td><code>/foo/</code></td> 260 * <td><js>""</js></td> 261 * </tr> 262 * <tr> 263 * <td><code>/foo//</code></td> 264 * <td><js>"/"</js></td> 265 * </tr> 266 * <tr> 267 * <td><code>/foo///</code></td> 268 * <td><js>"//"</js></td> 269 * </tr> 270 * <tr> 271 * <td><code>/foo/a/b</code></td> 272 * <td><js>"a/b"</js></td> 273 * </tr> 274 * <tr> 275 * <td><code>/foo//a/b/</code></td> 276 * <td><js>"/a/b/"</js></td> 277 * </tr> 278 * <tr> 279 * <td><code>/foo/a%2Fb</code></td> 280 * <td><js>"a/b"</js></td> 281 * </tr> 282 * </table> 283 * 284 * <h5 class='section'>Example:</h5> 285 * <p class='bcode'> 286 * <jc>// REST method</jc> 287 * <ja>@RestMethod</ja>(name=<jsf>GET</jsf>,path=<js>"/foo/{bar}/*"</js>) 288 * <jk>public</jk> String doGetById(RequestPathMatch path, <jk>int</jk> bar) { 289 * <jk>return</jk> path.getRemainder(); 290 * } 291 * </p> 292 * 293 * @return The path remainder string. 294 */ 295 public String getRemainder() { 296 return urlDecode(remainder); 297 } 298 299 /** 300 * Same as {@link #getRemainder()} but doesn't decode characters. 301 * 302 * @return The un-decoded path remainder. 303 */ 304 public String getRemainderUndecoded() { 305 return remainder; 306 } 307 308 /** 309 * Returns the path pattern that matched this request. 310 * 311 * @return The path pattern that matched this request. 312 */ 313 public String getPattern() { 314 return pattern; 315 } 316}