1d9038ba8SKryštof Tulinger /* 2d9038ba8SKryštof Tulinger * CDDL HEADER START 3d9038ba8SKryštof Tulinger * 4d9038ba8SKryštof Tulinger * The contents of this file are subject to the terms of the 5d9038ba8SKryštof Tulinger * Common Development and Distribution License (the "License"). 6d9038ba8SKryštof Tulinger * You may not use this file except in compliance with the License. 7d9038ba8SKryštof Tulinger * 8d9038ba8SKryštof Tulinger * See LICENSE.txt included in this distribution for the specific 9d9038ba8SKryštof Tulinger * language governing permissions and limitations under the License. 10d9038ba8SKryštof Tulinger * 11d9038ba8SKryštof Tulinger * When distributing Covered Code, include this CDDL HEADER in each 12d9038ba8SKryštof Tulinger * file and include the License file at LICENSE.txt. 13d9038ba8SKryštof Tulinger * If applicable, add the following below this CDDL HEADER, with the 14d9038ba8SKryštof Tulinger * fields enclosed by brackets "[]" replaced with your own identifying 15d9038ba8SKryštof Tulinger * information: Portions Copyright [yyyy] [name of copyright owner] 16d9038ba8SKryštof Tulinger * 17d9038ba8SKryštof Tulinger * CDDL HEADER END 18d9038ba8SKryštof Tulinger */ 19d9038ba8SKryštof Tulinger 20d9038ba8SKryštof Tulinger /* 21*5d9f3aa0SAdam Hornáček * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. 22d9038ba8SKryštof Tulinger * Portions Copyright (c) 2019, Krystof Tulinger (tulinkry). 23d9038ba8SKryštof Tulinger */ 24d9038ba8SKryštof Tulinger package org.opengrok.indexer.util; 25d9038ba8SKryštof Tulinger 26d9038ba8SKryštof Tulinger import java.util.Arrays; 27d9038ba8SKryštof Tulinger import java.util.stream.Stream; 28d9038ba8SKryštof Tulinger 29d9038ba8SKryštof Tulinger /** 30d9038ba8SKryštof Tulinger * This class implements portions of semantic versioning from version noted as 31d9038ba8SKryštof Tulinger * <pre> 32d9038ba8SKryštof Tulinger * a.b.c.d.e.f 33d9038ba8SKryštof Tulinger * </pre> 34d9038ba8SKryštof Tulinger * where 35d9038ba8SKryštof Tulinger * <pre> 36d9038ba8SKryštof Tulinger * a - major 37d9038ba8SKryštof Tulinger * b - minor 38d9038ba8SKryštof Tulinger * c - patch 39d9038ba8SKryštof Tulinger * d ... - others 40d9038ba8SKryštof Tulinger * </pre> 41d9038ba8SKryštof Tulinger * 42d9038ba8SKryštof Tulinger * @author Krystof Tulinger (tulinkry) 43d9038ba8SKryštof Tulinger * @see <a href="https://semver.org/">https://semver.org/</a> 44d9038ba8SKryštof Tulinger */ 45d9038ba8SKryštof Tulinger public class Version implements Comparable<Version> { 46d9038ba8SKryštof Tulinger private final Integer[] versions; 47d9038ba8SKryštof Tulinger 48d9038ba8SKryštof Tulinger /** 49d9038ba8SKryštof Tulinger * Construct the version from integer parts. 50d9038ba8SKryštof Tulinger * The order is: 51d9038ba8SKryštof Tulinger * <ol> 52d9038ba8SKryštof Tulinger * <li>major</li> 53d9038ba8SKryštof Tulinger * <li>minor</li> 54d9038ba8SKryštof Tulinger * <li>patch</li> 55d9038ba8SKryštof Tulinger * <li>... others</li> 56d9038ba8SKryštof Tulinger * </ol> 57d9038ba8SKryštof Tulinger * 58d9038ba8SKryštof Tulinger * @param parts integer values for version partials 59d9038ba8SKryštof Tulinger */ Version(Integer... parts)60d9038ba8SKryštof Tulinger public Version(Integer... parts) { 61d9038ba8SKryštof Tulinger // cut off trailing zeros 62d9038ba8SKryštof Tulinger int cutOffLength = parts.length; 63d9038ba8SKryštof Tulinger for (int i = parts.length - 1; i >= 0; i--) { 64d9038ba8SKryštof Tulinger if (parts[i] != 0) { 65d9038ba8SKryštof Tulinger break; 66d9038ba8SKryštof Tulinger } 67d9038ba8SKryštof Tulinger cutOffLength--; 68d9038ba8SKryštof Tulinger } 69d9038ba8SKryštof Tulinger versions = Arrays.copyOf(parts, cutOffLength); 70d9038ba8SKryštof Tulinger } 71d9038ba8SKryštof Tulinger 72d9038ba8SKryštof Tulinger /** 73d9038ba8SKryštof Tulinger * Construct the version from a string. 74d9038ba8SKryštof Tulinger * 75d9038ba8SKryštof Tulinger * @param string string representing the version (e. g. 1.2.1) 76d9038ba8SKryštof Tulinger * @return the new instance of version from the string 77d9038ba8SKryštof Tulinger * @throws NumberFormatException when parts can not be converted to integers 78d9038ba8SKryštof Tulinger */ from(String string)79d9038ba8SKryštof Tulinger public static Version from(String string) throws NumberFormatException { 80d9038ba8SKryštof Tulinger return new Version( 81d9038ba8SKryštof Tulinger Stream.of(string.trim().split("\\.")) 82d9038ba8SKryštof Tulinger .map(String::trim) 83d9038ba8SKryštof Tulinger .map(Integer::parseInt) 84d9038ba8SKryštof Tulinger .toArray(Integer[]::new) 85d9038ba8SKryštof Tulinger ); 86d9038ba8SKryštof Tulinger } 87d9038ba8SKryštof Tulinger 88d9038ba8SKryštof Tulinger @Override equals(Object o)89d9038ba8SKryštof Tulinger public boolean equals(Object o) { 90d9038ba8SKryštof Tulinger if (this == o) { 91d9038ba8SKryštof Tulinger return true; 92d9038ba8SKryštof Tulinger } 93d9038ba8SKryštof Tulinger if (o == null || getClass() != o.getClass()) { 94d9038ba8SKryštof Tulinger return false; 95d9038ba8SKryštof Tulinger } 96d9038ba8SKryštof Tulinger Version version = (Version) o; 97d9038ba8SKryštof Tulinger return Arrays.equals(versions, version.versions); 98d9038ba8SKryštof Tulinger } 99d9038ba8SKryštof Tulinger 100d9038ba8SKryštof Tulinger @Override hashCode()101d9038ba8SKryštof Tulinger public int hashCode() { 102d9038ba8SKryštof Tulinger return Arrays.hashCode(versions); 103d9038ba8SKryštof Tulinger } 104d9038ba8SKryštof Tulinger 105d9038ba8SKryštof Tulinger @Override compareTo(Version o)106d9038ba8SKryštof Tulinger public int compareTo(Version o) { 107d9038ba8SKryštof Tulinger if (o == null) { 108d9038ba8SKryštof Tulinger return 1; 109d9038ba8SKryštof Tulinger } 110d9038ba8SKryštof Tulinger 111d9038ba8SKryštof Tulinger // first different number determines the result 112d9038ba8SKryštof Tulinger for (int i = 0; i < Math.min(versions.length, o.versions.length); i++) { 113d9038ba8SKryštof Tulinger if (!versions[i].equals(o.versions[i])) { 114d9038ba8SKryštof Tulinger return Integer.compare(versions[i], o.versions[i]); 115d9038ba8SKryštof Tulinger } 116d9038ba8SKryštof Tulinger } 117d9038ba8SKryštof Tulinger 118d9038ba8SKryštof Tulinger // the comparable parts are the same, the longer has some trailing non-null element which 119d9038ba8SKryštof Tulinger // makes it greater then the shorter 120d9038ba8SKryštof Tulinger // e. g. 1.0.0.0.1 vs. 1.0.0 121d9038ba8SKryštof Tulinger return Integer.compare(versions.length, o.versions.length); 122d9038ba8SKryštof Tulinger } 123d9038ba8SKryštof Tulinger } 124