move config and settings to datastructures, deprecate this project
This commit is contained in:
parent
cf295dce5a
commit
ce3eb16efa
69 changed files with 61 additions and 2591 deletions
|
@ -1,5 +1,7 @@
|
||||||
# xbib Content
|
# xbib Content
|
||||||
|
|
||||||
|
Deperecated, use datastructures instead.
|
||||||
|
|
||||||
This is a Java library for processing structured data ("content") in the most popular formats, such as
|
This is a Java library for processing structured data ("content") in the most popular formats, such as
|
||||||
JSON, SMILE-JSON, YAML, XML, CSV, and also semantic descriptions in RDF (N-Triples, Turtle, RDF/XML).
|
JSON, SMILE-JSON, YAML, XML, CSV, and also semantic descriptions in RDF (N-Triples, Turtle, RDF/XML).
|
||||||
|
|
||||||
|
|
11
build.gradle
11
build.gradle
|
@ -4,9 +4,10 @@ plugins {
|
||||||
id "pmd"
|
id "pmd"
|
||||||
id 'maven-publish'
|
id 'maven-publish'
|
||||||
id 'signing'
|
id 'signing'
|
||||||
id "io.github.gradle-nexus.publish-plugin" version "1.3.0"
|
id "io.github.gradle-nexus.publish-plugin" version "2.0.0-rc-1"
|
||||||
id "com.github.spotbugs" version "5.0.14"
|
id "com.github.spotbugs" version "6.0.0-beta.3"
|
||||||
id "org.cyclonedx.bom" version "1.7.2"
|
id "org.cyclonedx.bom" version "1.7.4"
|
||||||
|
id "org.xbib.gradle.plugin.asciidoctor" version "3.0.0"
|
||||||
}
|
}
|
||||||
|
|
||||||
wrapper {
|
wrapper {
|
||||||
|
@ -30,13 +31,13 @@ ext {
|
||||||
}
|
}
|
||||||
|
|
||||||
subprojects {
|
subprojects {
|
||||||
apply from: rootProject.file('gradle/ide/idea.gradle')
|
//apply from: rootProject.file('gradle/ide/idea.gradle')
|
||||||
apply from: rootProject.file('gradle/repositories/maven.gradle')
|
apply from: rootProject.file('gradle/repositories/maven.gradle')
|
||||||
apply from: rootProject.file('gradle/compile/java.gradle')
|
apply from: rootProject.file('gradle/compile/java.gradle')
|
||||||
apply from: rootProject.file('gradle/test/junit5.gradle')
|
apply from: rootProject.file('gradle/test/junit5.gradle')
|
||||||
apply from: rootProject.file('gradle/quality/checkstyle.gradle')
|
apply from: rootProject.file('gradle/quality/checkstyle.gradle')
|
||||||
apply from: rootProject.file('gradle/quality/pmd.gradle')
|
apply from: rootProject.file('gradle/quality/pmd.gradle')
|
||||||
apply from: rootProject.file('gradle/quality/spotbugs.gradle')
|
//apply from: rootProject.file('gradle/quality/spotbugs.gradle')
|
||||||
apply from: rootProject.file('gradle/publish/maven.gradle')
|
apply from: rootProject.file('gradle/publish/maven.gradle')
|
||||||
}
|
}
|
||||||
apply from: rootProject.file('gradle/publish/sonatype.gradle')
|
apply from: rootProject.file('gradle/publish/sonatype.gradle')
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
dependencies {
|
|
||||||
api project(':settings-datastructures')
|
|
||||||
testImplementation project(':settings-datastructures-json')
|
|
||||||
testImplementation project(':settings-datastructures-yaml')
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
import org.xbib.config.ConfigLogger;
|
|
||||||
import org.xbib.config.NullConfigLogger;
|
|
||||||
import org.xbib.config.SystemConfigLogger;
|
|
||||||
import org.xbib.settings.SettingsLoader;
|
|
||||||
|
|
||||||
module org.xbib.config {
|
|
||||||
exports org.xbib.config;
|
|
||||||
uses ConfigLogger;
|
|
||||||
uses SettingsLoader;
|
|
||||||
provides ConfigLogger with NullConfigLogger, SystemConfigLogger;
|
|
||||||
requires org.xbib.settings.api;
|
|
||||||
requires transitive org.xbib.settings.datastructures;
|
|
||||||
}
|
|
|
@ -1,17 +0,0 @@
|
||||||
package org.xbib.config;
|
|
||||||
|
|
||||||
@SuppressWarnings("serial")
|
|
||||||
public class ConfigException extends RuntimeException {
|
|
||||||
|
|
||||||
public ConfigException(Exception e) {
|
|
||||||
super(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConfigException(String message) {
|
|
||||||
super(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConfigException(String message, Throwable cause) {
|
|
||||||
super(message, cause);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,168 +0,0 @@
|
||||||
package org.xbib.config;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.nio.file.FileSystem;
|
|
||||||
import java.nio.file.FileSystems;
|
|
||||||
import java.nio.file.FileVisitOption;
|
|
||||||
import java.nio.file.FileVisitResult;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.nio.file.PathMatcher;
|
|
||||||
import java.nio.file.SimpleFileVisitor;
|
|
||||||
import java.nio.file.attribute.BasicFileAttributes;
|
|
||||||
import java.nio.file.attribute.FileTime;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.EnumSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
public class ConfigFinder {
|
|
||||||
|
|
||||||
private final FileSystem fileSystem;
|
|
||||||
|
|
||||||
private final EnumSet<FileVisitOption> opts;
|
|
||||||
|
|
||||||
private final List<Path> result;
|
|
||||||
|
|
||||||
private Comparator<Path> comparator;
|
|
||||||
|
|
||||||
public ConfigFinder() {
|
|
||||||
this(FileSystems.getDefault(), EnumSet.of(FileVisitOption.FOLLOW_LINKS));
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConfigFinder(FileSystem fileSystem, EnumSet<FileVisitOption> opts) {
|
|
||||||
this.fileSystem = fileSystem;
|
|
||||||
this.opts = opts;
|
|
||||||
this.result = new ArrayList<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConfigFinder find(String path, String pathPattern) throws IOException {
|
|
||||||
return find(null, null, fileSystem.getPath(path), pathPattern);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConfigFinder find(String base, String basePattern, String path, String pathPattern) throws IOException {
|
|
||||||
return find(base == null || base.isEmpty() ? null : fileSystem.getPath(base), basePattern,
|
|
||||||
path == null || path.isEmpty() ? null : fileSystem.getPath(path), pathPattern);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConfigFinder find(Path base, String basePattern, Path path, String pathPattern) throws IOException {
|
|
||||||
return find(base, basePattern, path, pathPattern, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find the most recent version of a file.
|
|
||||||
*
|
|
||||||
* @param base the path of the base directory
|
|
||||||
* @param basePattern a pattern to match directory entries in the base directory or null to match '*'
|
|
||||||
* @param path the path of the file if no recent path can be found in the base directory or null
|
|
||||||
* @param pathPattern the file name pattern to match
|
|
||||||
* @param modifiedSince time stamp for file or null
|
|
||||||
* @return this Finder
|
|
||||||
* @throws IOException if find fails
|
|
||||||
*/
|
|
||||||
public ConfigFinder find(Path base,
|
|
||||||
String basePattern,
|
|
||||||
Path path,
|
|
||||||
String pathPattern,
|
|
||||||
FileTime modifiedSince) throws IOException {
|
|
||||||
if (base != null && path == null) {
|
|
||||||
// find input in base
|
|
||||||
final PathMatcher baseMatcher = base.getFileSystem()
|
|
||||||
.getPathMatcher("glob:" + (basePattern != null ? basePattern : "*"));
|
|
||||||
final PathMatcher pathMatcher = base.getFileSystem()
|
|
||||||
.getPathMatcher("glob:" + (pathPattern != null ? pathPattern : "*"));
|
|
||||||
List<Path> directories = new ArrayList<>();
|
|
||||||
List<Path> list = Files.find(base, 1,
|
|
||||||
(p, a) -> {
|
|
||||||
if (Files.isDirectory(p) && baseMatcher.matches(p.getFileName())) {
|
|
||||||
directories.add(p);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return Files.isRegularFile(p) && pathMatcher.matches(p.getFileName());
|
|
||||||
}, FileVisitOption.FOLLOW_LINKS)
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
if (directories.isEmpty()) {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
list.sort(LAST_MODIFIED_COMPARATOR.reversed());
|
|
||||||
result.addAll(list);
|
|
||||||
path = list.iterator().next();
|
|
||||||
}
|
|
||||||
if (path == null) {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
final PathMatcher pathMatcher = path.getFileSystem()
|
|
||||||
.getPathMatcher("glob:" + (pathPattern != null ? pathPattern : "*"));
|
|
||||||
Files.walkFileTree(path, opts, Integer.MAX_VALUE, new SimpleFileVisitor<>() {
|
|
||||||
@Override
|
|
||||||
public FileVisitResult visitFile(Path p, BasicFileAttributes a) {
|
|
||||||
if ((Files.isRegularFile(p) && pathMatcher.matches(p.getFileName())) &&
|
|
||||||
(modifiedSince == null || a.lastModifiedTime().toMillis() > modifiedSince.toMillis())) {
|
|
||||||
result.add(p);
|
|
||||||
}
|
|
||||||
return FileVisitResult.CONTINUE;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConfigFinder sortBy(String mode) {
|
|
||||||
if ("lastmodified".equals(mode)) {
|
|
||||||
this.comparator = LAST_MODIFIED_COMPARATOR;
|
|
||||||
} else if ("name".equals(mode)) {
|
|
||||||
this.comparator = PATH_NAME_COMPARATOR;
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConfigFinder order(String mode) {
|
|
||||||
if ("desc".equals(mode)) {
|
|
||||||
this.comparator = Collections.reverseOrder(comparator);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Stream<Path> getPathFiles() {
|
|
||||||
return getPathFiles(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Stream<Path> getPathFiles(long max) {
|
|
||||||
if (comparator != null) {
|
|
||||||
result.sort(comparator);
|
|
||||||
}
|
|
||||||
return result.stream().limit(max < 0 ? result.size() : max);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Stream<Path> skipPathFiles(long skip) {
|
|
||||||
if (comparator != null) {
|
|
||||||
result.sort(comparator);
|
|
||||||
}
|
|
||||||
return result.stream().skip(skip < 0 ? 0 : skip);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Stream<String> getPaths() {
|
|
||||||
return getPaths(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Stream<String> getPaths(long max) {
|
|
||||||
if (comparator != null) {
|
|
||||||
result.sort(comparator);
|
|
||||||
}
|
|
||||||
return result.stream()
|
|
||||||
.map(p -> p.toAbsolutePath().toString())
|
|
||||||
.limit(max < 0 ? result.size() : max);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final Comparator<Path> LAST_MODIFIED_COMPARATOR = Comparator.comparing(p -> {
|
|
||||||
try {
|
|
||||||
return Files.getLastModifiedTime(p);
|
|
||||||
} catch (IOException e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
private static final Comparator<Path> PATH_NAME_COMPARATOR = Comparator.comparing(Path::toString);
|
|
||||||
}
|
|
|
@ -1,311 +0,0 @@
|
||||||
package org.xbib.config;
|
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.io.Reader;
|
|
||||||
import java.io.StringReader;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.nio.file.Paths;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.ServiceLoader;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import org.xbib.settings.Settings;
|
|
||||||
import org.xbib.settings.SettingsBuilder;
|
|
||||||
import org.xbib.settings.SettingsLoader;
|
|
||||||
import org.xbib.settings.SettingsLoaderService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A configuration loader for configuration files.
|
|
||||||
*/
|
|
||||||
public class ConfigLoader {
|
|
||||||
|
|
||||||
private static final Map<ConfigParams, Settings> map = new HashMap<>();
|
|
||||||
|
|
||||||
private ConfigLogger logger;
|
|
||||||
|
|
||||||
private ConfigLoader() {
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class Holder {
|
|
||||||
private static ConfigLogger createConfigLogger() {
|
|
||||||
ServiceLoader<ConfigLogger> serviceLoader = ServiceLoader.load(ConfigLogger.class);
|
|
||||||
Optional<ConfigLogger> optionalConfigLogger = serviceLoader.findFirst();
|
|
||||||
return optionalConfigLogger.orElse(new NullConfigLogger());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final ConfigLoader configLoader = new ConfigLoader().withLogger(createConfigLogger());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ConfigLoader getInstance() {
|
|
||||||
return Holder.configLoader;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConfigLoader withLogger(ConfigLogger logger) {
|
|
||||||
this.logger = logger;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized Settings load(ConfigParams configParams) throws ConfigException {
|
|
||||||
map.computeIfAbsent(configParams, p -> internalLoad(p)
|
|
||||||
.replacePropertyPlaceholders()
|
|
||||||
.build());
|
|
||||||
return map.get(configParams);
|
|
||||||
}
|
|
||||||
|
|
||||||
private SettingsBuilder internalLoad(ConfigParams params) throws ConfigException {
|
|
||||||
SettingsBuilder settings = Settings.settingsBuilder();
|
|
||||||
if (params.withSystemEnvironment) {
|
|
||||||
settings.loadFromSystemEnvironment();
|
|
||||||
}
|
|
||||||
if (params.withSystemProperties) {
|
|
||||||
settings.loadFromSystemProperties();
|
|
||||||
}
|
|
||||||
if (!params.settings.isEmpty()) {
|
|
||||||
for (Settings s : params.settings) {
|
|
||||||
settings.put(s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!params.reader.isEmpty()) {
|
|
||||||
for (ConfigParams.SuffixedReader reader : params.reader) {
|
|
||||||
SettingsBuilder readerSettings = createSettingsFromReader(reader.reader, reader.suffix);
|
|
||||||
if (readerSettings != null) {
|
|
||||||
settings.put(readerSettings.build());
|
|
||||||
if (!params.includeAll) {
|
|
||||||
return overrideFromProperties(params, settings);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (params.args != null) {
|
|
||||||
SettingsBuilder argsSettings = createSettingsFromArgs(params);
|
|
||||||
if (argsSettings != null) {
|
|
||||||
settings.put(argsSettings.build());
|
|
||||||
if (!params.includeAll) {
|
|
||||||
return overrideFromProperties(params, settings);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (params.withStdin) {
|
|
||||||
SettingsBuilder stdinSettings = createSettingsFromStdin();
|
|
||||||
if (stdinSettings != null) {
|
|
||||||
settings.put(stdinSettings.build());
|
|
||||||
if (!params.includeAll) {
|
|
||||||
return overrideFromProperties(params, settings);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!params.fileLocations.isEmpty()) {
|
|
||||||
SettingsBuilder fileSettings = createSettingsFromFile(params.fileLocations);
|
|
||||||
if (fileSettings != null) {
|
|
||||||
settings.put(fileSettings.build());
|
|
||||||
if (!params.includeAll) {
|
|
||||||
return overrideFromProperties(params, settings);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!params.fileNamesWithoutSuffix.isEmpty()) {
|
|
||||||
for (String fileNameWithoutSuffix : params.fileNamesWithoutSuffix) {
|
|
||||||
SettingsBuilder fileSettings = createSettingsFromFile(createListOfLocations(params, fileNameWithoutSuffix));
|
|
||||||
if (fileSettings != null) {
|
|
||||||
settings.put(fileSettings.build());
|
|
||||||
if (!params.includeAll) {
|
|
||||||
return overrideFromProperties(params, settings);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (String fileNameWithoutSuffix : params.fileNamesWithoutSuffix) {
|
|
||||||
if (params.classLoaders != null) {
|
|
||||||
for (ClassLoader cl : params.classLoaders) {
|
|
||||||
if (cl != null) {
|
|
||||||
SettingsBuilder classpathSettings = createClasspathSettings(params, cl, fileNameWithoutSuffix);
|
|
||||||
if (classpathSettings != null) {
|
|
||||||
settings.put(classpathSettings.build());
|
|
||||||
if (!params.includeAll) {
|
|
||||||
return overrideFromProperties(params, settings);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!params.jdbcLookups.isEmpty()) {
|
|
||||||
for (ConfigParams.JdbcLookup jdbcLookup : params.jdbcLookups) {
|
|
||||||
try {
|
|
||||||
settings.fromJdbc(jdbcLookup.connection, jdbcLookup.statement, jdbcLookup.params);
|
|
||||||
} catch (SQLException sqlException) {
|
|
||||||
throw new ConfigException(sqlException);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (params.includeAll) {
|
|
||||||
return overrideFromProperties(params, settings);
|
|
||||||
}
|
|
||||||
if (params.failIfEmpty) {
|
|
||||||
throw new ConfigException("no config found");
|
|
||||||
}
|
|
||||||
return settings;
|
|
||||||
}
|
|
||||||
|
|
||||||
private SettingsBuilder createSettingsFromArgs(ConfigParams params) throws ConfigException {
|
|
||||||
if (!params.fileNamesWithoutSuffix.isEmpty() && params.args != null) {
|
|
||||||
for (String fileNameWithoutSuffix : params.fileNamesWithoutSuffix) {
|
|
||||||
for (String suffix : SettingsLoaderService.getInstance().getSuffixes()) {
|
|
||||||
for (int i = 0; i < params.args.size() - 1; i++) {
|
|
||||||
String arg = params.args.get(i);
|
|
||||||
String s = params.directoryName != null ?
|
|
||||||
"--" + params.directoryName + "-" + fileNameWithoutSuffix + "." + suffix :
|
|
||||||
"--" + fileNameWithoutSuffix + "." + suffix;
|
|
||||||
if (arg.equals(s)) {
|
|
||||||
return createSettingsFromReader(new StringReader(params.args.get(i + 1)), suffix);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private SettingsBuilder createSettingsFromStdin() throws ConfigException {
|
|
||||||
if (System.in != null) {
|
|
||||||
try {
|
|
||||||
int numBytesWaiting = System.in.available();
|
|
||||||
if (numBytesWaiting > 0) {
|
|
||||||
String suffix = System.getProperty("config.format", "yaml");
|
|
||||||
return createSettingsFromStream(System.in, "." + suffix);
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new ConfigException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private SettingsBuilder createSettingsFromFile(List<String> settingsFileNames) throws ConfigException {
|
|
||||||
SettingsBuilder settings = Settings.settingsBuilder();
|
|
||||||
for (String settingsFileName: settingsFileNames) {
|
|
||||||
int pos = settingsFileName.lastIndexOf('.');
|
|
||||||
String suffix = (pos > 0 ? settingsFileName.substring(pos + 1) : "").toLowerCase(Locale.ROOT);
|
|
||||||
Path path = Paths.get(settingsFileName);
|
|
||||||
if (logger != null) {
|
|
||||||
logger.info("trying " + path);
|
|
||||||
}
|
|
||||||
if (Files.exists(path)) {
|
|
||||||
if (logger != null) {
|
|
||||||
logger.info("found path: " + path);
|
|
||||||
}
|
|
||||||
System.setProperty("config.path", path.getParent().toString());
|
|
||||||
try {
|
|
||||||
InputStream inputStream = Files.newInputStream(path);
|
|
||||||
SettingsBuilder fileSettings = createSettingsFromStream(inputStream, suffix);
|
|
||||||
if (fileSettings != null) {
|
|
||||||
settings.put(fileSettings.build());
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new ConfigException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return settings.isEmpty() ? null : settings;
|
|
||||||
}
|
|
||||||
|
|
||||||
private SettingsBuilder createClasspathSettings(ConfigParams params,
|
|
||||||
ClassLoader classLoader,
|
|
||||||
String fileNameWithoutSuffix) throws ConfigException {
|
|
||||||
SettingsBuilder settings = Settings.settingsBuilder();
|
|
||||||
for (String suffix : SettingsLoaderService.getInstance().getSuffixes()) {
|
|
||||||
String path = params.directoryName != null ?
|
|
||||||
params.directoryName + '-' + fileNameWithoutSuffix + suffix : fileNameWithoutSuffix + suffix;
|
|
||||||
InputStream inputStream = classLoader.getResourceAsStream(path);
|
|
||||||
if (inputStream != null) {
|
|
||||||
if (logger != null) {
|
|
||||||
logger.info("found resource: " + path);
|
|
||||||
}
|
|
||||||
SettingsBuilder streamSettings = createSettingsFromStream(inputStream, suffix);
|
|
||||||
if (streamSettings != null) {
|
|
||||||
settings.put(streamSettings.build());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return settings.isEmpty() ? null : settings;
|
|
||||||
}
|
|
||||||
|
|
||||||
private SettingsBuilder createSettingsFromStream(InputStream inputStream,
|
|
||||||
String suffix) throws ConfigException {
|
|
||||||
if (inputStream == null) {
|
|
||||||
if (logger != null) {
|
|
||||||
logger.error("unable to open input stream");
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return createSettingsFromReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8), suffix);
|
|
||||||
}
|
|
||||||
|
|
||||||
private SettingsBuilder createSettingsFromReader(Reader reader,
|
|
||||||
String suffix) throws ConfigException {
|
|
||||||
if (reader == null) {
|
|
||||||
if (logger != null) {
|
|
||||||
logger.error("unable to open reader");
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
SettingsLoader settingsLoader = SettingsLoaderService.getInstance().loaderFromResource(suffix);
|
|
||||||
if (settingsLoader != null) {
|
|
||||||
SettingsBuilder settings;
|
|
||||||
try (BufferedReader bufferedReader = new BufferedReader(reader)) {
|
|
||||||
String content = bufferedReader.lines().collect(Collectors.joining("\n"));
|
|
||||||
settings = Settings.settingsBuilder().put(settingsLoader.load(content));
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new ConfigException(e);
|
|
||||||
}
|
|
||||||
return settings;
|
|
||||||
} else {
|
|
||||||
if (logger != null) {
|
|
||||||
logger.error("suffix is invalid: " + suffix);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private SettingsBuilder overrideFromProperties(ConfigParams params, SettingsBuilder settingsBuilder) {
|
|
||||||
if (params.withSystemPropertiesOverride) {
|
|
||||||
settingsBuilder.map(e -> {
|
|
||||||
String key = e.getKey();
|
|
||||||
String value = System.getProperty(params.directoryName != null ? params.directoryName + '.' + key : key);
|
|
||||||
return value != null ? Map.entry(key, value) : Map.entry(key, e.getValue());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return settingsBuilder;
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<String> createListOfLocations(ConfigParams params,
|
|
||||||
String fileNameWithoutSuffix) {
|
|
||||||
List<String> list = new ArrayList<>();
|
|
||||||
for (String suffix : SettingsLoaderService.getInstance().getSuffixes()) {
|
|
||||||
String xdgConfigHome = System.getenv("XDG_CONFIG_HOME");
|
|
||||||
if (xdgConfigHome == null) {
|
|
||||||
xdgConfigHome = System.getProperty("user.home") + "/.config";
|
|
||||||
}
|
|
||||||
if (params.directoryName != null) {
|
|
||||||
list.add(params.directoryName + '-' + fileNameWithoutSuffix + "." + suffix);
|
|
||||||
list.add(xdgConfigHome + '/' + params.directoryName + '/' + fileNameWithoutSuffix + "." + suffix);
|
|
||||||
list.add("/etc/" + params.directoryName + '/' + fileNameWithoutSuffix + "." + suffix);
|
|
||||||
} else {
|
|
||||||
list.add(fileNameWithoutSuffix + "." + suffix);
|
|
||||||
list.add(xdgConfigHome + '/' + fileNameWithoutSuffix + "." + suffix);
|
|
||||||
list.add("/etc/" + fileNameWithoutSuffix + "." + suffix);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
package org.xbib.config;
|
|
||||||
|
|
||||||
public interface ConfigLogger {
|
|
||||||
|
|
||||||
void info(String string);
|
|
||||||
|
|
||||||
void warn(String string);
|
|
||||||
|
|
||||||
void error(String message);
|
|
||||||
}
|
|
|
@ -1,192 +0,0 @@
|
||||||
package org.xbib.config;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.Reader;
|
|
||||||
import java.sql.Connection;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
|
||||||
import org.xbib.settings.Settings;
|
|
||||||
import org.xbib.settings.datastructures.DatastructureSettings;
|
|
||||||
|
|
||||||
public class ConfigParams implements Comparable<ConfigParams> {
|
|
||||||
|
|
||||||
private static final Comparator<ConfigParams> COMPARATOR =
|
|
||||||
Comparator.comparing(ConfigParams::toString);
|
|
||||||
|
|
||||||
boolean withSystemEnvironment = false;
|
|
||||||
|
|
||||||
boolean withSystemProperties = false;
|
|
||||||
|
|
||||||
boolean failIfEmpty = false;
|
|
||||||
|
|
||||||
boolean includeAll = false;
|
|
||||||
|
|
||||||
boolean withStdin = false;
|
|
||||||
|
|
||||||
boolean withSystemPropertiesOverride = false;
|
|
||||||
|
|
||||||
List<ClassLoader> classLoaders = null;
|
|
||||||
|
|
||||||
final List<SuffixedReader> reader = new ArrayList<>();
|
|
||||||
|
|
||||||
final List<JdbcLookup> jdbcLookups = new ArrayList<>();
|
|
||||||
|
|
||||||
final List<DatastructureSettings> settings = new ArrayList<>();
|
|
||||||
|
|
||||||
List<String> args = null;
|
|
||||||
|
|
||||||
String directoryName = null;
|
|
||||||
|
|
||||||
final List<String> fileNamesWithoutSuffix = new ArrayList<>();
|
|
||||||
|
|
||||||
final List<String> fileLocations = new ArrayList<>();
|
|
||||||
|
|
||||||
public ConfigParams() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConfigParams withSystemEnvironment() {
|
|
||||||
this.withSystemEnvironment = true;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConfigParams withSystemProperties() {
|
|
||||||
this.withSystemProperties = true;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConfigParams withSystemPropertiesOverride() {
|
|
||||||
this.withSystemPropertiesOverride = true;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConfigParams includeAll() {
|
|
||||||
this.includeAll = true;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConfigParams failIfEmpty() {
|
|
||||||
this.failIfEmpty = true;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConfigParams withStdin(boolean withStdin) {
|
|
||||||
this.withStdin = withStdin;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConfigParams withArgs(String[] args) {
|
|
||||||
this.args = Arrays.asList(args);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConfigParams withClassLoaders(ClassLoader... classLoaders) {
|
|
||||||
this.classLoaders = Arrays.asList(classLoaders);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConfigParams withReader(Reader reader, String suffix) {
|
|
||||||
SuffixedReader suffixedReader = new SuffixedReader();
|
|
||||||
suffixedReader.reader = reader;
|
|
||||||
suffixedReader.suffix = suffix;
|
|
||||||
this.reader.add(suffixedReader);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConfigParams withSettings(Settings settings) {
|
|
||||||
this.settings.add(DatastructureSettings.builder().put(settings.getAsMap()).build());
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConfigParams withDirectoryName(String directoryName) {
|
|
||||||
this.directoryName = directoryName;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConfigParams withFileNamesWithoutSuffix(String... fileNamesWithoutSuffix) {
|
|
||||||
this.fileNamesWithoutSuffix.addAll(Arrays.asList(fileNamesWithoutSuffix));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConfigParams withLocation(String location) {
|
|
||||||
this.fileLocations.add(location);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConfigParams withPath(String basePath, String basePattern, String path, String pathPattern) throws IOException {
|
|
||||||
ConfigFinder configFinder = new ConfigFinder();
|
|
||||||
configFinder.find(basePath, basePattern, path, pathPattern).getPaths().forEach(this::withLocation);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConfigParams withJdbc(Connection connection, String statement, String[] params) {
|
|
||||||
JdbcLookup jdbcLookup = new JdbcLookup();
|
|
||||||
jdbcLookup.connection = connection;
|
|
||||||
jdbcLookup.statement = statement;
|
|
||||||
jdbcLookup.params = params;
|
|
||||||
jdbcLookups.add(jdbcLookup);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return toString().hashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (o == null || getClass() != o.getClass()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
ConfigParams that = (ConfigParams) o;
|
|
||||||
return withSystemEnvironment == that.withSystemEnvironment &&
|
|
||||||
withSystemProperties == that.withSystemProperties &&
|
|
||||||
failIfEmpty == that.failIfEmpty &&
|
|
||||||
includeAll == that.includeAll &&
|
|
||||||
withStdin == that.withStdin &&
|
|
||||||
withSystemPropertiesOverride == that.withSystemPropertiesOverride &&
|
|
||||||
Objects.equals(classLoaders, that.classLoaders) &&
|
|
||||||
Objects.equals(reader, that.reader) &&
|
|
||||||
Objects.equals(jdbcLookups, that.jdbcLookups) &&
|
|
||||||
Objects.equals(settings, that.settings) &&
|
|
||||||
Objects.equals(args, that.args) &&
|
|
||||||
Objects.equals(directoryName, that.directoryName) &&
|
|
||||||
Objects.equals(fileNamesWithoutSuffix, that.fileNamesWithoutSuffix) &&
|
|
||||||
Objects.equals(fileLocations, that.fileLocations);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int compareTo(ConfigParams o) {
|
|
||||||
return COMPARATOR.compare(this, o);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "" +
|
|
||||||
withSystemEnvironment +
|
|
||||||
withSystemProperties +
|
|
||||||
withStdin +
|
|
||||||
classLoaders +
|
|
||||||
reader +
|
|
||||||
args +
|
|
||||||
directoryName +
|
|
||||||
fileNamesWithoutSuffix +
|
|
||||||
fileLocations;
|
|
||||||
}
|
|
||||||
|
|
||||||
static class SuffixedReader {
|
|
||||||
Reader reader;
|
|
||||||
String suffix;
|
|
||||||
}
|
|
||||||
|
|
||||||
static class JdbcLookup {
|
|
||||||
Connection connection;
|
|
||||||
String statement;
|
|
||||||
String[] params;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,19 +0,0 @@
|
||||||
package org.xbib.config;
|
|
||||||
|
|
||||||
public class NullConfigLogger implements ConfigLogger {
|
|
||||||
|
|
||||||
public NullConfigLogger() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void info(String string) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void warn(String message) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void error(String message) {
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
package org.xbib.config;
|
|
||||||
|
|
||||||
public class SystemConfigLogger implements ConfigLogger {
|
|
||||||
|
|
||||||
public SystemConfigLogger() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void info(String string) {
|
|
||||||
System.err.println("info: " + string);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void warn(String message) {
|
|
||||||
System.err.println("warning: " + message);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void error(String message) {
|
|
||||||
System.err.println("error: " + message);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,4 +0,0 @@
|
||||||
/**
|
|
||||||
* Classes for configuration setup.
|
|
||||||
*/
|
|
||||||
package org.xbib.config;
|
|
|
@ -1,76 +0,0 @@
|
||||||
package org.xbib.config.test;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.Reader;
|
|
||||||
import java.io.StringReader;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.xbib.config.ConfigLoader;
|
|
||||||
import org.xbib.config.ConfigParams;
|
|
||||||
import org.xbib.settings.Settings;
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
|
||||||
|
|
||||||
public class ConfigLoaderTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void configEmptyTest() {
|
|
||||||
Settings settings = ConfigLoader.getInstance()
|
|
||||||
.load(new ConfigParams());
|
|
||||||
assertTrue(settings.isEmpty());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void configSettingsTest() {
|
|
||||||
Settings configSettings = Settings.settingsBuilder()
|
|
||||||
.put("hello", "world")
|
|
||||||
.build();
|
|
||||||
Settings settings = ConfigLoader.getInstance()
|
|
||||||
.load(new ConfigParams().withSettings(configSettings));
|
|
||||||
assertEquals("world", settings.get("hello"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void configArgsTest() {
|
|
||||||
String[] args = new String[] {
|
|
||||||
"--config.yaml",
|
|
||||||
"hello: world"
|
|
||||||
};
|
|
||||||
Settings settings = ConfigLoader.getInstance()
|
|
||||||
.load(new ConfigParams()
|
|
||||||
.withArgs(args)
|
|
||||||
.withFileNamesWithoutSuffix("config"));
|
|
||||||
assertEquals("world", settings.get("hello"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void configPropertiesTest() {
|
|
||||||
Reader reader = new StringReader("a=b");
|
|
||||||
Settings settings = ConfigLoader.getInstance()
|
|
||||||
.load(new ConfigParams()
|
|
||||||
.withReader(reader, "properties"));
|
|
||||||
assertEquals("b", settings.get("a"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void configFileTest() throws IOException {
|
|
||||||
Settings settings = ConfigLoader.getInstance()
|
|
||||||
.load(new ConfigParams()
|
|
||||||
.withPath(null, null, "src/test/resources", "config.*"));
|
|
||||||
assertEquals("world", settings.get("hello"));
|
|
||||||
assertEquals("world2", settings.get("hello2"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSystemPropertiesOverride() throws IOException {
|
|
||||||
System.setProperty("hello", "override");
|
|
||||||
Settings settings = ConfigLoader.getInstance()
|
|
||||||
.load(new ConfigParams()
|
|
||||||
.withPath(null, null, "src/test/resources", "config.*"));
|
|
||||||
assertEquals("world", settings.get("hello"));
|
|
||||||
settings = ConfigLoader.getInstance()
|
|
||||||
.load(new ConfigParams()
|
|
||||||
.withSystemPropertiesOverride()
|
|
||||||
.withPath(null, null, "src/test/resources", "config.*"));
|
|
||||||
assertEquals("override", settings.get("hello"));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,4 +0,0 @@
|
||||||
/**
|
|
||||||
* Test classes for config.
|
|
||||||
*/
|
|
||||||
package org.xbib.config.test;
|
|
|
@ -1,2 +0,0 @@
|
||||||
org.xbib.config.NullConfigLogger
|
|
||||||
org.xbib.config.SystemConfigLogger
|
|
|
@ -1,3 +0,0 @@
|
||||||
org.xbib.settings.datastructures.PropertiesSettingsLoader
|
|
||||||
org.xbib.settings.datastructures.json.JsonSettingsLoader
|
|
||||||
org.xbib.settings.datastructures.yaml.YamlSettingsLoader
|
|
|
@ -1,3 +0,0 @@
|
||||||
{
|
|
||||||
"hello2": "world2"
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
hello: world
|
|
|
@ -7,6 +7,7 @@ import com.fasterxml.jackson.core.JsonParseException;
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.Disabled;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -15,6 +16,7 @@ import java.io.Reader;
|
||||||
import java.io.StringReader;
|
import java.io.StringReader;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
@Disabled("mockito defunct")
|
||||||
public final class JsonNodeReaderTest {
|
public final class JsonNodeReaderTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -13,15 +13,14 @@ import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
import com.fasterxml.jackson.core.TreeNode;
|
import com.fasterxml.jackson.core.TreeNode;
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.Disabled;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
@Disabled("mockito defunct")
|
||||||
*
|
|
||||||
*/
|
|
||||||
public final class TreePointerTest {
|
public final class TreePointerTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
/**
|
|
||||||
* Classes for testing JSON pointer.
|
|
||||||
*/
|
|
||||||
package org.xbib.content.json.pointer;
|
|
|
@ -1,5 +1,5 @@
|
||||||
group = org.xbib
|
group = org.xbib
|
||||||
name = content
|
name = content
|
||||||
version = 5.0.4
|
version = 5.1.0
|
||||||
|
|
||||||
org.gradle.warning.mode = ALL
|
org.gradle.warning.mode = ALL
|
||||||
|
|
|
@ -2,29 +2,25 @@
|
||||||
apply plugin: 'java-library'
|
apply plugin: 'java-library'
|
||||||
|
|
||||||
java {
|
java {
|
||||||
|
toolchain {
|
||||||
|
languageVersion = JavaLanguageVersion.of(21)
|
||||||
|
}
|
||||||
modularity.inferModulePath.set(true)
|
modularity.inferModulePath.set(true)
|
||||||
withSourcesJar()
|
withSourcesJar()
|
||||||
withJavadocJar()
|
withJavadocJar()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
compileJava {
|
|
||||||
sourceCompatibility = JavaVersion.VERSION_17
|
|
||||||
targetCompatibility = JavaVersion.VERSION_17
|
|
||||||
}
|
|
||||||
|
|
||||||
compileTestJava {
|
|
||||||
sourceCompatibility = JavaVersion.VERSION_17
|
|
||||||
targetCompatibility = JavaVersion.VERSION_17
|
|
||||||
}
|
|
||||||
|
|
||||||
jar {
|
jar {
|
||||||
manifest {
|
manifest {
|
||||||
attributes('Implementation-Version': project.version)
|
attributes('Implementation-Version': project.version)
|
||||||
|
attributes('X-Java-Compiler-Version': JavaLanguageVersion.of(21).toString())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.withType(JavaCompile) {
|
tasks.withType(JavaCompile) {
|
||||||
|
options.fork = true
|
||||||
|
options.forkOptions.jvmArgs += ['-Duser.language=en','-Duser.country=US']
|
||||||
options.compilerArgs << '-Xlint:all'
|
options.compilerArgs << '-Xlint:all'
|
||||||
options.encoding = 'UTF-8'
|
options.encoding = 'UTF-8'
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ dependencies {
|
||||||
testImplementation libs.junit.jupiter.params
|
testImplementation libs.junit.jupiter.params
|
||||||
testImplementation libs.hamcrest
|
testImplementation libs.hamcrest
|
||||||
testRuntimeOnly libs.junit.jupiter.engine
|
testRuntimeOnly libs.junit.jupiter.engine
|
||||||
|
testRuntimeOnly libs.junit.jupiter.platform.launcher
|
||||||
}
|
}
|
||||||
|
|
||||||
test {
|
test {
|
||||||
|
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
3
gradle/wrapper/gradle-wrapper.properties
vendored
3
gradle/wrapper/gradle-wrapper.properties
vendored
|
@ -1,6 +1,7 @@
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-all.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-rc-1-all.zip
|
||||||
networkTimeout=10000
|
networkTimeout=10000
|
||||||
|
validateDistributionUrl=true
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
|
22
gradlew
vendored
22
gradlew
vendored
|
@ -83,7 +83,8 @@ done
|
||||||
# This is normally unused
|
# This is normally unused
|
||||||
# shellcheck disable=SC2034
|
# shellcheck disable=SC2034
|
||||||
APP_BASE_NAME=${0##*/}
|
APP_BASE_NAME=${0##*/}
|
||||||
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
|
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||||
|
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
|
||||||
|
|
||||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
MAX_FD=maximum
|
MAX_FD=maximum
|
||||||
|
@ -130,18 +131,21 @@ location of your Java installation."
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
JAVACMD=java
|
JAVACMD=java
|
||||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
if ! command -v java >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
|
||||||
Please set the JAVA_HOME variable in your environment to match the
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
location of your Java installation."
|
location of your Java installation."
|
||||||
fi
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
# Increase the maximum file descriptors if we can.
|
# Increase the maximum file descriptors if we can.
|
||||||
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||||
case $MAX_FD in #(
|
case $MAX_FD in #(
|
||||||
max*)
|
max*)
|
||||||
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||||
# shellcheck disable=SC3045
|
# shellcheck disable=SC2039,SC3045
|
||||||
MAX_FD=$( ulimit -H -n ) ||
|
MAX_FD=$( ulimit -H -n ) ||
|
||||||
warn "Could not query maximum file descriptor limit"
|
warn "Could not query maximum file descriptor limit"
|
||||||
esac
|
esac
|
||||||
|
@ -149,7 +153,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||||
'' | soft) :;; #(
|
'' | soft) :;; #(
|
||||||
*)
|
*)
|
||||||
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||||
# shellcheck disable=SC3045
|
# shellcheck disable=SC2039,SC3045
|
||||||
ulimit -n "$MAX_FD" ||
|
ulimit -n "$MAX_FD" ||
|
||||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||||
esac
|
esac
|
||||||
|
@ -198,11 +202,11 @@ fi
|
||||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||||
|
|
||||||
# Collect all arguments for the java command;
|
# Collect all arguments for the java command:
|
||||||
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
|
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||||
# shell script including quotes and variable substitutions, so put them in
|
# and any embedded shellness will be escaped.
|
||||||
# double quotes to make sure that they get re-expanded; and
|
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
||||||
# * put everything else in single quotes, so that it's not re-expanded.
|
# treated as '${Hostname}' itself on the command line.
|
||||||
|
|
||||||
set -- \
|
set -- \
|
||||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
dependencies {
|
|
||||||
api libs.datastructures.api
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
import org.xbib.settings.SettingsBuilder;
|
|
||||||
import org.xbib.settings.SettingsLoader;
|
|
||||||
|
|
||||||
module org.xbib.settings.api {
|
|
||||||
exports org.xbib.settings;
|
|
||||||
uses SettingsBuilder;
|
|
||||||
uses SettingsLoader;
|
|
||||||
requires transitive org.xbib.datastructures.api;
|
|
||||||
requires transitive java.sql;
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
package org.xbib.settings;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Strategy interface used to resolve replacement values for placeholders contained in Strings.
|
|
||||||
*/
|
|
||||||
@FunctionalInterface
|
|
||||||
public interface PlaceholderResolver {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resolves the supplied placeholder name into the replacement value.
|
|
||||||
*
|
|
||||||
* @param placeholderName the name of the placeholder to resolve.
|
|
||||||
* @return the replacement value or <code>null</code> if no replacement is to be made.
|
|
||||||
*/
|
|
||||||
String resolvePlaceholder(String placeholderName);
|
|
||||||
}
|
|
|
@ -1,120 +0,0 @@
|
||||||
package org.xbib.settings;
|
|
||||||
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class PropertyPlaceholder {
|
|
||||||
|
|
||||||
private final String placeholderPrefix;
|
|
||||||
|
|
||||||
private final String placeholderSuffix;
|
|
||||||
|
|
||||||
private final boolean ignoreUnresolvablePlaceholders;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new <code>PropertyPlaceholderHelper</code> that uses the supplied prefix and suffix.
|
|
||||||
*
|
|
||||||
* @param placeholderPrefix the prefix that denotes the start of a placeholder.
|
|
||||||
* @param placeholderSuffix the suffix that denotes the end of a placeholder.
|
|
||||||
* @param ignoreUnresolvablePlaceholders indicates whether unresolvable placeholders should be ignored
|
|
||||||
* (<code>true</code>) or cause an exception (<code>false</code>).
|
|
||||||
*/
|
|
||||||
public PropertyPlaceholder(String placeholderPrefix,
|
|
||||||
String placeholderSuffix,
|
|
||||||
boolean ignoreUnresolvablePlaceholders) {
|
|
||||||
this.placeholderPrefix = placeholderPrefix;
|
|
||||||
this.placeholderSuffix = placeholderSuffix;
|
|
||||||
this.ignoreUnresolvablePlaceholders = ignoreUnresolvablePlaceholders;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Replaces all placeholders of format <code>${name}</code> with the value returned from the supplied {@link
|
|
||||||
* PlaceholderResolver}.
|
|
||||||
*
|
|
||||||
* @param value the value containing the placeholders to be replaced.
|
|
||||||
* @param placeholderResolver the <code>PlaceholderResolver</code> to use for replacement.
|
|
||||||
* @return the supplied value with placeholders replaced inline.
|
|
||||||
*/
|
|
||||||
public String replacePlaceholders(String value,
|
|
||||||
PlaceholderResolver placeholderResolver) {
|
|
||||||
return parseStringValue(value, placeholderResolver, new HashSet<>());
|
|
||||||
}
|
|
||||||
|
|
||||||
protected String parseStringValue(String value,
|
|
||||||
PlaceholderResolver placeholderResolver,
|
|
||||||
Set<String> visitedPlaceholders) {
|
|
||||||
if (value == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
StringBuilder sb = new StringBuilder(value);
|
|
||||||
int startIndex = value.indexOf(this.placeholderPrefix);
|
|
||||||
while (startIndex != -1) {
|
|
||||||
int endIndex = findPlaceholderEndIndex(sb, startIndex);
|
|
||||||
if (endIndex != -1) {
|
|
||||||
String placeholder = sb.substring(startIndex + this.placeholderPrefix.length(), endIndex);
|
|
||||||
if (!visitedPlaceholders.add(placeholder)) {
|
|
||||||
throw new IllegalArgumentException("Circular placeholder reference '" + placeholder + "' in property definitions");
|
|
||||||
}
|
|
||||||
placeholder = parseStringValue(placeholder, placeholderResolver, visitedPlaceholders);
|
|
||||||
int defaultValueIdx = placeholder.indexOf(':');
|
|
||||||
String defaultValue = null;
|
|
||||||
if (defaultValueIdx != -1) {
|
|
||||||
defaultValue = placeholder.substring(defaultValueIdx + 1);
|
|
||||||
placeholder = placeholder.substring(0, defaultValueIdx);
|
|
||||||
}
|
|
||||||
String propVal = placeholderResolver.resolvePlaceholder(placeholder);
|
|
||||||
if (propVal == null) {
|
|
||||||
propVal = defaultValue;
|
|
||||||
}
|
|
||||||
if (propVal != null) {
|
|
||||||
propVal = parseStringValue(propVal, placeholderResolver, visitedPlaceholders);
|
|
||||||
sb.replace(startIndex, endIndex + this.placeholderSuffix.length(), propVal);
|
|
||||||
startIndex = sb.indexOf(this.placeholderPrefix, startIndex + propVal.length());
|
|
||||||
} else if (this.ignoreUnresolvablePlaceholders) {
|
|
||||||
// Proceed with unprocessed value.
|
|
||||||
startIndex = sb.indexOf(this.placeholderPrefix, endIndex + this.placeholderSuffix.length());
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException("could not resolve placeholder '" + placeholder + "'");
|
|
||||||
}
|
|
||||||
visitedPlaceholders.remove(placeholder);
|
|
||||||
} else {
|
|
||||||
startIndex = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private int findPlaceholderEndIndex(CharSequence charSequence, int startIndex) {
|
|
||||||
int index = startIndex + this.placeholderPrefix.length();
|
|
||||||
int withinNestedPlaceholder = 0;
|
|
||||||
while (index < charSequence.length()) {
|
|
||||||
if (substringMatch(charSequence, index, this.placeholderSuffix)) {
|
|
||||||
if (withinNestedPlaceholder > 0) {
|
|
||||||
withinNestedPlaceholder--;
|
|
||||||
index = index + this.placeholderPrefix.length() - 1;
|
|
||||||
} else {
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
} else if (substringMatch(charSequence, index, this.placeholderPrefix)) {
|
|
||||||
withinNestedPlaceholder++;
|
|
||||||
index = index + this.placeholderPrefix.length();
|
|
||||||
} else {
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean substringMatch(CharSequence charSequence, int index, CharSequence substring) {
|
|
||||||
for (int j = 0; j < substring.length(); j++) {
|
|
||||||
int i = index + j;
|
|
||||||
if (i >= charSequence.length() || charSequence.charAt(i) != substring.charAt(j)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,71 +0,0 @@
|
||||||
package org.xbib.settings;
|
|
||||||
|
|
||||||
import org.xbib.datastructures.api.ByteSizeValue;
|
|
||||||
import org.xbib.datastructures.api.TimeValue;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.ServiceLoader;
|
|
||||||
|
|
||||||
public interface Settings extends AutoCloseable {
|
|
||||||
|
|
||||||
class Holder {
|
|
||||||
|
|
||||||
private Holder() {
|
|
||||||
}
|
|
||||||
|
|
||||||
private static SettingsBuilder createBuilder() {
|
|
||||||
ServiceLoader<SettingsBuilder> serviceLoader = ServiceLoader.load(SettingsBuilder.class);
|
|
||||||
Optional<SettingsBuilder> optionalSettingsBuilder = serviceLoader.findFirst();
|
|
||||||
return optionalSettingsBuilder.orElse(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final Settings emptySettings = createBuilder().build();
|
|
||||||
}
|
|
||||||
|
|
||||||
static SettingsBuilder settingsBuilder() {
|
|
||||||
return Holder.createBuilder();
|
|
||||||
}
|
|
||||||
|
|
||||||
static Settings emptySettings() {
|
|
||||||
return Holder.emptySettings;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean isEmpty();
|
|
||||||
|
|
||||||
String get(String setting);
|
|
||||||
|
|
||||||
String get(String setting, String defaultValue);
|
|
||||||
|
|
||||||
float getAsFloat(String setting, float defaultValue);
|
|
||||||
|
|
||||||
double getAsDouble(String setting, double defaultValue);
|
|
||||||
|
|
||||||
int getAsInt(String setting, int defaultValue);
|
|
||||||
|
|
||||||
long getAsLong(String setting, long defaultValue);
|
|
||||||
|
|
||||||
boolean getAsBoolean(String setting, boolean defaultValue);
|
|
||||||
|
|
||||||
TimeValue getAsTime(String setting, TimeValue defaultValue);
|
|
||||||
|
|
||||||
ByteSizeValue getAsBytesSize(String setting, ByteSizeValue defaultValue);
|
|
||||||
|
|
||||||
String[] getAsArray(String settingPrefix);
|
|
||||||
|
|
||||||
String[] getAsArray(String settingPrefix, String[] defaultArray);
|
|
||||||
|
|
||||||
Map<String, String> getAsMap();
|
|
||||||
|
|
||||||
Map<String, Object> getAsStructuredMap();
|
|
||||||
|
|
||||||
Map<String, Settings> getGroups(String prefix);
|
|
||||||
|
|
||||||
Settings getAsSettings(String setting);
|
|
||||||
|
|
||||||
Settings getByPrefix(String prefix);
|
|
||||||
|
|
||||||
boolean containsSetting(String setting);
|
|
||||||
|
|
||||||
void close() throws IOException;
|
|
||||||
}
|
|
|
@ -1,105 +0,0 @@
|
||||||
package org.xbib.settings;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.sql.Connection;
|
|
||||||
import java.sql.PreparedStatement;
|
|
||||||
import java.sql.ResultSet;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
public interface SettingsBuilder {
|
|
||||||
|
|
||||||
SettingsBuilder put(String setting, String value);
|
|
||||||
|
|
||||||
SettingsBuilder put(String setting, boolean value);
|
|
||||||
|
|
||||||
SettingsBuilder put(String setting, int value);
|
|
||||||
|
|
||||||
SettingsBuilder put(String setting, long value);
|
|
||||||
|
|
||||||
SettingsBuilder put(String setting, float value);
|
|
||||||
|
|
||||||
SettingsBuilder put(String setting, double value);
|
|
||||||
|
|
||||||
SettingsBuilder putArray(String setting, String... values);
|
|
||||||
|
|
||||||
SettingsBuilder putArray(String setting, List<String> values);
|
|
||||||
|
|
||||||
SettingsBuilder put(String settingPrefix, String groupName, String[] settings, String[] values)
|
|
||||||
throws SettingsException;
|
|
||||||
|
|
||||||
SettingsBuilder put(Settings settings);
|
|
||||||
|
|
||||||
SettingsBuilder put(Map<String, String> settings);
|
|
||||||
|
|
||||||
SettingsBuilder loadFromString(String resourceName, String content);
|
|
||||||
|
|
||||||
SettingsBuilder loadFromResource(String resourceName, InputStream inputStream);
|
|
||||||
|
|
||||||
default SettingsBuilder fromJdbc(Connection connection, String statement, String[] params) throws SQLException {
|
|
||||||
try (PreparedStatement preparedStatement = connection.prepareStatement(statement, params);
|
|
||||||
ResultSet resultSet = preparedStatement.executeQuery()) {
|
|
||||||
while (resultSet.next()) {
|
|
||||||
String key = resultSet.getString("key");
|
|
||||||
String value = resultSet.getString("value");
|
|
||||||
put(key, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
SettingsBuilder loadFromSystemProperties();
|
|
||||||
|
|
||||||
SettingsBuilder loadFromSystemEnvironment();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Runs across all the settings set on this builder and replaces {@code ${...}} elements in the
|
|
||||||
* each setting value according to the following logic:
|
|
||||||
* First, tries to resolve it against a System property ({@link System#getProperty(String)}), next,
|
|
||||||
* tries and resolve it against an environment variable ({@link System#getenv(String)}), next,
|
|
||||||
* tries and resolve it against a date pattern to resolve the current date,
|
|
||||||
* and last, tries and replace it with another setting already set on this builder.
|
|
||||||
* @param propertyPlaceholder the property place holder
|
|
||||||
* @param placeholderResolver the place holder resolver
|
|
||||||
* @return this builder
|
|
||||||
*/
|
|
||||||
SettingsBuilder replacePropertyPlaceholders(PropertyPlaceholder propertyPlaceholder,
|
|
||||||
PlaceholderResolver placeholderResolver);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A default method to replace property placeholders.
|
|
||||||
* @return this builder
|
|
||||||
*/
|
|
||||||
SettingsBuilder replacePropertyPlaceholders();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Optional settings refresh mechanism, using reloading from a path after a give time period.
|
|
||||||
* May not be implemented at all.
|
|
||||||
*/
|
|
||||||
SettingsBuilder setRefresh(Path path, long initialDelay, long period, TimeUnit timeUnit);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Map all settings keys and values to other keys and values.
|
|
||||||
* Example usage is to override settings from another priority source.
|
|
||||||
* @return this builder
|
|
||||||
*/
|
|
||||||
SettingsBuilder map(Function<Map.Entry<String, String>, Map.Entry<String, String>> function);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the Settings from this SettingsBuilder.
|
|
||||||
* @return the settings
|
|
||||||
*/
|
|
||||||
Settings build();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if the settings builder is empty.
|
|
||||||
* @return true if empty
|
|
||||||
*/
|
|
||||||
boolean isEmpty();
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
package org.xbib.settings;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A generic failure to handle settings.
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("serial")
|
|
||||||
public class SettingsException extends RuntimeException {
|
|
||||||
|
|
||||||
public SettingsException(String message) {
|
|
||||||
super(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public SettingsException(String message, Throwable cause) {
|
|
||||||
super(message, cause);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,33 +0,0 @@
|
||||||
package org.xbib.settings;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides the ability to load settings from
|
|
||||||
* the actual source content that represents them.
|
|
||||||
*/
|
|
||||||
public interface SettingsLoader {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Suffices for file names to load from.
|
|
||||||
* @return a set of suffices
|
|
||||||
*/
|
|
||||||
Set<String> suffixes();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads the settings from a source string.
|
|
||||||
* @param source the source
|
|
||||||
* @return a Map
|
|
||||||
*/
|
|
||||||
Map<String, String> load(String source) throws IOException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads the settings from a map.
|
|
||||||
* @param source the map with the source
|
|
||||||
* @return a Map
|
|
||||||
*/
|
|
||||||
Map<String, String> load(Map<String, Object> source) throws IOException;
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,54 +0,0 @@
|
||||||
package org.xbib.settings;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.ServiceLoader;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A settings loader service for loading {@link SettingsLoader} implementations.
|
|
||||||
*/
|
|
||||||
public final class SettingsLoaderService {
|
|
||||||
|
|
||||||
private static final SettingsLoaderService INSTANCE = new SettingsLoaderService();
|
|
||||||
|
|
||||||
private final Map<Set<String>, SettingsLoader> settingsLoaderMap;
|
|
||||||
|
|
||||||
private SettingsLoaderService() {
|
|
||||||
this.settingsLoaderMap = new HashMap<>();
|
|
||||||
ServiceLoader<SettingsLoader> serviceLoader = ServiceLoader.load(SettingsLoader.class);
|
|
||||||
for (SettingsLoader settingsLoader : serviceLoader) {
|
|
||||||
settingsLoaderMap.put(settingsLoader.suffixes(), settingsLoader);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SettingsLoaderService getInstance() {
|
|
||||||
return INSTANCE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a {@link SettingsLoader} based on the resource name.
|
|
||||||
* @param resourceName the resource
|
|
||||||
* @return the settings loader
|
|
||||||
*/
|
|
||||||
public SettingsLoader loaderFromResource(String resourceName) {
|
|
||||||
for (Map.Entry<Set<String>, SettingsLoader> entry : settingsLoaderMap.entrySet()) {
|
|
||||||
Set<String> suffixes = entry.getKey();
|
|
||||||
for (String suffix : suffixes) {
|
|
||||||
if (resourceName.endsWith(suffix)) {
|
|
||||||
return entry.getValue();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw new IllegalArgumentException("no settings loader for " + resourceName + " in " + settingsLoaderMap.keySet());
|
|
||||||
}
|
|
||||||
|
|
||||||
public Set<String> getSuffixes() {
|
|
||||||
Set<String> suffixes = new HashSet<>();
|
|
||||||
for (Set<String> set : settingsLoaderMap.keySet()) {
|
|
||||||
suffixes.addAll(set);
|
|
||||||
}
|
|
||||||
return suffixes;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,4 +0,0 @@
|
||||||
/**
|
|
||||||
* Settings API.
|
|
||||||
*/
|
|
||||||
package org.xbib.settings;
|
|
|
@ -1,6 +1,5 @@
|
||||||
dependencies {
|
dependencies {
|
||||||
api project(':settings-api')
|
api libs.settings.api
|
||||||
api project(':content-core')
|
api project(':content-core')
|
||||||
api libs.datastructures.tiny
|
|
||||||
testImplementation project(":settings-content-json")
|
testImplementation project(":settings-content-json")
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,6 @@ module org.xbib.settings.content {
|
||||||
uses SettingsBuilder;
|
uses SettingsBuilder;
|
||||||
provides SettingsBuilder with ContentSettingsBuilder;
|
provides SettingsBuilder with ContentSettingsBuilder;
|
||||||
exports org.xbib.settings.content;
|
exports org.xbib.settings.content;
|
||||||
requires transitive org.xbib.settings.api;
|
requires org.xbib.settings.api;
|
||||||
requires transitive org.xbib.content.core;
|
requires org.xbib.content.core;
|
||||||
requires transitive org.xbib.datastructures.tiny;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,9 +8,9 @@ import org.xbib.content.XContentGenerator;
|
||||||
import org.xbib.content.XContentParser;
|
import org.xbib.content.XContentParser;
|
||||||
import org.xbib.content.io.BytesReference;
|
import org.xbib.content.io.BytesReference;
|
||||||
import org.xbib.content.io.BytesStreamOutput;
|
import org.xbib.content.io.BytesStreamOutput;
|
||||||
import org.xbib.datastructures.tiny.TinyMap;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@ -41,14 +41,14 @@ public abstract class AbstractSettingsLoader implements SettingsLoader {
|
||||||
|
|
||||||
public Map<String, String> load(XContentParser xContentParser) throws IOException {
|
public Map<String, String> load(XContentParser xContentParser) throws IOException {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
TinyMap.Builder<String, String> map = TinyMap.builder();
|
Map<String, String> map = new LinkedHashMap<>();
|
||||||
List<String> path = new ArrayList<>();
|
List<String> path = new ArrayList<>();
|
||||||
XContentParser.Token token = xContentParser.nextToken();
|
XContentParser.Token token = xContentParser.nextToken();
|
||||||
if (token == null) {
|
if (token == null) {
|
||||||
return map.build();
|
return map;
|
||||||
}
|
}
|
||||||
parseObject(map, sb, path, xContentParser, null);
|
parseObject(map, sb, path, xContentParser, null);
|
||||||
return map.build();
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String flatMapAsString(BytesReference bytesReference) throws IOException {
|
public String flatMapAsString(BytesReference bytesReference) throws IOException {
|
||||||
|
|
|
@ -6,7 +6,6 @@ import org.xbib.settings.SettingsLoader;
|
||||||
import org.xbib.settings.SettingsLoaderService;
|
import org.xbib.settings.SettingsLoaderService;
|
||||||
import org.xbib.datastructures.api.ByteSizeValue;
|
import org.xbib.datastructures.api.ByteSizeValue;
|
||||||
import org.xbib.datastructures.api.TimeValue;
|
import org.xbib.datastructures.api.TimeValue;
|
||||||
import org.xbib.datastructures.tiny.TinyMap;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
|
@ -14,6 +13,7 @@ import java.io.Writer;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
|
@ -36,9 +36,7 @@ public class ContentSettings implements Settings, AutoCloseable {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ContentSettings(Map<String, String> map, Path path, long initialDelay, long period, TimeUnit timeUnit) {
|
protected ContentSettings(Map<String, String> map, Path path, long initialDelay, long period, TimeUnit timeUnit) {
|
||||||
TinyMap.Builder<String, String> builder = TinyMap.builder();
|
this.map = new LinkedHashMap<>(map);
|
||||||
builder.putAll(map);
|
|
||||||
this.map = builder.build();
|
|
||||||
if (path != null && initialDelay >= 0L && period > 0L) {
|
if (path != null && initialDelay >= 0L && period > 0L) {
|
||||||
this.refresher = new DefaultSettingsRefresher(path, initialDelay, period, timeUnit);
|
this.refresher = new DefaultSettingsRefresher(path, initialDelay, period, timeUnit);
|
||||||
}
|
}
|
||||||
|
@ -130,7 +128,7 @@ public class ContentSettings implements Settings, AutoCloseable {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String, Object> getAsStructuredMap() {
|
public Map<String, Object> getAsStructuredMap() {
|
||||||
TinyMap.Builder<String, Object> stringObjectMap = TinyMap.builder();
|
Map<String, Object> stringObjectMap = new LinkedHashMap<>();
|
||||||
for (Map.Entry<String, String> entry : this.map.entrySet()) {
|
for (Map.Entry<String, String> entry : this.map.entrySet()) {
|
||||||
processSetting(stringObjectMap, "", entry.getKey(), entry.getValue());
|
processSetting(stringObjectMap, "", entry.getKey(), entry.getValue());
|
||||||
}
|
}
|
||||||
|
@ -141,7 +139,7 @@ public class ContentSettings implements Settings, AutoCloseable {
|
||||||
entry.setValue(convertMapsToArrays(valMap));
|
entry.setValue(convertMapsToArrays(valMap));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return stringObjectMap.build();
|
return stringObjectMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -300,7 +298,7 @@ public class ContentSettings implements Settings, AutoCloseable {
|
||||||
settingPrefix = settingPrefix + ".";
|
settingPrefix = settingPrefix + ".";
|
||||||
}
|
}
|
||||||
// we don't really care that it might happen twice
|
// we don't really care that it might happen twice
|
||||||
TinyMap.Builder<String, Map<String, String>> hashMap = TinyMap.builder();
|
Map<String, Map<String, String>> hashMap = new LinkedHashMap<>();
|
||||||
for (String o : this.map.keySet()) {
|
for (String o : this.map.keySet()) {
|
||||||
if (o.startsWith(settingPrefix)) {
|
if (o.startsWith(settingPrefix)) {
|
||||||
String nameValue = o.substring(settingPrefix.length());
|
String nameValue = o.substring(settingPrefix.length());
|
||||||
|
@ -312,15 +310,15 @@ public class ContentSettings implements Settings, AutoCloseable {
|
||||||
}
|
}
|
||||||
String name = nameValue.substring(0, dotIndex);
|
String name = nameValue.substring(0, dotIndex);
|
||||||
String value = nameValue.substring(dotIndex + 1);
|
String value = nameValue.substring(dotIndex + 1);
|
||||||
Map<String, String> groupSettings = hashMap.computeIfAbsent(name, k -> TinyMap.builder());
|
Map<String, String> groupSettings = hashMap.computeIfAbsent(name, k -> new LinkedHashMap<>());
|
||||||
groupSettings.put(value, get(o));
|
groupSettings.put(value, get(o));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TinyMap.Builder<String, Settings> retVal = TinyMap.builder();
|
Map<String, Settings> retVal = new LinkedHashMap<>();
|
||||||
for (Map.Entry<String, Map<String, String>> entry : hashMap.entrySet()) {
|
for (Map.Entry<String, Map<String, String>> entry : hashMap.entrySet()) {
|
||||||
retVal.put(entry.getKey(), new ContentSettings(entry.getValue()));
|
retVal.put(entry.getKey(), new ContentSettings(entry.getValue()));
|
||||||
}
|
}
|
||||||
return retVal.build();
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -356,7 +354,7 @@ public class ContentSettings implements Settings, AutoCloseable {
|
||||||
String rest = setting.substring(prefixLength + 1);
|
String rest = setting.substring(prefixLength + 1);
|
||||||
Object existingValue = map.get(prefix + key);
|
Object existingValue = map.get(prefix + key);
|
||||||
if (existingValue == null) {
|
if (existingValue == null) {
|
||||||
Map<String, Object> newMap = TinyMap.builder();
|
Map<String, Object> newMap = new LinkedHashMap<>();
|
||||||
processSetting(newMap, "", rest, value);
|
processSetting(newMap, "", rest, value);
|
||||||
map.put(key, newMap);
|
map.put(key, newMap);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -7,7 +7,6 @@ import org.xbib.settings.SettingsBuilder;
|
||||||
import org.xbib.settings.SettingsException;
|
import org.xbib.settings.SettingsException;
|
||||||
import org.xbib.settings.SettingsLoader;
|
import org.xbib.settings.SettingsLoader;
|
||||||
import org.xbib.settings.SettingsLoaderService;
|
import org.xbib.settings.SettingsLoaderService;
|
||||||
import org.xbib.datastructures.tiny.TinyMap;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
@ -18,14 +17,12 @@ import java.nio.file.Path;
|
||||||
import java.time.DateTimeException;
|
import java.time.DateTimeException;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class ContentSettingsBuilder implements SettingsBuilder {
|
public class ContentSettingsBuilder implements SettingsBuilder {
|
||||||
|
|
||||||
private final SettingsLoaderService settingsLoaderService;
|
private final SettingsLoaderService settingsLoaderService;
|
||||||
|
@ -42,7 +39,7 @@ public class ContentSettingsBuilder implements SettingsBuilder {
|
||||||
|
|
||||||
public ContentSettingsBuilder() {
|
public ContentSettingsBuilder() {
|
||||||
this.settingsLoaderService = SettingsLoaderService.getInstance();
|
this.settingsLoaderService = SettingsLoaderService.getInstance();
|
||||||
this.map = TinyMap.builder();
|
this.map = new LinkedHashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String remove(String key) {
|
public String remove(String key) {
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
dependencies {
|
|
||||||
api project(':settings-datastructures')
|
|
||||||
api libs.datastructures.json.tiny
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
import org.xbib.settings.SettingsLoader;
|
|
||||||
import org.xbib.settings.datastructures.json.JsonSettingsLoader;
|
|
||||||
|
|
||||||
module org.xbib.settings.datastructures.json {
|
|
||||||
exports org.xbib.settings.datastructures.json;
|
|
||||||
requires transitive org.xbib.settings.datastructures;
|
|
||||||
requires org.xbib.datastructures.json.tiny;
|
|
||||||
uses SettingsLoader;
|
|
||||||
provides SettingsLoader with JsonSettingsLoader;
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
package org.xbib.settings.datastructures.json;
|
|
||||||
|
|
||||||
import org.xbib.settings.datastructures.AbstractSettingsLoader;
|
|
||||||
import org.xbib.datastructures.api.DataStructure;
|
|
||||||
import org.xbib.datastructures.json.tiny.Json;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public class JsonSettingsLoader extends AbstractSettingsLoader {
|
|
||||||
|
|
||||||
public JsonSettingsLoader() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DataStructure dataStructure() {
|
|
||||||
return new Json();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<String> suffixes() {
|
|
||||||
return Set.of("json");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,4 +0,0 @@
|
||||||
/**
|
|
||||||
* JSON settings with the datastructures package.
|
|
||||||
*/
|
|
||||||
package org.xbib.settings.datastructures.json;
|
|
|
@ -1 +0,0 @@
|
||||||
org.xbib.settings.datastructures.json.JsonSettingsLoader
|
|
|
@ -1,82 +0,0 @@
|
||||||
package org.xbib.settings.datastructures.json.test;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.xbib.settings.Settings;
|
|
||||||
import org.xbib.settings.SettingsLoader;
|
|
||||||
import org.xbib.settings.datastructures.json.JsonSettingsLoader;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
||||||
|
|
||||||
public class JsonSettingsTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testMapForSettings() throws IOException {
|
|
||||||
Map<String, String> map = new HashMap<>();
|
|
||||||
map.put("hello", "world");
|
|
||||||
Map<String, Object> settingsMap = new HashMap<>();
|
|
||||||
settingsMap.put("map", map);
|
|
||||||
SettingsLoader settingsLoader = new JsonSettingsLoader();
|
|
||||||
Settings settings = Settings.settingsBuilder()
|
|
||||||
.put(settingsLoader.load(settingsMap))
|
|
||||||
.build();
|
|
||||||
assertEquals("{map.hello=world}", settings.getAsMap().toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testMapSettingsFromReader() throws IOException {
|
|
||||||
Map<String, Object> map = Map.of("map", Map.of("hello", "world"));
|
|
||||||
SettingsLoader settingsLoader = new JsonSettingsLoader();
|
|
||||||
Settings settings = Settings.settingsBuilder()
|
|
||||||
.put(settingsLoader.load(map))
|
|
||||||
.build();
|
|
||||||
assertEquals("{map.hello=world}", settings.getAsMap().toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testLoadFromString() throws IOException {
|
|
||||||
String json = "{\"Hello\":\"World\"}";
|
|
||||||
SettingsLoader loader = new JsonSettingsLoader();
|
|
||||||
Map<String, String> result = loader.load(json);
|
|
||||||
assertEquals("{Hello=World}", result.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testLoadSettingsFromString() {
|
|
||||||
String json = "{\"Hello\":\"World\"}";
|
|
||||||
Settings settings = Settings.settingsBuilder().loadFromString("json", json).build();
|
|
||||||
assertEquals("{Hello=World}", settings.getAsMap().toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testFlatLoader() throws IOException {
|
|
||||||
String s = "{\"a\":{\"b\":\"c\"}}";
|
|
||||||
SettingsLoader loader = new JsonSettingsLoader();
|
|
||||||
Map<String, String> flatMap = loader.load(s);
|
|
||||||
assertEquals("{a.b=c}", flatMap.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testLoadFromMap() throws IOException {
|
|
||||||
Map<String, Object> map = new LinkedHashMap<>();
|
|
||||||
Map<String, Object> code = new LinkedHashMap<>();
|
|
||||||
code.put("a", "b");
|
|
||||||
code.put("b", "c");
|
|
||||||
Map<String, Object> name = new LinkedHashMap<>();
|
|
||||||
name.put("a", "b");
|
|
||||||
name.put("b", "c");
|
|
||||||
List<String> list = Arrays.asList("a", "b");
|
|
||||||
map.put("code", code);
|
|
||||||
map.put("name", name);
|
|
||||||
map.put("list", list);
|
|
||||||
map.put("null", null);
|
|
||||||
SettingsLoader loader = new JsonSettingsLoader();
|
|
||||||
Map<String, String> result = loader.load(map);
|
|
||||||
assertEquals("{code.a=b, code.b=c, name.a=b, name.b=c, list.0=a, list.1=b, null=null}", result.toString());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,4 +0,0 @@
|
||||||
/**
|
|
||||||
* Testing JSON settings with the datastructures package.
|
|
||||||
*/
|
|
||||||
package org.xbib.settings.datastructures.json.test;
|
|
|
@ -1 +0,0 @@
|
||||||
org.xbib.settings.datastructures.json.JsonSettingsLoader
|
|
|
@ -1,3 +0,0 @@
|
||||||
{
|
|
||||||
"a": "b"
|
|
||||||
}
|
|
|
@ -1,4 +0,0 @@
|
||||||
dependencies {
|
|
||||||
api project(':settings-datastructures')
|
|
||||||
api libs.datastructures.yaml.tiny
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
import org.xbib.settings.SettingsLoader;
|
|
||||||
import org.xbib.settings.datastructures.yaml.YamlSettingsLoader;
|
|
||||||
|
|
||||||
module org.xbib.settings.datastructures.yaml {
|
|
||||||
exports org.xbib.settings.datastructures.yaml;
|
|
||||||
requires transitive org.xbib.settings.datastructures;
|
|
||||||
requires org.xbib.datastructures.yaml.tiny;
|
|
||||||
uses SettingsLoader;
|
|
||||||
provides SettingsLoader with YamlSettingsLoader;
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
package org.xbib.settings.datastructures.yaml;
|
|
||||||
|
|
||||||
import org.xbib.settings.datastructures.AbstractSettingsLoader;
|
|
||||||
import org.xbib.datastructures.api.DataStructure;
|
|
||||||
import org.xbib.datastructures.yaml.tiny.Yaml;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public class YamlSettingsLoader extends AbstractSettingsLoader {
|
|
||||||
|
|
||||||
public YamlSettingsLoader() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DataStructure dataStructure() {
|
|
||||||
return new Yaml();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<String> suffixes() {
|
|
||||||
return Set.of("yml", "yaml");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String, String> load(String source) throws IOException {
|
|
||||||
// replace tabs with whitespace (yaml does not accept tabs, but many users might use it still...)
|
|
||||||
return super.load(source.replace("\t", " "));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,4 +0,0 @@
|
||||||
/**
|
|
||||||
* YAML settings with the datastructures package.
|
|
||||||
*/
|
|
||||||
package org.xbib.settings.datastructures.yaml;
|
|
|
@ -1 +0,0 @@
|
||||||
org.xbib.settings.datastructures.yaml.YamlSettingsLoader
|
|
|
@ -1,67 +0,0 @@
|
||||||
package org.xbib.settings.datastructures.yaml.test;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.xbib.settings.Settings;
|
|
||||||
import org.xbib.settings.SettingsLoader;
|
|
||||||
import org.xbib.settings.datastructures.yaml.YamlSettingsLoader;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class YamlSettingsTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testMapForSettings() throws IOException {
|
|
||||||
Map<String, String> map = new HashMap<>();
|
|
||||||
map.put("hello", "world");
|
|
||||||
Map<String, Object> settingsMap = new HashMap<>();
|
|
||||||
settingsMap.put("map", map);
|
|
||||||
SettingsLoader settingsLoader = new YamlSettingsLoader();
|
|
||||||
Settings settings = Settings.settingsBuilder()
|
|
||||||
.put(settingsLoader.load(settingsMap))
|
|
||||||
.build();
|
|
||||||
assertEquals("{map.hello=world}", settings.getAsMap().toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testMapSettingsFromReader() throws IOException {
|
|
||||||
Map<String, Object> map = Map.of("map", Map.of("hello", "world"));
|
|
||||||
SettingsLoader settingsLoader = new YamlSettingsLoader();
|
|
||||||
Settings settings = Settings.settingsBuilder()
|
|
||||||
.put(settingsLoader.load(map))
|
|
||||||
.build();
|
|
||||||
assertEquals("{map.hello=world}", settings.getAsMap().toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testFlatLoader() throws IOException {
|
|
||||||
String s = "a:\n b: c\n";
|
|
||||||
SettingsLoader loader = new YamlSettingsLoader();
|
|
||||||
Map<String, String> flatMap = loader.load(s);
|
|
||||||
assertEquals("{a.b=c}", flatMap.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testLoadFromMap() throws IOException {
|
|
||||||
Map<String, Object> map = new LinkedHashMap<>();
|
|
||||||
Map<String, Object> code = new LinkedHashMap<>();
|
|
||||||
code.put("a", "b");
|
|
||||||
code.put("b", "c");
|
|
||||||
Map<String, Object> name = new LinkedHashMap<>();
|
|
||||||
name.put("a", "b");
|
|
||||||
name.put("b", "c");
|
|
||||||
List<String> list = Arrays.asList("a", "b");
|
|
||||||
map.put("code", code);
|
|
||||||
map.put("name", name);
|
|
||||||
map.put("list", list);
|
|
||||||
map.put("null", null);
|
|
||||||
SettingsLoader loader = new YamlSettingsLoader();
|
|
||||||
Map<String, String> result = loader.load(map);
|
|
||||||
assertEquals("{code.a=b, code.b=c, name.a=b, name.b=c, list.0=a, list.1=b, null=null}", result.toString());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,4 +0,0 @@
|
||||||
/**
|
|
||||||
* Testing YAML settings with the datastructures package.
|
|
||||||
*/
|
|
||||||
package org.xbib.settings.datastructures.yaml.test;
|
|
|
@ -1,4 +0,0 @@
|
||||||
dependencies {
|
|
||||||
api project(':settings-api')
|
|
||||||
api libs.datastructures.tiny
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
import org.xbib.settings.SettingsBuilder;
|
|
||||||
import org.xbib.settings.SettingsLoader;
|
|
||||||
import org.xbib.settings.datastructures.DatastructureSettingsBuilder;
|
|
||||||
import org.xbib.settings.datastructures.PropertiesSettingsLoader;
|
|
||||||
|
|
||||||
module org.xbib.settings.datastructures {
|
|
||||||
uses SettingsLoader;
|
|
||||||
provides SettingsLoader with PropertiesSettingsLoader;
|
|
||||||
uses SettingsBuilder;
|
|
||||||
provides SettingsBuilder with DatastructureSettingsBuilder;
|
|
||||||
exports org.xbib.settings.datastructures;
|
|
||||||
requires transitive org.xbib.settings.api;
|
|
||||||
requires org.xbib.datastructures.tiny;
|
|
||||||
requires transitive org.xbib.datastructures.api;
|
|
||||||
}
|
|
|
@ -1,80 +0,0 @@
|
||||||
package org.xbib.settings.datastructures;
|
|
||||||
|
|
||||||
import org.xbib.settings.SettingsLoader;
|
|
||||||
import org.xbib.datastructures.api.Builder;
|
|
||||||
import org.xbib.datastructures.api.DataStructure;
|
|
||||||
import org.xbib.datastructures.api.ListNode;
|
|
||||||
import org.xbib.datastructures.api.MapNode;
|
|
||||||
import org.xbib.datastructures.api.Node;
|
|
||||||
import org.xbib.datastructures.api.Parser;
|
|
||||||
import org.xbib.datastructures.api.ValueNode;
|
|
||||||
import org.xbib.datastructures.tiny.TinyMap;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.Reader;
|
|
||||||
import java.io.StringReader;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public abstract class AbstractSettingsLoader implements SettingsLoader {
|
|
||||||
|
|
||||||
public AbstractSettingsLoader() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract DataStructure dataStructure();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String, String> load(Map<String, Object> map) throws IOException {
|
|
||||||
Builder builder = dataStructure().createBuilder();
|
|
||||||
builder.buildMap(map);
|
|
||||||
return load(builder.build());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String, String> load(String source) throws IOException {
|
|
||||||
Parser parser = dataStructure().createParser();
|
|
||||||
return load(parser, new StringReader(source));
|
|
||||||
}
|
|
||||||
|
|
||||||
private Map<String, String> load(Parser parser, Reader reader) throws IOException {
|
|
||||||
List<CharSequence> path = new ArrayList<>();
|
|
||||||
TinyMap.Builder<String, String> map = TinyMap.builder();
|
|
||||||
Node<?> node = parser.parse(reader);
|
|
||||||
parseObject(node, map, path, null);
|
|
||||||
return map.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void parseObject(Node<?> node,
|
|
||||||
TinyMap.Builder<String, String> map,
|
|
||||||
List<CharSequence> path,
|
|
||||||
CharSequence name) {
|
|
||||||
if (node instanceof ValueNode) {
|
|
||||||
ValueNode valueNode = (ValueNode) node;
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
for (CharSequence s : path) {
|
|
||||||
sb.append(s).append('.');
|
|
||||||
}
|
|
||||||
sb.append(name);
|
|
||||||
Object object = valueNode.get();
|
|
||||||
map.put(sb.toString(), object != null ? object.toString() : null);
|
|
||||||
} else if (node instanceof ListNode) {
|
|
||||||
ListNode listNode = (ListNode) node;
|
|
||||||
int counter = 0;
|
|
||||||
for (Node<?> nn : listNode.get()) {
|
|
||||||
parseObject(nn, map, path, name + "." + (counter++));
|
|
||||||
}
|
|
||||||
} else if (node instanceof MapNode) {
|
|
||||||
if (name != null) {
|
|
||||||
path.add(name);
|
|
||||||
}
|
|
||||||
MapNode mapNode = (MapNode) node;
|
|
||||||
for (Map.Entry<CharSequence, Node<?>> me : mapNode.get().entrySet()) {
|
|
||||||
parseObject(me.getValue(), map, path, me.getKey());
|
|
||||||
}
|
|
||||||
if (name != null) {
|
|
||||||
path.remove(path.size() - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,367 +0,0 @@
|
||||||
package org.xbib.settings.datastructures;
|
|
||||||
|
|
||||||
import org.xbib.settings.Settings;
|
|
||||||
import org.xbib.settings.SettingsException;
|
|
||||||
import org.xbib.datastructures.api.ByteSizeValue;
|
|
||||||
import org.xbib.datastructures.api.TimeValue;
|
|
||||||
import org.xbib.datastructures.tiny.TinyMap;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class DatastructureSettings implements Settings {
|
|
||||||
|
|
||||||
private static final String[] EMPTY_ARRAY = new String[0];
|
|
||||||
|
|
||||||
private final TinyMap<String, String> map;
|
|
||||||
|
|
||||||
DatastructureSettings(TinyMap<String, String> map) {
|
|
||||||
this.map = map;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static DatastructureSettingsBuilder builder() {
|
|
||||||
return new DatastructureSettingsBuilder();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static DatastructureSettings fromMap(Map<String, Object> map) {
|
|
||||||
DatastructureSettingsBuilder builder = new DatastructureSettingsBuilder();
|
|
||||||
for (Map.Entry<String, Object> entry : map.entrySet()) {
|
|
||||||
builder.put(entry.getKey(), entry.getValue() != null ? entry.getValue().toString() : null);
|
|
||||||
}
|
|
||||||
return builder.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void toMap(DatastructureSettings settings, Map<String, Object> map) {
|
|
||||||
for (String key : settings.getAsMap().keySet()) {
|
|
||||||
map.put(key, settings.get(key));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String[] splitStringByCommaToArray(String s) {
|
|
||||||
return splitStringToArray(s, ',');
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String[] splitStringToArray(String s, char c) {
|
|
||||||
if (s.length() == 0) {
|
|
||||||
return EMPTY_ARRAY;
|
|
||||||
}
|
|
||||||
final char[] chars = s.toCharArray();
|
|
||||||
int count = 1;
|
|
||||||
for (final char x : chars) {
|
|
||||||
if (x == c) {
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
final String[] result = new String[count];
|
|
||||||
final int len = chars.length;
|
|
||||||
int start = 0;
|
|
||||||
int pos = 0;
|
|
||||||
int i = 0;
|
|
||||||
for (; pos < len; pos++) {
|
|
||||||
if (chars[pos] == c) {
|
|
||||||
int size = pos - start;
|
|
||||||
if (size > 0) {
|
|
||||||
result[i++] = new String(chars, start, size);
|
|
||||||
}
|
|
||||||
start = pos + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int size = pos - start;
|
|
||||||
if (size > 0) {
|
|
||||||
result[i++] = new String(chars, start, size);
|
|
||||||
}
|
|
||||||
if (i != count) {
|
|
||||||
String[] result1 = new String[i];
|
|
||||||
System.arraycopy(result, 0, result1, 0, i);
|
|
||||||
return result1;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String, String> getAsMap() {
|
|
||||||
return this.map;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String, Object> getAsStructuredMap() {
|
|
||||||
TinyMap.Builder<String, Object> stringObjectMap = TinyMap.builder();
|
|
||||||
for (Map.Entry<String, String> entry : map.entrySet()) {
|
|
||||||
String key = entry.getKey();
|
|
||||||
String value = entry.getValue();
|
|
||||||
processSetting(stringObjectMap, "", key, value);
|
|
||||||
}
|
|
||||||
for (Map.Entry<String, Object> entry : stringObjectMap.entrySet()) {
|
|
||||||
String key = entry.getKey();
|
|
||||||
Object object = entry.getValue();
|
|
||||||
if (object instanceof Map) {
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
Map<String, Object> valMap = (Map<String, Object>) object;
|
|
||||||
stringObjectMap.put(key, convertMapsToArrays(valMap));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return stringObjectMap.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Settings getByPrefix(String prefix) {
|
|
||||||
DatastructureSettingsBuilder builder = new DatastructureSettingsBuilder();
|
|
||||||
for (Map.Entry<String, String> entry : map.entrySet()) {
|
|
||||||
String key = entry.getKey();
|
|
||||||
String value = entry.getValue();
|
|
||||||
if (key.startsWith(prefix)) {
|
|
||||||
if (key.length() < prefix.length()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
builder.put(key.substring(prefix.length()), value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return builder.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Settings getAsSettings(String setting) {
|
|
||||||
return getByPrefix(setting + ".");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean containsSetting(String setting) {
|
|
||||||
if (map.containsKey(setting)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
for (String key : map.keySet()) {
|
|
||||||
if (key.startsWith(setting)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String get(String setting) {
|
|
||||||
return map.get(setting);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String get(String setting, String defaultValue) {
|
|
||||||
String s = map.get(setting);
|
|
||||||
return s == null ? defaultValue : s;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public float getAsFloat(String setting, float defaultValue) {
|
|
||||||
String s = get(setting);
|
|
||||||
try {
|
|
||||||
return s == null ? defaultValue : Float.parseFloat(s);
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
throw new SettingsException("Failed to parse float setting [" + setting + "] with value [" + s + "]", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public double getAsDouble(String setting, double defaultValue) {
|
|
||||||
String s = get(setting);
|
|
||||||
try {
|
|
||||||
return s == null ? defaultValue : Double.parseDouble(s);
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
throw new SettingsException("Failed to parse double setting [" + setting + "] with value [" + s + "]", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getAsInt(String setting, int defaultValue) {
|
|
||||||
String s = get(setting);
|
|
||||||
try {
|
|
||||||
return s == null ? defaultValue : Integer.parseInt(s);
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
throw new SettingsException("Failed to parse int setting [" + setting + "] with value [" + s + "]", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getAsLong(String setting, long defaultValue) {
|
|
||||||
String s = get(setting);
|
|
||||||
try {
|
|
||||||
return s == null ? defaultValue : Long.parseLong(s);
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
throw new SettingsException("Failed to parse long setting [" + setting + "] with value [" + s + "]", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean getAsBoolean(String setting, boolean defaultValue) {
|
|
||||||
String value = get(setting);
|
|
||||||
if (value == null) {
|
|
||||||
return defaultValue;
|
|
||||||
}
|
|
||||||
return !("false".equals(value) || "0".equals(value) || "off".equals(value) || "no".equals(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public TimeValue getAsTime(String setting, TimeValue defaultValue) {
|
|
||||||
return TimeValue.parseTimeValue(get(setting), defaultValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ByteSizeValue getAsBytesSize(String setting, ByteSizeValue defaultValue) {
|
|
||||||
return ByteSizeValue.parseBytesSizeValue(get(setting), defaultValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String[] getAsArray(String settingPrefix) {
|
|
||||||
return getAsArray(settingPrefix, EMPTY_ARRAY);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String[] getAsArray(String settingPrefix, String[] defaultArray) {
|
|
||||||
List<String> result = new ArrayList<>();
|
|
||||||
if (get(settingPrefix) != null) {
|
|
||||||
String[] strings = splitStringByCommaToArray(get(settingPrefix));
|
|
||||||
if (strings.length > 0) {
|
|
||||||
for (String string : strings) {
|
|
||||||
result.add(string.trim());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int counter = 0;
|
|
||||||
while (true) {
|
|
||||||
String value = get(settingPrefix + '.' + (counter++));
|
|
||||||
if (value == null) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
result.add(value.trim());
|
|
||||||
}
|
|
||||||
if (result.isEmpty()) {
|
|
||||||
return defaultArray;
|
|
||||||
}
|
|
||||||
return result.toArray(new String[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String, Settings> getGroups(String prefix) {
|
|
||||||
String settingPrefix = prefix;
|
|
||||||
if (settingPrefix.charAt(settingPrefix.length() - 1) != '.') {
|
|
||||||
settingPrefix = settingPrefix + ".";
|
|
||||||
}
|
|
||||||
// we don't really care that it might happen twice
|
|
||||||
TinyMap.Builder<String, TinyMap.Builder<String, String>> hashMap = TinyMap.builder();
|
|
||||||
for (String o : this.map.keySet()) {
|
|
||||||
if (o.startsWith(settingPrefix)) {
|
|
||||||
String nameValue = o.substring(settingPrefix.length());
|
|
||||||
int dotIndex = nameValue.indexOf('.');
|
|
||||||
if (dotIndex == -1) {
|
|
||||||
throw new SettingsException("failed to get setting group for ["
|
|
||||||
+ settingPrefix
|
|
||||||
+ "] setting prefix and setting [" + o + "] because of a missing '.'");
|
|
||||||
}
|
|
||||||
String name = nameValue.substring(0, dotIndex);
|
|
||||||
String value = nameValue.substring(dotIndex + 1);
|
|
||||||
Map<String, String> groupSettings = hashMap.computeIfAbsent(name, k -> TinyMap.builder());
|
|
||||||
groupSettings.put(value, get(o));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
TinyMap.Builder<String, Settings> retVal = TinyMap.builder();
|
|
||||||
for (Map.Entry<String, TinyMap.Builder<String, String>> entry : hashMap.entrySet()) {
|
|
||||||
String key = entry.getKey();
|
|
||||||
TinyMap.Builder<String, String> value = entry.getValue();
|
|
||||||
retVal.put(key, new DatastructureSettings(value.build()));
|
|
||||||
}
|
|
||||||
return retVal.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
return this == o || !(o == null || getClass() != o.getClass()) && map.equals(((DatastructureSettings) o).map);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return map.hashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void processSetting(Map<String, Object> map, String prefix, String setting, String value) {
|
|
||||||
int prefixLength = setting.indexOf('.');
|
|
||||||
if (prefixLength == -1) {
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
Map<String, Object> innerMap = (Map<String, Object>) map.get(prefix + setting);
|
|
||||||
if (innerMap != null) {
|
|
||||||
for (Map.Entry<String, Object> e : innerMap.entrySet()) {
|
|
||||||
String k = e.getKey();
|
|
||||||
Object v = e.getValue();
|
|
||||||
map.put(prefix + setting + "." + k, v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
map.put(prefix + setting, value);
|
|
||||||
} else {
|
|
||||||
String key = setting.substring(0, prefixLength);
|
|
||||||
String rest = setting.substring(prefixLength + 1);
|
|
||||||
Object existingValue = map.get(prefix + key);
|
|
||||||
if (existingValue == null) {
|
|
||||||
Map<String, Object> newMap = TinyMap.builder();
|
|
||||||
processSetting(newMap, "", rest, value);
|
|
||||||
map.put(key, newMap);
|
|
||||||
} else {
|
|
||||||
if (existingValue instanceof Map) {
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
Map<String, Object> innerMap = (Map<String, Object>) existingValue;
|
|
||||||
processSetting(innerMap, "", rest, value);
|
|
||||||
map.put(key, innerMap);
|
|
||||||
} else {
|
|
||||||
processSetting(map, prefix + key + ".", rest, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Object convertMapsToArrays(Map<String, Object> map) {
|
|
||||||
if (map.isEmpty()) {
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
boolean isArray = true;
|
|
||||||
int maxIndex = -1;
|
|
||||||
for (Map.Entry<String, Object> entry : map.entrySet()) {
|
|
||||||
String key = entry.getKey();
|
|
||||||
Object value = entry.getValue();
|
|
||||||
if (isArray) {
|
|
||||||
try {
|
|
||||||
int index = Integer.parseInt(key);
|
|
||||||
if (index >= 0) {
|
|
||||||
maxIndex = Math.max(maxIndex, index);
|
|
||||||
} else {
|
|
||||||
isArray = false;
|
|
||||||
}
|
|
||||||
} catch (NumberFormatException ex) {
|
|
||||||
isArray = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (value instanceof Map) {
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
Map<String, Object> valMap = (Map<String, Object>) value;
|
|
||||||
map.put(key, convertMapsToArrays(valMap));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (isArray && (maxIndex + 1) == map.size()) {
|
|
||||||
ArrayList<Object> newValue = new ArrayList<>(maxIndex + 1);
|
|
||||||
for (int i = 0; i <= maxIndex; i++) {
|
|
||||||
Object obj = map.get(Integer.toString(i));
|
|
||||||
if (obj == null) {
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
newValue.add(obj);
|
|
||||||
}
|
|
||||||
return newValue;
|
|
||||||
}
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isEmpty() {
|
|
||||||
return map.isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() throws IOException {
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,332 +0,0 @@
|
||||||
package org.xbib.settings.datastructures;
|
|
||||||
|
|
||||||
import org.xbib.settings.PlaceholderResolver;
|
|
||||||
import org.xbib.settings.PropertyPlaceholder;
|
|
||||||
import org.xbib.settings.Settings;
|
|
||||||
import org.xbib.settings.SettingsBuilder;
|
|
||||||
import org.xbib.settings.SettingsException;
|
|
||||||
import org.xbib.settings.SettingsLoader;
|
|
||||||
import org.xbib.settings.SettingsLoaderService;
|
|
||||||
import org.xbib.datastructures.tiny.TinyMap;
|
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.time.DateTimeException;
|
|
||||||
import java.time.LocalDate;
|
|
||||||
import java.time.format.DateTimeFormatter;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class DatastructureSettingsBuilder implements SettingsBuilder {
|
|
||||||
|
|
||||||
private final SettingsLoaderService settingsLoaderService;
|
|
||||||
|
|
||||||
private final TinyMap.Builder<String, String> map;
|
|
||||||
|
|
||||||
public DatastructureSettingsBuilder() {
|
|
||||||
this.settingsLoaderService = SettingsLoaderService.getInstance();
|
|
||||||
this.map = TinyMap.builder();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String remove(String key) {
|
|
||||||
return map.remove(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isEmpty() {
|
|
||||||
return map.isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets a setting with the provided setting key and value.
|
|
||||||
*
|
|
||||||
* @param key The setting key
|
|
||||||
* @param value The setting value
|
|
||||||
* @return The builder
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public DatastructureSettingsBuilder put(String key, String value) {
|
|
||||||
map.put(key, value);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the setting with the provided setting key and the boolean value.
|
|
||||||
*
|
|
||||||
* @param setting The setting key
|
|
||||||
* @param value The boolean value
|
|
||||||
* @return The builder
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public DatastructureSettingsBuilder put(String setting, boolean value) {
|
|
||||||
put(setting, String.valueOf(value));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the setting with the provided setting key and the int value.
|
|
||||||
*
|
|
||||||
* @param setting The setting key
|
|
||||||
* @param value The int value
|
|
||||||
* @return The builder
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public DatastructureSettingsBuilder put(String setting, int value) {
|
|
||||||
put(setting, String.valueOf(value));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the setting with the provided setting key and the long value.
|
|
||||||
*
|
|
||||||
* @param setting The setting key
|
|
||||||
* @param value The long value
|
|
||||||
* @return The builder
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public DatastructureSettingsBuilder put(String setting, long value) {
|
|
||||||
put(setting, String.valueOf(value));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the setting with the provided setting key and the float value.
|
|
||||||
*
|
|
||||||
* @param setting The setting key
|
|
||||||
* @param value The float value
|
|
||||||
* @return The builder
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public DatastructureSettingsBuilder put(String setting, float value) {
|
|
||||||
put(setting, String.valueOf(value));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the setting with the provided setting key and the double value.
|
|
||||||
*
|
|
||||||
* @param setting The setting key
|
|
||||||
* @param value The double value
|
|
||||||
* @return The builder
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public DatastructureSettingsBuilder put(String setting, double value) {
|
|
||||||
put(setting, String.valueOf(value));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the setting with the provided setting key and an array of values.
|
|
||||||
*
|
|
||||||
* @param setting The setting key
|
|
||||||
* @param values The values
|
|
||||||
* @return The builder
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public DatastructureSettingsBuilder putArray(String setting, String... values) {
|
|
||||||
remove(setting);
|
|
||||||
int counter = 0;
|
|
||||||
while (true) {
|
|
||||||
String value = map.remove(setting + '.' + (counter++));
|
|
||||||
if (value == null) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (int i = 0; i < values.length; i++) {
|
|
||||||
put(setting + '.' + i, values[i]);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the setting with the provided setting key and an array of values.
|
|
||||||
*
|
|
||||||
* @param setting The setting key
|
|
||||||
* @param values The values
|
|
||||||
* @return The builder
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public DatastructureSettingsBuilder putArray(String setting, List<String> values) {
|
|
||||||
remove(setting);
|
|
||||||
int counter = 0;
|
|
||||||
while (true) {
|
|
||||||
String value = map.remove(setting + '.' + (counter++));
|
|
||||||
if (value == null) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (int i = 0; i < values.size(); i++) {
|
|
||||||
put(setting + '.' + i, values.get(i));
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the setting group.
|
|
||||||
*
|
|
||||||
* @param settingPrefix setting prefix
|
|
||||||
* @param groupName group name
|
|
||||||
* @param settings settings
|
|
||||||
* @param values values
|
|
||||||
* @return a builder
|
|
||||||
* @throws SettingsException if setting fails
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public DatastructureSettingsBuilder put(String settingPrefix, String groupName, String[] settings, String[] values)
|
|
||||||
throws SettingsException {
|
|
||||||
if (settings.length != values.length) {
|
|
||||||
throw new SettingsException("the settings length must match the value length");
|
|
||||||
}
|
|
||||||
for (int i = 0; i < settings.length; i++) {
|
|
||||||
if (values[i] == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
put(settingPrefix + "" + groupName + "." + settings[i], values[i]);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets all the provided settings.
|
|
||||||
*
|
|
||||||
* @param settings settings
|
|
||||||
* @return builder
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public DatastructureSettingsBuilder put(Settings settings) {
|
|
||||||
map.putAll(settings.getAsMap());
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets all the provided settings.
|
|
||||||
*
|
|
||||||
* @param settings settings
|
|
||||||
* @return a builder
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public DatastructureSettingsBuilder put(Map<String, String> settings) {
|
|
||||||
map.putAll(settings);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads settings from a resource.
|
|
||||||
*
|
|
||||||
* @param resourceName resource name
|
|
||||||
* @param inputStream input stream
|
|
||||||
* @return builder
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public DatastructureSettingsBuilder loadFromResource(String resourceName, InputStream inputStream) {
|
|
||||||
SettingsLoader settingsLoader = settingsLoaderService.loaderFromResource(resourceName);
|
|
||||||
try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))) {
|
|
||||||
Map<String, String> loadedSettings = settingsLoader.load(bufferedReader.lines().collect(Collectors.joining()));
|
|
||||||
put(loadedSettings);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new SettingsException("failed to load settings from [" + resourceName + "]", e);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads settings from the actual string content that represents them using the
|
|
||||||
* {@link SettingsLoaderService#loaderFromResource(String)} (String)}.
|
|
||||||
*
|
|
||||||
* @param resourceName the resource name
|
|
||||||
* @param source the source
|
|
||||||
* @return builder
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public DatastructureSettingsBuilder loadFromString(String resourceName, String source) {
|
|
||||||
SettingsLoader settingsLoader = settingsLoaderService.loaderFromResource(resourceName);
|
|
||||||
try {
|
|
||||||
put(settingsLoader.load(source));
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new SettingsException("failed to load settings from [" + source + "]", e);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Load system properties to this settings.
|
|
||||||
*
|
|
||||||
* @return builder
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public DatastructureSettingsBuilder loadFromSystemProperties() {
|
|
||||||
for (Map.Entry<Object, Object> entry : System.getProperties().entrySet()) {
|
|
||||||
put((String) entry.getKey(), (String) entry.getValue());
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Load system environment to this settings.
|
|
||||||
*
|
|
||||||
* @return builder
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public DatastructureSettingsBuilder loadFromSystemEnvironment() {
|
|
||||||
for (Map.Entry<String, String> entry : System.getenv().entrySet()) {
|
|
||||||
put(entry.getKey(), entry.getValue());
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DatastructureSettingsBuilder replacePropertyPlaceholders(PropertyPlaceholder propertyPlaceholder,
|
|
||||||
PlaceholderResolver placeholderResolver) {
|
|
||||||
map.replaceAll((k, v) -> propertyPlaceholder.replacePlaceholders(v, placeholderResolver));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DatastructureSettingsBuilder replacePropertyPlaceholders() {
|
|
||||||
return replacePropertyPlaceholders(new PropertyPlaceholder("${", "}", false),
|
|
||||||
placeholderName -> {
|
|
||||||
// system property
|
|
||||||
String value = System.getProperty(placeholderName);
|
|
||||||
if (value != null) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
// environment
|
|
||||||
value = System.getenv(placeholderName);
|
|
||||||
if (value != null) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
// current date
|
|
||||||
try {
|
|
||||||
return DateTimeFormatter.ofPattern(placeholderName).format(LocalDate.now());
|
|
||||||
} catch (IllegalArgumentException | DateTimeException e) {
|
|
||||||
return map.get(placeholderName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DatastructureSettingsBuilder setRefresh(Path path, long initialDelay, long period, TimeUnit timeUnit) {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SettingsBuilder map(Function<Map.Entry<String, String>, Map.Entry<String, String>> function) {
|
|
||||||
map.entrySet().stream().map(function).forEach(e -> put(e.getKey(), e.getValue()));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DatastructureSettings build() {
|
|
||||||
return new DatastructureSettings(map.build());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,47 +0,0 @@
|
||||||
package org.xbib.settings.datastructures;
|
|
||||||
|
|
||||||
import org.xbib.settings.SettingsLoader;
|
|
||||||
import org.xbib.datastructures.tiny.TinyMap;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.StringReader;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Properties;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Settings loader that loads (parses) the settings in a properties format.
|
|
||||||
*/
|
|
||||||
public class PropertiesSettingsLoader implements SettingsLoader {
|
|
||||||
|
|
||||||
public PropertiesSettingsLoader() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<String> suffixes() {
|
|
||||||
return Set.of("properties");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String, String> load(String source) throws IOException {
|
|
||||||
Properties props = new Properties();
|
|
||||||
try (StringReader reader = new StringReader(source)) {
|
|
||||||
props.load(reader);
|
|
||||||
TinyMap.Builder<String, String> result = TinyMap.builder();
|
|
||||||
for (Map.Entry<Object, Object> entry : props.entrySet()) {
|
|
||||||
result.put((String) entry.getKey(), (String) entry.getValue());
|
|
||||||
}
|
|
||||||
return result.build();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String, String> load(Map<String, Object> source) {
|
|
||||||
Properties props = new Properties();
|
|
||||||
props.putAll(source);
|
|
||||||
TinyMap.Builder<String, String> result = TinyMap.builder();
|
|
||||||
for (Map.Entry<Object, Object> entry : props.entrySet()) {
|
|
||||||
result.put((String) entry.getKey(), (String) entry.getValue());
|
|
||||||
}
|
|
||||||
return result.build();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,4 +0,0 @@
|
||||||
/**
|
|
||||||
* Classes for settings using the datastructures API.
|
|
||||||
*/
|
|
||||||
package org.xbib.settings.datastructures;
|
|
|
@ -1 +0,0 @@
|
||||||
org.xbib.settings.datastructures.DatastructureSettingsBuilder
|
|
|
@ -1,134 +0,0 @@
|
||||||
package org.xbib.settings.datastructures.test;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.xbib.settings.Settings;
|
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.time.LocalDate;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
|
||||||
|
|
||||||
public class SettingsTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testEmpty() {
|
|
||||||
Settings settings = Settings.emptySettings();
|
|
||||||
assertTrue(settings.isEmpty());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSimpleSettings() {
|
|
||||||
Settings settings = Settings.settingsBuilder()
|
|
||||||
.put("a", "b")
|
|
||||||
.build();
|
|
||||||
assertEquals("{a=b}", settings.getAsMap().toString());
|
|
||||||
assertEquals("{a=b}", settings.getAsStructuredMap().toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testArray() {
|
|
||||||
Settings settings = Settings.settingsBuilder()
|
|
||||||
.putArray("input", Arrays.asList("a", "b", "c")).build();
|
|
||||||
assertEquals("a", settings.getAsArray("input")[0]);
|
|
||||||
assertEquals("b", settings.getAsArray("input")[1]);
|
|
||||||
assertEquals("c", settings.getAsArray("input")[2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Test
|
|
||||||
public void testArrayOfMaps() {
|
|
||||||
Settings settings = Settings.settingsBuilder()
|
|
||||||
.put("location.0.code", "Code 0")
|
|
||||||
.put("location.0.name", "Name 0")
|
|
||||||
.put("location.1.code", "Code 1")
|
|
||||||
.put("location.1.name", "Name 1")
|
|
||||||
.build();
|
|
||||||
|
|
||||||
// turn map with index keys 0,1,... into a list of maps
|
|
||||||
Map<String, Object> map = settings.getAsSettings("location").getAsStructuredMap();
|
|
||||||
List<Map<String, Object>> list = new ArrayList<>();
|
|
||||||
for (Map.Entry<String, Object> entry : map.entrySet()) {
|
|
||||||
list.add((Map<String, Object>) entry.getValue());
|
|
||||||
}
|
|
||||||
assertEquals("[{code=Code 0, name=Name 0}, {code=Code 1, name=Name 1}]", list.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testGroups() {
|
|
||||||
Settings settings = Settings.settingsBuilder()
|
|
||||||
.put("prefix.group1.k1", "v1")
|
|
||||||
.put("prefix.group1.k2", "v2")
|
|
||||||
.put("prefix.group1.k3", "v3")
|
|
||||||
.put("prefix.group2.k1", "v1")
|
|
||||||
.put("prefix.group2.k2", "v2")
|
|
||||||
.put("prefix.group2.k3", "v3")
|
|
||||||
.build();
|
|
||||||
Map<String, Settings> groups = settings.getGroups("prefix");
|
|
||||||
assertEquals("[group1, group2]", groups.keySet().toString());
|
|
||||||
assertTrue(groups.get("group1").getAsMap().containsKey("k1"));
|
|
||||||
assertTrue(groups.get("group1").getAsMap().containsKey("k2"));
|
|
||||||
assertTrue(groups.get("group1").getAsMap().containsKey("k3"));
|
|
||||||
assertTrue(groups.get("group2").getAsMap().containsKey("k1"));
|
|
||||||
assertTrue(groups.get("group2").getAsMap().containsKey("k2"));
|
|
||||||
assertTrue(groups.get("group2").getAsMap().containsKey("k3"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testCurrentYearInSettings() {
|
|
||||||
Settings settings = Settings.settingsBuilder()
|
|
||||||
.put("date", "${yyyy}")
|
|
||||||
.replacePropertyPlaceholders()
|
|
||||||
.build();
|
|
||||||
assertEquals(LocalDate.now().getYear(), Integer.parseInt(settings.get("date")));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testPropertyReplaceNull() {
|
|
||||||
Settings settings = Settings.settingsBuilder()
|
|
||||||
.put("null", null)
|
|
||||||
.replacePropertyPlaceholders()
|
|
||||||
.build();
|
|
||||||
assertNull(settings.get("null"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSystemEnvironment() {
|
|
||||||
Settings settings = Settings.settingsBuilder()
|
|
||||||
.loadFromSystemEnvironment()
|
|
||||||
.build();
|
|
||||||
assertFalse(settings.getAsMap().isEmpty());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSystemProperties() {
|
|
||||||
Settings settings = Settings.settingsBuilder()
|
|
||||||
.loadFromSystemProperties()
|
|
||||||
.build();
|
|
||||||
assertFalse(settings.getAsMap().isEmpty());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testPropertiesLoaderFromResource() {
|
|
||||||
Settings settings = Settings.settingsBuilder()
|
|
||||||
.loadFromResource("properties", new ByteArrayInputStream("a.b=c".getBytes(StandardCharsets.UTF_8)))
|
|
||||||
.build();
|
|
||||||
assertEquals("{a.b=c}", settings.getAsMap().toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testPropertiesLoaderFromString() {
|
|
||||||
Settings settings = Settings.settingsBuilder()
|
|
||||||
.loadFromString("properties", "#\na.b=c")
|
|
||||||
.build();
|
|
||||||
assertEquals("{a.b=c}", settings.getAsMap().toString());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
org.xbib.settings.datastructures.PropertiesSettingsLoader
|
|
|
@ -15,13 +15,14 @@ pluginManagement {
|
||||||
dependencyResolutionManagement {
|
dependencyResolutionManagement {
|
||||||
versionCatalogs {
|
versionCatalogs {
|
||||||
libs {
|
libs {
|
||||||
version('gradle', '8.1.1')
|
version('gradle', '8.4-rc-1')
|
||||||
version('junit', '5.10.0')
|
version('junit', '5.10.0')
|
||||||
version('jackson', '2.15.2')
|
version('jackson', '2.15.2')
|
||||||
version('datastructures', '2.3.0')
|
version('settings', '5.0.5')
|
||||||
library('junit-jupiter-api', 'org.junit.jupiter', 'junit-jupiter-api').versionRef('junit')
|
library('junit-jupiter-api', 'org.junit.jupiter', 'junit-jupiter-api').versionRef('junit')
|
||||||
library('junit-jupiter-params', 'org.junit.jupiter', 'junit-jupiter-params').versionRef('junit')
|
library('junit-jupiter-params', 'org.junit.jupiter', 'junit-jupiter-params').versionRef('junit')
|
||||||
library('junit-jupiter-engine', 'org.junit.jupiter', 'junit-jupiter-engine').versionRef('junit')
|
library('junit-jupiter-engine', 'org.junit.jupiter', 'junit-jupiter-engine').versionRef('junit')
|
||||||
|
library('junit-jupiter-platform-launcher', 'org.junit.platform', 'junit-platform-launcher').version('1.10.0')
|
||||||
library('junit4', 'junit', 'junit').version('4.13.2')
|
library('junit4', 'junit', 'junit').version('4.13.2')
|
||||||
library('hamcrest', 'org.hamcrest:hamcrest-library:2.2')
|
library('hamcrest', 'org.hamcrest:hamcrest-library:2.2')
|
||||||
library('jackson-core', 'com.fasterxml.jackson.core', 'jackson-core').versionRef('jackson')
|
library('jackson-core', 'com.fasterxml.jackson.core', 'jackson-core').versionRef('jackson')
|
||||||
|
@ -29,18 +30,16 @@ dependencyResolutionManagement {
|
||||||
library('jackson-dataformat-smile', 'com.fasterxml.jackson.dataformat', 'jackson-dataformat-smile').versionRef('jackson')
|
library('jackson-dataformat-smile', 'com.fasterxml.jackson.dataformat', 'jackson-dataformat-smile').versionRef('jackson')
|
||||||
library('jackson-dataformat-xml', 'com.fasterxml.jackson.dataformat', 'jackson-dataformat-xml').versionRef('jackson')
|
library('jackson-dataformat-xml', 'com.fasterxml.jackson.dataformat', 'jackson-dataformat-xml').versionRef('jackson')
|
||||||
library('jackson-dataformat-yaml', 'com.fasterxml.jackson.dataformat', 'jackson-dataformat-yaml').versionRef('jackson')
|
library('jackson-dataformat-yaml', 'com.fasterxml.jackson.dataformat', 'jackson-dataformat-yaml').versionRef('jackson')
|
||||||
library('datastructures-api', 'org.xbib', 'datastructures-api').versionRef('datastructures')
|
library('settings-api', 'org.xbib', 'settings-api').versionRef('settings')
|
||||||
library('datastructures-tiny', 'org.xbib', 'datastructures-tiny').versionRef('datastructures')
|
library('mockito-core', 'org.mockito', 'mockito-core').version('5.2.0')
|
||||||
library('datastructures-json-tiny', 'org.xbib', 'datastructures-json-tiny').versionRef('datastructures')
|
library('mockito-inline', 'org.mockito', 'mockito-inline').version('5.2.0')
|
||||||
library('datastructures-yaml-tiny', 'org.xbib', 'datastructures-yaml-tiny').versionRef('datastructures')
|
library('net', 'org.xbib', 'net').version('4.0.0')
|
||||||
library('mockito-core', 'org.mockito', 'mockito-core').version('4.11.0')
|
|
||||||
library('mockito-inline', 'org.mockito', 'mockito-inline').version('4.11.0')
|
|
||||||
library('net', 'org.xbib', 'net').version('3.3.4')
|
|
||||||
library('woodstox', 'com.fasterxml.woodstox', 'woodstox-core').version('6.5.1')
|
library('woodstox', 'com.fasterxml.woodstox', 'woodstox-core').version('6.5.1')
|
||||||
library('snakeyaml', 'org.yaml', 'snakeyaml').version('2.2')
|
library('snakeyaml', 'org.yaml', 'snakeyaml').version('2.2')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
include 'content-api'
|
include 'content-api'
|
||||||
include 'content-core'
|
include 'content-core'
|
||||||
include 'content-csv'
|
include 'content-csv'
|
||||||
|
@ -51,11 +50,6 @@ include 'content-resource'
|
||||||
include 'content-smile'
|
include 'content-smile'
|
||||||
include 'content-xml'
|
include 'content-xml'
|
||||||
include 'content-yaml'
|
include 'content-yaml'
|
||||||
include 'settings-api'
|
|
||||||
include 'settings-content'
|
include 'settings-content'
|
||||||
include 'settings-content-json'
|
include 'settings-content-json'
|
||||||
include 'settings-content-yaml'
|
include 'settings-content-yaml'
|
||||||
include 'settings-datastructures'
|
|
||||||
include 'settings-datastructures-json'
|
|
||||||
include 'settings-datastructures-yaml'
|
|
||||||
include 'config'
|
|
||||||
|
|
Loading…
Reference in a new issue