com.mooltiverse.oss.nyx.configuration.Configuration 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.configuration;
import static com.mooltiverse.oss.nyx.log.Markers.CONFIGURATION;
import java.io.File;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.List;
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.presets.Presets;
import com.mooltiverse.oss.nyx.entities.Attachment;
import com.mooltiverse.oss.nyx.entities.ChangelogConfiguration;
import com.mooltiverse.oss.nyx.entities.CommitMessageConvention;
import com.mooltiverse.oss.nyx.entities.CommitMessageConventions;
import com.mooltiverse.oss.nyx.entities.GitConfiguration;
import com.mooltiverse.oss.nyx.entities.GitRemoteConfiguration;
import com.mooltiverse.oss.nyx.entities.IllegalPropertyException;
import com.mooltiverse.oss.nyx.entities.ReleaseType;
import com.mooltiverse.oss.nyx.entities.ReleaseTypes;
import com.mooltiverse.oss.nyx.entities.ServiceConfiguration;
import com.mooltiverse.oss.nyx.entities.Substitution;
import com.mooltiverse.oss.nyx.entities.Substitutions;
import com.mooltiverse.oss.nyx.entities.Verbosity;
import com.mooltiverse.oss.nyx.io.DataAccessException;
import com.mooltiverse.oss.nyx.io.FileMapper;
import com.mooltiverse.oss.nyx.version.Scheme;
/**
* The Nyx configuration. The configuration is a live object that resolves each option lazily, only when required.
* This not only improves the overall performances but is also safer as in case of malformed configuration options, only
* those actually needed are resolved.
*
* This means that even if the configuration sources don't change throughout a release process, the state of the
* configuration may change every time a not yet resolved option is requested and evaluated.
*
* The configuration is layered, where each layer represents a source of configuration options. There is a clear definition
* of priorities among different layers so there is a clear precedence of options coming from one layer or another.
* Thanks to this, each option can be overridden by other layer with higher priority.
*
* There must be only one instance of this class for every execution and it's retrieved by {@link Nyx#configuration()}.
*/
public class Configuration implements ConfigurationRoot {
/**
* The private logger instance
*/
private static final Logger logger = LoggerFactory.getLogger(Configuration.class);
/**
* The private instance of the changelog configuration section.
*/
private ChangelogConfiguration changelogSection = null;
/**
* The private instance of the commit message convention configuration section.
*/
private CommitMessageConventions commitMessageConventionsSection = null;
/**
* The private instance of the Git configuration section.
*/
private GitConfiguration gitSection = null;
/**
* The private instance of the release assets configuration section.
*/
private Map releaseAssetsSection = null;
/**
* The private instance of the release types configuration section.
*/
private ReleaseTypes releaseTypesSection = null;
/**
* The private instance of the services configuration section.
*/
private Map servicesSection = null;
/**
* The private instance of the substitutions configuration section.
*/
private Substitutions substitutionsSection = null;
/**
* The internal representation of the configuration layers and their priorities.
*
* Map entries are ordered by the natural order of the {@link LayerPriority} keys so by iterating over the
* entries in this map we are assured that the evaluation order is safe.
*
* This instance is initialized with the {@link DefaultLayer} (which has the least priority) as a last resort
* when looking up configuration options.
*/
private final EnumMap layers = new EnumMap(LayerPriority.class){
// The default serial version UID
private static final long serialVersionUID = 1L;
{
// Initialize the layers with the default values, which have the least priority
// and the environment variables layer, with an high priority
put(LayerPriority.DEFAULT, DefaultLayer.getInstance());
put(LayerPriority.ENVIRONMENT, EnvironmentConfigurationLayer.getInstance());
}
};
/**
* Default constructor. Returns a new configuration object at its initial state.
*
* Instances of this class are created using the {@link Nyx#configuration()} method so this constructor should never be used alone.
*
* See {@link Nyx#configuration()}
*
* @throws DataAccessException in case data cannot be read or accessed.
* @throws IllegalPropertyException in case some option has been defined but has incorrect values or it can't be resolved.
*/
public Configuration()
throws DataAccessException, IllegalPropertyException {
super();
logger.trace(CONFIGURATION, "New configuration object");
loadStandardConfigurationFileLayers();
}
/**
* Returns a file built on the given path if it's already an absolute file path, otherwise make it absolute by resolving it with the
* configured (or default) directory.
*
* @param path the file to make absolute
*
* @return the absolute representation of the file
*
* @see #getDirectory()
*
* @throws DataAccessException in case data cannot be read or accessed.
* @throws IllegalPropertyException in case some option has been defined but has incorrect values or it can't be resolved.
*/
private File getAbsoluteFilePath(String path)
throws DataAccessException, IllegalPropertyException {
File res = new File(path);
return res.isAbsolute() ? res : new File(new File(getDirectory()), path);
}
/**
* Loads the various standard configuration file layers, if found, searched at their default locations.
*
* @throws DataAccessException in case data cannot be read or accessed.
* @throws IllegalPropertyException in case some option has been defined but has incorrect values or it can't be resolved.
*/
private void loadStandardConfigurationFileLayers()
throws DataAccessException, IllegalPropertyException {
logger.debug(CONFIGURATION, "Searching for standard configuration files...");
// load standard local configuration files first, if any
for (String fileName: List.of(".nyx.json", ".nyx.yaml", ".nyx.yml")) {
File file = getAbsoluteFilePath(fileName);
if (file.exists() && file.isFile()) {
logger.debug(CONFIGURATION, "Standard local configuration file found at '{}'. Loading...", file.getAbsolutePath());
layers.put(LayerPriority.STANDARD_LOCAL_FILE, FileMapper.load(file, SimpleConfigurationLayer.class));
logger.debug(CONFIGURATION, "Standard local configuration file '{}' loaded", file.getAbsolutePath());
break;
}
else logger.debug(CONFIGURATION, "Standard local configuration file '{}' not found.", file.getAbsolutePath());
}
// then load standard shared configuration files, if any
for (String fileName: List.of(".nyx-shared.json", ".nyx-shared.yaml", ".nyx-shared.yml")) {
File file = getAbsoluteFilePath(fileName);
if (file.exists() && file.isFile()) {
logger.debug(CONFIGURATION, "Standard shared configuration file found at '{}'. Loading...", file.getAbsolutePath());
layers.put(LayerPriority.STANDARD_SHARED_FILE, FileMapper.load(file, SimpleConfigurationLayer.class));
logger.debug(CONFIGURATION, "Standard shared configuration file '{}' loaded", file.getAbsolutePath());
break;
}
else logger.debug(CONFIGURATION, "Standard shared configuration file '{}' not found.", file.getAbsolutePath());
}
if (layers.containsKey(LayerPriority.STANDARD_LOCAL_FILE) || layers.containsKey(LayerPriority.STANDARD_SHARED_FILE))
updateConfiguredConfigurationLayers();
}
/**
* Resets the cache of resolved options.
*/
private synchronized void resetCache() {
logger.trace(CONFIGURATION, "Clearing the configuration cache");
changelogSection = null;
commitMessageConventionsSection = null;
gitSection = null;
releaseAssetsSection = null;
releaseTypesSection = null;
servicesSection = null;
substitutionsSection = null;
}
/**
* Makes sure that the configuration layers that can be configured (custom configuration file, custom shared
* configuration file, preset) are added or removed into the internal layers representation, according to the
* actual configuration parameters.
*
* This method must be invoked after any core layer (not among the configured ones) changes, or after a batch
* of those changes.
*
* @throws DataAccessException in case data cannot be read or accessed.
* @throws IllegalPropertyException in case some option has been defined but has incorrect values or it can't be resolved.
*/
private synchronized void updateConfiguredConfigurationLayers()
throws DataAccessException, IllegalPropertyException {
// follow the evaluation order from top to bottom to make sure that any change applied here does not
// require further changes to the layers that we already checked
// start with the local custom configuration file
if (Objects.isNull(getConfigurationFile())) {
logger.debug(CONFIGURATION, "Clearing the custom local configuration file, if any");
layers.remove(LayerPriority.CUSTOM_LOCAL_FILE);
}
else if (getConfigurationFile().isBlank()) {
logger.error(CONFIGURATION, "An empty path has been defined for the local custom configuration file and it will be ignored");
layers.remove(LayerPriority.CUSTOM_LOCAL_FILE);
}
else {
File customLocalConfigurationFile = getAbsoluteFilePath(getConfigurationFile());
logger.debug(CONFIGURATION, "Loading custom local configuration file at '{}'", customLocalConfigurationFile.getAbsolutePath());
layers.put(LayerPriority.CUSTOM_LOCAL_FILE, FileMapper.load(customLocalConfigurationFile, SimpleConfigurationLayer.class));
logger.debug(CONFIGURATION, "Custom local configuration file '{}' loaded", customLocalConfigurationFile.getAbsolutePath());
}
// now the local shared configuration file
if (Objects.isNull(getSharedConfigurationFile())) {
logger.debug(CONFIGURATION, "Clearing the custom shared configuration file, if any");
layers.remove(LayerPriority.CUSTOM_SHARED_FILE);
}
else if (getSharedConfigurationFile().isBlank()) {
logger.error(CONFIGURATION, "An empty path has been defined for the local shared configuration file and it will be ignored");
layers.remove(LayerPriority.CUSTOM_SHARED_FILE);
}
else {
File customSharedConfigurationFile = getAbsoluteFilePath(getSharedConfigurationFile());
logger.debug(CONFIGURATION, "Loading custom shared configuration file at '{}'", customSharedConfigurationFile.getAbsolutePath());
layers.put(LayerPriority.CUSTOM_SHARED_FILE, FileMapper.load(customSharedConfigurationFile, SimpleConfigurationLayer.class));
logger.debug(CONFIGURATION, "Custom shared configuration file '{}' loaded", customSharedConfigurationFile.getAbsolutePath());
}
// now the preset
if (Objects.isNull(getPreset())) {
logger.debug(CONFIGURATION, "Clearing the preset configuration, if any");
layers.remove(LayerPriority.PRESET);
}
else if (getPreset().isBlank()) {
logger.error(CONFIGURATION, "An empty name has been defined for the preset configuration and it will be ignored");
layers.remove(LayerPriority.PRESET);
}
else {
logger.debug(CONFIGURATION, "Loading preset configuration '{}'", getPreset());
layers.put(LayerPriority.PRESET, Presets.byName(getPreset()));
logger.debug(CONFIGURATION, "Preset configuration '{}' loaded", getPreset());
}
}
/**
* Adds, replaces or removes the layer at the {@link LayerPriority#COMMAND_LINE} level.
*
* @param layer the configuration layer to set at the {@link LayerPriority#COMMAND_LINE} level.
* If {@code null} any existing configuration layer at the same level is removed (if any).
*
* @return a reference to this same object.
*
* @throws DataAccessException in case data cannot be read or accessed.
* @throws IllegalPropertyException in case some option has been defined but has incorrect values or it can't be resolved.
*/
public Configuration withCommandLineConfiguration(ConfigurationLayer layer)
throws DataAccessException, IllegalPropertyException {
if (Objects.isNull(layer)) {
logger.debug(CONFIGURATION, "Removing the existing '{}' configuration layer, if any", LayerPriority.COMMAND_LINE);
layers.remove(LayerPriority.COMMAND_LINE);
}
else {
logger.debug(CONFIGURATION, "Adding or replacing the '{}' configuration layer", LayerPriority.COMMAND_LINE);
layers.put(LayerPriority.COMMAND_LINE, layer);
}
updateConfiguredConfigurationLayers();
resetCache();
return this;
}
/**
* Adds, replaces or removes the layer at the {@link LayerPriority#PLUGIN} level.
*
* @param layer the configuration layer to set at the {@link LayerPriority#PLUGIN} level.
* If {@code null} any existing configuration layer at the same level is removed (if any).
*
* @return a reference to this same object.
*
* @throws DataAccessException in case data cannot be read or accessed.
* @throws IllegalPropertyException in case some option has been defined but has incorrect values or it can't be resolved.
*/
public Configuration withPluginConfiguration(ConfigurationLayer layer)
throws DataAccessException, IllegalPropertyException {
if (Objects.isNull(layer)) {
logger.debug(CONFIGURATION, "Removing the existing '{}' configuration layer, if any", LayerPriority.PLUGIN);
layers.remove(LayerPriority.PLUGIN);
}
else {
logger.debug(CONFIGURATION, "Adding or replacing the '{}' configuration layer", LayerPriority.PLUGIN);
layers.put(LayerPriority.PLUGIN, layer);
}
updateConfiguredConfigurationLayers();
resetCache();
return this;
}
/**
* Adds, replaces or removes the layer at the {@link LayerPriority#RUNTIME} level, which is the one that can override
* all other layers.
*
* @param layer the configuration layer to set at the {@link LayerPriority#RUNTIME} level.
* If {@code null} any existing configuration layer at the same level is removed (if any).
*
* @return a reference to this same object.
*
* @throws DataAccessException in case data cannot be read or accessed.
* @throws IllegalPropertyException in case some option has been defined but has incorrect values or it can't be resolved.
*/
public Configuration withRuntimeConfiguration(ConfigurationLayer layer)
throws DataAccessException, IllegalPropertyException {
if (Objects.isNull(layer)) {
logger.debug(CONFIGURATION, "Removing the existing '{}' configuration layer, if any", LayerPriority.RUNTIME);
layers.remove(LayerPriority.RUNTIME);
}
else {
logger.debug(CONFIGURATION, "Adding or replacing the '{}' configuration layer", LayerPriority.RUNTIME);
layers.put(LayerPriority.RUNTIME, layer);
}
updateConfiguredConfigurationLayers();
resetCache();
return this;
}
/**
* {@inheritDoc}
*/
@Override
public String getBump()
throws DataAccessException, IllegalPropertyException {
logger.trace(CONFIGURATION, "Retrieving the '{}' configuration option", "bump");
for (ConfigurationLayer layer: layers.values()) {
String bump = layer.getBump();
if (!Objects.isNull(bump)) {
logger.trace(CONFIGURATION, "The '{}' configuration option value is: '{}'", "bump", bump);
return bump;
}
}
return DefaultLayer.getInstance().getBump();
}
/**
* {@inheritDoc}
*/
@Override
public ChangelogConfiguration getChangelog()
throws DataAccessException, IllegalPropertyException {
logger.trace(CONFIGURATION, "Retrieving the changelog configuration");
if (Objects.isNull(changelogSection)) {
changelogSection = new ChangelogConfiguration();
for (ConfigurationLayer layer: layers.values()) {
// Since all attributes of the changelog configuration are objects we assume that if they are null
// they have the default values and we keep non null values as those overriding defaults.
// The sections map is assumed to override inherited values if its size is not 0
if (Objects.isNull(changelogSection.getAppend()))
changelogSection.setAppend(layer.getChangelog().getAppend());
if (Objects.isNull(changelogSection.getPath()))
changelogSection.setPath(layer.getChangelog().getPath());
if (Objects.isNull(changelogSection.getSections()) || changelogSection.getSections().isEmpty())
changelogSection.setSections(layer.getChangelog().getSections());
if (Objects.isNull(changelogSection.getSubstitutions()) || changelogSection.getSubstitutions().isEmpty())
changelogSection.setSubstitutions(layer.getChangelog().getSubstitutions());
if (Objects.isNull(changelogSection.getTemplate()))
changelogSection.setTemplate(layer.getChangelog().getTemplate());
}
logger.trace(CONFIGURATION, "The '{}' configuration option has been resolved", "changelog");
}
return changelogSection;
}
/**
* {@inheritDoc}
*/
@Override
public CommitMessageConventions getCommitMessageConventions()
throws DataAccessException, IllegalPropertyException {
logger.trace(CONFIGURATION, "Retrieving the commit message conventions");
if (Objects.isNull(commitMessageConventionsSection)) {
// parse the 'enabled' items list
List enabled = new ArrayList();
for (ConfigurationLayer layer: layers.values()) {
if (!Objects.isNull(layer.getCommitMessageConventions().getEnabled()) && !layer.getCommitMessageConventions().getEnabled().isEmpty()) {
enabled = layer.getCommitMessageConventions().getEnabled();
logger.trace(CONFIGURATION, "The '{}.{}' configuration option value is: '{}'", "commitMessageConventions", "enabled", String.join(", ", enabled));
break;
}
}
// parse the 'items' map
Map items = new HashMap();
for (String enabledItem: enabled) {
for (ConfigurationLayer layer: layers.values()) {
CommitMessageConvention item = layer.getCommitMessageConventions().getItems().get(enabledItem);
if (!Objects.isNull(item)) {
items.put(enabledItem, item);
logger.trace(CONFIGURATION, "The '{}.{}[{}]' configuration option has been resolved", "commitMessageConventions", "items", enabledItem);
break;
}
}
}
commitMessageConventionsSection = new CommitMessageConventions(enabled, items);
logger.trace(CONFIGURATION, "The '{}' configuration option has been resolved", "commitMessageConventions");
}
return commitMessageConventionsSection;
}
/**
* {@inheritDoc}
*/
@Override
public String getConfigurationFile()
throws DataAccessException, IllegalPropertyException {
logger.trace(CONFIGURATION, "Retrieving the '{}' configuration option", "configurationFile");
for (Map.Entry layerEntry: layers.entrySet()) {
// custom configuration file configuration is ignored on custom configuration file layers to avoid chaining
if (!LayerPriority.CUSTOM_LOCAL_FILE.equals(layerEntry.getKey())) {
String configurationFile = layerEntry.getValue().getConfigurationFile();
if (!Objects.isNull(configurationFile)) {
logger.trace(CONFIGURATION, "The '{}' configuration option value is: '{}'", "configurationFile", configurationFile);
return configurationFile;
}
}
}
return DefaultLayer.getInstance().getConfigurationFile();
}
/**
* {@inheritDoc}
*/
@Override
public String getDirectory()
throws DataAccessException, IllegalPropertyException {
logger.trace(CONFIGURATION, "Retrieving the '{}' configuration option", "directory");
for (ConfigurationLayer layer: layers.values()) {
String directory = layer.getDirectory();
if (!Objects.isNull(directory)) {
logger.trace(CONFIGURATION, "The '{}' configuration option value is: '{}'", "directory", directory);
return directory;
}
}
return DefaultLayer.getInstance().getDirectory();
}
/**
* This method allows to override the default directory that will be returned by {@link #getDirectory()}.
* This method must be invoked before instances of {@link Nyx} or other classes are created or the given value may be ignored.
*
* @param directory the new default directory. If {@code null} then the standard default directory will be used.
*/
public static void setDefaultDirectory(File directory) {
logger.trace(CONFIGURATION, "Setting the default directory '{}'", Objects.isNull(directory) ? "null" : directory.getAbsolutePath());
DefaultLayer.getInstance().setDirectory(Objects.isNull(directory) ? null : directory.getAbsolutePath());
}
/**
* {@inheritDoc}
*/
@Override
public Boolean getDryRun()
throws DataAccessException, IllegalPropertyException {
logger.trace(CONFIGURATION, "Retrieving the '{}' configuration option", "dryRun");
for (ConfigurationLayer layer: layers.values()) {
Boolean dryRun = layer.getDryRun();
if (!Objects.isNull(dryRun)) {
logger.trace(CONFIGURATION, "The '{}' configuration option value is: '{}'", "dryRun", dryRun);
return dryRun;
}
}
return DefaultLayer.getInstance().getDryRun();
}
/**
* {@inheritDoc}
*/
@Override
public GitConfiguration getGit()
throws DataAccessException, IllegalPropertyException {
logger.trace(CONFIGURATION, "Retrieving the Git configuration");
if (Objects.isNull(gitSection)) {
// parse the 'remotes' map
Map remotes = new HashMap();
for (ConfigurationLayer layer: layers.values()) {
for (String remoteName: layer.getGit().getRemotes().keySet()) {
GitRemoteConfiguration remote = layer.getGit().getRemotes().get(remoteName);
if (!Objects.isNull(remote) && !remotes.containsKey(remoteName)) {
remotes.put(remoteName, remote);
logger.trace(CONFIGURATION, "The '{}.{}[{}]' configuration option has been resolved", "git", "remotes", remoteName);
}
}
}
gitSection = new GitConfiguration(remotes);
}
return gitSection;
}
/**
* {@inheritDoc}
*/
@Override
public String getInitialVersion()
throws DataAccessException, IllegalPropertyException {
logger.trace(CONFIGURATION, "Retrieving the '{}' configuration option", "initialVersion");
for (ConfigurationLayer layer: layers.values()) {
String initialVersion = layer.getInitialVersion();
if (!Objects.isNull(initialVersion)) {
logger.trace(CONFIGURATION, "The '{}' configuration option value is: '{}'", "initialVersion", initialVersion);
return initialVersion;
}
}
return DefaultLayer.getInstance().getInitialVersion();
}
/**
* {@inheritDoc}
*/
@Override
public String getPreset()
throws DataAccessException, IllegalPropertyException {
logger.trace(CONFIGURATION, "Retrieving the '{}' configuration option", "preset");
for (Map.Entry layerEntry: layers.entrySet()) {
// preset configuration is ignored on preset layers to avoid chaining
if (!LayerPriority.PRESET.equals(layerEntry.getKey())) {
String preset = layerEntry.getValue().getPreset();
if (!Objects.isNull(preset)) {
logger.trace(CONFIGURATION, "The '{}' configuration option value is: '{}'", "preset", preset);
return preset;
}
}
}
return DefaultLayer.getInstance().getPreset();
}
/**
* {@inheritDoc}
*/
@Override
public Map getReleaseAssets()
throws DataAccessException, IllegalPropertyException {
logger.trace(CONFIGURATION, "Retrieving the release assets");
if (Objects.isNull(releaseAssetsSection)) {
// parse the 'releaseAssets' map
releaseAssetsSection = new HashMap();
for (ConfigurationLayer layer: layers.values()) {
for (String releaseAssetName: layer.getReleaseAssets().keySet()) {
if (!releaseAssetsSection.containsKey(releaseAssetName)) {
releaseAssetsSection.put(releaseAssetName, layer.getReleaseAssets().get(releaseAssetName));
logger.trace(CONFIGURATION, "The '{}[{}]' configuration option has been resolved", "releaseAssets", releaseAssetName);
}
}
}
}
return releaseAssetsSection;
}
/**
* {@inheritDoc}
*/
@Override
public Boolean getReleaseLenient()
throws DataAccessException, IllegalPropertyException {
logger.trace(CONFIGURATION, "Retrieving the '{}' configuration option", "releaseLenient");
for (ConfigurationLayer layer: layers.values()) {
Boolean releaseLenient = layer.getReleaseLenient();
if (!Objects.isNull(releaseLenient)) {
logger.trace(CONFIGURATION, "The '{}' configuration option value is: '{}'", "releaseLenient", releaseLenient);
return releaseLenient;
}
}
return DefaultLayer.getInstance().getReleaseLenient();
}
/**
* {@inheritDoc}
*/
@Override
public String getReleasePrefix()
throws DataAccessException, IllegalPropertyException {
logger.trace(CONFIGURATION, "Retrieving the '{}' configuration option", "releasePrefix");
for (ConfigurationLayer layer: layers.values()) {
String releasePrefix = layer.getReleasePrefix();
if (!Objects.isNull(releasePrefix)) {
logger.trace(CONFIGURATION, "The '{}' configuration option value is: '{}'", "releasePrefix", releasePrefix);
return releasePrefix;
}
}
return DefaultLayer.getInstance().getReleasePrefix();
}
/**
* {@inheritDoc}
*/
@Override
public ReleaseTypes getReleaseTypes()
throws DataAccessException, IllegalPropertyException {
logger.trace(CONFIGURATION, "Retrieving the release types");
if (Objects.isNull(releaseTypesSection)) {
// parse the 'enabled' items list
List enabled = new ArrayList();
for (ConfigurationLayer layer: layers.values()) {
if (!Objects.isNull(layer.getReleaseTypes().getEnabled()) && !layer.getReleaseTypes().getEnabled().isEmpty()) {
enabled = layer.getReleaseTypes().getEnabled();
logger.trace(CONFIGURATION, "The '{}.{}' configuration option value is: '{}'", "releaseTypes", "enabled", String.join(", ", enabled));
break;
}
}
// parse the 'publicationServices' items list
List publicationServices = new ArrayList();
for (ConfigurationLayer layer: layers.values()) {
if (!Objects.isNull(layer.getReleaseTypes().getPublicationServices()) && !layer.getReleaseTypes().getPublicationServices().isEmpty()) {
publicationServices = layer.getReleaseTypes().getPublicationServices();
logger.trace(CONFIGURATION, "The '{}.{}' configuration option value is: '{}'", "releaseTypes", "publicationServices", String.join(", ", publicationServices));
break;
}
}
// parse the 'remoteRepositories' items list
List remoteRepositories = new ArrayList();
for (ConfigurationLayer layer: layers.values()) {
if (!Objects.isNull(layer.getReleaseTypes().getRemoteRepositories()) && !layer.getReleaseTypes().getRemoteRepositories().isEmpty()) {
remoteRepositories = layer.getReleaseTypes().getRemoteRepositories();
logger.trace(CONFIGURATION, "The '{}.{}' configuration option value is: '{}'", "releaseTypes", "remoteRepositories", String.join(", ", remoteRepositories));
break;
}
}
// parse the 'items' map
Map items = new HashMap();
for (String enabledItem: enabled) {
for (ConfigurationLayer layer: layers.values()) {
ReleaseType item = layer.getReleaseTypes().getItems().get(enabledItem);
if (!Objects.isNull(item)) {
items.put(enabledItem, item);
logger.trace(CONFIGURATION, "The '{}.{}[{}]' configuration option has been resolved", "releaseTypes", "items", enabledItem);
break;
}
}
}
releaseTypesSection = new ReleaseTypes(enabled, publicationServices, remoteRepositories, items);
}
return releaseTypesSection;
}
/**
* {@inheritDoc}
*/
@Override
public Boolean getResume()
throws DataAccessException, IllegalPropertyException {
logger.trace(CONFIGURATION, "Retrieving the '{}' configuration option", "resume");
for (ConfigurationLayer layer: layers.values()) {
Boolean resume = layer.getResume();
if (!Objects.isNull(resume)) {
logger.trace(CONFIGURATION, "The '{}' configuration option value is: '{}'", "resume", resume);
return resume;
}
}
return DefaultLayer.getInstance().getResume();
}
/**
* {@inheritDoc}
*/
@Override
public Scheme getScheme()
throws DataAccessException, IllegalPropertyException {
logger.trace(CONFIGURATION, "Retrieving the '{}' configuration option", "scheme");
for (ConfigurationLayer layer: layers.values()) {
Scheme scheme = layer.getScheme();
if (!Objects.isNull(scheme)) {
logger.trace(CONFIGURATION, "The '{}' configuration option value is: '{}'", "scheme", scheme);
return scheme;
}
}
return DefaultLayer.getInstance().getScheme();
}
/**
* {@inheritDoc}
*/
@Override
public Map getServices()
throws DataAccessException, IllegalPropertyException {
logger.trace(CONFIGURATION, "Retrieving the services");
if (Objects.isNull(servicesSection)) {
// parse the 'services' map
servicesSection = new HashMap();
for (ConfigurationLayer layer: layers.values()) {
for (String serviceName: layer.getServices().keySet()) {
if (!servicesSection.containsKey(serviceName)) {
servicesSection.put(serviceName, layer.getServices().get(serviceName));
logger.trace(CONFIGURATION, "The '{}[{}]' configuration option has been resolved", "services", serviceName);
}
}
}
}
return servicesSection;
}
/**
* {@inheritDoc}
*/
@Override
public String getSharedConfigurationFile()
throws DataAccessException, IllegalPropertyException {
logger.trace(CONFIGURATION, "Retrieving the '{}' configuration option", "sharedConfigurationFile");
for (Map.Entry layerEntry: layers.entrySet()) {
// custom shared configuration file configuration is ignored on custom shared configuration file layers to avoid chaining
if (!LayerPriority.CUSTOM_SHARED_FILE.equals(layerEntry.getKey())) {
String sharedConfigurationFile = layerEntry.getValue().getSharedConfigurationFile();
if (!Objects.isNull(sharedConfigurationFile)) {
logger.trace(CONFIGURATION, "The '{}' configuration option value is: '{}'", "sharedConfigurationFile", sharedConfigurationFile);
return sharedConfigurationFile;
}
}
}
return DefaultLayer.getInstance().getSharedConfigurationFile();
}
/**
* {@inheritDoc}
*/
@Override
public String getStateFile()
throws DataAccessException, IllegalPropertyException {
logger.trace(CONFIGURATION, "Retrieving the '{}' configuration option", "stateFile");
for (ConfigurationLayer layer: layers.values()) {
String stateFile = layer.getStateFile();
if (!Objects.isNull(stateFile)) {
logger.trace(CONFIGURATION, "The '{}' configuration option value is: '{}'", "stateFile", stateFile);
return stateFile;
}
}
return DefaultLayer.getInstance().getStateFile();
}
/**
* {@inheritDoc}
*/
@Override
public Substitutions getSubstitutions()
throws DataAccessException, IllegalPropertyException {
logger.trace(CONFIGURATION, "Retrieving the substitutions");
if (Objects.isNull(substitutionsSection)) {
// parse the 'enabled' items list
List enabled = new ArrayList();
for (ConfigurationLayer layer: layers.values()) {
if (!Objects.isNull(layer.getSubstitutions().getEnabled()) && !layer.getSubstitutions().getEnabled().isEmpty()) {
enabled = layer.getSubstitutions().getEnabled();
logger.trace(CONFIGURATION, "The '{}.{}' configuration option value is: '{}'", "substitutions", "enabled", String.join(", ", enabled));
break;
}
}
// parse the 'items' map
Map items = new HashMap();
for (String enabledItem: enabled) {
for (ConfigurationLayer layer: layers.values()) {
Substitution item = layer.getSubstitutions().getItems().get(enabledItem);
if (!Objects.isNull(item)) {
items.put(enabledItem, item);
logger.trace(CONFIGURATION, "The '{}.{}[{}]' configuration option has been resolved", "substitutions", "items", enabledItem);
break;
}
}
}
substitutionsSection = new Substitutions(enabled, items);
logger.trace(CONFIGURATION, "The '{}' configuration option has been resolved", "substitutions");
}
return substitutionsSection;
}
/**
* {@inheritDoc}
*/
@Override
public Boolean getSummary()
throws DataAccessException, IllegalPropertyException {
logger.trace(CONFIGURATION, "Retrieving the '{}' configuration option", "summary");
for (ConfigurationLayer layer: layers.values()) {
Boolean summary = layer.getSummary();
if (!Objects.isNull(summary)) {
logger.trace(CONFIGURATION, "The '{}' configuration option value is: '{}'", "summary", summary);
return summary;
}
}
return DefaultLayer.getInstance().getSummary();
}
/**
* {@inheritDoc}
*/
@Override
public String getSummaryFile()
throws DataAccessException, IllegalPropertyException {
logger.trace(CONFIGURATION, "Retrieving the '{}' configuration option", "summaryFile");
for (ConfigurationLayer layer: layers.values()) {
String summaryFile = layer.getSummaryFile();
if (!Objects.isNull(summaryFile)) {
logger.trace(CONFIGURATION, "The '{}' configuration option value is: '{}'", "summaryFile", summaryFile);
return summaryFile;
}
}
return DefaultLayer.getInstance().getSummaryFile();
}
/**
* {@inheritDoc}
*/
@Override
public Verbosity getVerbosity()
throws DataAccessException, IllegalPropertyException {
logger.trace(CONFIGURATION, "Retrieving the '{}' configuration option", "verbosity");
for (ConfigurationLayer layer: layers.values()) {
Verbosity verbosity = layer.getVerbosity();
if (!Objects.isNull(verbosity)) {
logger.trace(CONFIGURATION, "The '{}' configuration option value is: '{}'", "verbosity", verbosity);
return verbosity;
}
}
return DefaultLayer.getInstance().getVerbosity();
}
/**
* {@inheritDoc}
*/
@Override
public String getVersion()
throws DataAccessException, IllegalPropertyException {
logger.trace(CONFIGURATION, "Retrieving the '{}' configuration option", "version");
for (ConfigurationLayer layer: layers.values()) {
String version = layer.getVersion();
if (!Objects.isNull(version)) {
logger.trace(CONFIGURATION, "The '{}' configuration option value is: '{}'", "version", version);
return version;
}
}
return DefaultLayer.getInstance().getVersion();
}
}