768 lines
23 KiB
Java
768 lines
23 KiB
Java
/*
|
|
* The MIT License
|
|
*
|
|
* Copyright 2012-2018 The SemanticVersioning Authors (see LICENSE file in root of project).
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
* THE SOFTWARE.
|
|
*/
|
|
package com.dorkbox.version;
|
|
|
|
import java.io.Serializable;
|
|
import java.util.Comparator;
|
|
|
|
import com.dorkbox.version.expr.Expression;
|
|
import com.dorkbox.version.expr.ExpressionParser;
|
|
import com.dorkbox.version.expr.LexerException;
|
|
import com.dorkbox.version.expr.UnexpectedTokenException;
|
|
|
|
/**
|
|
* The {@code Version} class is the main class of the Java SemVer library.
|
|
* <p>
|
|
* This class implements the Facade design pattern.
|
|
* It is also immutable, which makes the class thread-safe.
|
|
*
|
|
* @author Zafar Khaja <zafarkhaja@gmail.com>
|
|
*/
|
|
public
|
|
class Version implements Comparable<Version>, Serializable {
|
|
|
|
private static final long serialVersionUID = -2008891377046871654L;
|
|
|
|
/**
|
|
* A comparator that respects the build metadata when comparing versions.
|
|
*/
|
|
public static final Comparator<Version> BUILD_AWARE_ORDER = new BuildAwareOrder();
|
|
/**
|
|
* A separator that separates the build metadata from
|
|
* the normal version or the pre-release version.
|
|
*/
|
|
private static final String BUILD_PREFIX = "+";
|
|
/**
|
|
* A separator that separates the pre-release
|
|
* version from the normal version.
|
|
*/
|
|
private static final String PRE_RELEASE_PREFIX = "-";
|
|
|
|
|
|
/**
|
|
* A mutable builder for the immutable {@code Version} class.
|
|
*/
|
|
public static
|
|
class Builder {
|
|
|
|
/**
|
|
* The normal version string.
|
|
*/
|
|
private String normal;
|
|
|
|
/**
|
|
* The pre-release version string.
|
|
*/
|
|
private String preRelease;
|
|
|
|
/**
|
|
* The build metadata string.
|
|
*/
|
|
private String metaData;
|
|
|
|
/**
|
|
* Constructs a {@code Builder} instance.
|
|
*/
|
|
public
|
|
Builder() {
|
|
|
|
}
|
|
|
|
/**
|
|
* Constructs a {@code Builder} instance with the
|
|
* string representation of the normal version.
|
|
*
|
|
* @param normal the string representation of the normal version
|
|
*/
|
|
public
|
|
Builder(String normal) {
|
|
this.normal = normal;
|
|
}
|
|
|
|
/**
|
|
* Builds a {@code Version} object.
|
|
*
|
|
* @return a newly built {@code Version} instance
|
|
*
|
|
* @throws ParseException when invalid version string is provided
|
|
* @throws UnexpectedCharacterException is a special case of {@code ParseException}
|
|
*/
|
|
public
|
|
Version build() {
|
|
StringBuilder sb = new StringBuilder();
|
|
if (isFilled(normal)) {
|
|
sb.append(normal);
|
|
}
|
|
if (isFilled(preRelease)) {
|
|
sb.append(PRE_RELEASE_PREFIX).append(preRelease);
|
|
}
|
|
if (isFilled(metaData)) {
|
|
sb.append(BUILD_PREFIX).append(metaData);
|
|
}
|
|
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();
|
|
}
|
|
|
|
/**
|
|
* Sets the build metadata.
|
|
*
|
|
* @param metaData the string representation of the build metadata
|
|
*
|
|
* @return this builder instance
|
|
*/
|
|
public
|
|
Builder setBuildMetadata(String metaData) {
|
|
this.metaData = metaData;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Sets the normal version.
|
|
*
|
|
* @param normal the string representation of the normal version
|
|
*
|
|
* @return this builder instance
|
|
*/
|
|
public
|
|
Builder setNormalVersion(String normal) {
|
|
this.normal = normal;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Sets the pre-release version.
|
|
*
|
|
* @param preRelease the string representation of the pre-release version
|
|
*
|
|
* @return this builder instance
|
|
*/
|
|
public
|
|
Builder setPreReleaseVersion(String preRelease) {
|
|
this.preRelease = preRelease;
|
|
return this;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* A build-aware comparator.
|
|
*/
|
|
private static
|
|
class BuildAwareOrder implements Comparator<Version> {
|
|
|
|
/**
|
|
* Compares two {@code Version} instances taking
|
|
* into account their build metadata.
|
|
* <p>
|
|
* When compared build metadata is divided into identifiers. The
|
|
* numeric identifiers are compared numerically, and the alphanumeric
|
|
* identifiers are compared in the ASCII sort order.
|
|
* <p>
|
|
* If one of the compared versions has no defined build
|
|
* metadata, this version is considered to have a lower
|
|
* precedence than that of the other.
|
|
*
|
|
* @return a negative integer, zero, or a positive integer as the
|
|
* first argument is less than, equal to, or greater than the
|
|
* second.
|
|
*/
|
|
@Override
|
|
public
|
|
int compare(Version v1, Version v2) {
|
|
int result = v1.compareTo(v2);
|
|
if (result == 0) {
|
|
result = v1.build.compareTo(v2.build);
|
|
if (v1.build == MetadataVersion.NULL || v2.build == MetadataVersion.NULL) {
|
|
/**
|
|
* Build metadata should have a higher precedence
|
|
* than the associated normal version which is the
|
|
* opposite compared to pre-release versions.
|
|
*/
|
|
result = -1 * result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Gets the version number.
|
|
*/
|
|
public static
|
|
String getVersion() {
|
|
return "2.3";
|
|
}
|
|
|
|
/**
|
|
* Creates a new instance of {@code Version} as a
|
|
* result of parsing the specified version string.
|
|
*
|
|
* @param version the version string to parse
|
|
*
|
|
* @return a new instance of the {@code Version} class
|
|
*
|
|
* @throws IllegalArgumentException if the input string is {@code NULL} or empty
|
|
* @throws ParseException when invalid version string is provided
|
|
* @throws UnexpectedCharacterException is a special case of {@code ParseException}
|
|
*/
|
|
public static
|
|
Version from(String version) {
|
|
return VersionParser.parseValidSemVer(version);
|
|
}
|
|
|
|
/**
|
|
* Creates a new instance of {@code Version}
|
|
* for the specified version numbers.
|
|
*
|
|
* @param majorAndMinor the major and minor version number, in double notation
|
|
*
|
|
* @return a new instance of the {@code Version} class
|
|
*
|
|
* @throws IllegalArgumentException if a negative double is passed
|
|
*/
|
|
public static
|
|
Version from(double majorAndMinor) {
|
|
if (majorAndMinor < 0.0) {
|
|
throw new IllegalArgumentException("Major.minor number MUST be non-negative!");
|
|
}
|
|
return VersionParser.parseValidSemVer(Double.toString(majorAndMinor));
|
|
}
|
|
|
|
|
|
/**
|
|
* Creates a new instance of {@code Version}
|
|
* for the specified version numbers.
|
|
*
|
|
* @param major the major version number
|
|
*
|
|
* @return a new instance of the {@code Version} class
|
|
*
|
|
* @throws IllegalArgumentException if a negative integer is passed
|
|
*/
|
|
public static
|
|
Version from(int major) {
|
|
return new Version(new NormalVersion(major, 0));
|
|
}
|
|
|
|
/**
|
|
* Creates a new instance of {@code Version}
|
|
* for the specified version numbers.
|
|
*
|
|
* @param major the major version number
|
|
* @param minor the minor version number
|
|
*
|
|
* @return a new instance of the {@code Version} class
|
|
*
|
|
* @throws IllegalArgumentException if a negative integer is passed
|
|
*/
|
|
public static
|
|
Version from(int major, int minor) {
|
|
return new Version(new NormalVersion(major, minor));
|
|
}
|
|
|
|
/**
|
|
* Creates a new instance of {@code Version}
|
|
* for the specified version numbers.
|
|
*
|
|
* @param major the major version number
|
|
* @param minor the minor version number
|
|
* @param patch the patch version number
|
|
*
|
|
* @return a new instance of the {@code Version} class
|
|
*
|
|
* @throws IllegalArgumentException if a negative integer is passed
|
|
*/
|
|
public static
|
|
Version from(int major, int minor, int patch) {
|
|
return new Version(new NormalVersion(major, minor, patch));
|
|
}
|
|
|
|
/**
|
|
* The normal version.
|
|
*/
|
|
private final NormalVersion normal;
|
|
/**
|
|
* The pre-release version.
|
|
*/
|
|
private final MetadataVersion preRelease;
|
|
/**
|
|
* The build metadata.
|
|
*/
|
|
private final MetadataVersion build;
|
|
|
|
/**
|
|
* Constructs a {@code Version} instance with the normal version.
|
|
*
|
|
* @param normal the normal version
|
|
*/
|
|
Version(NormalVersion normal) {
|
|
this(normal, MetadataVersion.NULL, MetadataVersion.NULL);
|
|
}
|
|
|
|
/**
|
|
* Constructs a {@code Version} instance with the
|
|
* normal version and the pre-release version.
|
|
*
|
|
* @param normal the normal version
|
|
* @param preRelease the pre-release version
|
|
*/
|
|
Version(NormalVersion normal, MetadataVersion preRelease) {
|
|
this(normal, preRelease, MetadataVersion.NULL);
|
|
}
|
|
|
|
/**
|
|
* Constructs a {@code Version} instance with the normal
|
|
* version, the pre-release version and the build metadata.
|
|
*
|
|
* @param normal the normal version
|
|
* @param preRelease the pre-release version
|
|
* @param build the build metadata
|
|
*/
|
|
Version(NormalVersion normal, MetadataVersion preRelease, MetadataVersion build) {
|
|
this.normal = normal;
|
|
this.preRelease = preRelease;
|
|
this.build = build;
|
|
}
|
|
|
|
/**
|
|
* Compares this version to the other version.
|
|
* <p>
|
|
* This method does not take into account the versions' build
|
|
* metadata. If you want to compare the versions' build metadata
|
|
* use the {@code Version.compareWithBuildsTo} method or the
|
|
* {@code Version.BUILD_AWARE_ORDER} comparator.
|
|
*
|
|
* @param other the other version to compare to
|
|
*
|
|
* @return a negative integer, zero or a positive integer if this version
|
|
* is less than, equal to or greater the the specified version
|
|
*
|
|
* @see #BUILD_AWARE_ORDER
|
|
* @see #compareWithBuildsTo(Version other)
|
|
*/
|
|
@Override
|
|
public
|
|
int compareTo(Version other) {
|
|
int result = normal.compareTo(other.normal);
|
|
if (result == 0) {
|
|
result = preRelease.compareTo(other.preRelease);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Compare this version to the other version
|
|
* taking into account the build metadata.
|
|
* <p>
|
|
* The method makes use of the {@code Version.BUILD_AWARE_ORDER} comparator.
|
|
*
|
|
* @param other the other version to compare to
|
|
*
|
|
* @return integer result of comparison compatible with
|
|
* that of the {@code Comparable.compareTo} method
|
|
*
|
|
* @see #BUILD_AWARE_ORDER
|
|
*/
|
|
public
|
|
int compareWithBuildsTo(Version other) {
|
|
return BUILD_AWARE_ORDER.compare(this, other);
|
|
}
|
|
|
|
/**
|
|
* Checks if this version equals the other version.
|
|
* <p>
|
|
* The comparison is done by the {@code Version.compareTo} method.
|
|
*
|
|
* @param other the other version to compare to
|
|
*
|
|
* @return {@code true} if this version equals the other version
|
|
* or {@code false} otherwise
|
|
*
|
|
* @see #compareTo(Version other)
|
|
*/
|
|
@Override
|
|
public
|
|
boolean equals(Object other) {
|
|
if (this == other) {
|
|
return true;
|
|
}
|
|
if (!(other instanceof Version)) {
|
|
return false;
|
|
}
|
|
return compareTo((Version) other) == 0;
|
|
}
|
|
|
|
/**
|
|
* Returns the string representation of the build metadata.
|
|
*
|
|
* @return the string representation of the build metadata
|
|
*/
|
|
public
|
|
String getBuildMetadata() {
|
|
return build.toString();
|
|
}
|
|
|
|
/**
|
|
* Sets the build metadata.
|
|
*
|
|
* @param build the build metadata to set
|
|
*
|
|
* @return a new instance of the {@code Version} class
|
|
*
|
|
* @throws IllegalArgumentException if the input string is {@code NULL} or empty
|
|
* @throws ParseException when invalid version string is provided
|
|
* @throws UnexpectedCharacterException is a special case of {@code ParseException}
|
|
*/
|
|
public
|
|
Version setBuildMetadata(String build) {
|
|
return new Version(normal, preRelease, VersionParser.parseBuild(build));
|
|
}
|
|
|
|
/**
|
|
* Returns the major version number.
|
|
*
|
|
* @return the major version number
|
|
*/
|
|
public
|
|
long getMajorVersion() {
|
|
return normal.getMajor();
|
|
}
|
|
|
|
/**
|
|
* Returns the minor version number.
|
|
*
|
|
* @return the minor version number
|
|
*/
|
|
public
|
|
long getMinorVersion() {
|
|
return normal.getMinor();
|
|
}
|
|
|
|
/**
|
|
* Returns the string representation of the normal version.
|
|
*
|
|
* @return the string representation of the normal version
|
|
*/
|
|
public
|
|
String getNormalVersion() {
|
|
return normal.toString();
|
|
}
|
|
|
|
/**
|
|
* Returns the patch version number.
|
|
*
|
|
* @return the patch version number
|
|
*/
|
|
public
|
|
long getPatchVersion() {
|
|
return normal.getPatch();
|
|
}
|
|
|
|
/**
|
|
* Returns the string representation of the pre-release version.
|
|
*
|
|
* @return the string representation of the pre-release version
|
|
*/
|
|
public
|
|
String getPreReleaseVersion() {
|
|
return preRelease.toString();
|
|
}
|
|
|
|
/**
|
|
* Sets the pre-release version.
|
|
*
|
|
* @param preRelease the pre-release version to set
|
|
*
|
|
* @return a new instance of the {@code Version} class
|
|
*
|
|
* @throws IllegalArgumentException if the input string is {@code NULL} or empty
|
|
* @throws ParseException when invalid version string is provided
|
|
* @throws UnexpectedCharacterException is a special case of {@code ParseException}
|
|
*/
|
|
public
|
|
Version setPreReleaseVersion(String preRelease) {
|
|
return new Version(normal, VersionParser.parsePreRelease(preRelease));
|
|
}
|
|
|
|
/**
|
|
* Checks if this version is greater than the other version.
|
|
*
|
|
* @param other the other version to compare to
|
|
*
|
|
* @return {@code true} if this version is greater than the other version
|
|
* or {@code false} otherwise
|
|
*
|
|
* @see #compareTo(Version other)
|
|
*/
|
|
public
|
|
boolean greaterThan(Version other) {
|
|
return compareTo(other) > 0;
|
|
}
|
|
|
|
/**
|
|
* Checks if this version is greater than or equal to the other version.
|
|
*
|
|
* @param other the other version to compare to
|
|
*
|
|
* @return {@code true} if this version is greater than or equal
|
|
* to the other version or {@code false} otherwise
|
|
*
|
|
* @see #compareTo(Version other)
|
|
*/
|
|
public
|
|
boolean greaterThanOrEqualTo(Version other) {
|
|
return compareTo(other) >= 0;
|
|
}
|
|
|
|
@Override
|
|
public
|
|
int hashCode() {
|
|
int hash = 5;
|
|
hash = 97 * hash + normal.hashCode();
|
|
hash = 97 * hash + preRelease.hashCode();
|
|
return hash;
|
|
}
|
|
|
|
/**
|
|
* Increments the build metadata.
|
|
*
|
|
* @return a new instance of the {@code Version} class
|
|
*/
|
|
public
|
|
Version incrementBuildMetadata() {
|
|
return new Version(normal, preRelease, build.increment());
|
|
}
|
|
|
|
/**
|
|
* Increments the major version.
|
|
*
|
|
* @return a new instance of the {@code Version} class
|
|
*/
|
|
public
|
|
Version incrementMajorVersion() {
|
|
return new Version(normal.incrementMajor());
|
|
}
|
|
|
|
/**
|
|
* Increments the major version and appends the pre-release version.
|
|
*
|
|
* @param preRelease the pre-release version to append
|
|
*
|
|
* @return a new instance of the {@code Version} class
|
|
*
|
|
* @throws IllegalArgumentException if the input string is {@code NULL} or empty
|
|
* @throws ParseException when invalid version string is provided
|
|
* @throws UnexpectedCharacterException is a special case of {@code ParseException}
|
|
*/
|
|
public
|
|
Version incrementMajorVersion(String preRelease) {
|
|
return new Version(normal.incrementMajor(), VersionParser.parsePreRelease(preRelease));
|
|
}
|
|
|
|
/**
|
|
* Increments the minor version.
|
|
*
|
|
* @return a new instance of the {@code Version} class
|
|
*/
|
|
public
|
|
Version incrementMinorVersion() {
|
|
return new Version(normal.incrementMinor());
|
|
}
|
|
|
|
/**
|
|
* Increments the minor version and appends the pre-release version.
|
|
*
|
|
* @param preRelease the pre-release version to append
|
|
*
|
|
* @return a new instance of the {@code Version} class
|
|
*
|
|
* @throws IllegalArgumentException if the input string is {@code NULL} or empty
|
|
* @throws ParseException when invalid version string is provided
|
|
* @throws UnexpectedCharacterException is a special case of {@code ParseException}
|
|
*/
|
|
public
|
|
Version incrementMinorVersion(String preRelease) {
|
|
return new Version(normal.incrementMinor(), VersionParser.parsePreRelease(preRelease));
|
|
}
|
|
|
|
/**
|
|
* Increments the patch version.
|
|
*
|
|
* @return a new instance of the {@code Version} class
|
|
*/
|
|
public
|
|
Version incrementPatchVersion() {
|
|
return new Version(normal.incrementPatch());
|
|
}
|
|
|
|
/**
|
|
* Increments the patch version and appends the pre-release version.
|
|
*
|
|
* @param preRelease the pre-release version to append
|
|
*
|
|
* @return a new instance of the {@code Version} class
|
|
*
|
|
* @throws IllegalArgumentException if the input string is {@code NULL} or empty
|
|
* @throws ParseException when invalid version string is provided
|
|
* @throws UnexpectedCharacterException is a special case of {@code ParseException}
|
|
*/
|
|
public
|
|
Version incrementPatchVersion(String preRelease) {
|
|
return new Version(normal.incrementPatch(), VersionParser.parsePreRelease(preRelease));
|
|
}
|
|
|
|
/**
|
|
* Increments the pre-release version.
|
|
*
|
|
* @return a new instance of the {@code Version} class
|
|
*/
|
|
public
|
|
Version incrementPreReleaseVersion() {
|
|
return new Version(normal, preRelease.increment());
|
|
}
|
|
|
|
/**
|
|
* Checks if this version is compatible with the
|
|
* other version in terms of their major versions.
|
|
* <p>
|
|
* When checking compatibility no assumptions
|
|
* are made about the versions' precedence.
|
|
*
|
|
* @param other the other version to check with
|
|
*
|
|
* @return {@code true} if this version is compatible with
|
|
* the other version or {@code false} otherwise
|
|
*/
|
|
public
|
|
boolean isMajorVersionCompatible(Version other) {
|
|
return this.getMajorVersion() == other.getMajorVersion();
|
|
}
|
|
|
|
/**
|
|
* Checks if this version is compatible with the
|
|
* other version in terms of their minor versions.
|
|
* <p>
|
|
* When checking compatibility no assumptions
|
|
* are made about the versions' precedence.
|
|
*
|
|
* @param other the other version to check with
|
|
*
|
|
* @return {@code true} if this version is compatible with
|
|
* the other version or {@code false} otherwise
|
|
*/
|
|
public
|
|
boolean isMinorVersionCompatible(Version other) {
|
|
return this.getMajorVersion() == other.getMajorVersion() && this.getMinorVersion() == other.getMinorVersion();
|
|
}
|
|
|
|
/**
|
|
* Checks if this version is less than the other version.
|
|
*
|
|
* @param other the other version to compare to
|
|
*
|
|
* @return {@code true} if this version is less than the other version
|
|
* or {@code false} otherwise
|
|
*
|
|
* @see #compareTo(Version other)
|
|
*/
|
|
public
|
|
boolean lessThan(Version other) {
|
|
return compareTo(other) < 0;
|
|
}
|
|
|
|
/**
|
|
* Checks if this version is less than or equal to the other version.
|
|
*
|
|
* @param other the other version to compare to
|
|
*
|
|
* @return {@code true} if this version is less than or equal
|
|
* to the other version or {@code false} otherwise
|
|
*
|
|
* @see #compareTo(Version other)
|
|
*/
|
|
public
|
|
boolean lessThanOrEqualTo(Version other) {
|
|
return compareTo(other) <= 0;
|
|
}
|
|
|
|
/**
|
|
* Checks if this version satisfies the specified SemVer Expression string.
|
|
* <p>
|
|
* This method is a part of the SemVer Expressions API.
|
|
*
|
|
* @param expr the SemVer Expression string
|
|
*
|
|
* @return {@code true} if this version satisfies the specified
|
|
* SemVer Expression or {@code false} otherwise
|
|
*
|
|
* @throws ParseException in case of a general parse error
|
|
* @throws LexerException when encounters an illegal character
|
|
* @throws UnexpectedTokenException when comes across an unexpected token
|
|
*/
|
|
public
|
|
boolean satisfies(String expr) {
|
|
Parser<Expression> parser = ExpressionParser.newInstance();
|
|
return satisfies(parser.parse(expr));
|
|
}
|
|
|
|
/**
|
|
* Checks if this version satisfies the specified SemVer Expression.
|
|
* <p>
|
|
* This method is a part of the SemVer Expressions API.
|
|
*
|
|
* @param expr the SemVer Expression
|
|
*
|
|
* @return {@code true} if this version satisfies the specified
|
|
* SemVer Expression or {@code false} otherwise
|
|
*/
|
|
public
|
|
boolean satisfies(Expression expr) {
|
|
return expr.interpret(this);
|
|
}
|
|
|
|
@Override
|
|
public
|
|
String toString() {
|
|
StringBuilder sb = new StringBuilder(getNormalVersion());
|
|
if (!getPreReleaseVersion().isEmpty()) {
|
|
sb.append(PRE_RELEASE_PREFIX).append(getPreReleaseVersion());
|
|
}
|
|
if (!getBuildMetadata().isEmpty()) {
|
|
sb.append(BUILD_PREFIX).append(getBuildMetadata());
|
|
}
|
|
return sb.toString();
|
|
}
|
|
}
|