/*******************************************************************************
 * Copyright (c) 2009 Cloudsmith and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     Cloudsmith Inc - initial API and implementation.
 *******************************************************************************/

package org.eclipse.equinox.p2.metadata;

import java.io.Serializable;
import org.eclipse.equinox.internal.p2.metadata.*;

/**
 * A class that represents a Version in the Omni Version format. A Version can be though of as an
 * array of comparable elements and an optional pad value. The pad value is used when comparing
 * two versions with a different number of segments.
 *
 * The Omni Version can convert almost any version into a raw format that it uses for comparisons.
 * This enables a unified order of all such versions and solves problems that arise when the
 * version semantics are different. A good example is the OSGi version versus the version used in Maven.
 * The lack of qualifier in the OSGi version implies that the qualifier is an empty string. So a version
 * without a qualifier is the smallest of all other versions with the same major,minor,micro number.
 * With Maven semantics, it's the opposite. If the qualifier is removed, the resulting version is
 * considered higher then all other versions with the same major, minor, and micro number. The
 * Omni version solves this by using different raw representations of the OSGi and Maven versions.
 *
 * The Omni version addresses a lot of other issues as well, such as reordering of the elements
 * or treating some parts of a version as irrelevant when comparing.
 * 
 * The class is signature compatible with {@link org.osgi.framework.Version} but attempts
 * to use it as such might render a {@link UnsupportedOperationException} in case the
 * raw vector holds incompatible values. The method {@link #isOSGiCompatible()} can be used
 * to test.
 * @since 2.0
 */
public abstract class Version implements Comparable<Version>, Serializable {
	public static final String RAW_PREFIX = "raw:"; //$NON-NLS-1$

	/**
	 * The version that is semantically greater then all other versions.
	 */
	public static final Version MAX_VERSION = OmniVersion.createMaxVersion();

	/**
	 * The version that is semantically less then all other versions.
	 */
	public static final Version emptyVersion = OmniVersion.createMinVersion();

	private static final long serialVersionUID = 6218979149720923857L;

	/**
	 * Compile a version format string into a compiled format..
	 *
	 * @param format The format to compile.
	 * @return The compiled format
	 * @throws VersionFormatException If the format could not be compiled
	 */
	public static IVersionFormat compile(String format) throws VersionFormatException {
		return VersionFormat.compile(format, 0, format.length());
	}

	/**
	 * Parses a version identifier from the specified string.
	 * 
	 * @param version String representation of the version identifier. Leading
	 *        and trailing whitespace will be ignored.
	 * @return A <code>Version</code> object representing the version identifier
	 *         or <code>null</code> if <code>version</code> is <code>null</code> or
	 *         an empty string.
	 * @throws IllegalArgumentException If <code>version</code> is improperly
	 *         formatted.
	 */
	public static Version create(String version) {
		return version == null ? null : VersionParser.parse(version, 0, version.length());
	}

	/**
	 * Creates an OSGi version identifier from the specified numerical components.
	 * 
	 * <p>
	 * The qualifier is set to the empty string.
	 * 
	 * @param major Major component of the version identifier.
	 * @param minor Minor component of the version identifier.
	 * @param micro Micro component of the version identifier.
	 * @throws IllegalArgumentException If the numerical components are
	 *         negative.
	 */
	public static Version createOSGi(int major, int minor, int micro) {
		return createOSGi(major, minor, micro, null);
	}

	/**
	 * Creates an OSGi version identifier from the specified components.
	 * 
	 * @param major Major component of the version identifier.
	 * @param minor Minor component of the version identifier.
	 * @param micro Micro component of the version identifier.
	 * @param qualifier Qualifier component of the version identifier. If
	 *        <code>null</code> is specified, then the qualifier will be set to
	 *        the empty string.
	 * @throws IllegalArgumentException If the numerical components are negative
	 *         or the qualifier string is invalid.
	 */
	public static Version createOSGi(int major, int minor, int micro, String qualifier) {
		Comparable<?> logicQualifier;
		if (qualifier == null || qualifier.length() == 0) {
			if (major == 0 && minor == 0 && micro == 0)
				return emptyVersion;
			logicQualifier = VersionVector.MINS_VALUE; // So that we can do identity compare
		} else if (qualifier.equals(IVersionFormat.DEFAULT_MAX_STRING_TRANSLATION))
			logicQualifier = VersionVector.MAXS_VALUE;
		else
			logicQualifier = qualifier;
		return new OSGiVersion(major, minor, micro, logicQualifier);
	}

	/**
	 * Create an omni version from an OSGi <code>version</code>.
	 * @param version The OSGi version. Can be <code>null</code>.
	 * @return The created omni version
	 */
	public static Version fromOSGiVersion(org.osgi.framework.Version version) {
		if (version == null)
			return null;
		if (version.getMajor() == Integer.MAX_VALUE && version.getMicro() == Integer.MAX_VALUE && version.getMicro() == Integer.MAX_VALUE)
			return MAX_VERSION;
		return createOSGi(version.getMajor(), version.getMinor(), version.getMicro(), version.getQualifier());
	}

	/**
	 * Parses a version identifier from the specified string. This method is for backward
	 * compatibility with OSGi and will return the OSGi &quot;0.0.0&quot; version when
	 * the provided string is empty or <code>null</code>.
	 * 
	 * @param version String representation of the version identifier. Leading
	 *        and trailing whitespace will be ignored.
	 * @return A <code>Version</code> object representing the version
	 *         identifier. If <code>version</code> is <code>null</code> or
	 *         the empty string then the OSGi <code>emptyVersion</code> will be
	 *         returned.
	 * @throws IllegalArgumentException If <code>version</code> is improperly
	 *         formatted.
	 * @see #create(String)
	 */
	public static Version parseVersion(String version) {
		if (version == null || version.length() == 0)
			return Version.emptyVersion;
		Version v = create(version);
		return v == null ? Version.emptyVersion : v;
	}

	/**
	 * Convert <code>version</code> into its OSGi equivalent if possible.
	 *
	 * @param version The version to convert. Can be <code>null</code>
	 * @return The converted version or <code>null</code> if the argument was <code>null</code>
	 * @throws UnsupportedOperationException if the version could not be converted into an OSGi version
	 */
	public static org.osgi.framework.Version toOSGiVersion(Version version) {
		if (version == null)
			return null;
		if (version == emptyVersion)
			return org.osgi.framework.Version.emptyVersion;
		if (version == MAX_VERSION)
			return new org.osgi.framework.Version(Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE);

		BasicVersion bv = (BasicVersion) version;
		return new org.osgi.framework.Version(bv.getMajor(), bv.getMinor(), bv.getMicro(), bv.getQualifier());
	}

	/**
	 * Returns the optional format.
	 */
	public abstract IVersionFormat getFormat();

	/**
	 * Returns the <code>original</code> part of the string for this version
	 * or <code>null</code> if no such part was provided when the version was
	 * created. An OSGi type version will always return the OSGi string representation.
	 *
	 * @return The <code>original</code> part of the version string or
	 * <code>null</code> if that part was missing.
	 */
	public abstract String getOriginal();

	/**
	 * Returns the pad value used when comparing this versions to
	 * versions that has a larger number of segments
	 * @return The pad value or <code>null</code> if not set.
	 */
	public abstract Comparable<?> getPad();

	/**
	 * An element from the raw vector representation of this version.
	 * @param index The zero based index of the desired element
	 * @return An element from the raw vector
	 */
	public abstract Comparable<?> getSegment(int index);

	/**
	 * Returns the number of elements in the raw vector representation of this version.
	 * @return The number of elements in the raw vector.
	 */
	public abstract int getSegmentCount();

	/**
	 * Checks if this version is in compliance with the OSGi version spec.
	 * @return A flag indicating whether the version is OSGi compatible or not.
	 */
	public abstract boolean isOSGiCompatible();

	public String toString() {
		StringBuffer buf = new StringBuffer(20);
		toString(buf);
		return buf.toString();
	}

	/**
	 * Appends the string representation of this version onto the
	 * <code>sb</code> StringBuffer.
	 * @param sb The buffer that will receive the version string
	 */
	public abstract void toString(StringBuffer sb);
}
