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

org.sonar.api.utils.Version Maven / Gradle / Ivy

The newest version!
/*
 * SonarQube
 * Copyright (C) 2009-2022 SonarSource SA
 * mailto:info AT sonarsource DOT com
 *
 * This program 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 3 of the License, or (at your option) any later version.
 *
 * This program 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.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
package org.sonar.api.utils;

import java.util.regex.Pattern;
import javax.annotation.concurrent.Immutable;

import static java.lang.Integer.parseInt;
import static java.lang.Long.parseLong;
import static java.util.Objects.requireNonNull;
import static org.apache.commons.lang.StringUtils.substringAfter;
import static org.apache.commons.lang.StringUtils.substringBefore;
import static org.apache.commons.lang.StringUtils.trimToEmpty;

/**
 * Version composed of maximum four fields (major, minor, patch and build ID numbers) and optionally a qualifier.
 * 

* Examples: 1.0, 1.0.0, 1.2.3, 1.2-beta1, 1.2.1-beta-1, 1.2.3.4567 *

*

IMPORTANT NOTE

* Qualifier is ignored when comparing objects (methods {@link #equals(Object)}, {@link #hashCode()} * and {@link #compareTo(Version)}). *

*

 *   assertThat(Version.parse("1.2")).isEqualTo(Version.parse("1.2-beta1"));
 *   assertThat(Version.parse("1.2").compareTo(Version.parse("1.2-beta1"))).isZero();
 * 
* * @since 5.5 */ @Immutable public class Version implements Comparable { private static final long DEFAULT_BUILD_NUMBER = 0L; private static final int DEFAULT_PATCH = 0; private static final String DEFAULT_QUALIFIER = ""; private static final String QUALIFIER_SEPARATOR = "-"; private static final String SEQUENCE_SEPARATOR = "."; private final int major; private final int minor; private final int patch; private final long buildNumber; private final String qualifier; private Version(int major, int minor, int patch, long buildNumber, String qualifier) { this.major = major; this.minor = minor; this.patch = patch; this.buildNumber = buildNumber; this.qualifier = requireNonNull(qualifier, "Version qualifier must not be null"); } public int major() { return major; } public int minor() { return minor; } public int patch() { return patch; } /** * Build number if the fourth field, for example {@code 12345} for "6.3.0.12345". * If absent, then value is zero. * * @since 6.3 */ public long buildNumber() { return buildNumber; } /** * @return non-null suffix. Empty if absent, else the suffix without the first character "-" */ public String qualifier() { return qualifier; } /** * Convert a {@link String} to a Version. Supported formats: *
    *
  • 1
  • *
  • 1.2
  • *
  • 1.2.3
  • *
  • 1-beta-1
  • *
  • 1.2-beta-1
  • *
  • 1.2.3-beta-1
  • *
  • 1.2.3.4567
  • *
  • 1.2.3.4567-beta-1
  • *
* Note that the optional qualifier is the part after the first "-". * * @throws IllegalArgumentException if parameter is badly formatted, for example * if it defines 5 integer-sequences. */ public static Version parse(String text) { String s = trimToEmpty(text); String qualifier = substringAfter(s, QUALIFIER_SEPARATOR); if (!qualifier.isEmpty()) { s = substringBefore(s, QUALIFIER_SEPARATOR); } String[] fields = s.split(Pattern.quote(SEQUENCE_SEPARATOR)); int major = 0; int minor = 0; int patch = DEFAULT_PATCH; long buildNumber = DEFAULT_BUILD_NUMBER; int size = fields.length; if (size > 0) { major = parseFieldAsInt(fields[0]); if (size > 1) { minor = parseFieldAsInt(fields[1]); if (size > 2) { patch = parseFieldAsInt(fields[2]); if (size > 3) { buildNumber = parseFieldAsLong(fields[3]); if (size > 4) { throw new IllegalArgumentException("Maximum 4 fields are accepted: " + text); } } } } } return new Version(major, minor, patch, buildNumber, qualifier); } public static Version create(int major, int minor) { return new Version(major, minor, DEFAULT_PATCH, DEFAULT_BUILD_NUMBER, DEFAULT_QUALIFIER); } public static Version create(int major, int minor, int patch) { return new Version(major, minor, patch, DEFAULT_BUILD_NUMBER, DEFAULT_QUALIFIER); } private static int parseFieldAsInt(String field) { if (field.isEmpty()) { return 0; } return parseInt(field); } private static long parseFieldAsLong(String field) { if (field.isEmpty()) { return 0L; } return parseLong(field); } public boolean isGreaterThanOrEqual(Version than) { return this.compareTo(than) >= 0; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } Version version = (Version) o; if (major != version.major) { return false; } if (minor != version.minor) { return false; } if (patch != version.patch) { return false; } return buildNumber == version.buildNumber; } @Override public int hashCode() { int result = major; result = 31 * result + minor; result = 31 * result + patch; result = 31 * result + (int) (buildNumber ^ (buildNumber >>> 32)); return result; } @Override public int compareTo(Version other) { int c = major - other.major; if (c == 0) { c = minor - other.minor; if (c == 0) { c = patch - other.patch; if (c == 0) { long diff = buildNumber - other.buildNumber; c = (diff > 0) ? 1 : ((diff < 0) ? -1 : 0); } } } return c; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append(major).append(SEQUENCE_SEPARATOR).append(minor); if (patch > 0 || buildNumber > 0) { sb.append(SEQUENCE_SEPARATOR).append(patch); if (buildNumber > 0) { sb.append(SEQUENCE_SEPARATOR).append(buildNumber); } } if (!qualifier.isEmpty()) { sb.append(QUALIFIER_SEPARATOR).append(qualifier); } return sb.toString(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy