All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.conqat.lib.commons.version.Version Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) CQSE GmbH
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.conqat.lib.commons.version;

import java.io.Serializable;
import java.util.Comparator;
import java.util.Objects;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.conqat.lib.commons.error.FormatException;
import org.conqat.lib.commons.test.IndexValueClass;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;

/**
 * A class to describe versions of software (or other) artifacts. A version has a major and a minor
 * version number. Version are ordered. This class is immutable.
 */
@IndexValueClass
public final class Version implements Comparable, Serializable {

	/** The name of the JSON property name for {@link #major}. */
	private static final String MAJOR_PROPERTY = "major";

	/** The name of the JSON property name for {@link #minor}. */
	private static final String MINOR_PROPERTY = "minor";

	/** The name of the JSON property name for {@link #patch}. */
	private static final String PATCH_PROPERTY = "patch";

	/** Version used for serialization. */
	private static final long serialVersionUID = 1;

	/** Major version. */
	@JsonProperty(MAJOR_PROPERTY)
	private final int major;

	/** Minor version. */
	@JsonProperty(MINOR_PROPERTY)
	private final int minor;

	/** Patch level. */
	@JsonProperty(PATCH_PROPERTY)
	private final int patch;

	/**
	 * Create a new version.
	 * 
	 * @param major
	 *            major version number.
	 * @param minor
	 *            minor version number.
	 * @throws IllegalArgumentException
	 *             if one of the version numbers is less than 0.
	 */
	public Version(int major, int minor) {
		this(major, minor, 0);
	}

	/**
	 * Create a new version.
	 *
	 * @param major
	 *            major version number.
	 * @param minor
	 *            minor version number.
	 * @param patch
	 *            patch version number.
	 * @throws IllegalArgumentException
	 *             if one of the version numbers is less than 0.
	 */
	@JsonCreator
	public Version(@JsonProperty(MAJOR_PROPERTY) int major, @JsonProperty(MINOR_PROPERTY) int minor,
			@JsonProperty(PATCH_PROPERTY) int patch) {
		if (major < 0 || minor < 0 || patch < 0) {
			throw new IllegalArgumentException("Versions may not be less than 0.");
		}

		this.major = major;
		this.minor = minor;
		this.patch = patch;
	}

	/**
	 * Parses a version from a string. The format has to be "major.minor.patch", while patch is
	 * optional.
	 * 
	 * @throws FormatException
	 *             if the string does not follow the expected pattern.
	 */
	public static Version parseVersion(String s) throws FormatException {
		Matcher m = Pattern.compile("\\s*(\\d+)\\.(\\d+)(?:\\.(\\d+))?\\s*").matcher(s);
		if (!m.matches()) {
			throw new FormatException("The provided string did not match the pattern!");
		}

		int major = Integer.parseInt(m.group(1));
		int minor = Integer.parseInt(m.group(2));
		int patch = Optional.ofNullable(m.group(3)).map(Integer::parseInt).orElse(0);
		return new Version(major, minor, patch);
	}

	/**
	 * Compares to version numbers by their major and minor numbers.
	 */
	@Override
	public int compareTo(Version other) {
		return Comparator.comparingInt(Version::getMajor).thenComparingInt(Version::getMinor)
				.thenComparingInt(Version::getPatch).compare(this, other);
	}

	/**
	 * Two version are equal if their major and minor version numbers are equal.
	 */
	@Override
	public boolean equals(Object other) {
		if (other == this) {
			return true;
		}

		if (!(other instanceof Version)) {
			return false;
		}

		return compareTo((Version) other) == 0;
	}

	/** Get major version number. */
	public int getMajor() {
		return major;
	}

	/** Get minor version number. */
	public int getMinor() {
		return minor;
	}

	/** Get patch version number. */
	public int getPatch() {
		return patch;
	}

	@Override
	public int hashCode() {
		return Objects.hash(major, minor, patch);
	}

	/**
	 * This method is used to check version compatibility in dependency management.
	 * 

* Consider the following situation and artifact A (the depender) depends on another artifact B (the * dependee). A claims that it requires B in version 1.3. B states that it has version 1.5 but is * downward compatible to version 1.1. *

* Using this method one can find out if the version provided by B satisfies A's requirement. It is * satisfied iff * *

	 * requiredVersion <= currentVersion && requiredVersion >= compatibleVersion
	 * 
* * where requiredVersion is this instance and the other two are provided as method * parameters. * * @throws IllegalArgumentException * if compatibleVersion is greater than currentVersion. */ public boolean isSatisfied(Version currentVersion, Version compatibleVersion) { if (compatibleVersion.compareTo(currentVersion) > 0) { throw new IllegalArgumentException("Compatible version greater than current version."); } return compareTo(currentVersion) <= 0 && compareTo(compatibleVersion) >= 0; } /** * Returns whether this version is greater or equal to the given other version */ public boolean isGreaterOrEqual(Version other) { return compareTo(other) >= 0; } /** * String representation: major.minor */ @Override public String toString() { String result = major + "." + minor; if (patch > 0) { result += "." + patch; } return result; } /** * Returns the full string representation: major.minor.patch *

* Note that the difference to {@link #toString()} is that {@code patch} is always included even if * it is {@code 0}. */ public String toFullString() { return major + "." + minor + "." + patch; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy