/* 
 * E-XML Library:  For XML, XML-RPC, HTTP, and related.
 * Copyright (C) 2002-2008  Elias Ross
 * 
 * genman@noderunner.net
 * http://noderunner.net/~genman
 * 
 * 1025 NE 73RD ST
 * SEATTLE WA 98115
 * USA
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * $Id$
 */

package net.noderunner.http;

import java.util.NoSuchElementException;
import java.util.StringTokenizer;

/**
 * This represents an <code>HTTP-Version</code> data object, as found in RFC
 * 2616. It is immutable.
 */
public class HttpVersion {
	
	private int major;

	private int minor;

	private String toString;
	
	/**
	 * Represents HTTP version 1.1
	 */
	public static final HttpVersion HTTP11 = new HttpVersion(1, 1);

	/**
	 * Represents HTTP version 1.0
	 */
	public static final HttpVersion HTTP10 = new HttpVersion(1, 0);

	/**
	 * The string <code>HTTP/</code>.
	 */
	public static final String HTTP_VERSION_BEGIN = "HTTP/";

	/**
	 * Constructs a <code>HttpVersionImpl</code> out of a parsable String.
	 */
	public HttpVersion(String line) throws HttpException {
		if (line == null)
			throw new IllegalArgumentException("Null HTTP version line");
		if (!line.startsWith(HTTP_VERSION_BEGIN))
			throw new HttpException("HTTP Version prefix invalid: " + line);
		StringTokenizer st = new StringTokenizer(line, "/.");
		try {
			st.nextToken();
			major = Integer.parseInt(st.nextToken());
			minor = Integer.parseInt(st.nextToken());
		} catch (NoSuchElementException e) {
			throw new HttpException("HTTP version invalid syntax");
		} catch (NumberFormatException e) {
			throw new HttpException("HTTP version invalid number");
		}
		this.toString = HTTP_VERSION_BEGIN + getMajorVersion() + '.'
				+ getMinorVersion();
	}

	/**
	 * Based on the string supplied, returns either
	 * <code>HttpVersion.HTTP10</code> or <code>HttpVersion.HTTP11</code> or
	 * a newly constructed <code>HttpVersion</code> instance.
	 */
	public static HttpVersion parseVersion(String version) throws HttpException {
		if (version.equals(HTTP10.toString()))
			return HTTP10;
		if (version.equals(HTTP11.toString()))
			return HTTP11;
		return new HttpVersion(version);
	}

	/**
	 * Constructs a <code>HttpVersionImpl</code> out of version number parts.
	 */
	public HttpVersion(int major, int minor) {
		this.major = major;
		this.minor = minor;
		this.toString = HTTP_VERSION_BEGIN + getMinorVersion() + '.'
				+ getMajorVersion();
	}

	/**
	 * Returns the minor version number in use.
	 */
	public int getMinorVersion() {
		return minor;
	}
	
	/**
	 * Returns the major version number in use.
	 */
	public int getMajorVersion() {
		return major;
	}

	/**
	 * Returns <pre>HTTP_VERSION_BEGIN + getMinorVersion() + '.' + getMajorVersion()</pre>
	 */
	public String toString() {
		return toString;
	}

	/**
	 * Returns true if the other object is an HttpVersion with the same minor
	 * and major versions.
	 */
	public boolean equals(Object other) {
		if (!(other instanceof HttpVersion))
			return false;
		HttpVersion v = (HttpVersion) other;
		return v.getMinorVersion() == getMinorVersion()
				&& v.getMajorVersion() == getMajorVersion();
	}

	/**
	 * Returns the hashcode.
	 */
	public int hashCode() {
		return major * 10 + minor;
	}
}
