Complete saving?
This commit is contained in:
parent
5e7f42b76e
commit
94173eb473
@ -0,0 +1,11 @@
|
|||||||
|
package me.braydon.feather.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Braydon
|
||||||
|
*/
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(ElementType.FIELD)
|
||||||
|
@Documented @Inherited
|
||||||
|
public @interface Serializable { }
|
25
src/main/java/me/braydon/feather/common/Tuple.java
Normal file
25
src/main/java/me/braydon/feather/common/Tuple.java
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
package me.braydon.feather.common;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents an object that
|
||||||
|
* holds a pair of two values.
|
||||||
|
*
|
||||||
|
* @author Braydon
|
||||||
|
*/
|
||||||
|
@NoArgsConstructor @AllArgsConstructor @Setter @Getter
|
||||||
|
public class Tuple<L, R> {
|
||||||
|
/**
|
||||||
|
* The left value of this tuple.
|
||||||
|
*/
|
||||||
|
private L left;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The right value of this tuple.
|
||||||
|
*/
|
||||||
|
private R right;
|
||||||
|
}
|
@ -8,11 +8,10 @@ import me.braydon.feather.IDatabase;
|
|||||||
import me.braydon.feather.annotation.Collection;
|
import me.braydon.feather.annotation.Collection;
|
||||||
import me.braydon.feather.annotation.Field;
|
import me.braydon.feather.annotation.Field;
|
||||||
import me.braydon.feather.annotation.Id;
|
import me.braydon.feather.annotation.Id;
|
||||||
|
import me.braydon.feather.annotation.Serializable;
|
||||||
|
import me.braydon.feather.common.Tuple;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.*;
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A document is a key-value pair that is stored
|
* A document is a key-value pair that is stored
|
||||||
@ -38,12 +37,18 @@ public class Document<V> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The mapped data of this document.
|
* The mapped data of this document.
|
||||||
|
* <p>
|
||||||
|
* The key of this key-value pair is the identifier
|
||||||
|
* for the field within this document. The value is
|
||||||
|
* a tuple that contains the Java field, as well as
|
||||||
|
* the field value.
|
||||||
|
* </p>
|
||||||
*
|
*
|
||||||
* @see V for value type
|
* @see V for value type
|
||||||
*/
|
*/
|
||||||
private final Map<String, V> mappedData = Collections.synchronizedMap(new LinkedHashMap<>());
|
private final Map<String, Tuple<java.lang.reflect.Field, V>> mappedData = Collections.synchronizedMap(new LinkedHashMap<>());
|
||||||
|
|
||||||
public Document(@NonNull Object element, boolean rawObject) {
|
public Document(@NonNull Object element) {
|
||||||
Class<?> clazz = element.getClass(); // Get the element class
|
Class<?> clazz = element.getClass(); // Get the element class
|
||||||
String idKey = null; // The key for the id field
|
String idKey = null; // The key for the id field
|
||||||
for (java.lang.reflect.Field field : clazz.getDeclaredFields()) {
|
for (java.lang.reflect.Field field : clazz.getDeclaredFields()) {
|
||||||
@ -64,20 +69,15 @@ public class Document<V> {
|
|||||||
}
|
}
|
||||||
Class<?> fieldType = field.getType(); // The type of the field
|
Class<?> fieldType = field.getType(); // The type of the field
|
||||||
try {
|
try {
|
||||||
Object value; // The value of the field
|
Object value = field.get(element); // The value of the field
|
||||||
|
|
||||||
if (fieldType == UUID.class) { // Convert UUIDs into strings
|
if (field.isAnnotationPresent(Serializable.class)) { // Serialize the field if @Serializable is present
|
||||||
value = ((UUID) field.get(element)).toString();
|
value = FeatherSettings.getGson().toJson(field.get(element));
|
||||||
} else if (rawObject) { // Use the raw object from the field
|
} else if (fieldType == UUID.class) { // Convert UUIDs into strings
|
||||||
value = field.get(element);
|
value = ((UUID) value).toString();
|
||||||
} else { // Otherwise, turn the value into a string
|
|
||||||
if (fieldType == String.class) { // Already a string, cast it
|
|
||||||
value = field.get(element);
|
|
||||||
} else { // Convert the field into json using Gson
|
|
||||||
value = FeatherSettings.getGson().toJson(field.get(element));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
mappedData.put(key, (V) value); // Store in our map
|
|
||||||
|
mappedData.put(key, new Tuple<>(field, (V) value)); // Store in our map
|
||||||
} catch (IllegalAccessException ex) {
|
} catch (IllegalAccessException ex) {
|
||||||
throw new RuntimeException(ex);
|
throw new RuntimeException(ex);
|
||||||
}
|
}
|
||||||
@ -85,10 +85,25 @@ public class Document<V> {
|
|||||||
assert idKey != null; // We need an id key
|
assert idKey != null; // We need an id key
|
||||||
this.idKey = idKey; // We have our id key
|
this.idKey = idKey; // We have our id key
|
||||||
|
|
||||||
V key = mappedData.get(idKey); // Get the id from the data map
|
Tuple<java.lang.reflect.Field, V> key = mappedData.get(idKey); // Get the id from the data map
|
||||||
if (key == null) { // The element is missing an id field
|
if (key == null) { // The element is missing an id field
|
||||||
throw new IllegalArgumentException("No @Id annotated field found in " + clazz.getSimpleName());
|
throw new IllegalArgumentException("No @Id annotated field found in " + clazz.getSimpleName());
|
||||||
}
|
}
|
||||||
this.key = key;
|
this.key = key.getRight();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turn this document into a map.
|
||||||
|
*
|
||||||
|
* @return the mapped data
|
||||||
|
* @see #mappedData for stored data
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public Map<String, V> toMappedData() {
|
||||||
|
Map<String, V> mappedData = new LinkedHashMap<>(); // The mapped data
|
||||||
|
for (Map.Entry<String, Tuple<java.lang.reflect.Field, V>> entry : this.mappedData.entrySet()) {
|
||||||
|
mappedData.put(entry.getKey(), entry.getValue().getRight());
|
||||||
|
}
|
||||||
|
return mappedData;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -6,13 +6,18 @@ import com.mongodb.client.MongoClients;
|
|||||||
import com.mongodb.client.MongoCollection;
|
import com.mongodb.client.MongoCollection;
|
||||||
import com.mongodb.client.MongoDatabase;
|
import com.mongodb.client.MongoDatabase;
|
||||||
import com.mongodb.client.model.Filters;
|
import com.mongodb.client.model.Filters;
|
||||||
|
import com.mongodb.client.model.Indexes;
|
||||||
import com.mongodb.client.model.UpdateOptions;
|
import com.mongodb.client.model.UpdateOptions;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
import me.braydon.feather.IDatabase;
|
import me.braydon.feather.IDatabase;
|
||||||
import me.braydon.feather.annotation.Collection;
|
import me.braydon.feather.annotation.Collection;
|
||||||
import me.braydon.feather.annotation.Field;
|
import me.braydon.feather.annotation.Field;
|
||||||
|
import me.braydon.feather.common.Tuple;
|
||||||
import me.braydon.feather.data.Document;
|
import me.braydon.feather.data.Document;
|
||||||
|
import me.braydon.feather.databases.mongodb.annotation.Index;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The {@link IDatabase} implementation for MongoDB.
|
* The {@link IDatabase} implementation for MongoDB.
|
||||||
@ -137,14 +142,22 @@ public class MongoDB implements IDatabase<MongoClient, ConnectionString, MongoSy
|
|||||||
throw new IllegalStateException("Missing collection name in @Collection for " + clazz.getSimpleName());
|
throw new IllegalStateException("Missing collection name in @Collection for " + clazz.getSimpleName());
|
||||||
}
|
}
|
||||||
MongoCollection<org.bson.Document> collection = database.getCollection(collectionName); // Get the collection
|
MongoCollection<org.bson.Document> collection = database.getCollection(collectionName); // Get the collection
|
||||||
Document<Object> document = new Document<>(element, true); // Construct the document from the element
|
Document<Object> document = new Document<>(element); // Construct the document from the element
|
||||||
|
|
||||||
// Set the map in the database
|
// Set the map in the database
|
||||||
collection.updateOne(
|
collection.updateOne(
|
||||||
Filters.eq(document.getIdKey(), document.getKey()),
|
Filters.eq(document.getIdKey(), document.getKey()),
|
||||||
new org.bson.Document("$set", new org.bson.Document(document.getMappedData())),
|
new org.bson.Document("$set", new org.bson.Document(document.toMappedData())),
|
||||||
new UpdateOptions().upsert(true)
|
new UpdateOptions().upsert(true)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Create indexes for @Index fields
|
||||||
|
for (Map.Entry<String, Tuple<java.lang.reflect.Field, Object>> entry : document.getMappedData().entrySet()) {
|
||||||
|
java.lang.reflect.Field field = entry.getValue().getLeft();
|
||||||
|
if (field.isAnnotationPresent(Index.class)) {
|
||||||
|
collection.createIndex(Indexes.text(entry.getKey()));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -0,0 +1,16 @@
|
|||||||
|
package me.braydon.feather.databases.mongodb.annotation;
|
||||||
|
|
||||||
|
import me.braydon.feather.databases.mongodb.MongoDB;
|
||||||
|
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fields flagged with this annotation will be
|
||||||
|
* treated as an indexed field within {@link MongoDB}.
|
||||||
|
*
|
||||||
|
* @author Braydon
|
||||||
|
*/
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(ElementType.FIELD)
|
||||||
|
@Documented @Inherited
|
||||||
|
public @interface Index { }
|
@ -126,8 +126,8 @@ public class Redis implements IDatabase<StatefulRedisConnection<String, String>,
|
|||||||
if (!element.getClass().isAnnotationPresent(Collection.class)) { // Missing annotation
|
if (!element.getClass().isAnnotationPresent(Collection.class)) { // Missing annotation
|
||||||
throw new IllegalStateException("Element is missing @Collection annotation");
|
throw new IllegalStateException("Element is missing @Collection annotation");
|
||||||
}
|
}
|
||||||
Document<String> document = new Document<>(element, false); // Construct the document from the element
|
Document<String> document = new Document<>(element); // Construct the document from the element
|
||||||
sync().hmset(String.valueOf(document.getKey()), document.getMappedData()); // Set the map in the database
|
sync().hmset(String.valueOf(document.getKey()), document.toMappedData()); // Set the map in the database
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -20,4 +20,13 @@ public abstract class Repository<D extends IDatabase<?, ?, ?, ?>> {
|
|||||||
* @see D for database
|
* @see D for database
|
||||||
*/
|
*/
|
||||||
@NonNull private final D database;
|
@NonNull private final D database;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save the given element to the database.
|
||||||
|
*
|
||||||
|
* @param element the element to save
|
||||||
|
*/
|
||||||
|
public final void save(@NonNull Object element) {
|
||||||
|
database.write(element);
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user