diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/version/Version.java b/initializr-generator/src/main/java/io/spring/initializr/generator/version/Version.java
index 0a1c47e4..78bc4b57 100644
--- a/initializr-generator/src/main/java/io/spring/initializr/generator/version/Version.java
+++ b/initializr-generator/src/main/java/io/spring/initializr/generator/version/Version.java
@@ -23,19 +23,25 @@ import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.StringJoiner;
+import java.util.function.Function;
+import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
- * Define the version number of a module. A typical version is represented as
- * {@code MAJOR.MINOR.PATCH.QUALIFIER} where the qualifier can have an extra version.
+ * Define a version. A typical version is represented as
+ * {@code MAJOR.MINOR.PATCH[QUALIFIER]} where the qualifier is optional and can have an
+ * extra version.
*
* For example: {@code 1.2.0.RC1} is the first release candidate of 1.2.0 and
- * {@code 1.5.0.M4} is the fourth milestone of 1.5.0. The special {@code RELEASE}
- * qualifier indicates a final release (a.k.a. GA)
+ * {@code 1.5.0-M4} is the fourth milestone of 1.5.0. The special {@code RELEASE}
+ * qualifier indicates a final release (a.k.a. GA).
*
- * The main purpose of parsing a version is to compare it with another version, see
- * {@link Comparable}.
+ * Two formats are currently supported, {@link Format#V1} that uses a dot to separate the
+ * qualifier from the version itself and {@link Format#V2} that is SemVer compliant (and
+ * therefore uses a dash to separate the qualifier).
+ *
+ * The main purpose of parsing a version is to compare it with another version.
*
* @author Stephane Nicoll
*/
@@ -54,11 +60,68 @@ public final class Version implements Serializable, Comparable {
private final Qualifier qualifier;
+ private final Format format;
+
public Version(Integer major, Integer minor, Integer patch, Qualifier qualifier) {
this.major = major;
this.minor = minor;
this.patch = patch;
this.qualifier = qualifier;
+ this.format = determineFormat(qualifier);
+ }
+
+ private static Format determineFormat(Qualifier qualifier) {
+ if (qualifier == null) {
+ return Format.V2;
+ }
+ return (qualifier.getSeparator().equals(".")) ? Format.V1 : Format.V2;
+ }
+
+ /**
+ * Format this version to the specified {@link Format}.
+ * @param format the format to use
+ * @return a version compliant with the specified format.
+ */
+ public Version format(Format format) {
+ Assert.notNull(format, () -> "Format must not be null");
+ if (this.format == format) {
+ return this;
+ }
+ if (format == Format.V1) {
+ Qualifier qualifier = formatQualifier(".", this::toV1Qualifier);
+ return new Version(this.major, this.minor, this.patch, qualifier);
+ }
+ Qualifier qualifier = formatQualifier("-", this::toV2Qualifier);
+ return new Version(this.major, this.minor, this.patch, qualifier);
+ }
+
+ private Qualifier formatQualifier(String newSeparator, Function idTransformer) {
+ String originalQualifier = (this.qualifier != null) ? this.qualifier.getId() : null;
+ String newId = idTransformer.apply(originalQualifier);
+ if (newId != null) {
+ return new Qualifier(newId, (this.qualifier != null) ? this.qualifier.getVersion() : null, newSeparator);
+ }
+ return null;
+ }
+
+ private String toV1Qualifier(String id) {
+ if ("SNAPSHOT".equals(id)) {
+ return "BUILD-SNAPSHOT";
+ }
+ if (id == null) {
+ return "RELEASE";
+ }
+ return id;
+ }
+
+ private String toV2Qualifier(String id) {
+ if ("BUILD-SNAPSHOT".equals(id)) {
+ return "SNAPSHOT";
+ }
+ if ("RELEASE".equals(id)) {
+ return null;
+ }
+ return id;
}
public Integer getMajor() {
@@ -77,6 +140,10 @@ public final class Version implements Serializable, Comparable {
return this.qualifier;
}
+ public Format getFormat() {
+ return this.format;
+ }
+
/**
* Parse the string representation of a {@link Version}. Throws an
* {@link InvalidVersionException} if the version could not be parsed.
@@ -262,6 +329,26 @@ public final class Version implements Serializable, Comparable {
}
+ /**
+ * Define the supported version format.
+ */
+ public enum Format {
+
+ /**
+ * Original version format, i.e. {@code Major.Minor.Patch.Qualifier} using
+ * {@code BUILD-SNAPSHOT} as the qualifier for snapshots and {@code RELEASE} for
+ * GAs.
+ */
+ V1,
+
+ /**
+ * SemVer-compliant format, i.e. {@code Major.Minor.Patch-Qualifier} using
+ * {@code SNAPSHOT} as the qualifier for snapshots and no qualifier for GAs.
+ */
+ V2;
+
+ }
+
private static class VersionQualifierComparator implements Comparator {
static final String RELEASE = "RELEASE";
diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/version/VersionRange.java b/initializr-generator/src/main/java/io/spring/initializr/generator/version/VersionRange.java
index 8b1d11fa..506a475f 100644
--- a/initializr-generator/src/main/java/io/spring/initializr/generator/version/VersionRange.java
+++ b/initializr-generator/src/main/java/io/spring/initializr/generator/version/VersionRange.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2019 the original author or authors.
+ * Copyright 2012-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,6 +16,8 @@
package io.spring.initializr.generator.version;
+import io.spring.initializr.generator.version.Version.Format;
+
import org.springframework.util.Assert;
/**
@@ -27,9 +29,8 @@ import org.springframework.util.Assert;
*
* - "[1.2.0.RELEASE,1.3.0.RELEASE)" version 1.2.0 and any version after this, up to,
* but not including, version 1.3.0.
- * - "(2.0.0.RELEASE,3.2.0.RELEASE]" any version after 2.0.0 up to and including version
- * 3.2.0.
- * - "1.4.5.RELEASE", version 1.4.5 and all later versions.
+ * - "(2.0.0,3.2.0]" any version after 2.0.0 up to and including version 3.2.0.
+ * - "2.5.0-M1", the first milestone of 2.5.0 and any version after that.
*
*
* @author Stephane Nicoll
@@ -83,6 +84,17 @@ public class VersionRange {
return true;
}
+ /**
+ * Format this version range to the specified {@link Format}.
+ * @param format the version format to use
+ * @return a version range whose boundaries are compliant with the specified format.
+ */
+ public VersionRange format(Format format) {
+ Version lower = this.lowerVersion.format(format);
+ Version higher = (this.higherVersion != null) ? this.higherVersion.format(format) : null;
+ return new VersionRange(lower, this.lowerInclusive, higher, this.higherInclusive);
+ }
+
public Version getLowerVersion() {
return this.lowerVersion;
}
diff --git a/initializr-generator/src/test/java/io/spring/initializr/generator/version/VersionRangeTests.java b/initializr-generator/src/test/java/io/spring/initializr/generator/version/VersionRangeTests.java
index 1d68de48..ccb06861 100755
--- a/initializr-generator/src/test/java/io/spring/initializr/generator/version/VersionRangeTests.java
+++ b/initializr-generator/src/test/java/io/spring/initializr/generator/version/VersionRangeTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2019 the original author or authors.
+ * Copyright 2012-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,12 +19,15 @@ package io.spring.initializr.generator.version;
import java.util.Arrays;
import java.util.Collections;
+import io.spring.initializr.generator.version.Version.Format;
import org.assertj.core.api.Condition;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
/**
+ * Tests for {@link VersionRange}.
+ *
* @author Stephane Nicoll
*/
class VersionRangeTests {
@@ -148,6 +151,34 @@ class VersionRangeTests {
assertThat(range.toRangeString()).isEqualTo("(1.3.5.RELEASE,1.5.5.RELEASE)");
}
+ @Test
+ void formatLowerOnlyV1toV2() {
+ VersionRange range = parse("1.2.0.RELEASE").format(Format.V2);
+ assertThat(range.toRangeString()).isEqualTo("1.2.0");
+ }
+
+ @Test
+ void formatV1toV2() {
+ VersionRange range = parse("[1.2.0.RELEASE,1.3.0.M1)").format(Format.V2);
+ assertThat(range.toRangeString()).isEqualTo("[1.2.0,1.3.0-M1)");
+ }
+
+ @Test
+ void formatLowerOnlyV2toV1() {
+ VersionRange range = parse("1.2.0").format(Format.V1);
+ assertThat(range.toRangeString()).isEqualTo("1.2.0.RELEASE");
+ }
+
+ @Test
+ void formatV2toV1() {
+ VersionRange range = parse("[1.2.0,1.3.0-M1)").format(Format.V1);
+ assertThat(range.toRangeString()).isEqualTo("[1.2.0.RELEASE,1.3.0.M1)");
+ }
+
+ private static VersionRange parse(String text) {
+ return new VersionParser(Collections.emptyList()).parseRange(text);
+ }
+
private static Condition match(String range) {
return match(range, new VersionParser(Collections.emptyList()));
}
diff --git a/initializr-generator/src/test/java/io/spring/initializr/generator/version/VersionTests.java b/initializr-generator/src/test/java/io/spring/initializr/generator/version/VersionTests.java
index 4aef3f48..9366482f 100755
--- a/initializr-generator/src/test/java/io/spring/initializr/generator/version/VersionTests.java
+++ b/initializr-generator/src/test/java/io/spring/initializr/generator/version/VersionTests.java
@@ -21,11 +21,14 @@ import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
+import io.spring.initializr.generator.version.Version.Format;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
/**
+ * Tests for {@link Version}.
+ *
* @author Stephane Nicoll
*/
class VersionTests {
@@ -153,6 +156,54 @@ class VersionTests {
"2020.0.0-SNAPSHOT", "2020.0.0");
}
+ @Test
+ void formatV1toV1() {
+ Version version = Version.parse("1.2.0.RELEASE");
+ assertThat(version.format(Format.V1)).isSameAs(version);
+ }
+
+ @Test
+ void formatV1SnapshotToV2() {
+ Version version = Version.parse("1.2.0.BUILD-SNAPSHOT");
+ assertThat(version.format(Format.V2)).hasToString("1.2.0-SNAPSHOT");
+ }
+
+ @Test
+ void formatV1GAToV2() {
+ Version version = Version.parse("1.2.0.RELEASE");
+ assertThat(version.format(Format.V2)).hasToString("1.2.0");
+ }
+
+ @Test
+ void formatNoQualifierToV1() {
+ Version version = Version.parse("1.2.0");
+ assertThat(version.format(Format.V1)).hasToString("1.2.0.RELEASE");
+ }
+
+ @Test
+ void formatV2toV2() {
+ Version version = Version.parse("1.2.0-RC1");
+ assertThat(version.format(Format.V2)).isSameAs(version);
+ }
+
+ @Test
+ void formatV2SnapshotToV1() {
+ Version version = Version.parse("1.2.0-SNAPSHOT");
+ assertThat(version.format(Format.V1)).hasToString("1.2.0.BUILD-SNAPSHOT");
+ }
+
+ @Test
+ void formatV2GAToV1() {
+ Version version = Version.parse("1.2.0");
+ assertThat(version.format(Format.V1)).hasToString("1.2.0.RELEASE");
+ }
+
+ @Test
+ void formatNoQualifierToV2() {
+ Version version = Version.parse("1.2.0");
+ assertThat(version.format(Format.V2)).hasToString("1.2.0");
+ }
+
private Version parse(String text) {
return this.parser.parse(text);
}