Skip to content

Commit

Permalink
DataHandler: Added modification status check
Browse files Browse the repository at this point in the history
This prevents unnecessarily saving anything that relies on a DataMap. Basically DataHandler implementations must check if the DataMap has actually been modified or not before saving, if not, saving can be skipped, if modified, saving can be done and the map must be marked as unmodified in order to save again later on. FlatStorage and YamlFile (And all Yaml extensions) already do this so most developers won't even have to worry about this unless they are making their own DataHandler implementations.
  • Loading branch information
xDec0de committed Nov 5, 2024
1 parent 8d8087c commit caff930
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 3 deletions.
9 changes: 7 additions & 2 deletions shared/src/main/java/net/codersky/mcutils/storage/Config.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package net.codersky.mcutils.storage;

import net.codersky.mcutils.Reloadable;
import net.codersky.mcutils.java.MCCollections;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

Expand All @@ -10,7 +9,6 @@
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.function.Predicate;

public interface Config extends DataHandler, Reloadable {

Expand All @@ -33,6 +31,13 @@ public interface Config extends DataHandler, Reloadable {
* time to save, so it is recommended to call this
* method <b>asynchronously</b> in order to prevent
* possible performance issues.
* <p>
* Also, for {@link Config} implementations, remember that
* {@link DataMap} features a {@link DataMap#isModified() modification}
* check and that you should {@link DataMap#setModified(boolean) reset}
* it every time you save in order to avoid saving unmodified
* data. If you are just using a {@link Config} and not
* implementing one, you don't have to worry about this.
*
* @return {@code true} if this {@link Config} was
* able to save correctly, {@code false} otherwise.
Expand Down
18 changes: 18 additions & 0 deletions shared/src/main/java/net/codersky/mcutils/storage/DataHandler.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package net.codersky.mcutils.storage;

import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;

/**
Expand All @@ -18,6 +19,23 @@
*/
public interface DataHandler {

/**
* Provides access to the <b>internal</b> {@link DataMap} that
* this {@link DataHandler} is using. Keep in mind once again
* that this is for <b>internal</b> usage only, and you should
* not use it unless you <b>really</b> know what you are doing.
* That being said, for any {@link DataHandler} implementation
* that saves this map, please remember that it features a
* {@link DataMap#isModified() modification} check and that you
* should {@link DataMap#setModified(boolean) reset} it every
* time you save in order to avoid saving unmodified data.
*
* @return the <b>internal</b> {@link DataMap} that this
* {@link DataHandler} is using.
*
* @since MCUtils 1.0.0
*/
@ApiStatus.Internal
@NotNull
DataMap getMap();

Expand Down
50 changes: 49 additions & 1 deletion shared/src/main/java/net/codersky/mcutils/storage/DataMap.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

public class DataMap {

private boolean isModified = false;
private final boolean useNesting;
private final LinkedHashMap<String, Object> map = new LinkedHashMap<>();

Expand All @@ -30,6 +31,50 @@ public boolean usesNesting() {
return useNesting;
}

/**
* Checks whether this {@link DataMap} has been modified
* and thus its content may require to be saved or not.
* <p>
* Keep in mind that you need to {@link #setModified(boolean) set}
* the modification status to {@code false} manually whenever
* you consider that the map has been saved and needs to be modified
* once again to save it.
*
* @return {@code true} if this {@link DataMap} has been
* modified, {@code false} otherwise.
*
* @since MCUtils 1.0.0
*
* @see #setModified(boolean)
*/
public boolean isModified() {
return isModified;
}

/**
* Sets the modification status of this {@link DataMap}.
* This is generally set to {@code false} by any class that
* relies on a {@link DataMap} saves it. {@link DataMap}
* will already set the modification status to {@code true}
* whenever {@link #set(String, Object)} or {@link #setList(String, List)}
* are successfully called and actually modifies the map, though
* it is not checked if the previously stored object is the exact
* same as the new one for performance reasons.
*
* @param modified the new modification status.
*
* @return This {@link DataMap}.
*
* @since MCUtils 1.0.0
*
* @see #isModified()
*/
@NotNull
public DataMap setModified(boolean modified) {
this.isModified = modified;
return this;
}

/*
* Nesting utilities
*/
Expand Down Expand Up @@ -183,8 +228,10 @@ public <T> T set(@NotNull String key, @NotNull T value) {
}
final String actualKey = getActualKey(key);
final Map<String, Object> source = getActualMap(key, true);
if (source != null)
if (source != null) {
isModified = true;
source.put(actualKey, value);
}
return value;
}

Expand All @@ -194,6 +241,7 @@ public <T> List<T> setList(@NotNull String key, @NotNull List<T> value) {
final Map<String, Object> source = getActualMap(key, true);
if (source == null)
return value;
isModified = true;
if (value instanceof LinkedList<T> lst)
source.put(actualKey, lst);
else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ public final boolean exists() {

@Override
public boolean save() {
if (!getMap().isModified())
return true;
if (!setup())
return false;
int errors = 0;
Expand All @@ -99,6 +101,8 @@ public boolean save() {
}
if (errors != 0)
System.err.println("Failed to save " + file.getPath() + " because of " + errors + " error(s) shown above.");
else
getMap().setModified(false);
return errors == 0;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,15 @@ public boolean setup() {
}

public boolean save() {
if (!getMap().isModified())
return true;
if (!exists() && !MCFiles.create(file))
return false;
try {
final FileWriter writer = new FileWriter(file, StandardCharsets.UTF_8);
yaml.dump(data.getInternalMap(), writer);
writer.close();
getMap().setModified(false);
return true;
} catch (IOException e) {
return false;
Expand Down

0 comments on commit caff930

Please sign in to comment.