import java.net.* ;
import java.io.* ; 
import java.util.Vector ;
import java.util.Hashtable ;
import java.util.Properties ;
import java.util.Enumeration ;

public class HttpParameter {
	
	// This ought to be the .toString() method, but at the moment it needs to
	// be able to throw UnsupportedEncodingException, until I decide how better
	// to handle that exception.  Probably need to have setEncoding check for 
	// it, somehow.
	public String getParameterString() throws UnsupportedEncodingException {
		if (this.getParameterNames().size() != this.getParameterValues().size()) {
			throw new RuntimeException("Vector names size " + this.getParameterNames().size() + " and vector values size " + this.getParameterValues().size() + "are not the same.") ;
		}
		Vector v = new Vector(this.getParameterNames().size()) ;
		for (int i=0; i < this.getParameterNames().size(); i++)  {
			v.add(encodeParameter(this.getParameterNames().elementAt(i).toString(), 
								  this.getParameterValues().elementAt(i).toString())) ;
		}
		return concatenateParameters(v) ;
	}

	// Note that using a Hashtable is inherently incomplete, since
	// HTTP parameters are not necessarily a one-for-one matching,
	// they can have a single parameter name with multiple values.
	//
	// Also, although the servlet spec, etc, don't care about the
	// order of parameters, some web applications might, so using
	// the paired Vectors approach lets you specify that.
	//
	// But many situations don't call for multiple parameter values,
	// and a Hashtable is a convenient way of passing in values
	// for those situations.
	public void setParameters(Hashtable parameters) {
		Vector names = new Vector() ;
		Vector values = new Vector() ;
		Enumeration enum = parameters.keys() ;
		String name ;
		String value ;
		while (enum.hasMoreElements()) {
			name = enum.nextElement().toString() ;
			value = parameters.get(name).toString() ;
			names.add(name) ;
			values.add(value) ;
		}
		this.setParameters(names, values) ;
	}

	// Add a single parameter name/value to the existing set 
	public void add(String name, String value) {
		if (null == this.getParameterNames()) {
			this.setParameterNames(new Vector()) ;
		}
		if (null == this.getParameterValues()) {
			this.setParameterValues(new Vector()) ;
		}
		this.getParameterNames().add(name) ;
		this.getParameterValues().add(value) ;
	}
	
	// Set the names and values as a same-length pair of Vectors
	//
	// This really ought to be implemented with a parameter class that
	// holds name and value.
	public void setParameters(Vector names, Vector values) {
		if (names.size() != values.size()) {
			throw new RuntimeException("Vector names size " + names.size() + " and vector values size " + values.size() + "are not the same.") ;
		}
		this.setParameterNames(names) ;
		this.setParameterValues(values) ;
	}

	// Simple instance variables with accessors/mutators
	public Vector parameterNames ;
	public void setParameterNames(Vector parameterNames) {
		this.parameterNames = parameterNames ;
	}
	public Vector getParameterNames() {
		return this.parameterNames ;
	}

	public Vector parameterValues ;
	public void setParameterValues(Vector parameterValues) {
		this.parameterValues = parameterValues ;
	}
	public Vector getParameterValues() {
		return this.parameterValues ;
	}

	// The encodeParameters(String name, String value) method, of
	// course, urlencodes the value and concatenates name and value
	// with a "=" character.
	public String parameterEqualString = "=" ;
	public String defaultEncodingType = "UTF-8" ;
	public String encodeParameter(String name, String value) throws java.io.UnsupportedEncodingException {
		// Given a "name" and "value", return "name=urlencodedvalue"
		StringBuffer parameter = new StringBuffer(name);
		parameter.append(this.parameterEqualString) ;

		parameter.append(URLEncoder.encode(value, this.defaultEncodingType)) ;
		return parameter.toString() ;
	}

	public String parameterSeparatorString = "&" ;
	public String concatenateParameters(Vector parameters) throws java.io.UnsupportedEncodingException {
		// Passed in a vector of "name=value" parameter strings (each
		// built by encodeParameter), concatenate them together with "&"
		// between them and a newline at the end.
		StringBuffer parameterString = new StringBuffer();
		Enumeration enum = parameters.elements() ;
		while (enum.hasMoreElements()) {
			parameterString.append(enum.nextElement().toString()) ;
			if (enum.hasMoreElements()) {
				parameterString.append(this.parameterSeparatorString) ;
			}
			// The books say you need a \n on the end,
			// But it appears that URLConnection escapes this \n and appends a new one.
			// 
			// FIXME:  it's unclear how multiple parameter lines are handled.
			/* else {
			   parameterString.append("\n") ;
			   }
			*/

		}
		return parameterString.toString() ;
	}
}

