function Version(major, minor, micro, qualifier) {
	if (!Version._isInteger(major) || major < 0)
		throw "invalid major:" + major;

	if (!Version._isInteger(minor) || minor < 0)
		throw "invalid minor:" + minor;

	if (!Version._isInteger(micro) || micro < 0)
		throw "invalid micro:" + micro;

	if (qualifier === null || qualifier === undefined)
		qualifier = "";
	else if (typeof qualifier !== "string" || !qualifier.match(/[\w\-]*/))
		throw "invalid qualifier: " + qualifier;

	this._major = (major > Version.MAX_VALUE) ? Version.MAX_VALUE : major;
	this._minor = (minor > Version.MAX_VALUE) ? Version.MAX_VALUE : minor;
	this._micro = (micro > Version.MAX_VALUE) ? Version.MAX_VALUE : micro;

	if (this._major == Version.MAX_VALUE && this._minor == Version.MAX_VALUE && this._micro == Version.MAX_VALUE)
		this._qualifier = "";
	else
		this._qualifier = qualifier;
};

Version.prototype = {
	getMajor : function() {
		return this._major;
	},
	getMinor : function() {
		return this._minor;
	},
	getMicro : function() {
		return this._micro;
	},
	getQualifier : function() {
		return this._qualifier;
	},
	toString : function() {
		var result = "" + this._major + "." + this._minor + "." + this._micro;
		if (this._qualifier.length > 0)
			result += "." + this._qualifier;
		return result;
	},
	equals : function(other) {
		return other instanceof Version && this._major === other._major && this._minor === other._minor && this._micro === other._micro && this._qualifier === other._qualifier;
	},
	compareTo : function(other) {
		if (this === other)
			return 0;

		var result = this._major - other._major;
		if (result !== 0)
			return result;

		result = this._minor - other._minor;
		if (result !== 0)
			return result;

		result = this._micro - other._micro;
		if (result !== 0)
			return result;

		if (this._qualifier === other._qualifier)
			return 0;

		return this._qualifier > other._qualifier ? 1 : -1;
	}
};
Version._isInteger = function(number) {
	return (typeof number == "number" && !isNaN(number) && isFinite(number) && Math.floor(number) == number);
};
Version.MAX_VALUE = Math.pow(2, 32);
Version.EMPTY_VERSION = new Version(0, 0, 0);
Version.MAX_VERSION = new Version(Version.MAX_VALUE, Version.MAX_VALUE, Version.MAX_VALUE);
Version.parseVersion = function(text) {
	if (text === null || text === undefined)
		return Version.EMPTY_VERSION;

	if (typeof text !== "string")
		throw "invalid text:" + text;

	text = text.replace(/^\s+|\s+$/g, '');
	if (text.length === 0 || text === "0.0.0")
		return Version.EMPTY_VERSION;

	var tokens = text.split(".");
	if (tokens.length > 4)
		throw "invalid format: " + text;

	if (!tokens[0].match(/[\d]+/))
		throw "invalid format: " + text;

	var major = parseInt(tokens[0]);
	var minor = 0;
	var micro = 0;
	var qualifier = "";

	if (tokens.length > 1) {
		if (!tokens[1].match(/[\d]+/))
			throw "invalid format: " + text;
		minor = parseInt(tokens[1]);

		if (tokens.length > 2) {
			if (!tokens[2].match(/[\d]+/))
				throw "invalid format: " + text;
			micro = parseInt(tokens[2]);

			if (tokens.length > 3)
				qualifier = tokens[3];
		}
	}
	return new Version(major, minor, micro, qualifier);
};
