/*
* Conditions Of Use
*
* This software was developed by employees of the National Institute of
* Standards and Technology (NIST), an agency of the Federal Government.
* Pursuant to title 15 Untied States Code Section 105, works of NIST
* employees are not subject to copyright protection in the United States
* and are considered to be in the public domain. As a result, a formal
* license is not needed to use the software.
*
* This software is provided by NIST as a service and is expressly
* provided "AS IS." NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT
* AND DATA ACCURACY. NIST does not warrant or make any representations
* regarding the use of the software or the results thereof, including but
* not limited to the correctness, accuracy, reliability or usefulness of
* the software.
*
* Permission to use this software is contingent upon your acceptance
* of the terms of this agreement
*
* .
*
*/
/*******************************************************************************
* Product of NIST/ITL Advanced Networking Technologies Division (ANTD). *
*******************************************************************************/
package gov.nist.core;
import java.util.Map.Entry;
/*
* Bug reports and fixes: Kirby Kiem, Jeroen van Bemmel.
*/
/**
* Generic structure for storing name-value pairs.
*
* @version 1.2
*
* @author M. Ranganathan <br/>
*
*
*
*/
public class NameValue extends GenericObject implements Entry<String,String> {
private static final long serialVersionUID = -1857729012596437950L;
protected boolean isQuotedString;
protected final boolean isFlagParameter;
private String separator;
private String quotes;
private String name;
private Object value;
public NameValue() {
name = null;
value = "";
separator = Separators.EQUALS;
this.quotes = "";
this.isFlagParameter = false;
}
/**
* New constructor, taking a boolean which is set if the NV pair is a flag
*
* @param n
* @param v
* @param isFlag
*/
public NameValue(String n, Object v, boolean isFlag) {
// assert (v != null ); // I dont think this assertion is correct mranga
name = n;
value = v;
separator = Separators.EQUALS;
quotes = "";
this.isFlagParameter = isFlag;
}
/**
* Original constructor, sets isFlagParameter to 'false'
*
* @param n
* @param v
*/
public NameValue(String n, Object v) {
this(n, v, false);
}
/**
* Set the separator for the encoding method below.
*/
public void setSeparator(String sep) {
separator = sep;
}
/**
* A flag that indicates that doublequotes should be put around the value
* when encoded (for example name=value when value is doublequoted).
*/
public void setQuotedValue() {
isQuotedString = true;
this.quotes = Separators.DOUBLE_QUOTE;
}
/**
* Return true if the value is quoted in doublequotes.
*/
public boolean isValueQuoted() {
return isQuotedString;
}
public String getName() {
return name;
}
public Object getValueAsObject() {
return isFlagParameter ? "" : value; // never return null for flag
// params
}
/**
* Set the name member
*/
public void setName(String n) {
name = n;
}
/**
* Set the value member
*/
public void setValueAsObject(Object v) {
value = v;
}
/**
* Get the encoded representation of this namevalue object. Added
* doublequote for encoding doublequoted values.
*
* Bug: RFC3261 stipulates that an opaque parameter in authenticate header
* has to be:
* opaque = "opaque" EQUAL quoted-string
* so returning just the name is not acceptable. (e.g. LinkSys phones
* are picky about this)
*
* @since 1.0
* @return an encoded name value (eg. name=value) string.
*/
public String encode() {
return encode(new StringBuffer()).toString();
}
public StringBuffer encode(StringBuffer buffer) {
if (name != null && value != null && !isFlagParameter) {
if (GenericObject.isMySubclass(value.getClass())) {
GenericObject gv = (GenericObject) value;
buffer.append(name).append(separator).append(quotes);
gv.encode(buffer);
buffer.append(quotes);
return buffer;
} else if (GenericObjectList.isMySubclass(value.getClass())) {
GenericObjectList gvlist = (GenericObjectList) value;
buffer.append(name).append(separator).append(gvlist.encode());
return buffer;
} else if ( value.toString().length() == 0) {
// opaque="" bug fix - pmusgrave
/*if (name.toString().equals(gov.nist.javax.sip.header.ParameterNames.OPAQUE))
return name + separator + quotes + quotes;
else
return name;*/
if ( this.isQuotedString ) {
buffer.append(name).append(separator).append(quotes).append(quotes);
return buffer;
} else {
buffer.append(name).append(separator); // JvB: fix, case: "sip:host?subject="
return buffer;
}
} else {
buffer.append(name).append(separator).append(quotes).append(value.toString()).append(quotes);
return buffer;
}
} else if (name == null && value != null) {
if (GenericObject.isMySubclass(value.getClass())) {
GenericObject gv = (GenericObject) value;
gv.encode(buffer);
return buffer;
} else if (GenericObjectList.isMySubclass(value.getClass())) {
GenericObjectList gvlist = (GenericObjectList) value;
buffer.append(gvlist.encode());
return buffer;
} else {
buffer.append(quotes).append(value.toString()).append(quotes);
return buffer;
}
} else if (name != null && (value == null || isFlagParameter)) {
buffer.append(name);
return buffer;
} else {
return buffer;
}
}
public Object clone() {
NameValue retval = (NameValue) super.clone();
if (value != null)
retval.value = makeClone(value);
return retval;
}
/**
* Equality comparison predicate.
*/
public boolean equals(Object other) {
if (other == null ) return false;
if (!other.getClass().equals(this.getClass()))
return false;
NameValue that = (NameValue) other;
if (this == that)
return true;
if (this.name == null && that.name != null || this.name != null
&& that.name == null)
return false;
if (this.name != null && that.name != null
&& this.name.compareToIgnoreCase(that.name) != 0)
return false;
if (this.value != null && that.value == null || this.value == null
&& that.value != null)
return false;
if (this.value == that.value)
return true;
if (value instanceof String) {
// Quoted string comparisions are case sensitive.
if (isQuotedString)
return this.value.equals(that.value);
String val = (String) this.value;
String val1 = (String) that.value;
return val.compareToIgnoreCase(val1) == 0;
} else
return this.value.equals(that.value);
}
/*
* (non-Javadoc)
* @see java.util.Map$Entry#getKey()
*/
public String getKey() {
return this.name;
}
/*
* (non-Javadoc)
* @see java.util.Map$Entry#getValue()
*/
public String getValue() {
return value == null ? null : this.value.toString();
}
/*
* (non-Javadoc)
* @see java.util.Map$Entry#setValue(java.lang.Object)
*/
public String setValue(String value) {
String retval = this.value == null ? null : value;
this.value = value;
return retval;
}
@Override
public int hashCode() {
return this.encode().toLowerCase().hashCode();
}
}