Refactor VersionParser to handle illegal inputs

This commit is contained in:
Zafar Khaja 2014-01-23 18:43:11 +04:00
parent b312d18eaf
commit 988059b444
4 changed files with 69 additions and 36 deletions

View File

@ -85,19 +85,29 @@ public class Version implements Comparable<Version> {
*/ */
private String build; private String build;
/**
* Constructs a {@code Builder} instance.
*/
public Builder() {
}
/** /**
* Constructs a {@code Builder} instance with the * Constructs a {@code Builder} instance with the
* string representation of the normal version. * string representation of the normal version.
* *
* @param normal the string representation of the normal version * @param normal the string representation of the normal version
* @throws NullPointerException if the specified normal version is null
*/ */
public Builder(String normal) { public Builder(String normal) {
if (normal == null) { this.normal = normal;
throw new NullPointerException( }
"Normal version MUST NOT be NULL"
); /**
} * Sets the normal version.
*
* @param normal the string representation of the normal version
*/
public void setNormalVersion(String normal) {
this.normal = normal; this.normal = normal;
} }
@ -125,11 +135,27 @@ public class Version implements Comparable<Version> {
* @return a newly built {@code Version} instance * @return a newly built {@code Version} instance
*/ */
public Version build() { public Version build() {
return new Version( StringBuilder sb = new StringBuilder();
VersionParser.parseVersionCore(normal), if (isFilled(normal)) {
VersionParser.parsePreRelease(preRelease), sb.append(normal);
VersionParser.parseBuild(build) }
); if (isFilled(preRelease)) {
sb.append(PRE_RELEASE_PREFIX).append(preRelease);
}
if (isFilled(build)) {
sb.append(BUILD_PREFIX).append(build);
}
return VersionParser.parseValidSemVer(sb.toString());
}
/**
* Checks if a string has a usable value.
*
* @param str the string to check
* @return {@code true} if the string is filled or {@code false} otherwise
*/
private boolean isFilled(String str) {
return str != null && !str.isEmpty();
} }
} }
@ -221,6 +247,7 @@ public class Version implements Comparable<Version> {
* *
* @param version the version string to parse * @param version the version string to parse
* @return a new instance of the {@code Version} class * @return a new instance of the {@code Version} class
* @throws IllegalArgumentException if the input string is {@code NULL} or empty
*/ */
public static Version valueOf(String version) { public static Version valueOf(String version) {
return VersionParser.parseValidSemVer(version); return VersionParser.parseValidSemVer(version);
@ -294,6 +321,7 @@ public class Version implements Comparable<Version> {
* *
* @param preRelease the pre-release version to append * @param preRelease the pre-release version to append
* @return a new instance of the {@code Version} class * @return a new instance of the {@code Version} class
* @throws IllegalArgumentException if the input string is {@code NULL} or empty
*/ */
public Version incrementMajorVersion(String preRelease) { public Version incrementMajorVersion(String preRelease) {
return new Version( return new Version(
@ -316,6 +344,7 @@ public class Version implements Comparable<Version> {
* *
* @param preRelease the pre-release version to append * @param preRelease the pre-release version to append
* @return a new instance of the {@code Version} class * @return a new instance of the {@code Version} class
* @throws IllegalArgumentException if the input string is {@code NULL} or empty
*/ */
public Version incrementMinorVersion(String preRelease) { public Version incrementMinorVersion(String preRelease) {
return new Version( return new Version(
@ -338,6 +367,7 @@ public class Version implements Comparable<Version> {
* *
* @param preRelease the pre-release version to append * @param preRelease the pre-release version to append
* @return a new instance of the {@code Version} class * @return a new instance of the {@code Version} class
* @throws IllegalArgumentException if the input string is {@code NULL} or empty
*/ */
public Version incrementPatchVersion(String preRelease) { public Version incrementPatchVersion(String preRelease) {
return new Version( return new Version(
@ -369,6 +399,7 @@ public class Version implements Comparable<Version> {
* *
* @param preRelease the pre-release version to set * @param preRelease the pre-release version to set
* @return a new instance of the {@code Version} class * @return a new instance of the {@code Version} class
* @throws IllegalArgumentException if the input string is {@code NULL} or empty
*/ */
public Version setPreReleaseVersion(String preRelease) { public Version setPreReleaseVersion(String preRelease) {
return new Version(normal, VersionParser.parsePreRelease(preRelease)); return new Version(normal, VersionParser.parsePreRelease(preRelease));
@ -379,6 +410,7 @@ public class Version implements Comparable<Version> {
* *
* @param build the build metadata to set * @param build the build metadata to set
* @return a new instance of the {@code Version} class * @return a new instance of the {@code Version} class
* @throws IllegalArgumentException if the input string is {@code NULL} or empty
*/ */
public Version setBuildMetadata(String build) { public Version setBuildMetadata(String build) {
return new Version(normal, preRelease, VersionParser.parseBuild(build)); return new Version(normal, preRelease, VersionParser.parseBuild(build));

View File

@ -124,8 +124,12 @@ class VersionParser implements Parser<Version> {
* with the input string to parse. * with the input string to parse.
* *
* @param input the input string to parse * @param input the input string to parse
* @throws IllegalArgumentException if the input string is {@code NULL} or empty
*/ */
VersionParser(String input) { VersionParser(String input) {
if (input == null || input.isEmpty()) {
throw new IllegalArgumentException("Input string is NULL or empty");
}
Character[] elements = new Character[input.length()]; Character[] elements = new Character[input.length()];
for (int i = 0; i < input.length(); i++) { for (int i = 0; i < input.length(); i++) {
elements[i] = Character.valueOf(input.charAt(i)); elements[i] = Character.valueOf(input.charAt(i));
@ -152,6 +156,7 @@ class VersionParser implements Parser<Version> {
* *
* @param version the version string to parse * @param version the version string to parse
* @return a valid version object * @return a valid version object
* @throws IllegalArgumentException if the input string is {@code NULL} or empty
* @throws ParseException when there is an error defined in * @throws ParseException when there is an error defined in
* the SemVer or the formal grammar * the SemVer or the formal grammar
* @throws UnexpectedElementException when encounters an unexpected character type * @throws UnexpectedElementException when encounters an unexpected character type
@ -166,6 +171,7 @@ class VersionParser implements Parser<Version> {
* *
* @param versionCore the version core string to parse * @param versionCore the version core string to parse
* @return a valid normal version object * @return a valid normal version object
* @throws IllegalArgumentException if the input string is {@code NULL} or empty
* @throws ParseException when there is an error defined in * @throws ParseException when there is an error defined in
* the SemVer or the formal grammar * the SemVer or the formal grammar
* @throws UnexpectedElementException when encounters an unexpected character type * @throws UnexpectedElementException when encounters an unexpected character type
@ -180,13 +186,11 @@ class VersionParser implements Parser<Version> {
* *
* @param preRelease the pre-release version string to parse * @param preRelease the pre-release version string to parse
* @return a valid pre-release version object * @return a valid pre-release version object
* @throws IllegalArgumentException if the input string is {@code NULL} or empty
* @throws ParseException when there is an error defined in * @throws ParseException when there is an error defined in
* the SemVer or the formal grammar * the SemVer or the formal grammar
*/ */
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();
} }
@ -196,13 +200,11 @@ class VersionParser implements Parser<Version> {
* *
* @param build the build metadata string to parse * @param build the build metadata string to parse
* @return a valid build metadata object * @return a valid build metadata object
* @throws IllegalArgumentException if the input string is {@code NULL} or empty
* @throws ParseException when there is an error defined in * @throws ParseException when there is an error defined in
* the SemVer or the formal grammar * the SemVer or the formal grammar
*/ */
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();
} }

View File

@ -54,12 +54,6 @@ 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 {
@ -86,12 +80,6 @@ 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 {
@ -124,4 +112,16 @@ public class VersionParserTest {
version version
); );
} }
@Test
public void shouldRaiseErrorForIllegalInputString() {
for (String illegal : new String[] { "", null }) {
try {
new VersionParser(illegal);
} catch (IllegalArgumentException e) {
continue;
}
fail("Should raise error for illegal input string");
}
}
} }

View File

@ -394,13 +394,12 @@ public class VersionTest {
public static class BuilderTest { public static class BuilderTest {
@Test @Test
public void shouldThrowNullPointerExceptionIfNormalVersionIsNull() { public void shouldBuildVersionInSteps() {
try { Version.Builder builder = new Version.Builder();
new Version.Builder(null); builder.setNormalVersion("1.0.0");
} catch (NullPointerException e) { builder.setPreReleaseVersion("alpha");
return; builder.setBuildMetadata("build");
} assertEquals(Version.valueOf("1.0.0-alpha+build"), builder.build());
fail("Builder was expected to throw NullPointerException");
} }
@Test @Test