1/*
2* Conditions Of Use
3*
4* This software was developed by employees of the National Institute of
5* Standards and Technology (NIST), an agency of the Federal Government.
6* Pursuant to title 15 Untied States Code Section 105, works of NIST
7* employees are not subject to copyright protection in the United States
8* and are considered to be in the public domain.  As a result, a formal
9* license is not needed to use the software.
10*
11* This software is provided by NIST as a service and is expressly
12* provided "AS IS."  NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED
13* OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF
14* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT
15* AND DATA ACCURACY.  NIST does not warrant or make any representations
16* regarding the use of the software or the results thereof, including but
17* not limited to the correctness, accuracy, reliability or usefulness of
18* the software.
19*
20* Permission to use this software is contingent upon your acceptance
21* of the terms of this agreement
22*
23* .
24*
25*/
26/**************************************************************************/
27/* Product of NIST Advanced Networking Technologies Division  */
28/**************************************************************************/
29
30package gov.nist.javax.sip.header;
31import gov.nist.core.DuplicateNameValueList;
32import gov.nist.core.NameValue;
33import gov.nist.core.NameValueList;
34import gov.nist.javax.sip.address.GenericURI;
35
36import java.io.Serializable;
37import java.text.ParseException;
38import java.util.Iterator;
39
40import javax.sip.header.Parameters;
41
42/**
43 * Parameters header. Suitable for extension by headers that have parameters.
44 *
45 * @author M. Ranganathan   <br/>
46 *
47 *
48 * @version 1.2 $Revision: 1.15 $ $Date: 2010/01/12 00:05:27 $
49 *
50 */
51public abstract class ParametersHeader
52    extends SIPHeader
53    implements javax.sip.header.Parameters, Serializable {
54    protected NameValueList parameters;
55
56    protected DuplicateNameValueList duplicates;
57
58    protected ParametersHeader() {
59        this.parameters = new NameValueList();
60        this.duplicates = new DuplicateNameValueList();
61    }
62
63    protected ParametersHeader(String hdrName) {
64        super(hdrName);
65        this.parameters = new NameValueList();
66        this.duplicates = new DuplicateNameValueList();
67    }
68
69    protected ParametersHeader(String hdrName, boolean sync) {
70        super(hdrName);
71        this.parameters = new NameValueList(sync);
72        this.duplicates = new DuplicateNameValueList();
73    }
74
75    /**
76     * Returns the value of the named parameter, or null if it is not set. A
77     * zero-length String indicates flag parameter.
78     *
79     * @param name name of parameter to retrieve
80     * @return the value of specified parameter
81     */
82
83    public String getParameter(String name) {
84        return this.parameters.getParameter(name);
85
86    }
87
88    /**
89     * Return the parameter as an object (dont convert to string).
90     *
91     * @param name is the name of the parameter to get.
92     * @return the object associated with the name.
93     */
94    public Object getParameterValue(String name) {
95        return this.parameters.getValue(name);
96    }
97
98    /**
99     * Returns an Iterator over the names (Strings) of all parameters present
100     * in this ParametersHeader.
101     *
102     * @return an Iterator over all the parameter names
103     */
104
105    public Iterator<String> getParameterNames() {
106        return parameters.getNames();
107    }
108
109    /** Return true if you have a parameter and false otherwise.
110     *
111     *@return true if the parameters list is non-empty.
112     */
113
114    public boolean hasParameters() {
115        return parameters != null && !parameters.isEmpty();
116    }
117
118    /**
119    * Removes the specified parameter from Parameters of this ParametersHeader.
120    * This method returns silently if the parameter is not part of the
121    * ParametersHeader.
122    *
123    * @param name - a String specifying the parameter name
124    */
125
126    public void removeParameter(String name) {
127        this.parameters.delete(name);
128    }
129
130    /**
131     * Sets the value of the specified parameter. If the parameter already had
132     *
133     * a value it will be overwritten. A zero-length String indicates flag
134     *
135     * parameter.
136     *
137     *
138     *
139     * @param name - a String specifying the parameter name
140     *
141     * @param value - a String specifying the parameter value
142     *
143     * @throws ParseException which signals that an error has been reached
144     *
145     * unexpectedly while parsing the parameter name or value.
146     *
147     */
148    public void setParameter(String name, String value) throws ParseException {
149        NameValue nv = parameters.getNameValue(name);
150        if (nv != null) {
151            nv.setValueAsObject(value);
152        } else {
153            nv = new NameValue(name, value);
154            this.parameters.set(nv);
155        }
156    }
157
158    /**
159     * Sets the value of the specified parameter. If the parameter already had
160     *
161     * a value it will be overwritten. A zero-length String indicates flag
162     *
163     * parameter.
164     *
165     *
166     *
167     * @param name - a String specifying the parameter name
168     *
169     * @param value - a String specifying the parameter value
170     *
171     * @throws ParseException which signals that an error has been reached
172     *
173     * unexpectedly while parsing the parameter name or value.
174     *
175     */
176    public void setQuotedParameter(String name, String value)
177        throws ParseException {
178        NameValue nv = parameters.getNameValue(name);
179        if (nv != null) {
180            nv.setValueAsObject(value);
181            nv.setQuotedValue();
182        } else {
183            nv = new NameValue(name, value);
184            nv.setQuotedValue();
185            this.parameters.set(nv);
186        }
187    }
188
189    /**
190     * Sets the value of the specified parameter. If the parameter already had
191     *
192     * a value it will be overwritten.
193     *
194     *
195     * @param name - a String specifying the parameter name
196     *
197     * @param value - an int specifying the parameter value
198     *
199     * @throws ParseException which signals that an error has been reached
200     *
201     * unexpectedly while parsing the parameter name or value.
202     *
203     */
204    protected void setParameter(String name, int value) {
205        Integer val = Integer.valueOf(value);
206        this.parameters.set(name,val);
207
208    }
209
210    /**
211     * Sets the value of the specified parameter. If the parameter already had
212     *
213     * a value it will be overwritten.
214     *
215     *
216     * @param name - a String specifying the parameter name
217     *
218     * @param value - a boolean specifying the parameter value
219     *
220     * @throws ParseException which signals that an error has been reached
221     *
222     * unexpectedly while parsing the parameter name or value.
223     *
224     */
225    protected void setParameter(String name, boolean value) {
226        Boolean val = Boolean.valueOf(value);
227        this.parameters.set(name,val);
228    }
229
230    /**
231     * Sets the value of the specified parameter. If the parameter already had
232     *
233     * a value it will be overwritten.
234     *
235     * @param name - a String specifying the parameter name
236     *
237     * @param value - a boolean specifying the parameter value
238     *
239     * @throws ParseException which signals that an error has been reached
240     *
241     * unexpectedly while parsing the parameter name or value.
242     *
243     */
244    protected void setParameter(String name, float value) {
245        Float val = Float.valueOf(value);
246        NameValue nv = parameters.getNameValue(name);
247        if (nv != null) {
248            nv.setValueAsObject(val);
249        } else {
250            nv = new NameValue(name, val);
251            this.parameters.set(nv);
252        }
253    }
254
255    /**
256     * Sets the value of the specified parameter. If the parameter already had
257     *
258     * a value it will be overwritten. A zero-length String indicates flag
259     *
260     * parameter.
261     *
262     *
263     *
264     * @param name - a String specifying the parameter name
265     *
266     * @param value - a String specifying the parameter value
267     *
268     * @throws ParseException which signals that an error has been reached
269     *
270     * unexpectedly while parsing the parameter name or value.
271     *
272     */
273    protected void setParameter(String name, Object value) {
274        this.parameters.set(name,value);
275    }
276
277    /**
278     * Return true if has a parameter.
279     *
280     * @param parameterName is the name of the parameter.
281     *
282     * @return true if the parameter exists and false if not.
283     */
284    public boolean hasParameter(String parameterName) {
285        return this.parameters.hasNameValue(parameterName);
286    }
287
288    /**
289     *Remove all parameters.
290     */
291    public void removeParameters() {
292        this.parameters = new NameValueList();
293    }
294
295    /**
296     * get the parameter list.
297     * @return parameter list
298     */
299    public NameValueList getParameters() {
300        return parameters;
301    }
302
303    /** Set the parameter given a name and value.
304     *
305     * @param nameValue - the name value of the parameter to set.
306     */
307    public void setParameter(NameValue nameValue) {
308        this.parameters.set(nameValue);
309    }
310
311    /**
312     * Set the parameter list.
313     *
314     * @param parameters The name value list to set as the parameter list.
315     */
316    public void setParameters(NameValueList parameters) {
317        this.parameters = parameters;
318    }
319
320    /**
321     * Get the parameter as an integer value.
322     *
323     * @param parameterName -- the parameter name to fetch.
324     *
325     * @return -1 if the parameter is not defined in the header.
326     */
327    protected int getParameterAsInt(String parameterName) {
328        if (this.getParameterValue(parameterName) != null) {
329            try {
330                if (this.getParameterValue(parameterName) instanceof String) {
331                    return Integer.parseInt(this.getParameter(parameterName));
332                } else {
333                    return ((Integer) getParameterValue(parameterName))
334                        .intValue();
335                }
336            } catch (NumberFormatException ex) {
337                return -1;
338            }
339        } else
340            return -1;
341    }
342
343    /** Get the parameter as an integer when it is entered as a hex.
344     *
345     *@param parameterName -- The parameter name to fetch.
346     *
347     *@return -1 if the parameter is not defined in the header.
348     */
349    protected int getParameterAsHexInt(String parameterName) {
350        if (this.getParameterValue(parameterName) != null) {
351            try {
352                if (this.getParameterValue(parameterName) instanceof String) {
353                    return Integer.parseInt(
354                        this.getParameter(parameterName),
355                        16);
356                } else {
357                    return ((Integer) getParameterValue(parameterName))
358                        .intValue();
359                }
360            } catch (NumberFormatException ex) {
361                return -1;
362            }
363        } else
364            return -1;
365    }
366
367    /** Get the parameter as a float value.
368     *
369     *@param parameterName -- the parameter name to fetch
370     *
371     *@return -1 if the parameter is not defined or the parameter as a float.
372     */
373    protected float getParameterAsFloat(String parameterName) {
374
375        if (this.getParameterValue(parameterName) != null) {
376            try {
377                if (this.getParameterValue(parameterName) instanceof String) {
378                    return Float.parseFloat(this.getParameter(parameterName));
379                } else {
380                    return ((Float) getParameterValue(parameterName))
381                        .floatValue();
382                }
383            } catch (NumberFormatException ex) {
384                return -1;
385            }
386        } else
387            return -1;
388    }
389
390    /**
391     * Get the parameter as a long value.
392     *
393     * @param parameterName -- the parameter name to fetch.
394     *
395     * @return -1 if the parameter is not defined or the parameter as a long.
396     */
397    protected long getParameterAsLong(String parameterName) {
398        if (this.getParameterValue(parameterName) != null) {
399            try {
400                if (this.getParameterValue(parameterName) instanceof String) {
401                    return Long.parseLong(this.getParameter(parameterName));
402                } else {
403                    return ((Long) getParameterValue(parameterName))
404                        .longValue();
405                }
406            } catch (NumberFormatException ex) {
407                return -1;
408            }
409        } else
410            return -1;
411    }
412
413    /**
414     * Get the parameter value as a URI.
415     *
416     * @param parameterName -- the parameter name
417     *
418     * @return value of the parameter as a URI or null if the parameter
419     *  not present.
420     */
421    protected GenericURI getParameterAsURI(String parameterName) {
422        Object val = getParameterValue(parameterName);
423        if (val instanceof GenericURI)
424            return (GenericURI) val;
425        else {
426            try {
427                return new GenericURI((String) val);
428            } catch (ParseException ex) {
429                //catch ( URISyntaxException ex) {
430                return null;
431            }
432        }
433    }
434
435    /**
436     * Get the parameter value as a boolean.
437     *
438     * @param parameterName -- the parameter name
439     * @return boolean value of the parameter.
440     */
441    protected boolean getParameterAsBoolean(String parameterName) {
442        Object val = getParameterValue(parameterName);
443        if (val == null) {
444            return false;
445        } else if (val instanceof Boolean) {
446            return ((Boolean) val).booleanValue();
447        } else if (val instanceof String) {
448            return Boolean.valueOf((String) val).booleanValue();
449        } else
450            return false;
451    }
452
453    /**
454     * This is for the benifit of the TCK.
455     *
456     * @return the name value pair for the given parameter name.
457     */
458    public NameValue getNameValue(String parameterName) {
459        return parameters.getNameValue(parameterName);
460    }
461
462
463    public Object clone() {
464        ParametersHeader retval = (ParametersHeader) super.clone();
465        if (this.parameters != null)
466            retval.parameters = (NameValueList) this.parameters.clone();
467        return retval;
468    }
469
470    //-------------------------
471    /**
472     * Introduced specifically for the P-Charging-Function-Addresses Header and
473     * all other headers that may have multiple header parameters of the same name, but
474     * with multiple possible values.
475     *
476     * Example: P-Charging-Function-Addresses: ccf=[5555::b99:c88:d77:e66]; ccf=[5555::a55:b44:c33:d22];
477     *                                         ecf=[5555::1ff:2ee:3dd:4cc]; ecf=[5555::6aa:7bb:8cc:9dd]
478     * @param name of the parameter
479     * @param value of the parameter
480     */
481    public void setMultiParameter(String name, String value)
482    {
483    	NameValue nv = new NameValue();
484    	nv.setName(name);
485    	nv.setValue(value);
486    	duplicates.set(nv);
487    }
488
489    /** Set the parameter given a name and value.
490    *
491    * @param nameValue - the name value of the parameter to set.
492    */
493   public void setMultiParameter(NameValue nameValue) {
494       this.duplicates.set(nameValue);
495   }
496
497    /**
498     * Returns the parameter name
499     * @param name
500     * @return
501     */
502    public String getMultiParameter(String name) {
503        return this.duplicates.getParameter(name);
504
505    }
506
507
508    public DuplicateNameValueList getMultiParameters() {
509        return duplicates;
510    }
511
512
513    /**
514     * Return the parameter as an object (dont convert to string).
515     *
516     * @param name is the name of the parameter to get.
517     * @return the object associated with the name.
518     */
519    public Object getMultiParameterValue(String name) {
520        return this.duplicates.getValue(name);
521    }
522
523    /**
524     * Returns an Iterator over the names (Strings) of all parameters present
525     * in this ParametersHeader.
526     *
527     * @return an Iterator over all the parameter names
528     */
529
530    public Iterator<String> getMultiParameterNames() {
531        return duplicates.getNames();
532    }
533
534    /** Return true if you have a parameter and false otherwise.
535     *
536     *@return true if the parameters list is non-empty.
537     */
538
539    public boolean hasMultiParameters() {
540        return duplicates != null && !duplicates.isEmpty();
541    }
542
543    /**
544    * Removes the specified parameter from Parameters of this ParametersHeader.
545    * This method returns silently if the parameter is not part of the
546    * ParametersHeader.
547    *
548    * @param name - a String specifying the parameter name
549    */
550
551    public void removeMultiParameter(String name) {
552        this.duplicates.delete(name);
553    }
554
555    /**
556     * Return true if has a parameter.
557     *
558     * @param parameterName is the name of the parameter.
559     *
560     * @return true if the parameter exists and false if not.
561     */
562    public boolean hasMultiParameter(String parameterName) {
563        return this.duplicates.hasNameValue(parameterName);
564    }
565
566    /**
567     *Remove all parameters.
568     */
569    public void removeMultiParameters() {
570        this.duplicates = new DuplicateNameValueList();
571    }
572
573    //-------------------------------
574
575    @SuppressWarnings("unchecked")
576    protected final boolean equalParameters( Parameters other ) {
577        if (this==other) return true;
578
579        for ( Iterator i = this.getParameterNames(); i.hasNext();) {
580            String pname = (String) i.next();
581
582            String p1 = this.getParameter( pname );
583            String p2 = other.getParameter( pname );
584
585            // getting them based on this.getParameterNames. Note that p1 may be null
586            // if this is a name-only parameter like rport or lr.
587            if (p1 == null ^ p2 == null) return false;
588            else if (p1 != null && !p1.equalsIgnoreCase(p2) ) return false;
589        }
590
591        // Also compare other's parameters; some duplicate testing here...
592        for ( Iterator i = other.getParameterNames(); i.hasNext();) {
593            String pname = (String) i.next();
594
595            String p1 = other.getParameter( pname );
596            String p2 = this.getParameter( pname );
597
598                // assert( p1 != null );
599            // if ( p1 == null ) throw new RuntimeException("Assertion check failed!");
600            // if (p2==null) return false;
601
602            // getting them based on this.getParameterNames. Note that p1 may be null
603            // if this is a name-only parameter like rport or lr.
604
605            if (p1 == null ^ p2 == null) return false;
606            else if (p1 != null && !p1.equalsIgnoreCase(p2) ) return false;
607        }
608
609        return true;
610    }
611
612
613    // ----------- Abstract methods --------------
614    protected abstract String encodeBody();
615
616}
617