com.mooltiverse.oss.nyx.state.State Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of main Show documentation
Show all versions of main Show documentation
com.mooltiverse.oss.nyx:main:3.0.7 null
/*
* Copyright 2020 Mooltiverse
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mooltiverse.oss.nyx.state;
import static com.mooltiverse.oss.nyx.log.Markers.STATE;
import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.mooltiverse.oss.nyx.Nyx;
import com.mooltiverse.oss.nyx.configuration.Configuration;
import com.mooltiverse.oss.nyx.entities.Attachment;
import com.mooltiverse.oss.nyx.entities.Changelog;
import com.mooltiverse.oss.nyx.entities.IllegalPropertyException;
import com.mooltiverse.oss.nyx.entities.ReleaseScope;
import com.mooltiverse.oss.nyx.entities.ReleaseType;
import com.mooltiverse.oss.nyx.io.DataAccessException;
import com.mooltiverse.oss.nyx.io.FileMapper;
import com.mooltiverse.oss.nyx.template.Templates;
import com.mooltiverse.oss.nyx.version.Scheme;
import com.mooltiverse.oss.nyx.version.SemanticVersion;
import com.mooltiverse.oss.nyx.version.Versions;
/**
* The State class holds a number of attributes resulting from the execution of one or more command and so represents
* the current status of a release process at a certain point in time.
*
* Each command updates the state object with new or modified attributes so the same state instance is shared among
* all commands.
*
* There must be only one instance of this class for every execution and it's retrieved by {@link Nyx#state()}.
*/
public class State {
/**
* The private logger instance
*/
private static final Logger logger = LoggerFactory.getLogger(State.class);
/**
* The current Git branch name.
*/
private String branch = null;
/**
* The identifier to bump.
*/
private String bump = null;
/**
* The private instance of the configuration.
*/
private Changelog changelog = null;
/**
* The private instance of the configuration.
*/
private Configuration configuration = null;
/**
* The map containing the internal attributes.
*/
private Map internals = new HashMap();
/**
* The flag indicating if the {@link #version} is the latest in the repository,
* according to the {@link #getScheme() scheme}.
*/
private Boolean latestVersion = null;
/**
* The list containing the released assets.
*/
private List releaseAssets = new ArrayList();
/**
* The private instance of the release scope.
*/
private ReleaseScope releaseScope = new ReleaseScope();
/**
* The private instance of the release type.
*/
private ReleaseType releaseType = null;
/**
* The latest timestamp that was taken. This is initialized by default to the date and
* time the instance of this class has been created.
*/
private Long timestamp = Long.valueOf(System.currentTimeMillis());
/**
* The version that has been inferred.
*/
private String version = null;
/**
* The regular expression used to check the version against a range constraint.
*/
private String versionRange = null;
/**
* Default constructor. DO NOT USE THIS CONSTRUCTOR AS IT EXISTS ONLY FOR INTERNAL USE WHEN UNMARSHALLING
*/
@Deprecated
public State() {
super();
}
/**
* Standard constructor.
*
* @param configuration the configuration object held by this state
*
* @throws NullPointerException if the given argument is {@code null}
*
* @throws DataAccessException in case the state file is configured but cannot be read or accessed when resuming
* from a previously saved state.
* @throws IllegalPropertyException in case the state file is configured but has incorrect values or it can't be
* resolved when resuming from a previously saved state
*/
public State(Configuration configuration)
throws DataAccessException, IllegalPropertyException {
super();
Objects.requireNonNull(configuration);
this.configuration = configuration;
logger.trace(STATE, "New state object");
}
/**
* Loads the state attributes from a previously saved state file. All attributes are loaded from the given file
* but the nested configuration is replaced by the given one.
*
* @param stateFile the file to load the state from
* @param configuration the configuration object to use for the resumed state. This object will be set as the
* {@link #getConfiguration() configuration} of the returned instance.
*
* @return the new state object deserialized from the given state file
*
* @throws DataAccessException in case the state file cannot be read or accessed.
* @throws IllegalPropertyException in case the state file has incorrect values.
*/
public static State resume(File stateFile, Configuration configuration)
throws DataAccessException, IllegalPropertyException {
State state = FileMapper.load(stateFile, State.class);
state.configuration = configuration;
// The values that are overridden by the configuration must be set to null after deserialization so that
// their getter/setter methods will consistently check if they've been defined by the configuration and return those
// instead of local ones.
// Consider that setter methods for those values need to be permissive because when the State is unmarshalled
// the internal reference to the configuration is not yet set.
if (!Objects.isNull(configuration.getBump()))
state.bump = null;
if (!Objects.isNull(configuration.getVersion()))
state.version = null;
return state;
}
/**
* Returns the current Git branch name.
*
* @return the current Git branch name. This is {@code null} until {@link Nyx#infer()} has run.
*
* @throws DataAccessException in case the attribute cannot be read or accessed.
* @throws IllegalPropertyException in case the attribute has been defined but has incorrect values or it can't be resolved.
*/
public String getBranch()
throws DataAccessException, IllegalPropertyException {
return branch;
}
/**
* Returns {@code true} if the scope has a non {@code null} branch name.
*
* @return {@code true} if the scope has a non {@code null} branch name.
*
* @throws DataAccessException in case the attribute cannot be read or accessed.
* @throws IllegalPropertyException in case the attribute has been defined but has incorrect values or it can't be resolved.
*/
public boolean hasBranch()
throws DataAccessException, IllegalPropertyException {
return !Objects.isNull(getBranch());
}
/**
* Sets the current Git branch name
*
* @param branch the current Git branch name. It may be {@code null} to reset any previous value.
*
* @throws DataAccessException in case the attribute cannot be written or accessed.
* @throws IllegalPropertyException in case the attribute has incorrect values or it can't be resolved.
*/
public void setBranch(String branch)
throws DataAccessException, IllegalPropertyException {
this.branch = branch;
}
/**
* Returns the version identifier to bump or bumped on the previous release to produce the new release, if any.
* This value is only available after {@link Nyx#infer()} has run unless it's overridden by the configuration,
* in which case the configuration value is returned.
*
* @return the version identifier to bump or bumped on the previous release to produce the new release, if any.
* It may be {@code null} if no identifier has been bumped (i.e. because no significant changes have
* been detected in the release scope or because inference was inhibited by values overridden by user) and the
* configuration does not override this value.
*
* @throws DataAccessException in case the attribute cannot be read or accessed.
* @throws IllegalPropertyException in case the attribute has been defined but has incorrect values or it can't be resolved.
*
* @see Configuration#getBump()
*/
public String getBump()
throws DataAccessException, IllegalPropertyException {
return Objects.isNull(getConfiguration().getBump()) ? bump : getConfiguration().getBump();
}
/**
* Returns {@code true} if the scope has a non {@code null} bump identifier
* to bump or bumped on the previous release to produce the new release.
*
* @return {@code true} if the scope has a non {@code null} bump identifier
* to bump or bumped on the previous release to produce the new release.
*
* @throws DataAccessException in case the attribute cannot be read or accessed.
* @throws IllegalPropertyException in case the attribute has been defined but has incorrect values or it can't be resolved.
*/
public boolean hasBump()
throws DataAccessException, IllegalPropertyException {
return !Objects.isNull(getBump());
}
/**
* Sets the identifier to bump.
*
* Since this option can be overridden by configuration this method can only be invoked when the
* {@link #getConfiguration() configuration} doesn't already have a {@link Configuration#getBump() bump}
* attribute otherwise an {@link IllegalStateException} is thrown.
*
* @param bump the identifier to bump
*
* @throws DataAccessException in case the attribute cannot be written or accessed.
* @throws IllegalPropertyException in case the attribute has incorrect values or it can't be resolved.
* @throws IllegalStateException if the {@link #getConfiguration() configuration} already has a value for the
* {@link Configuration#getBump() bump} attribute.
*/
public void setBump(String bump)
throws DataAccessException, IllegalPropertyException, IllegalStateException {
// We need to be permissive here as when this method is called by the unmarshaller the configuration object is not set yet
// but on the other hand the 'resume' method will handle this situation right after unmarshalling by checking if the
// configuration overrides this value and, if so, set the local reference to null.
// This causes a temporary inconsistency until the unmarshalling is finished, but this has no consequences
if (Objects.isNull(getConfiguration()) || Objects.isNull(getConfiguration().getBump()))
this.bump = bump;
else throw new IllegalStateException(String.format("The state bump attribute can't be set when it's ovverridden by the configuration. Configuration bump attribute is '%s'", getConfiguration().getBump()));
}
/**
* Returns the current changelog data model.
*
* @return the current changelog data model. This is {@code null} until {@link Nyx#make()} has run.
*
* @throws DataAccessException in case the attribute cannot be read or accessed.
* @throws IllegalPropertyException in case the attribute has been defined but has incorrect values or it can't be resolved.
*/
public Changelog getChangelog()
throws DataAccessException, IllegalPropertyException {
return changelog;
}
/**
* Returns {@code true} if the scope has a non {@code null} changelog data model.
*
* @return {@code true} if the scope has a non {@code null} changelog data model.
*
* @throws DataAccessException in case the attribute cannot be read or accessed.
* @throws IllegalPropertyException in case the attribute has been defined but has incorrect values or it can't be resolved.
*/
public boolean hasChangelog()
throws DataAccessException, IllegalPropertyException {
return !Objects.isNull(getChangelog());
}
/**
* Sets the changelog data model
*
* @param changelog the current changelog data model. It may be {@code null} to reset any previous value.
*
* @throws DataAccessException in case the attribute cannot be written or accessed.
* @throws IllegalPropertyException in case the attribute has incorrect values or it can't be resolved.
*/
public void setChangelog(Changelog changelog)
throws DataAccessException, IllegalPropertyException {
this.changelog = changelog;
}
/**
* Returns the configuration object. The configuration is a live reference.
*
* @return the configuration object.
*/
public Configuration getConfiguration() {
return configuration;
}
/**
* Returns {@code true} if the version ({@link #getVersion()}) only brings core identifiers (according to the
* {@link #getScheme() scheme}), usually meaning it is an official version. This mehod also takes into account
* whether the {@link #getConfiguration() configuration} requires {@link Configuration#getReleaseLenient() leniency}
* or it has a {@link Configuration#getReleasePrefix() prefix} configured.
*
* @return {@code true} if the version only brings core identifiers. If this state has no {@link #hasVersion() version}
* then {@code false} is returned.
*
* @throws DataAccessException in case the attribute cannot be read or accessed.
* @throws IllegalPropertyException in case the attribute has been defined but has incorrect values or it can't be resolved.
*
* @see #getVersion()
* @see #getScheme()
* @see Configuration#getVersion()
*/
public Boolean getCoreVersion()
throws DataAccessException, IllegalPropertyException {
return hasVersion() ? Boolean.valueOf(getConfiguration().getReleaseLenient() ? Versions.isCore(getScheme(), getVersion(), getConfiguration().getReleaseLenient()) : Versions.isCore(getScheme(), getVersion(), getConfiguration().getReleasePrefix())) : null;
}
/**
* Returns the directory used as the working directory as it's defined by the configuration.
*
* @return the current value for this attribute.
*
* @throws DataAccessException in case the attribute cannot be read or accessed.
* @throws IllegalPropertyException in case the attribute has been defined but has incorrect values or it can't be resolved.
*
* @see Configuration#getDirectory()
*/
public File getDirectory()
throws DataAccessException, IllegalPropertyException {
return new File(getConfiguration().getDirectory());
}
/**
* Returns the live map of internal attributes.
*
* Internal attributes are not documented so they must not be used by users as the implementation may change
* them at any time. Commands and other implementation objects are free to store and remove their own
* attributes here (i.e. for caching or store their internal state).
*
* When handling these attributes, entities must make sure the names (keys) do not overlap, unless for
* shared attributes.
*
* This object takes no control over the values stored in this map.
*
* Sensitive informations must not be stored here as they would be exposed when marshalling the attributes
* to files.
*
* @return the live map of internal attributes. The returned map is never {@code null}
*/
public Map getInternals() {
return internals;
}
/**
* Returns the flag indicating if the {@link #getVersion() version} is the latest in the repository,
* according to the {@link #getScheme() scheme}.
*
* @return the flag indicating if the {@link #getVersion()} is the latest in the repository,
* according to the {@link #getScheme() scheme}. This is also {@code null} until this state has a {@link #hasVersion() version} set.
*
* @throws DataAccessException in case the attribute cannot be read or accessed.
* @throws IllegalPropertyException in case the attribute has been defined but has incorrect values or it can't be resolved.
*/
public Boolean getLatestVersion()
throws DataAccessException, IllegalPropertyException {
return hasVersion() ? latestVersion : null;
}
/**
* Returns {@code true} if the scope has a non {@code null} {@link #getLatestVersion()} flag.
*
* @return {@code true} if the scope has a non {@code null} {@link #getLatestVersion()} flag.
*
* @throws DataAccessException in case the attribute cannot be read or accessed.
* @throws IllegalPropertyException in case the attribute has been defined but has incorrect values or it can't be resolved.
*/
public boolean hasLatestVersion()
throws DataAccessException, IllegalPropertyException {
return !Objects.isNull(getLatestVersion());
}
/**
* Sets the flag indicating if the {@link #getVersion() version} is the latest in the repository,
* according to the {@link #getScheme() scheme}.
*
* @param latestVersion the flag indicating if the {@link #getVersion()} is the latest in the repository.
*
* @throws DataAccessException in case the attribute cannot be written or accessed.
* @throws IllegalPropertyException in case the attribute has incorrect values or it can't be resolved.
*/
public void setLatestVersion(Boolean latestVersion)
throws DataAccessException, IllegalPropertyException {
this.latestVersion = latestVersion;
}
/**
* Returns {@code true} if the version ({@link #getVersion()}) is different than the previous version
* ({@link #getReleaseScope()}{@link ReleaseScope#getPreviousVersion()}) and a new release has to be
* published on the new version.
*
* @return {@code true} if the version is new and has to be released.
*
* @throws DataAccessException in case the attribute cannot be read or accessed.
* @throws IllegalPropertyException in case the attribute has been defined but has incorrect values or it can't be resolved.
*
* @see #getVersion()
* @see #getReleaseScope()
* @see ReleaseScope#getPreviousVersion()
* @see Configuration#getVersion()
*/
public Boolean getNewRelease()
throws DataAccessException, IllegalPropertyException {
if (Objects.isNull(releaseType))
return Boolean.FALSE;
try {
return Boolean.valueOf(getNewVersion() && Templates.toBoolean(Templates.render(releaseType.getPublish(), this)));
}
catch (IOException ioe) {
throw new IllegalPropertyException(String.format("Unable to render the template '%s' specified for the publish option in the release type", releaseType.getPublish()), ioe);
}
}
/**
* Returns {@code true} if the version ({@link #getVersion()}) is different than the previous version
* ({@link #getReleaseScope()}{@link ReleaseScope#getPreviousVersion()}).
*
* @return {@code true} if the version is new.
*
* @throws DataAccessException in case the attribute cannot be read or accessed.
* @throws IllegalPropertyException in case the attribute has been defined but has incorrect values or it can't be resolved.
*
* @see #getVersion()
* @see #getReleaseScope()
* @see ReleaseScope#getPreviousVersion()
* @see Configuration#getVersion()
*/
public Boolean getNewVersion()
throws DataAccessException, IllegalPropertyException {
if (hasVersion()) {
if (getVersion().equals(getReleaseScope().getPreviousVersion()))
return false;
else {
if (hasReleaseType() && getReleaseType().getCollapseVersions()) {
if (getVersion().equals(getReleaseScope().getPrimeVersion())) {
return false;
}
else return true;
}
else return true;
}
}
else return false;
}
/**
* Returns the list of assets published with the release. The returned object is a live collection whose contents can be changed.
*
* @return the current value for this attribute.
*
* @throws DataAccessException in case the attribute cannot be read or accessed.
* @throws IllegalPropertyException in case the attribute has been defined but has incorrect values or it can't be resolved.
*/
public List getReleaseAssets()
throws DataAccessException, IllegalPropertyException {
return releaseAssets;
}
/**
* Returns the object modelling the attributes defining the scope of the release.
*
* @return the current value for this attribute.
*/
public ReleaseScope getReleaseScope() {
return releaseScope;
}
/**
* Returns the object modelling the attributes defining the type of the release.
*
* @return the current value for this attribute.
*
* @throws DataAccessException in case the attribute cannot be read or accessed.
* @throws IllegalPropertyException in case the attribute has been defined but has incorrect values or it can't be resolved.
*/
public ReleaseType getReleaseType()
throws DataAccessException, IllegalPropertyException {
return releaseType;
}
/**
* Returns {@code true} if the scope has a non {@code null} release type set.
*
* @return {@code true} if the scope has a non {@code null} release type set.
*
* @throws DataAccessException in case the attribute cannot be read or accessed.
* @throws IllegalPropertyException in case the attribute has been defined but has incorrect values or it can't be resolved.
*/
public boolean hasReleaseType()
throws DataAccessException, IllegalPropertyException {
return !Objects.isNull(getReleaseType());
}
/**
* Sets the selected release type.
*
* @param releaseType the selected release type.
*
* @throws DataAccessException in case the attribute cannot be written or accessed.
* @throws IllegalPropertyException in case the attribute has incorrect values or it can't be resolved.
*/
public void setReleaseType(ReleaseType releaseType)
throws DataAccessException, IllegalPropertyException {
this.releaseType = releaseType;
}
/**
* Returns the versioning scheme used as it's defined by the configuration.
*
* @return the current value for this attribute.
*
* @throws DataAccessException in case the attribute cannot be read or accessed.
* @throws IllegalPropertyException in case the attribute has been defined but has incorrect values or it can't be resolved.
*/
public Scheme getScheme()
throws DataAccessException, IllegalPropertyException {
return getConfiguration().getScheme();
}
/**
* Returns the current timestamp.
*
* @return the current timestamp.
*
* @throws DataAccessException in case the attribute cannot be read or accessed.
* @throws IllegalPropertyException in case the attribute has been defined but has incorrect values or it can't be resolved.
*/
public Long getTimestamp()
throws DataAccessException, IllegalPropertyException {
return timestamp;
}
/**
* Sets the state timestamp.
*
* @param timestamp the state timestamp.
*
* @throws DataAccessException in case the attribute cannot be written or accessed.
* @throws IllegalPropertyException in case the attribute has incorrect values or it can't be resolved.
*/
public void setTimestamp(Long timestamp)
throws DataAccessException, IllegalPropertyException {
this.timestamp = timestamp;
}
/**
* Returns the version inferred by Nyx, if any. If the version was overridden by configuration this will be the
* same as {@link Configuration#getVersion()}. This value is only available after {@link Nyx#infer()} has run.
*
* The returned version also has the configured prefix, if any.
*
* @return the current version inferred by Nyx. This is {@code null} until {@link Nyx#infer()} has run.
*
* @throws DataAccessException in case the attribute cannot be read or accessed.
* @throws IllegalPropertyException in case the attribute has been defined but has incorrect values or it can't be resolved.
*
* @see #getNewRelease()
* @see #getNewVersion()
* @see Configuration#getVersion()
*/
public String getVersion()
throws DataAccessException, IllegalPropertyException {
return Objects.isNull(getConfiguration().getVersion()) ? version : getConfiguration().getVersion();
}
/**
* Returns {@code true} if the scope has a non {@code null} version.
*
* @return {@code true} if the scope has a non {@code null} version.
*
* @throws DataAccessException in case the attribute cannot be read or accessed.
* @throws IllegalPropertyException in case the attribute has been defined but has incorrect values or it can't be resolved.
*/
public boolean hasVersion()
throws DataAccessException, IllegalPropertyException {
return !Objects.isNull(getVersion());
}
/**
* Sets the version inferred by Nyx.
*
* Since this option can be overridden by configuration this method can only be invoked when the
* {@link #getConfiguration() configuration} doesn't already have a {@link Configuration#getVersion() version}
* attribute otherwise an {@link IllegalStateException} is thrown.
*
* @param version the version inferred by Nyx.
*
* @throws DataAccessException in case the attribute cannot be written or accessed.
* @throws IllegalPropertyException in case the attribute has incorrect values or it can't be resolved.
* @throws IllegalStateException if the {@link #getConfiguration() configuration} has a value for the
* {@link Configuration#getVersion() version} attribute.
*
* @see Configuration#getVersion()
*/
public void setVersion(String version)
throws DataAccessException, IllegalPropertyException, IllegalStateException {
// We need to be permissive here as when this method is called by the unmarshaller the configuration object is not set yet
// but on the other hand the 'resume' method will handle this situation right after unmarshalling by checking if the
// configuration overrides this value and, if so, set the local reference to null.
// This causes a temporary inconsistency until the unmarshalling is finished, but this has no consequences
if (Objects.isNull(getConfiguration()) || Objects.isNull(getConfiguration().getVersion()))
this.version = version;
else throw new IllegalStateException(String.format("The state version attribute can't be set when it's ovverridden by the configuration. Configuration version attribute is '%s'", getConfiguration().getVersion()));
}
/**
* Returns the version build metadata inferred by Nyx, if any. If the configured version scheme is not {@code SEMVER}
* this method always returns {@code null}.
*
* @return the version build metadata number inferred by Nyx. This is {@code null} if {@link #getVersion()} is {@code null} or
* the configured version scheme is not {@code SEMVER}.
*
* @throws DataAccessException in case the attribute cannot be read or accessed.
* @throws IllegalPropertyException in case the attribute has been defined but has incorrect values or it can't be resolved.
*
* @see #getVersion()
*/
public String getVersionBuildMetadata()
throws DataAccessException, IllegalPropertyException {
if ((!hasVersion()) || (!Scheme.SEMVER.equals(getScheme()))) {
return null;
}
else {
return SemanticVersion.valueOf(getVersion(), true).getBuild();
}
}
/**
* Returns the version major number inferred by Nyx, if any. If the configured version scheme is not {@code SEMVER}
* this method always returns {@code null}.
*
* @return the version major number inferred by Nyx. This is {@code null} if {@link #getVersion()} is {@code null} or
* the configured version scheme is not {@code SEMVER}.
*
* @throws DataAccessException in case the attribute cannot be read or accessed.
* @throws IllegalPropertyException in case the attribute has been defined but has incorrect values or it can't be resolved.
*
* @see #getVersion()
*/
public String getVersionMajorNumber()
throws DataAccessException, IllegalPropertyException {
if ((!hasVersion()) || (!Scheme.SEMVER.equals(getScheme()))) {
return null;
}
else {
return Integer.toString(SemanticVersion.valueOf(getVersion(), true).getMajor());
}
}
/**
* Returns the version minor number inferred by Nyx, if any. If the configured version scheme is not {@code SEMVER}
* this method always returns {@code null}.
*
* @return the version minor number inferred by Nyx. This is {@code null} if {@link #getVersion()} is {@code null} or
* the configured version scheme is not {@code SEMVER}.
*
* @throws DataAccessException in case the attribute cannot be read or accessed.
* @throws IllegalPropertyException in case the attribute has been defined but has incorrect values or it can't be resolved.
*
* @see #getVersion()
*/
public String getVersionMinorNumber()
throws DataAccessException, IllegalPropertyException {
if ((!hasVersion()) || (!Scheme.SEMVER.equals(getScheme()))) {
return null;
}
else {
return Integer.toString(SemanticVersion.valueOf(getVersion(), true).getMinor());
}
}
/**
* Returns the version patch number inferred by Nyx, if any. If the configured version scheme is not {@code SEMVER}
* this method always returns {@code null}.
*
* @return the version patch number inferred by Nyx. This is {@code null} if {@link #getVersion()} is {@code null} or
* the configured version scheme is not {@code SEMVER}.
*
* @throws DataAccessException in case the attribute cannot be read or accessed.
* @throws IllegalPropertyException in case the attribute has been defined but has incorrect values or it can't be resolved.
*
* @see #getVersion()
*/
public String getVersionPatchNumber()
throws DataAccessException, IllegalPropertyException {
if ((!hasVersion()) || (!Scheme.SEMVER.equals(getScheme()))) {
return null;
}
else {
return Integer.toString(SemanticVersion.valueOf(getVersion(), true).getPatch());
}
}
/**
* Returns the version pre-release identifier inferred by Nyx, if any. If the configured version scheme is not {@code SEMVER}
* this method always returns {@code null}.
*
* @return the version pre-release identifier number inferred by Nyx. This is {@code null} if {@link #getVersion()} is {@code null} or
* the configured version scheme is not {@code SEMVER}.
*
* @throws DataAccessException in case the attribute cannot be read or accessed.
* @throws IllegalPropertyException in case the attribute has been defined but has incorrect values or it can't be resolved.
*
* @see #getVersion()
*/
public String getVersionPreReleaseIdentifier()
throws DataAccessException, IllegalPropertyException {
if ((!hasVersion()) || (!Scheme.SEMVER.equals(getScheme()))) {
return null;
}
else {
return SemanticVersion.valueOf(getVersion(), true).getPrerelease();
}
}
/**
* Returns the regular expression that is used to check whether or not the {@link #getVersion() version} is within a certain
* range. This value is only available after {@link Nyx#infer()} has run.
*
* This attribute has a value only if {@link ReleaseType#getVersionRange() version range} or
* {@link ReleaseType#getVersionRangeFromBranchName() version range from branch name} are enabled. If
* {@link ReleaseType#getVersionRange() version range} has a value then this attribute has the same value, otherwise if
* {@link ReleaseType#getVersionRangeFromBranchName() version range from branch name} is {@code true} this value has the dynamically
* generated regular expression inferred from the branch name.
*
* @return the regular expression that is used to check whether or not the {@link #getVersion() version} is within a certain
* range. This is {@code null} until {@link Nyx#infer()} has run.
*
* @throws DataAccessException in case the attribute cannot be read or accessed.
* @throws IllegalPropertyException in case the attribute has been defined but has incorrect values or it can't be resolved.
*
* @see ReleaseType#getVersionRange()
* @see ReleaseType#getVersionRangeFromBranchName()
*/
public String getVersionRange()
throws DataAccessException, IllegalPropertyException {
return versionRange;
}
/**
* Returns {@code true} if the scope has a non {@code null} version range.
*
* @return {@code true} if the scope has a non {@code null} version range.
*
* @throws DataAccessException in case the attribute cannot be read or accessed.
* @throws IllegalPropertyException in case the attribute has been defined but has incorrect values or it can't be resolved.
*/
public boolean hasVersionRange()
throws DataAccessException, IllegalPropertyException {
return !Objects.isNull(versionRange);
}
/**
* Sets the regular expression used to check the version against a range constraint.
*
* @param versionRange the regular expression used to check the version against a range constraint.
*
* @throws DataAccessException in case the attribute cannot be written or accessed.
* @throws IllegalPropertyException in case the attribute has incorrect values or it can't be resolved.
*/
public void setVersionRange(String versionRange)
throws DataAccessException, IllegalPropertyException {
this.versionRange = versionRange;
}
/**
* Updates the current timestamp and returns the updated value.
*
* @return the updated timestamp.
*
* @see #getTimestamp()
*/
public Long touchTimestamp() {
timestamp = Long.valueOf(System.currentTimeMillis());
return timestamp;
}
/**
* Returns a multi-line summary of the most relevant attributes in the current state object.
*
* @return a multi-line summary of the most relevant attributes in the current state object.
*
* @throws DataAccessException in case the attribute cannot be written or accessed.
* @throws IllegalPropertyException in case the attribute has incorrect values or it can't be resolved.
*/
public String summary()
throws DataAccessException, IllegalPropertyException {
StringWriter sw = new StringWriter();
BufferedWriter bw = new BufferedWriter(sw);
try {
bw.write(String.format("branch = %s", hasBranch() ? getBranch() : "")); bw.newLine();
bw.write(String.format("bump = %s", hasBump() ? getBump() : "")); bw.newLine();
bw.write(String.format("core version = %b", getCoreVersion().booleanValue())); bw.newLine();
bw.write(String.format("latest version = %b", hasLatestVersion() ? getLatestVersion().booleanValue() : false)); bw.newLine();
bw.write(String.format("new release = %b", getNewRelease().booleanValue())); bw.newLine();
bw.write(String.format("new version = %b", getNewVersion().booleanValue())); bw.newLine();
bw.write(String.format("scheme = %s", getScheme().toString())); bw.newLine();
bw.write(String.format("timestamp = %d", getTimestamp().longValue())); bw.newLine();
bw.write(String.format("current version = %s", hasVersion() ? getVersion() : "")); bw.newLine();
bw.write(String.format("previous version = %s", Objects.isNull(getReleaseScope()) || !getReleaseScope().hasPreviousVersion() ? "" : getReleaseScope().getPreviousVersion())); bw.newLine();
bw.write(String.format("prime version = %s", Objects.isNull(getReleaseScope()) || !getReleaseScope().hasPrimeVersion() ? "" : getReleaseScope().getPrimeVersion())); bw.newLine();
bw.flush();
sw.flush();
}
catch (IOException ioe) {
throw new DataAccessException("Unable to write the summary", ioe);
}
return sw.toString();
}
}