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/ITL Advanced Networking Technologies Division (ANTD).        *
28  *******************************************************************************/
29 package gov.nist.core;
30 
31 import java.util.Map.Entry;
32 
33 /*
34  * Bug reports and fixes: Kirby Kiem, Jeroen van Bemmel.
35  */
36 
37 /**
38  * Generic structure for storing name-value pairs.
39  *
40  * @version 1.2
41  *
42  * @author M. Ranganathan <br/>
43  *
44  *
45  *
46  */
47 public class NameValue extends GenericObject implements Entry<String,String> {
48 
49     private static final long serialVersionUID = -1857729012596437950L;
50 
51     protected boolean isQuotedString;
52 
53     protected final boolean isFlagParameter;
54 
55     private String separator;
56 
57     private String quotes;
58 
59     private String name;
60 
61     private Object value;
62 
NameValue()63     public NameValue() {
64         name = null;
65         value = "";
66         separator = Separators.EQUALS;
67         this.quotes = "";
68         this.isFlagParameter = false;
69     }
70 
71     /**
72      * New constructor, taking a boolean which is set if the NV pair is a flag
73      *
74      * @param n
75      * @param v
76      * @param isFlag
77      */
NameValue(String n, Object v, boolean isFlag)78     public NameValue(String n, Object v, boolean isFlag) {
79 
80         // assert (v != null ); // I dont think this assertion is correct mranga
81 
82         name = n;
83         value = v;
84         separator = Separators.EQUALS;
85         quotes = "";
86         this.isFlagParameter = isFlag;
87     }
88 
89     /**
90      * Original constructor, sets isFlagParameter to 'false'
91      *
92      * @param n
93      * @param v
94      */
NameValue(String n, Object v)95     public NameValue(String n, Object v) {
96         this(n, v, false);
97     }
98 
99     /**
100      * Set the separator for the encoding method below.
101      */
setSeparator(String sep)102     public void setSeparator(String sep) {
103         separator = sep;
104     }
105 
106     /**
107      * A flag that indicates that doublequotes should be put around the value
108      * when encoded (for example name=value when value is doublequoted).
109      */
setQuotedValue()110     public void setQuotedValue() {
111         isQuotedString = true;
112         this.quotes = Separators.DOUBLE_QUOTE;
113     }
114 
115     /**
116      * Return true if the value is quoted in doublequotes.
117      */
isValueQuoted()118     public boolean isValueQuoted() {
119         return isQuotedString;
120     }
121 
getName()122     public String getName() {
123         return name;
124     }
125 
getValueAsObject()126     public Object getValueAsObject() {
127         return isFlagParameter ? "" : value; // never return null for flag
128                                                 // params
129     }
130 
131     /**
132      * Set the name member
133      */
setName(String n)134     public void setName(String n) {
135         name = n;
136     }
137 
138     /**
139      * Set the value member
140      */
setValueAsObject(Object v)141     public void setValueAsObject(Object v) {
142         value = v;
143     }
144 
145     /**
146      * Get the encoded representation of this namevalue object. Added
147      * doublequote for encoding doublequoted values.
148      *
149      * Bug: RFC3261 stipulates that an opaque parameter in authenticate header
150      * has to be:
151      * opaque              =  "opaque" EQUAL quoted-string
152      * so returning just the name is not acceptable. (e.g. LinkSys phones
153      * are picky about this)
154      *
155      * @since 1.0
156      * @return an encoded name value (eg. name=value) string.
157      */
encode()158     public String encode() {
159         return encode(new StringBuffer()).toString();
160     }
161 
encode(StringBuffer buffer)162     public StringBuffer encode(StringBuffer buffer) {
163         if (name != null && value != null && !isFlagParameter) {
164             if (GenericObject.isMySubclass(value.getClass())) {
165                 GenericObject gv = (GenericObject) value;
166                 buffer.append(name).append(separator).append(quotes);
167                 gv.encode(buffer);
168                 buffer.append(quotes);
169                 return buffer;
170             } else if (GenericObjectList.isMySubclass(value.getClass())) {
171                 GenericObjectList gvlist = (GenericObjectList) value;
172                 buffer.append(name).append(separator).append(gvlist.encode());
173                 return buffer;
174             } else if ( value.toString().length() == 0) {
175                 // opaque="" bug fix - pmusgrave
176                 /*if (name.toString().equals(gov.nist.javax.sip.header.ParameterNames.OPAQUE))
177                     return name + separator + quotes + quotes;
178                 else
179                     return name;*/
180                 if ( this.isQuotedString ) {
181                     buffer.append(name).append(separator).append(quotes).append(quotes);
182                     return buffer;
183                 } else {
184                     buffer.append(name).append(separator); // JvB: fix, case: "sip:host?subject="
185                     return buffer;
186                 }
187             } else {
188                 buffer.append(name).append(separator).append(quotes).append(value.toString()).append(quotes);
189                 return buffer;
190             }
191         } else if (name == null && value != null) {
192             if (GenericObject.isMySubclass(value.getClass())) {
193                 GenericObject gv = (GenericObject) value;
194                 gv.encode(buffer);
195                 return buffer;
196             } else if (GenericObjectList.isMySubclass(value.getClass())) {
197                 GenericObjectList gvlist = (GenericObjectList) value;
198                 buffer.append(gvlist.encode());
199                 return buffer;
200             } else {
201                 buffer.append(quotes).append(value.toString()).append(quotes);
202                 return buffer;
203             }
204         } else if (name != null && (value == null || isFlagParameter)) {
205             buffer.append(name);
206             return buffer;
207         } else {
208             return buffer;
209         }
210     }
211 
clone()212     public Object clone() {
213         NameValue retval = (NameValue) super.clone();
214         if (value != null)
215             retval.value = makeClone(value);
216         return retval;
217     }
218 
219     /**
220      * Equality comparison predicate.
221      */
equals(Object other)222     public boolean equals(Object other) {
223         if (other == null ) return false;
224         if (!other.getClass().equals(this.getClass()))
225             return false;
226         NameValue that = (NameValue) other;
227         if (this == that)
228             return true;
229         if (this.name == null && that.name != null || this.name != null
230                 && that.name == null)
231             return false;
232         if (this.name != null && that.name != null
233                 && this.name.compareToIgnoreCase(that.name) != 0)
234             return false;
235         if (this.value != null && that.value == null || this.value == null
236                 && that.value != null)
237             return false;
238         if (this.value == that.value)
239             return true;
240         if (value instanceof String) {
241             // Quoted string comparisions are case sensitive.
242             if (isQuotedString)
243                 return this.value.equals(that.value);
244             String val = (String) this.value;
245             String val1 = (String) that.value;
246             return val.compareToIgnoreCase(val1) == 0;
247         } else
248             return this.value.equals(that.value);
249     }
250 
251     /*
252      * (non-Javadoc)
253      * @see java.util.Map$Entry#getKey()
254      */
getKey()255     public String getKey() {
256 
257         return this.name;
258     }
259 
260     /*
261      * (non-Javadoc)
262      * @see java.util.Map$Entry#getValue()
263      */
getValue()264     public String getValue() {
265 
266         return  value == null ? null : this.value.toString();
267     }
268 
269     /*
270      * (non-Javadoc)
271      * @see java.util.Map$Entry#setValue(java.lang.Object)
272      */
setValue(String value)273     public String setValue(String value) {
274         String retval = this.value == null ? null : value;
275         this.value = value;
276         return retval;
277 
278     }
279 
280     @Override
hashCode()281     public int hashCode() {
282         return this.encode().toLowerCase().hashCode();
283     }
284 
285 }
286