diff --git a/core/pom.xml b/core/pom.xml index 62c38e2..8f9e98b 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -5,7 +5,7 @@ easyconfiguration-parent cc.carm.lib - 4.0.7 + 4.0.8 4.0.0 diff --git a/demo/pom.xml b/demo/pom.xml index bc89f7d..9d84d6a 100644 --- a/demo/pom.xml +++ b/demo/pom.xml @@ -5,7 +5,7 @@ easyconfiguration-parent cc.carm.lib - 4.0.7 + 4.0.8 4.0.0 diff --git a/features/commentable/pom.xml b/features/commentable/pom.xml index 83bdddc..61912b7 100644 --- a/features/commentable/pom.xml +++ b/features/commentable/pom.xml @@ -6,7 +6,7 @@ cc.carm.lib easyconfiguration-parent - 4.0.7 + 4.0.8 ../../pom.xml diff --git a/features/file/pom.xml b/features/file/pom.xml index e899f77..5ac7568 100644 --- a/features/file/pom.xml +++ b/features/file/pom.xml @@ -6,7 +6,7 @@ cc.carm.lib easyconfiguration-parent - 4.0.7 + 4.0.8 ../../pom.xml diff --git a/features/section/pom.xml b/features/section/pom.xml index 79f4e45..c3969b1 100644 --- a/features/section/pom.xml +++ b/features/section/pom.xml @@ -6,7 +6,7 @@ cc.carm.lib easyconfiguration-parent - 4.0.7 + 4.0.8 ../../pom.xml diff --git a/features/section/src/main/java/cc/carm/lib/configuration/source/section/AbstractMapSection.java b/features/section/src/main/java/cc/carm/lib/configuration/source/section/AbstractMapSection.java index 63a9083..d225248 100644 --- a/features/section/src/main/java/cc/carm/lib/configuration/source/section/AbstractMapSection.java +++ b/features/section/src/main/java/cc/carm/lib/configuration/source/section/AbstractMapSection.java @@ -98,6 +98,11 @@ public abstract class AbstractMapSection> implem return Collections.unmodifiableMap(deep ? mappingValues(this, null, true, String.valueOf(pathSeparator())) : data()); } + @Override + public @NotNull @UnmodifiableView Set getKeys(boolean deep) { + return Collections.unmodifiableSet(deep ? mappingKeys(this, null, true, String.valueOf(pathSeparator())) : data().keySet()); + } + @Override public void set(@NotNull String path, @Nullable Object value) { if (value instanceof Map) value = createSection(path, (Map) value); @@ -157,5 +162,17 @@ public abstract class AbstractMapSection> implem return output; } + protected static Set mappingKeys(@NotNull AbstractMapSection section, @Nullable String parent, boolean deep, String pathSeparator) { + Set keys = new LinkedHashSet<>(); + for (Map.Entry entry : section.data().entrySet()) { + String path = (parent == null ? "" : parent + pathSeparator) + entry.getKey(); + keys.add(path); + if (deep && entry.getValue() instanceof AbstractMapSection) { + keys.addAll(mappingKeys((AbstractMapSection) entry.getValue(), path, true, pathSeparator)); + } + } + return keys; + } + } diff --git a/features/text/pom.xml b/features/text/pom.xml index 15e94ad..efc9d0e 100644 --- a/features/text/pom.xml +++ b/features/text/pom.xml @@ -6,7 +6,7 @@ cc.carm.lib easyconfiguration-parent - 4.0.7 + 4.0.8 ../../pom.xml diff --git a/features/versioned/pom.xml b/features/versioned/pom.xml index 4a6c9a3..44b4aae 100644 --- a/features/versioned/pom.xml +++ b/features/versioned/pom.xml @@ -6,7 +6,7 @@ cc.carm.lib easyconfiguration-parent - 4.0.7 + 4.0.8 ../../pom.xml diff --git a/pom.xml b/pom.xml index 4077842..282e37e 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ cc.carm.lib easyconfiguration-parent pom - 4.0.7 + 4.0.8 core features/section @@ -28,7 +28,7 @@ providers/gson - + providers/mongodb demo diff --git a/providers/gson/pom.xml b/providers/gson/pom.xml index e2bf4c9..a3c26c0 100644 --- a/providers/gson/pom.xml +++ b/providers/gson/pom.xml @@ -5,7 +5,7 @@ easyconfiguration-parent cc.carm.lib - 4.0.7 + 4.0.8 ../../pom.xml 4.0.0 diff --git a/providers/mongodb/pom.xml b/providers/mongodb/pom.xml index c8c2074..2768078 100644 --- a/providers/mongodb/pom.xml +++ b/providers/mongodb/pom.xml @@ -5,7 +5,7 @@ easyconfiguration-parent cc.carm.lib - 4.0.0 + 4.0.8 ../../pom.xml 4.0.0 @@ -15,6 +15,7 @@ UTF-8 UTF-8 + 5.3.1 2.24.3 easyconfiguration-mongodb @@ -30,7 +31,7 @@ ${project.parent.groupId} - easyconfiguration-gson + easyconfiguration-feature-section ${project.parent.version} compile @@ -38,14 +39,7 @@ org.mongodb mongodb-driver-sync - 5.3.1 - - - - ${project.parent.groupId} - easyconfiguration-demo - ${project.parent.version} - test + ${deps.mongodb.version} @@ -69,6 +63,20 @@ test + + ${project.parent.groupId} + easyconfiguration-demo + ${project.parent.version} + test + + + + ${project.parent.groupId} + easyconfiguration-gson + ${project.parent.version} + test + + diff --git a/providers/mongodb/src/main/java/cc/carm/lib/configuration/source/mongodb/MongoConfigFactory.java b/providers/mongodb/src/main/java/cc/carm/lib/configuration/source/mongodb/MongoConfigFactory.java new file mode 100644 index 0000000..5fc485e --- /dev/null +++ b/providers/mongodb/src/main/java/cc/carm/lib/configuration/source/mongodb/MongoConfigFactory.java @@ -0,0 +1,75 @@ +package cc.carm.lib.configuration.source.mongodb; + +import cc.carm.lib.configuration.source.ConfigurationFactory; +import cc.carm.lib.configuration.source.ConfigurationHolder; +import com.mongodb.client.MongoCollection; +import com.mongodb.client.MongoDatabase; +import org.bson.Document; +import org.jetbrains.annotations.NotNull; + +import java.util.function.Supplier; + +public class MongoConfigFactory extends ConfigurationFactory, MongoConfigFactory> { + + public static MongoConfigFactory from(@NotNull Supplier> collectionSupplier) { + return new MongoConfigFactory(collectionSupplier); + } + + public static MongoConfigFactory from(@NotNull MongoCollection collection) { + return from(() -> collection); + } + + public static MongoConfigFactory from(@NotNull MongoDatabase database, @NotNull String collectionName) { + return from(() -> database.getCollection(collectionName)); + } + + protected @NotNull Supplier> collectionSupplier; + protected @NotNull String namespace = "config"; + + public MongoConfigFactory(@NotNull Supplier> collectionSupplier) { + super(); + this.collectionSupplier = collectionSupplier; + } + + public MongoConfigFactory collection(@NotNull Supplier> collectionSupplier) { + this.collectionSupplier = collectionSupplier; + return this; + } + + public MongoConfigFactory collection(@NotNull MongoCollection collection) { + return collection(() -> collection); + } + + public MongoConfigFactory namespace(@NotNull String namespace) { + this.namespace = namespace; + return this; + } + + public MongoConfigFactory namespace(@NotNull Supplier namespace) { + return namespace(namespace.get()); + } + + + @Override + protected MongoConfigFactory self() { + return this; + } + + @Override + public @NotNull ConfigurationHolder build() { + MongoCollection collection = this.collectionSupplier.get(); + if (collection == null) { + throw new IllegalStateException("Failed to get MongoCollection from supplier"); + } + + return new ConfigurationHolder(this.adapters, this.options, this.metadata, this.initializer) { + final @NotNull MongoSource source = new MongoSource(this, System.currentTimeMillis(), collection, namespace); + + @Override + public @NotNull MongoSource config() { + return this.source; + } + }; + } + +} diff --git a/providers/mongodb/src/main/java/cc/carm/lib/configuration/source/mongodb/MongoSource.java b/providers/mongodb/src/main/java/cc/carm/lib/configuration/source/mongodb/MongoSource.java index c915857..d7d1866 100644 --- a/providers/mongodb/src/main/java/cc/carm/lib/configuration/source/mongodb/MongoSource.java +++ b/providers/mongodb/src/main/java/cc/carm/lib/configuration/source/mongodb/MongoSource.java @@ -1,4 +1,76 @@ package cc.carm.lib.configuration.source.mongodb; -public class MongoSource { +import cc.carm.lib.configuration.source.ConfigurationHolder; +import cc.carm.lib.configuration.source.section.ConfigureSource; +import cc.carm.lib.configuration.source.section.SourcedSection; +import com.mongodb.client.MongoCollection; +import com.mongodb.client.model.ReplaceOptions; +import org.bson.Document; +import org.jetbrains.annotations.NotNull; + +import java.util.Map; +import java.util.Objects; + +public class MongoSource extends ConfigureSource, MongoSource> { + + protected final @NotNull MongoCollection collection; + protected final @NotNull String namespace; + + protected SourcedSection rootSection; + + protected MongoSource(@NotNull ConfigurationHolder holder, long lastUpdateMillis, + @NotNull MongoCollection collection, @NotNull String namespace) { + super(holder, lastUpdateMillis); + this.collection = collection; + this.namespace = namespace; + try { + onReload(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + protected @NotNull MongoSource self() { + return this; + } + + @Override + public @NotNull Map original() { + return section().data(); + } + + @Override + public @NotNull SourcedSection section() { + return Objects.requireNonNull(rootSection, "RootSection is not initialized"); + } + + public @NotNull String namespace() { + return this.namespace; + } + + public @NotNull MongoCollection collection() { + return this.collection; + } + + @Override + public void save() throws Exception { + Map data = this.rootSection.rawMap(); + if (data.isEmpty()) return; // Skip saving if empty + if (data.containsKey("_id") && data.size() == 1) return; // Skip saving if only contains _id + + ReplaceOptions options = new ReplaceOptions().upsert(true); + Document storage = new Document(data).append("_id", this.namespace); + this.collection.replaceOne(new Document("_id", this.namespace), storage, options); + } + + @Override + protected void onReload() throws Exception { + Document storage = this.collection.find(new Document("_id", this.namespace)).first(); + if (storage == null) storage = new Document(); + else storage.remove("_id"); // Remove _id + this.rootSection = SourcedSection.root(this, storage); + } + + } diff --git a/providers/mongodb/src/test/java/config/MongoConfig.java b/providers/mongodb/src/test/java/config/MongoConfig.java new file mode 100644 index 0000000..b831c37 --- /dev/null +++ b/providers/mongodb/src/test/java/config/MongoConfig.java @@ -0,0 +1,12 @@ +package config; + +import cc.carm.lib.configuration.Configuration; +import cc.carm.lib.configuration.value.standard.ConfiguredValue; + +interface MongoConfig extends Configuration { + ConfiguredValue HOST = ConfiguredValue.of("127.0.0.1"); + ConfiguredValue PORT = ConfiguredValue.of(27017); + ConfiguredValue USERNAME = ConfiguredValue.of("minecraft"); + ConfiguredValue PASSWORD = ConfiguredValue.of("minecraft"); + ConfiguredValue DATABASE = ConfiguredValue.of("minecraft"); +} diff --git a/providers/mongodb/src/test/java/config/MongoTest.java b/providers/mongodb/src/test/java/config/MongoTest.java new file mode 100644 index 0000000..7abdfd1 --- /dev/null +++ b/providers/mongodb/src/test/java/config/MongoTest.java @@ -0,0 +1,57 @@ +package config; + +import cc.carm.lib.configuration.demo.tests.ConfigurationTest; +import cc.carm.lib.configuration.source.ConfigurationHolder; +import cc.carm.lib.configuration.source.json.JSONConfigFactory; +import cc.carm.lib.configuration.source.mongodb.MongoConfigFactory; +import com.mongodb.ConnectionString; +import com.mongodb.MongoClientSettings; +import com.mongodb.MongoCredential; +import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoClients; +import com.mongodb.client.MongoDatabase; +import org.bson.UuidRepresentation; +import org.junit.Test; + +import java.io.File; + +public class MongoTest { + + boolean local = false; + + @Test + public void test() { + + if (!local) return; + + ConfigurationHolder gsonHolder = JSONConfigFactory.from(new File("target/mongo.json")).build(); + gsonHolder.initialize(MongoConfig.class); + + MongoClientSettings settings = MongoClientSettings.builder() + .applyConnectionString(new ConnectionString( + "mongodb://" + MongoConfig.HOST.resolve() + ":" + MongoConfig.PORT.resolve() + )) + .credential(MongoCredential.createCredential( + MongoConfig.USERNAME.resolve(), MongoConfig.DATABASE.resolve(), + MongoConfig.PASSWORD.resolve().toCharArray() + )) + .uuidRepresentation(UuidRepresentation.STANDARD) + .build(); + MongoClient mongoClient = MongoClients.create(settings); + MongoDatabase mongoDatabase = mongoClient.getDatabase(MongoConfig.DATABASE.resolve()); + + ConfigurationHolder mongoHolder = MongoConfigFactory + .from(mongoDatabase, "configs") + .namespace("my_plugin") + .build(); + + // Test the configuration + ConfigurationTest.testDemo(mongoHolder); + ConfigurationTest.testInner(mongoHolder); + + ConfigurationTest.save(mongoHolder); + + } + + +} diff --git a/providers/yaml/pom.xml b/providers/yaml/pom.xml index d1e2bd1..42e4ace 100644 --- a/providers/yaml/pom.xml +++ b/providers/yaml/pom.xml @@ -6,7 +6,7 @@ easyconfiguration-parent cc.carm.lib - 4.0.7 + 4.0.8 ../../pom.xml