Skip to content

Commit

Permalink
Added new data handlers
Browse files Browse the repository at this point in the history
  • Loading branch information
WillFP committed Aug 24, 2024
1 parent 449bcc1 commit fd031e2
Show file tree
Hide file tree
Showing 8 changed files with 682 additions and 117 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.willfp.eco.core.data.handlers;

import com.willfp.eco.core.data.keys.PersistentDataKey;
import com.willfp.eco.core.data.keys.PersistentDataKeyType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.UUID;

/**
* Handles data read/write for a {@link com.willfp.eco.core.data.keys.PersistentDataKeyType} for a specific
* data handler.
*/
public abstract class DataTypeSerializer<T> {
/**
* Create a new data type serializer.
*/
protected DataTypeSerializer() {

}

/**
* Read a value.
*
* @param uuid The uuid.
* @param key The key.
* @return The value.
*/
@Nullable
public abstract T readAsync(@NotNull final UUID uuid,
@NotNull final PersistentDataKey<T> key);

/**
* Write a value.
*
* @param uuid The uuid.
* @param key The key.
* @param value The value.
*/
public abstract void writeAsync(@NotNull final UUID uuid,
@NotNull final PersistentDataKey<T> key,
@NotNull final T value);
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,28 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

public abstract class PersistentDataHandler implements Registrable {
/**
* The id of the handler.
*/
private final String id;

/**
* The executor.
*/
private final ExecutorService executor = Executors.newCachedThreadPool();

/**
* Create a new persistent data handler.
*
Expand All @@ -23,9 +36,38 @@ protected PersistentDataHandler(@NotNull final String id) {
this.id = id;
}

@Override
public @NotNull String getID() {
return id;
/**
* Get all UUIDs with saved data.
*
* @return All saved UUIDs.
*/
protected abstract Set<UUID> getSavedUUIDs();

/**
* Save to disk.
* <p>
* If write commits to disk, this method does not need to be overridden.
* <p>
* This method is called asynchronously.
*/
protected void doSave() {
// Save to disk
}

/**
* If the handler should autosave.
*
* @return If the handler should autosave.
*/
public boolean shouldAutosave() {
return true;
}

/**
* Save the data.
*/
public final void save() {
executor.submit(this::doSave);
}

/**
Expand All @@ -37,7 +79,18 @@ protected PersistentDataHandler(@NotNull final String id) {
* @return The value, or null if not found.
*/
@Nullable
public abstract <T> T read(@NotNull UUID uuid, @NotNull PersistentDataKey<T> key);
public final <T> T read(@NotNull final UUID uuid,
@NotNull final PersistentDataKey<T> key) {
DataTypeSerializer<T> serializer = key.getType().getSerializer(this);
Future<T> future = executor.submit(() -> serializer.readAsync(uuid, key));

try {
return future.get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
return null;
}
}

/**
* Write a key to persistent data.
Expand All @@ -47,7 +100,12 @@ protected PersistentDataHandler(@NotNull final String id) {
* @param value The value.
* @param <T> The type of the key.
*/
public abstract <T> void write(@NotNull UUID uuid, @NotNull PersistentDataKey<T> key, @NotNull T value);
public final <T> void write(@NotNull final UUID uuid,
@NotNull final PersistentDataKey<T> key,
@NotNull final T value) {
DataTypeSerializer<T> serializer = key.getType().getSerializer(this);
executor.submit(() -> serializer.writeAsync(uuid, key, value));
}

/**
* Serialize data.
Expand All @@ -56,12 +114,74 @@ protected PersistentDataHandler(@NotNull final String id) {
* @return The serialized data.
*/
@NotNull
public abstract Set<SerializedProfile> serializeData(@NotNull final Set<PersistentDataKey<?>> keys);
public final Set<SerializedProfile> serializeData(@NotNull final Set<PersistentDataKey<?>> keys) {
Set<SerializedProfile> profiles = new HashSet<>();

for (UUID uuid : getSavedUUIDs()) {
Map<PersistentDataKey<?>, Object> data = new HashMap<>();

for (PersistentDataKey<?> key : keys) {
Object value = read(uuid, key);
data.put(key, value);
}

profiles.add(new SerializedProfile(uuid, data));
}

return profiles;
}

/**
* Load profile data.
*
* @param data The data.
*/
public abstract void loadProfileData(@NotNull Set<SerializedProfile> data);
@SuppressWarnings("unchecked")
public final void loadProfileData(@NotNull Set<SerializedProfile> data) {
for (SerializedProfile profile : data) {
for (Map.Entry<PersistentDataKey<?>, Object> entry : profile.data().entrySet()) {
PersistentDataKey<?> key = entry.getKey();
Object value = entry.getValue();

// This cast is safe because the data is serialized
write(profile.uuid(), (PersistentDataKey<? super Object>) key, value);
}
}
}

/**
* Await outstanding writes.
*/
public final void awaitOutstandingWrites() throws InterruptedException {
boolean success = executor.awaitTermination(15, TimeUnit.SECONDS);

if (!success) {
throw new InterruptedException("Failed to await outstanding writes");
}
}

@Override
public final @NotNull String getID() {
return id;
}

@Override
public final boolean equals(@Nullable final Object obj) {
if (this == obj) {
return true;
}

if (obj == null || getClass() != obj.getClass()) {
return false;
}

PersistentDataHandler that = (PersistentDataHandler) obj;

return id.equals(that.id);
}

@Override
public final int hashCode() {
return id.hashCode();
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
package com.willfp.eco.core.data.keys;

import com.willfp.eco.core.config.interfaces.Config;
import com.willfp.eco.core.data.handlers.DataTypeSerializer;
import com.willfp.eco.core.data.handlers.PersistentDataHandler;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
Expand Down Expand Up @@ -60,24 +64,58 @@ public final class PersistentDataKeyType<T> {
*/
private final String name;

/**
* The serializers for this key type.
*/
private final Map<PersistentDataHandler, DataTypeSerializer<T>> serializers = new HashMap<>();

/**
* Create new PersistentDataKeyType.
*
* @param name The name.
*/
private PersistentDataKeyType(@NotNull final String name) {
VALUES.add(this);

this.name = name;
}

/**
* Get the name of the key type.
*
* @return The name.
*/
@NotNull
public String name() {
return name;
}

/**
* Create new PersistentDataKeyType.
* Register a serializer for this key type.
*
* @param name The name.
* @param handler The handler.
* @param serializer The serializer.
*/
private PersistentDataKeyType(@NotNull final String name) {
VALUES.add(this);
public void registerSerializer(@NotNull final PersistentDataHandler handler,
@NotNull final DataTypeSerializer<T> serializer) {
this.serializers.put(handler, serializer);
}

this.name = name;
/**
* Get the serializer for a handler.
*
* @param handler The handler.
* @return The serializer.
*/
@NotNull
public DataTypeSerializer<T> getSerializer(@NotNull final PersistentDataHandler handler) {
DataTypeSerializer<T> serializer = this.serializers.get(handler);

if (serializer == null) {
throw new IllegalArgumentException("No serializer for handler: " + handler);
}

return serializer;
}

@Override
Expand Down
Loading

0 comments on commit fd031e2

Please sign in to comment.