mirror of
https://github.com/CarmJos/EasyConfiguration.git
synced 2026-06-04 10:38:19 +08:00
feat(holder): Try to support MultiConfiguration. #169
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<artifactId>configured-parent</artifactId>
|
||||
<version>4.2.0</version>
|
||||
<version>4.2.1</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<properties>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<artifactId>configured-parent</artifactId>
|
||||
<version>4.2.0</version>
|
||||
<version>4.2.1</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<properties>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<artifactId>configured-parent</artifactId>
|
||||
<version>4.2.0</version>
|
||||
<version>4.2.1</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<properties>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<artifactId>configured-parent</artifactId>
|
||||
<version>4.2.0</version>
|
||||
<version>4.2.1</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<properties>
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<artifactId>configured-parent</artifactId>
|
||||
<version>4.2.1</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<properties>
|
||||
<maven.compiler.source>${project.jdk.version}</maven.compiler.source>
|
||||
<maven.compiler.target>${project.jdk.version}</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
|
||||
<kotlin.version>2.3.10</kotlin.version>
|
||||
</properties>
|
||||
<artifactId>configured-feature-multi</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>Configured - Record Feature</name>
|
||||
<url>https://github.com/CarmJos/configured</url>
|
||||
<description>Provides Java record type support for the Configured framework.</description>
|
||||
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<artifactId>configured-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<artifactId>configured-yaml</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -0,0 +1,135 @@
|
||||
package cc.carm.lib.configuration;
|
||||
|
||||
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public abstract class MultiConfiguration<K, T> {
|
||||
|
||||
protected final ConcurrentHashMap<K, T> valuesCache = new ConcurrentHashMap<>();
|
||||
|
||||
public MultiConfiguration() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the value of the key from the holder, and return the value.
|
||||
*
|
||||
* @param key The key of the value to read.
|
||||
* @param holder The holder of the value to read.
|
||||
* @return The value of the key, or null if the value is not exist.
|
||||
*/
|
||||
public abstract T read(@NotNull K key, @NotNull ConfigurationHolder<?> holder);
|
||||
|
||||
/**
|
||||
* Write (and save) the value of the key to the holder, then update the cache.
|
||||
*
|
||||
* @param holder The holder of the value to write.
|
||||
* @param value The value to write, which should not be null.
|
||||
*/
|
||||
public abstract void write(@NotNull ConfigurationHolder<?> holder, @NotNull T value);
|
||||
|
||||
/**
|
||||
* Get all holders of the configuration, which should be a concurrent map to support concurrent access.
|
||||
*
|
||||
* @return All holders of the configuration.
|
||||
*/
|
||||
public abstract @NotNull Map<K, ConfigurationHolder<?>> holders();
|
||||
|
||||
/**
|
||||
* Get the holder of the key.
|
||||
* If the holder of the key is not exist,
|
||||
* it should be created then return the created holder.
|
||||
*
|
||||
* @param key The key of the holder to get.
|
||||
* @return The holder of the key.
|
||||
*/
|
||||
public abstract @NotNull ConfigurationHolder<?> holder(@NotNull K key);
|
||||
|
||||
/**
|
||||
* Remove the holder of the key, and remove the value of the key from the cache.
|
||||
* Also delete the configuration file if necessary.
|
||||
*
|
||||
* @param key The key of the holder to remove.
|
||||
*/
|
||||
public abstract void removeHolder(@NotNull K key);
|
||||
|
||||
public void loadAll() {
|
||||
for (Map.Entry<K, ConfigurationHolder<?>> entry : holders().entrySet()) {
|
||||
K key = entry.getKey();
|
||||
ConfigurationHolder<?> holder = entry.getValue();
|
||||
try {
|
||||
T loaded = read(key, holder);
|
||||
if (loaded != null) {
|
||||
valuesCache.put(key, loaded);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void saveAll() {
|
||||
for (Map.Entry<K, T> entry : valuesCache.entrySet()) {
|
||||
K key = entry.getKey();
|
||||
T value = entry.getValue();
|
||||
ConfigurationHolder<?> holder = holder(key);
|
||||
try {
|
||||
write(holder, value);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get all keys in the cache.
|
||||
*
|
||||
* @return All keys in the cache.
|
||||
*/
|
||||
public @NotNull Set<K> keys() {
|
||||
return valuesCache.keySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all values in the cache.
|
||||
*
|
||||
* @return All values in the cache.
|
||||
*/
|
||||
public @NotNull Map<K, T> values() {
|
||||
return this.valuesCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of the key, or null if the value is not exist.
|
||||
*
|
||||
* @param key The key of the value to get.
|
||||
* @return The value of the key, or null if the value is not exist.
|
||||
*/
|
||||
public @Nullable T get(@NotNull K key) {
|
||||
return valuesCache.get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the value of the key, and return the old value.
|
||||
*
|
||||
* @param key The key of the value to update.
|
||||
* @param value The new value, or null to remove the value.
|
||||
* @return The old value, or null if the value is not exist.
|
||||
*/
|
||||
public @Nullable T update(@NotNull K key, @Nullable T value) {
|
||||
if (value == null) {
|
||||
T current = valuesCache.remove(key);
|
||||
removeHolder(key);
|
||||
return current;
|
||||
}
|
||||
ConfigurationHolder<?> holder = holder(key);
|
||||
write(holder, value);
|
||||
return valuesCache.put(key, value);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package cc.carm.lib.configuration.tests;
|
||||
|
||||
import cc.carm.lib.configuration.MultiConfiguration;
|
||||
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
||||
import cc.carm.lib.configuration.source.yaml.YAMLConfigFactory;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public abstract class ExampleUserStorage<T> extends MultiConfiguration<UUID, T> {
|
||||
|
||||
protected final @NotNull File dataFolder;
|
||||
protected final ConcurrentHashMap<UUID, ConfigurationHolder<?>> holders = new ConcurrentHashMap<>();
|
||||
|
||||
public ExampleUserStorage(@NotNull File dataFolder) {
|
||||
this.dataFolder = dataFolder;
|
||||
|
||||
// Load existing configuration files
|
||||
if (dataFolder.exists() && dataFolder.isDirectory()) {
|
||||
File[] files = dataFolder.listFiles((dir, name) -> name.endsWith(".yml"));
|
||||
if (files != null) {
|
||||
for (File file : files) {
|
||||
String fileName = file.getName();
|
||||
String uuidStr = fileName.substring(0, fileName.length() - 4); // Remove ".yml"
|
||||
try {
|
||||
UUID uuid = UUID.fromString(uuidStr);
|
||||
ConfigurationHolder<?> holder = YAMLConfigFactory.from(file).build();
|
||||
holders.put(uuid, holder);
|
||||
} catch (IllegalArgumentException e) {
|
||||
System.err.println("Invalid UUID in file name: " + fileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
loadAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Map<UUID, ConfigurationHolder<?>> holders() {
|
||||
return this.holders;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ConfigurationHolder<?> holder(@NotNull UUID key) {
|
||||
ConfigurationHolder<?> loaded = holders.get(key);
|
||||
if (loaded != null) return loaded;
|
||||
|
||||
ConfigurationHolder<?> created = YAMLConfigFactory.from(new File(dataFolder, key + ".yml")).build();
|
||||
holders.put(key, created);
|
||||
return created;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeHolder(@NotNull UUID key) {
|
||||
ConfigurationHolder<?> loaded = holders.remove(key);
|
||||
if (loaded == null) return;
|
||||
|
||||
File file = new File(dataFolder, key + ".yml");
|
||||
if (file.exists()) file.delete();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package cc.carm.lib.configuration.tests;
|
||||
|
||||
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
||||
import cc.carm.lib.configuration.source.section.ConfigureSection;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.UUID;
|
||||
|
||||
public class MultiFileTests {
|
||||
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
|
||||
ProfileStorage storage = new ProfileStorage(new File(new File("target"), "test-profiles"));
|
||||
UserProfile profile = new UserProfile(UUID.randomUUID(), "John Doe", "john@google.com", "123123123");
|
||||
storage.update(profile.getUniqueId(), profile);
|
||||
|
||||
System.out.println("Current users: ");
|
||||
storage.values().forEach((k, v) -> {
|
||||
System.out.println("# " + k);
|
||||
System.out.println("- " + v.getName() + " (" + v.getEmail() + ", " + v.getPhone() + ")");
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public static class ProfileStorage extends ExampleUserStorage<UserProfile> {
|
||||
|
||||
public ProfileStorage(@NotNull File dataFolder) {
|
||||
super(dataFolder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserProfile read(@NotNull UUID key, @NotNull ConfigurationHolder<?> holder) {
|
||||
ConfigureSection conf = holder.config();
|
||||
return new UserProfile(
|
||||
key,
|
||||
conf.getString("name", "Unknown"),
|
||||
conf.getString("email", "unset"),
|
||||
conf.getString("phone", "123123123")
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(@NotNull ConfigurationHolder<?> holder, @NotNull UserProfile value) {
|
||||
ConfigureSection conf = holder.config();
|
||||
conf.set("name", value.getName());
|
||||
conf.set("email", value.getEmail());
|
||||
conf.set("phone", value.getPhone());
|
||||
try {
|
||||
holder.save();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package cc.carm.lib.configuration.tests;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
public class UserProfile {
|
||||
|
||||
protected final @NotNull UUID uuid;
|
||||
protected final @NotNull String name;
|
||||
protected final @NotNull String email;
|
||||
protected final @NotNull String phone;
|
||||
|
||||
public UserProfile(@NotNull UUID uuid, @NotNull String name, @NotNull String email, @NotNull String phone) {
|
||||
this.uuid = uuid;
|
||||
this.name = name;
|
||||
this.email = email;
|
||||
this.phone = phone;
|
||||
}
|
||||
|
||||
public @NotNull UUID getUniqueId() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
public @NotNull String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public @NotNull String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
public @NotNull String getPhone() {
|
||||
return phone;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof UserProfile)) return false;
|
||||
UserProfile that = (UserProfile) o;
|
||||
return Objects.equals(name, that.name) && Objects.equals(email, that.email) && Objects.equals(phone, that.phone);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(name, email, phone);
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<artifactId>configured-parent</artifactId>
|
||||
<version>4.2.0</version>
|
||||
<version>4.2.1</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<artifactId>configured-parent</artifactId>
|
||||
<version>4.2.0</version>
|
||||
<version>4.2.1</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<properties>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<artifactId>configured-parent</artifactId>
|
||||
<version>4.2.0</version>
|
||||
<version>4.2.1</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<properties>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<artifactId>configured-parent</artifactId>
|
||||
<version>4.2.0</version>
|
||||
<version>4.2.1</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<properties>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<artifactId>configured-parent</artifactId>
|
||||
<version>4.2.0</version>
|
||||
<version>4.2.1</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<properties>
|
||||
|
||||
Reference in New Issue
Block a user