Skip to content

Commit

Permalink
Add strip method that returns a set containing removed paths
Browse files Browse the repository at this point in the history
  • Loading branch information
Almighty-Satan committed Oct 29, 2023
1 parent 33333e4 commit 849154b
Show file tree
Hide file tree
Showing 9 changed files with 83 additions and 38 deletions.
1 change: 1 addition & 0 deletions buildSrc/src/main/kotlin/jaskl.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ repositories {
dependencies {
compileOnly("org.jetbrains:annotations:24.0.1")

testCompileOnly("org.jetbrains:annotations:24.0.1")
testImplementation("org.junit.jupiter:junit-jupiter-api:5.10.0")
testFixturesImplementation("org.junit.jupiter:junit-jupiter-api:5.10.0")
testImplementation(testFixtures(project(":core")))
Expand Down
17 changes: 16 additions & 1 deletion core/src/main/java/io/github/almightysatan/jaskl/Config.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,12 @@

package io.github.almightysatan.jaskl;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.Unmodifiable;

import java.io.IOException;
import java.util.Set;

public interface Config {

Expand Down Expand Up @@ -61,9 +64,21 @@ public interface Config {
* Cleans up dead entries from the storage location.
* An entry is dead if no {@link ConfigEntry} references its path.
*
* @return a set containing all removed paths. Depending on the implementation map entries might be returned as
* separate paths.
* @throws IOException if an I/O exception occurs.
*/
void strip() throws IOException;
@Unmodifiable @NotNull Set<@NotNull String> strip0() throws IOException; // stripPaths ?

/**
* Cleans up dead entries from the storage location.
* An entry is dead if no {@link ConfigEntry} references its path.
*
* @throws IOException if an I/O exception occurs.
*/
default void strip() throws IOException {
this.strip0();
}

/**
* Closes the corresponding data storage location.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@
package io.github.almightysatan.jaskl.test;

import io.github.almightysatan.jaskl.impl.ConfigImpl;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Unmodifiable;

import java.util.Collections;
import java.util.Set;

public class NopConfigImpl extends ConfigImpl {

Expand All @@ -41,7 +46,8 @@ public void write() {
}

@Override
public void strip() {
public @Unmodifiable @NotNull Set<@NotNull String> strip0() {
return Collections.emptySet();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,7 @@
import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.function.Supplier;

public class ConfigTest {
Expand Down Expand Up @@ -404,7 +401,7 @@ public static void testStrip(Supplier<Config> configSupplier, File file) throws
ConfigEntry<String> stringConfigEntry1 = StringConfigEntry.of(config1, "example.string", "Example String", "default");

config1.load();
config1.strip();
Set<String> paths = config1.strip0();
config1.close();

Config config2 = configSupplier.get();
Expand All @@ -415,6 +412,9 @@ public static void testStrip(Supplier<Config> configSupplier, File file) throws

Assertions.assertEquals("modified", stringConfigEntry2.getValue());
Assertions.assertEquals(0, intConfigEntry2.getValue());
Assertions.assertEquals(1, paths.size());
Assertions.assertTrue(paths.contains("example.integer"));
Assertions.assertThrows(UnsupportedOperationException.class, () -> paths.add("test"));

config2.close();
}
Expand Down Expand Up @@ -454,7 +454,7 @@ public static void testStripMap(Supplier<Config> configSupplier, File file) thro
MapConfigEntry.of(config1, "example.1.map1", null, map1New, Type.STRING, Type.STRING);

config1.load();
config1.strip();
Set<String> paths = config1.strip0();
config1.close();

Config config2 = configSupplier.get();
Expand All @@ -465,6 +465,14 @@ public static void testStripMap(Supplier<Config> configSupplier, File file) thro

Assertions.assertEquals(map0New, mapConfigEntry0New.getValue());
Assertions.assertEquals(map1, mapConfigEntry1New.getValue());
Assertions.assertFalse(paths.isEmpty());
Assertions.assertTrue(paths.size() <= 2);
if (paths.size() == 1) {
Assertions.assertTrue(paths.contains("example.0.map0"));
} else {
Assertions.assertTrue(paths.contains("example.0.map0.Hello"));
Assertions.assertTrue(paths.contains("example.0.map0.abc"));
}

config2.close();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import io.github.almightysatan.jaskl.impl.WritableConfigEntry;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.Unmodifiable;

import java.io.File;
import java.io.FileWriter;
Expand Down Expand Up @@ -103,18 +104,20 @@ public void write() throws IOException {
}

@Override
public void strip() throws IOException {
public @Unmodifiable @NotNull Set<@NotNull String> strip0() throws IOException {
Config config = this.config;
if (config == null)
throw new IllegalStateException();
Util.createFileAndPath(this.file);

List<String> pathsToRemove = new ArrayList<>();
this.resolvePathsToStrip("", config.root(), this.getPaths(), pathsToRemove);
Set<String> pathsToRemove = new HashSet<>();
Set<String> valuePathsRemoved = new HashSet<>();
this.resolvePathsToStrip("", config.root(), this.getPaths(), pathsToRemove, valuePathsRemoved);
for (String path : pathsToRemove)
config = config.withoutPath(path);

this.writeIfNecessary(config, false);
return Collections.unmodifiableSet(valuePathsRemoved);
}

@Override
Expand All @@ -134,26 +137,23 @@ protected void writeIfNecessary(@NotNull Config config, boolean setDescription)
}
}

protected int resolvePathsToStrip(@NotNull String path, @NotNull ConfigObject node, @NotNull Set<String> paths, @NotNull List<String> toRemove) {
int numRemoved = 0;
protected void resolvePathsToStrip(@NotNull String path, @NotNull ConfigObject node, @NotNull Set<String> paths, @NotNull Set<String> toRemove, @NotNull Set<String> valuePathsRemoved) {
for (Map.Entry<String, ConfigValue> entry : node.entrySet()) {
String fieldPath = (path.isEmpty() ? "" : path + ".") + entry.getKey();
if (entry.getValue() instanceof ConfigObject) {
if (paths.contains(fieldPath))
continue;
ConfigObject child = (ConfigObject) entry.getValue();
int numChildrenRemoved = this.resolvePathsToStrip(fieldPath, child, paths, toRemove);
int numRemoved = toRemove.size();
this.resolvePathsToStrip(fieldPath, child, paths, toRemove, valuePathsRemoved);
int numChildren = child.entrySet().size();
if (numChildren == 0 || numChildren == numChildrenRemoved) {
if (numChildren == 0 || numChildren == (toRemove.size() - numRemoved))
toRemove.add(fieldPath);
numRemoved++;
}
} else if (!paths.contains(fieldPath)) {
toRemove.add(fieldPath);
numRemoved++;
valuePathsRemoved.add(fieldPath);
}
}
return numRemoved;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import io.github.almightysatan.jaskl.impl.WritableConfigEntry;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.Unmodifiable;

import java.io.File;
import java.io.IOException;
Expand Down Expand Up @@ -102,13 +103,15 @@ public void write() throws IOException {
}

@Override
public void strip() throws IOException {
public @Unmodifiable @NotNull Set<@NotNull String> strip0() throws IOException {
if (this.root == null)
throw new IllegalStateException();
Util.createFileAndPath(this.file);

if (stripNodes("", this.root, this.getPaths()))
Set<String> pathsRemoved = new HashSet<>();
if (stripNodes("", this.root, this.getPaths(), pathsRemoved))
this.mapper.writerWithDefaultPrettyPrinter().writeValue(this.file, this.root);
return Collections.unmodifiableSet(pathsRemoved);
}

@Override
Expand Down Expand Up @@ -137,7 +140,7 @@ protected void putNode(@NotNull String path, @NotNull JsonNode value) {
node.set(pathSplit[pathSplit.length - 1], value);
}

protected boolean stripNodes(@NotNull String path, @NotNull ObjectNode node, @NotNull Set<String> paths) {
protected boolean stripNodes(@NotNull String path, @NotNull ObjectNode node, @NotNull Set<String> paths, @NotNull Set<String> pathsRemoved) {
boolean changed = false;
List<String> toRemove = new ArrayList<>();
Iterator<Entry<String, JsonNode>> it = node.fields();
Expand All @@ -148,12 +151,14 @@ protected boolean stripNodes(@NotNull String path, @NotNull ObjectNode node, @No
if (paths.contains(fieldPath))
continue;
ObjectNode child = (ObjectNode) field.getValue();
changed |= stripNodes(fieldPath, child, paths);
changed |= stripNodes(fieldPath, child, paths, pathsRemoved);
if (child.isEmpty())
toRemove.add(field.getKey());
} else if (field.getValue() instanceof ArrayNode || field.getValue() instanceof ValueNode) {
if (!paths.contains(fieldPath))
if (!paths.contains(fieldPath)) {
pathsRemoved.add(fieldPath);
toRemove.add(field.getKey());
}
}
}
if (!toRemove.isEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import io.github.almightysatan.jaskl.impl.WritableConfigEntry;
import org.bson.Document;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Unmodifiable;

import java.io.IOException;
import java.math.BigDecimal;
Expand Down Expand Up @@ -120,24 +121,28 @@ public void write() throws IOException {
}

@Override
public void strip() throws IOException {
public @Unmodifiable @NotNull Set<@NotNull String> strip0() throws IOException {
if (this.mongoCollection == null)
throw new IllegalStateException();

Set<String> pathsRemoved = new HashSet<>();
try {
Set<String> paths = this.getPaths();
List<WriteModel<? extends Document>> writeModels = new ArrayList<>();
FindIterable<Document> documents = this.mongoCollection.find();
for (Document document : documents) {
String path = document.getString("_id");
if (!paths.contains(path))
if (!paths.contains(path)) {
pathsRemoved.add(path);
writeModels.add(new DeleteOneModel<>(Filters.eq("_id", path)));
}
}
if (!writeModels.isEmpty())
this.mongoCollection.bulkWrite(writeModels);
} catch (MongoException e) {
throw new IOException(e);
}
return Collections.unmodifiableSet(pathsRemoved);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,14 @@
import io.github.almightysatan.jaskl.impl.WritableConfigEntry;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.Unmodifiable;

import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.*;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Properties;
import java.util.Set;

public class PropertiesConfig extends ConfigImpl {

Expand Down Expand Up @@ -87,27 +86,28 @@ public void write() throws IOException {
}

@Override
public void strip() throws IOException {
public @Unmodifiable @NotNull Set<@NotNull String> strip0() throws IOException {
if (this.config == null)
throw new IllegalStateException();
Util.createFileAndPath(this.file);

boolean shouldWrite = false;
Properties stripped = new Properties();
Set<String> paths = this.getPaths();
Set<String> pathsRemoved = new HashSet<>();
for (Entry<Object, Object> entry : this.config.entrySet()) {
String key = (String) entry.getKey();
if (!paths.contains(key)) {
shouldWrite = true;
pathsRemoved.add(key);
continue;
}
stripped.setProperty(key, (String) entry.getValue());
}

if (shouldWrite) {
if (!pathsRemoved.isEmpty()) {
this.config = stripped;
writeToFile();
}
return Collections.unmodifiableSet(pathsRemoved);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import io.github.almightysatan.jaskl.impl.WritableConfigEntry;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.Unmodifiable;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.LoaderOptions;
import org.yaml.snakeyaml.Yaml;
Expand Down Expand Up @@ -108,15 +109,17 @@ public void write() throws IOException {
}

@Override
public void strip() throws IOException {
public @Unmodifiable @NotNull Set<@NotNull String> strip0() throws IOException {
if (this.yaml == null)
throw new IllegalStateException();
Util.createFileAndPath(this.file);

if (this.stripNodes("", this.root, this.getPaths()))
Set<String> removedPaths = new HashSet<>();
if (this.stripNodes("", this.root, this.getPaths(), removedPaths))
try (FileWriter fileWriter = new FileWriter(this.file)) {
this.yaml.serialize(this.root, fileWriter);
}
return Collections.unmodifiableSet(removedPaths);
}

@Override
Expand Down Expand Up @@ -205,7 +208,7 @@ protected void setComment(@NotNull Node node, @Nullable String comment) {
node.setBlockComments(new ArrayList<>(0)); // Remove comment
}

protected boolean stripNodes(@NotNull String path, @NotNull MappingNode node, @NotNull Set<String> paths) {
protected boolean stripNodes(@NotNull String path, @NotNull MappingNode node, @NotNull Set<String> paths, @NotNull Set<String> removedPaths) {
boolean changed = false;
List<NodeTuple> toRemove = new ArrayList<>();
for (NodeTuple tuple : node.getValue()) {
Expand All @@ -215,12 +218,14 @@ protected boolean stripNodes(@NotNull String path, @NotNull MappingNode node, @N
if (paths.contains(fieldPath))
continue;
MappingNode child = (MappingNode) valueNode;
changed |= this.stripNodes(fieldPath, child, paths);
changed |= this.stripNodes(fieldPath, child, paths, removedPaths);
if (child.getValue().isEmpty())
toRemove.add(tuple);
} else if (valueNode instanceof ScalarNode || valueNode instanceof SequenceNode) {
if (!paths.contains(fieldPath))
if (!paths.contains(fieldPath)) {
toRemove.add(tuple);
removedPaths.add(fieldPath);
}
}
}
if (!toRemove.isEmpty()) {
Expand Down

0 comments on commit 849154b

Please sign in to comment.