Create MetadataVersion.NULL object, refactor

This commit is contained in:
Zafar Khaja 2013-11-04 18:50:01 +04:00
parent 78266dc1ca
commit fac6ece28c
5 changed files with 159 additions and 69 deletions

View File

@ -31,6 +31,47 @@ import java.util.Arrays;
*/ */
class MetadataVersion implements Comparable<MetadataVersion> { class MetadataVersion implements Comparable<MetadataVersion> {
static final MetadataVersion NULL = new NullMetadataVersion();
private static class NullMetadataVersion extends MetadataVersion {
public NullMetadataVersion() {
super(null);
}
@Override
MetadataVersion increment() {
throw new NullPointerException("Metadata version is NULL");
}
@Override
public String toString() {
return "";
}
@Override
public int hashCode() {
return 0;
}
@Override
public boolean equals(Object other) {
return other instanceof NullMetadataVersion;
}
@Override
public int compareTo(MetadataVersion other) {
if (!equals(other)) {
/**
* Pre-release versions have a lower precedence than
* the associated normal version. (SemVer p.9)
*/
return 1;
}
return 0;
}
}
private final String[] idents; private final String[] idents;
MetadataVersion(String[] identifiers) { MetadataVersion(String[] identifiers) {
@ -69,14 +110,21 @@ class MetadataVersion implements Comparable<MetadataVersion> {
@Override @Override
public String toString() { public String toString() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
for (String id : idents) { for (String ident : idents) {
sb.append(id).append("."); sb.append(ident).append(".");
} }
return sb.deleteCharAt(sb.lastIndexOf(".")).toString(); return sb.deleteCharAt(sb.lastIndexOf(".")).toString();
} }
@Override @Override
public int compareTo(MetadataVersion other) { public int compareTo(MetadataVersion other) {
if (other == MetadataVersion.NULL) {
/**
* Pre-release versions have a lower precedence than
* the associated normal version. (SemVer p.9)
*/
return -1;
}
int result = compareIdentifierArrays(other.idents); int result = compareIdentifierArrays(other.idents);
if (result == 0) { if (result == 0) {
result = idents.length - other.idents.length; result = idents.length - other.idents.length;
@ -100,11 +148,11 @@ class MetadataVersion implements Comparable<MetadataVersion> {
return arr1.length <= arr2.length ? arr1.length : arr2.length; return arr1.length <= arr2.length ? arr1.length : arr2.length;
} }
private int compareIdentifiers(String id1, String id2) { private int compareIdentifiers(String ident1, String ident2) {
if (isInt(id1) && isInt(id2)) { if (isInt(ident1) && isInt(ident2)) {
return Integer.parseInt(id1) - Integer.parseInt(id2); return Integer.parseInt(ident1) - Integer.parseInt(ident2);
} else { } else {
return id1.compareTo(id2); return ident1.compareTo(ident2);
} }
} }

View File

@ -44,36 +44,28 @@ public class Version implements Comparable<Version> {
private String preRelease; private String preRelease;
private String build; private String build;
public Builder(String normalVersion) { public Builder(String normal) {
if (normalVersion == null) { if (normal == null) {
throw new NullPointerException( throw new NullPointerException(
"Normal version MUST NOT be NULL" "Normal version MUST NOT be NULL"
); );
} }
normal = normalVersion; this.normal = normal;
} }
public void setPreReleaseVersion(String preReleaseVersion) { public void setPreReleaseVersion(String preRelease) {
preRelease = preReleaseVersion; this.preRelease = preRelease;
} }
public void setBuildMetadata(String buildMetadata) { public void setBuildMetadata(String build) {
build = buildMetadata; this.build = build;
} }
public Version build() { public Version build() {
MetadataVersion preReleaseVersion = null;
if (preRelease != null) {
preReleaseVersion = VersionParser.parsePreRelease(preRelease);
}
MetadataVersion buildMetadata = null;
if (build != null) {
buildMetadata = VersionParser.parseBuild(build);
}
return new Version( return new Version(
VersionParser.parseVersionCore(normal), VersionParser.parseVersionCore(normal),
preReleaseVersion, VersionParser.parsePreRelease(preRelease),
buildMetadata VersionParser.parseBuild(build)
); );
} }
} }
@ -86,32 +78,28 @@ public class Version implements Comparable<Version> {
public int compare(Version v1, Version v2) { public int compare(Version v1, Version v2) {
int result = v1.compareTo(v2); int result = v1.compareTo(v2);
if (result == 0) { if (result == 0) {
result = compareBuilds(v1, v2);
}
return result;
}
private int compareBuilds(Version v1, Version v2) {
int result = 0;
if (v1.build != null && v2.build != null) {
result = v1.build.compareTo(v2.build); result = v1.build.compareTo(v2.build);
} else if (v1.build == null ^ v2.build == null) { if (v1.build == MetadataVersion.NULL ||
/** v2.build == MetadataVersion.NULL
* Build versions should have a higher precedence ) {
* than the associated normal version. /**
*/ * Build metadata should have a higher precedence
result = (v1.build == null) ? -1 : 1; * than the associated normal version which is the
* opposite compared to pre-release versions.
*/
result = -1 * result;
}
} }
return result; return result;
} }
} }
Version(NormalVersion normal) { Version(NormalVersion normal) {
this(normal, null, null); this(normal, MetadataVersion.NULL, MetadataVersion.NULL);
} }
Version(NormalVersion normal, MetadataVersion preRelease) { Version(NormalVersion normal, MetadataVersion preRelease) {
this(normal, preRelease, null); this(normal, preRelease, MetadataVersion.NULL);
} }
Version( Version(
@ -162,16 +150,10 @@ public class Version implements Comparable<Version> {
} }
public Version incrementPreReleaseVersion() { public Version incrementPreReleaseVersion() {
if (preRelease == null) {
throw new NullPointerException("Pre-release version is NULL");
}
return new Version(normal, preRelease.increment()); return new Version(normal, preRelease.increment());
} }
public Version incrementBuildMetadata() { public Version incrementBuildMetadata() {
if (build == null) {
throw new NullPointerException("Build metadata is NULL");
}
return new Version(normal, preRelease, build.increment()); return new Version(normal, preRelease, build.increment());
} }
@ -207,11 +189,11 @@ public class Version implements Comparable<Version> {
} }
public String getPreReleaseVersion() { public String getPreReleaseVersion() {
return (preRelease != null) ? preRelease.toString() : ""; return preRelease.toString();
} }
public String getBuildMetadata() { public String getBuildMetadata() {
return (build != null) ? build.toString() : ""; return build.toString();
} }
public boolean greaterThan(Version other) { public boolean greaterThan(Version other) {
@ -244,19 +226,19 @@ public class Version implements Comparable<Version> {
@Override @Override
public int hashCode() { public int hashCode() {
int hash = 5; int hash = 5;
hash = 97 * hash + (normal != null ? normal.hashCode() : 0); hash = 97 * hash + normal.hashCode();
hash = 97 * hash + (preRelease != null ? preRelease.hashCode() : 0); hash = 97 * hash + preRelease.hashCode();
hash = 97 * hash + (build != null ? build.hashCode() : 0); hash = 97 * hash + build.hashCode();
return hash; return hash;
} }
@Override @Override
public String toString() { public String toString() {
StringBuilder sb = new StringBuilder(getNormalVersion()); StringBuilder sb = new StringBuilder(getNormalVersion());
if (preRelease != null) { if (!getPreReleaseVersion().isEmpty()) {
sb.append(PRE_RELEASE_PREFIX).append(getPreReleaseVersion()); sb.append(PRE_RELEASE_PREFIX).append(getPreReleaseVersion());
} }
if (build != null) { if (!getBuildMetadata().isEmpty()) {
sb.append(BUILD_PREFIX).append(getBuildMetadata()); sb.append(BUILD_PREFIX).append(getBuildMetadata());
} }
return sb.toString(); return sb.toString();
@ -266,7 +248,7 @@ public class Version implements Comparable<Version> {
public int compareTo(Version other) { public int compareTo(Version other) {
int result = normal.compareTo(other.normal); int result = normal.compareTo(other.normal);
if (result == 0) { if (result == 0) {
result = comparePreReleases(other); result = preRelease.compareTo(other.preRelease);
} }
return result; return result;
} }
@ -274,18 +256,4 @@ public class Version implements Comparable<Version> {
public int compareWithBuildsTo(Version other) { public int compareWithBuildsTo(Version other) {
return BUILD_AWARE_ORDER.compare(this, other); return BUILD_AWARE_ORDER.compare(this, other);
} }
private int comparePreReleases(Version other) {
int result = 0;
if (preRelease != null && other.preRelease != null) {
result = preRelease.compareTo(other.preRelease);
} else if (preRelease == null ^ other.preRelease == null) {
/**
* Pre-release versions have a lower precedence than
* the associated normal version. (SemVer p.9)
*/
result = (preRelease == null) ? 1 : -1;
}
return result;
}
} }

View File

@ -173,19 +173,25 @@ class VersionParser implements Parser<Version> {
} }
static MetadataVersion parsePreRelease(String preRelease) { static MetadataVersion parsePreRelease(String preRelease) {
if (preRelease == null) {
return MetadataVersion.NULL;
}
VersionParser parser = new VersionParser(preRelease); VersionParser parser = new VersionParser(preRelease);
return parser.parsePreRelease(); return parser.parsePreRelease();
} }
static MetadataVersion parseBuild(String build) { static MetadataVersion parseBuild(String build) {
if (build == null) {
return MetadataVersion.NULL;
}
VersionParser parser = new VersionParser(build); VersionParser parser = new VersionParser(build);
return parser.parseBuild(); return parser.parseBuild();
} }
private Version parseValidSemVer() { private Version parseValidSemVer() {
NormalVersion normalVersion = parseVersionCore(); NormalVersion normalVersion = parseVersionCore();
MetadataVersion preReleaseVersion = null; MetadataVersion preReleaseVersion = MetadataVersion.NULL;
MetadataVersion buildMetadata = null; MetadataVersion buildMetadata = MetadataVersion.NULL;
if (chars.positiveLookahead(HYPHEN)) { if (chars.positiveLookahead(HYPHEN)) {
chars.consume(); chars.consume();
preReleaseVersion = parsePreRelease(); preReleaseVersion = parsePreRelease();

View File

@ -81,6 +81,13 @@ public class MetadataVersionTest {
assertTrue(0 < v1.compareTo(v2)); assertTrue(0 < v1.compareTo(v2));
} }
@Test
public void shouldReturnNegativeWhenComparedToNullMetadataVersion() {
MetadataVersion v1 = new MetadataVersion(new String[] {});
MetadataVersion v2 = MetadataVersion.NULL;
assertTrue(0 > v1.compareTo(v2));
}
@Test @Test
public void shouldOverrideEqualsMethod() { public void shouldOverrideEqualsMethod() {
MetadataVersion v1 = new MetadataVersion( MetadataVersion v1 = new MetadataVersion(
@ -124,6 +131,55 @@ public class MetadataVersionTest {
} }
} }
public static class NullMetadataVersionTest {
@Test
public void shouldReturnEmptyStringOnToString() {
MetadataVersion v = MetadataVersion.NULL;
assertTrue(v.toString().isEmpty());
}
@Test
public void shouldReturnZeroOnHashCode() {
MetadataVersion v = MetadataVersion.NULL;
assertEquals(0, v.hashCode());
}
@Test
public void shouldBeEqualOnlyToItsType() {
MetadataVersion v1 = MetadataVersion.NULL;
MetadataVersion v2 = MetadataVersion.NULL;
MetadataVersion v3 = new MetadataVersion(new String[] {});
assertTrue(v1.equals(v2));
assertTrue(v2.equals(v1));
assertFalse(v1.equals(v3));
}
@Test
public void shouldReturnPositiveWhenComparedToNonNullMetadataVersion() {
MetadataVersion v1 = MetadataVersion.NULL;
MetadataVersion v2 = new MetadataVersion(new String[] {});
assertTrue(0 < v1.compareTo(v2));
}
@Test
public void shouldReturnZeroWhenComparedToNullMetadataVersion() {
MetadataVersion v1 = MetadataVersion.NULL;
MetadataVersion v2 = MetadataVersion.NULL;
assertTrue(0 == v1.compareTo(v2));
}
@Test
public void shouldThrowNullPointerExceptionIfIncremented() {
try {
MetadataVersion.NULL.increment();
} catch (NullPointerException e) {
return;
}
fail("Should throw NullPointerException when incremented");
}
}
public static class EqualsMethodTest { public static class EqualsMethodTest {
@Test @Test

View File

@ -54,6 +54,12 @@ public class VersionParserTest {
assertEquals(new MetadataVersion(new String[] {"beta-1", "1"}), preRelease); assertEquals(new MetadataVersion(new String[] {"beta-1", "1"}), preRelease);
} }
@Test
public void shouldReturnNullMetadataVersionIfPreReleaseIsNull() {
MetadataVersion preRelease = VersionParser.parsePreRelease(null);
assertEquals(MetadataVersion.NULL, preRelease);
}
@Test @Test
public void shouldNotAllowDigitsInPreReleaseVersion() { public void shouldNotAllowDigitsInPreReleaseVersion() {
try { try {
@ -80,6 +86,12 @@ public class VersionParserTest {
assertEquals(new MetadataVersion(new String[] {"build", "1"}), build); assertEquals(new MetadataVersion(new String[] {"build", "1"}), build);
} }
@Test
public void shouldReturnNullMetadataVersionIfBuildIsNull() {
MetadataVersion build = VersionParser.parseBuild(null);
assertEquals(MetadataVersion.NULL, build);
}
@Test @Test
public void shouldAllowDigitsInBuildMetadata() { public void shouldAllowDigitsInBuildMetadata() {
try { try {