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.Field;
|
||||
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.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* A document is a key-value pair that is stored
|
||||
@ -38,12 +37,18 @@ public class Document<V> {
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
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
|
||||
String idKey = null; // The key for the id field
|
||||
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
|
||||
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
|
||||
value = ((UUID) field.get(element)).toString();
|
||||
} else if (rawObject) { // Use the raw object from the field
|
||||
value = field.get(element);
|
||||
} 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));
|
||||
}
|
||||
if (field.isAnnotationPresent(Serializable.class)) { // Serialize the field if @Serializable is present
|
||||
value = FeatherSettings.getGson().toJson(field.get(element));
|
||||
} else if (fieldType == UUID.class) { // Convert UUIDs into strings
|
||||
value = ((UUID) value).toString();
|
||||
}
|
||||
mappedData.put(key, (V) value); // Store in our map
|
||||
|
||||
mappedData.put(key, new Tuple<>(field, (V) value)); // Store in our map
|
||||
} catch (IllegalAccessException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
@ -85,10 +85,25 @@ public class Document<V> {
|
||||
assert idKey != null; // We need an 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
|
||||
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.MongoDatabase;
|
||||
import com.mongodb.client.model.Filters;
|
||||
import com.mongodb.client.model.Indexes;
|
||||
import com.mongodb.client.model.UpdateOptions;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import me.braydon.feather.IDatabase;
|
||||
import me.braydon.feather.annotation.Collection;
|
||||
import me.braydon.feather.annotation.Field;
|
||||
import me.braydon.feather.common.Tuple;
|
||||
import me.braydon.feather.data.Document;
|
||||
import me.braydon.feather.databases.mongodb.annotation.Index;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 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());
|
||||
}
|
||||
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
|
||||
collection.updateOne(
|
||||
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)
|
||||
);
|
||||
|
||||
// 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
|
||||
throw new IllegalStateException("Element is missing @Collection annotation");
|
||||
}
|
||||
Document<String> document = new Document<>(element, false); // Construct the document from the element
|
||||
sync().hmset(String.valueOf(document.getKey()), document.getMappedData()); // Set the map in the database
|
||||
Document<String> document = new Document<>(element); // Construct the document from the element
|
||||
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
|
||||
*/
|
||||
@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