Home | History | Annotate | Download | only in core
      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 
     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      */
     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      */
     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      */
    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      */
    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      */
    118     public boolean isValueQuoted() {
    119         return isQuotedString;
    120     }
    121 
    122     public String getName() {
    123         return name;
    124     }
    125 
    126     public Object getValueAsObject() {
    127         return isFlagParameter ? "" : value; // never return null for flag
    128                                                 // params
    129     }
    130 
    131     /**
    132      * Set the name member
    133      */
    134     public void setName(String n) {
    135         name = n;
    136     }
    137 
    138     /**
    139      * Set the value member
    140      */
    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      */
    158     public String encode() {
    159         return encode(new StringBuffer()).toString();
    160     }
    161 
    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 
    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      */
    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      */
    255     public String getKey() {
    256 
    257         return this.name;
    258     }
    259 
    260     /*
    261      * (non-Javadoc)
    262      * @see java.util.Map$Entry#getValue()
    263      */
    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      */
    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
    281     public int hashCode() {
    282         return this.encode().toLowerCase().hashCode();
    283     }
    284 
    285 }
    286