1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.struts.flow.core.source;
18
19 import java.io.Serializable;
20 import java.util.ArrayList;
21 import java.util.HashMap;
22 import java.util.Iterator;
23 import java.util.Map;
24 import java.util.StringTokenizer;
25
26 /***
27 * This class holds parameters for a <code>Source</code> object.
28 * It differs from the usual Parameters object because it can hold
29 * more than one value for a parameter, as is the case for HTTP
30 * request parameters.
31 * <p>
32 * Only particular kinds of <code>Source</code> implementations, such as
33 * {@link org.apache.struts.flow.core.source.impl.URLSource} support this kind of
34 * parameters, passed as the {@link SourceResolver#URI_PARAMETERS} entry
35 * in the <code>parameters</code> argument of
36 * {@link SourceResolver#resolveURI(String, String, Map)}.
37 *
38 * @author <a href="mailto:dev@avalon.apache.org">Avalon Development Team</a>
39 * @version $Id: SourceParameters.java,v 1.5 2004/03/12 13:02:55 cziegeler Exp $
40 */
41 public final class SourceParameters
42 implements Serializable, Cloneable
43 {
44 /*** The parameter names are the keys and the value is a List object */
45 private Map names = new HashMap( 5 );
46
47 /***
48 * Decode the string
49 */
50 private String parseName( String s )
51 {
52 StringBuffer sb = new StringBuffer();
53 for( int i = 0; i < s.length(); i++ )
54 {
55 char c = s.charAt( i );
56 switch( c )
57 {
58 case '+':
59 sb.append( ' ' );
60 break;
61 case '%':
62 try
63 {
64 sb.append( (char)Integer.parseInt( s.substring( i + 1, i + 3 ),
65 16 ) );
66 i += 2;
67 }
68 catch( NumberFormatException e )
69 {
70 throw new IllegalArgumentException();
71 }
72 catch( StringIndexOutOfBoundsException e )
73 {
74 String rest = s.substring( i );
75 sb.append( rest );
76 if( rest.length() == 2 )
77 i++;
78 }
79
80 break;
81 default:
82 sb.append( c );
83 break;
84 }
85 }
86 return sb.toString();
87 }
88
89 /***
90 * Standard Constructor creating an empty parameters object
91 */
92 public SourceParameters()
93 {
94 }
95
96 /***
97 * Construct a new object from a queryString
98 */
99 public SourceParameters( String queryString )
100 {
101 if( queryString != null )
102 {
103 StringTokenizer st = new StringTokenizer( queryString, "&" );
104 while( st.hasMoreTokens() )
105 {
106 String pair = st.nextToken();
107 int pos = pair.indexOf( '=' );
108 if( pos != -1 )
109 {
110 setParameter( parseName( pair.substring( 0, pos ) ),
111 parseName( pair.substring( pos + 1, pair.length() ) ) );
112 }
113 }
114 }
115 }
116
117 /***
118 * Add a parameter.
119 * The parameter is added with the given value.
120 * @param name The name of the parameter.
121 * @param value The value of the parameter.
122 */
123 public void setParameter( String name, String value )
124 {
125 ArrayList list;
126 if( names.containsKey( name ) == true )
127 {
128 list = (ArrayList)names.get( name );
129 }
130 else
131 {
132 list = new ArrayList( 3 );
133 names.put( name, list );
134 }
135 list.add( value );
136 }
137
138 /***
139 * Get the value of a parameter.
140 * @param name The name of the parameter.
141 * @return The value of the first parameter with the name
142 * or <CODE>null</CODE>
143 */
144 public String getParameter( String name )
145 {
146 if( names.containsKey( name ) == true )
147 {
148 return (String)( (ArrayList)names.get( name ) ).get( 0 );
149 }
150 return null;
151 }
152
153 /***
154 * Get the value of a parameter.
155 * @param name The name of the parameter.
156 * @param defaultValue The default value if the parameter does not exist.
157 * @return The value of the first parameter with the name
158 * or <CODE>defaultValue</CODE>
159 */
160 public String getParameter( String name, String defaultValue )
161 {
162 if( names.containsKey( name ) == true )
163 {
164 return (String)( (ArrayList)names.get( name ) ).get( 0 );
165 }
166 return defaultValue;
167 }
168
169 /***
170 * Get the integer value of a parameter.
171 * @param name The name of the parameter.
172 * @param defaultValue The default value if the parameter does not exist.
173 * @return The value of the first parameter with the name
174 * or <CODE>defaultValue</CODE>
175 */
176 public int getParameterAsInteger( String name, int defaultValue )
177 {
178 if( names.containsKey( name ) == true )
179 {
180 return new Integer( (String)( (ArrayList)names.get( name ) ).get( 0 ) ).intValue();
181 }
182 return defaultValue;
183 }
184
185 /***
186 * Get the boolean value of a parameter.
187 * @param name The name of the parameter.
188 * @param defaultValue The default value if the parameter does not exist.
189 * @return The value of the first parameter with the name
190 * or <CODE>defaultValue</CODE>
191 */
192 public boolean getParameterAsBoolean( String name, boolean defaultValue )
193 {
194 if( names.containsKey( name ) == true )
195 {
196 return new Boolean( (String)( (ArrayList)names.get( name ) ).get( 0 ) ).booleanValue();
197 }
198 return defaultValue;
199 }
200
201 /***
202 * Test if a value for this parameter exists.
203 * @param name The name of the parameter.
204 * @return <CODE>true</CODE> if a value exists, otherwise <CODE>false</CODE>
205 */
206 public boolean containsParameter( String name )
207 {
208 return names.containsKey( name );
209 }
210
211 /***
212 * Get all values of a parameter.
213 * @param name The name of the parameter.
214 * @return Iterator for the (String) values or null if the parameter
215 * is not defined.
216 */
217 public Iterator getParameterValues( String name )
218 {
219 if( names.containsKey( name ) == true )
220 {
221 ArrayList list = (ArrayList)names.get( name );
222 return list.iterator();
223 }
224 return null;
225 }
226
227 /***
228 * Get all values of a parameter.
229 * @param name The name of the parameter.
230 * @return An Array for the (String) values or null.
231 */
232 public String[] getParameterValuesAsArray( String name )
233 {
234 if( names.containsKey( name ) == true )
235 {
236 ArrayList list = (ArrayList)names.get( name );
237 String[] values = new String[list.size()];
238 for(int i=0;i<values.length;i++)
239 {
240 values[i] = (String)list.get(i);
241 }
242 return values;
243 }
244 return null;
245 }
246
247 /***
248 * Get all parameter names.
249 * @return Iterator for the (String) parameter names.
250 */
251 public Iterator getParameterNames()
252 {
253 return names.keySet().iterator();
254 }
255
256 /***
257 * Build a query string.
258 * The query string can e.g. be used for http connections.
259 * @return A query string which contains for each parameter/value pair
260 * a part, like "parameter=value" separated by "&".
261 * If no parameter is defined <CODE>null</CODE> is returned.
262 */
263 public String getQueryString()
264 {
265 StringBuffer result = new StringBuffer();
266 Iterator iter = this.names.keySet().iterator();
267 Iterator listIterator;
268 String key;
269 String value;
270 boolean first = true;
271 while( iter.hasNext() == true )
272 {
273 key = (String)iter.next();
274 listIterator = ( (ArrayList)names.get( key ) ).iterator();
275 while( listIterator.hasNext() == true )
276 {
277 if( first == false ) result.append( '&' );
278 value = (String)listIterator.next();
279 result.append( key ).append( '=' ).append( value );
280 first = false;
281 }
282 }
283 return ( result.length() == 0 ? null : result.toString() );
284 }
285
286 /***
287 * Build a query string and encode each parameter value.
288 * The query string can e.g. be used for http connections.
289 * @return A query string which contains for each parameter/value pair
290 * a part, like "parameter=value" separated by "&".
291 * If no parameter is defined <CODE>null</CODE> is returned.
292 */
293 public String getEncodedQueryString()
294 {
295 StringBuffer result = new StringBuffer();
296 Iterator iter = this.names.keySet().iterator();
297 Iterator listIterator;
298 String key;
299 String value;
300 boolean first = true;
301 while( iter.hasNext() == true )
302 {
303 key = (String)iter.next();
304 listIterator = ( (ArrayList)names.get( key ) ).iterator();
305 while( listIterator.hasNext() == true )
306 {
307 if( first == false ) result.append( '&' );
308 value = (String)listIterator.next();
309 result.append( key ).append( '=' ).append( SourceUtil.encode( value ) );
310 first = false;
311 }
312 }
313 return ( result.length() == 0 ? null : result.toString() );
314 }
315
316 /***
317 * Add all parameters from the incoming parameters object.
318 */
319 public void add( SourceParameters parameters )
320 {
321 if( null != parameters )
322 {
323 Iterator names = parameters.getParameterNames();
324 Iterator values;
325 String name;
326 String value;
327 while( names.hasNext() == true )
328 {
329 name = (String)names.next();
330 values = parameters.getParameterValues( name );
331 while( values.hasNext() == true )
332 {
333 value = (String)values.next();
334 this.setParameter( name, value );
335 }
336 }
337 }
338 }
339
340 /***
341 * Overriding toString
342 */
343 public String toString()
344 {
345 StringBuffer buffer = new StringBuffer( "SourceParameters: {" );
346 Iterator names = this.getParameterNames();
347 String name;
348 boolean firstName = true;
349 Iterator values;
350 String value;
351 boolean firstValue;
352 while( names.hasNext() == true )
353 {
354 name = (String)names.next();
355 if( firstName == false )
356 {
357 buffer.append( ", " );
358 }
359 else
360 {
361 firstName = false;
362 }
363 buffer.append( name ).append( " = (" );
364 values = this.getParameterValues( name );
365 firstValue = true;
366 while( values.hasNext() == true )
367 {
368 value = (String)values.next();
369 if( firstValue == false )
370 {
371 buffer.append( ", " );
372 }
373 else
374 {
375 firstValue = false;
376 }
377 buffer.append( value );
378 }
379 buffer.append( ')' );
380 }
381 buffer.append( '}' );
382 return buffer.toString();
383 }
384
385 /***
386 * Returns a copy of the parameters object.
387 */
388 public Object clone()
389 {
390 SourceParameters newObject = new SourceParameters();
391 Iterator names = this.getParameterNames();
392 Iterator values;
393 String name, value;
394 while( names.hasNext() )
395 {
396 name = (String)names.next();
397 values = this.getParameterValues( name );
398 while( values.hasNext() )
399 {
400 value = (String)values.next();
401 newObject.setParameter( name, value );
402 }
403 }
404 return newObject;
405 }
406
407 /***
408 * Test if there are any parameters.
409 */
410 public boolean hasParameters()
411 {
412 return ( this.names.size() > 0 );
413 }
414
415 /***
416 * Set the value of this parameter to the given value.
417 * Remove all other values for this parameter.
418 */
419 public void setSingleParameterValue( String name, String value )
420 {
421 this.removeParameter( name );
422 this.setParameter( name, value );
423 }
424
425 /***
426 * Remove all values for this parameter
427 */
428 public void removeParameter( String name )
429 {
430 if( this.names.containsKey( name ) )
431 {
432 this.names.remove( name );
433 }
434 }
435
436 /***
437 * Returns an immutable java.util.Map containing parameter names as keys and
438 * parameter values as map values. The keys in the parameter map are of type String.
439 * The values in the parameter map are of type String array.
440 */
441 public Map getParameterMap()
442 {
443 final Map m = new HashMap(this.names);
444 Iterator entries = m.entrySet().iterator();
445 while (entries.hasNext())
446 {
447 Map.Entry entry = (Map.Entry)entries.next();
448 ArrayList list = (ArrayList)entry.getValue();
449 String[] values = new String[list.size()];
450 for(int i=0;i<values.length;i++)
451 {
452 values[i] = (String)list.get(i);
453 }
454 entry.setValue(values);
455 }
456 return m;
457 }
458 }