Update structure
This commit is contained in:
parent
94173eb473
commit
8cb196233a
@ -38,15 +38,6 @@
|
|||||||
<!-- See: https://checkstyle.org/checks/imports/avoidstaticimport.html#AvoidStaticImport -->
|
<!-- See: https://checkstyle.org/checks/imports/avoidstaticimport.html#AvoidStaticImport -->
|
||||||
<module name="AvoidStaticImport" />
|
<module name="AvoidStaticImport" />
|
||||||
|
|
||||||
<!-- See: https://checkstyle.org/checks/naming/classtypeparametername.html#ClassTypeParameterName -->
|
|
||||||
<module name="ClassTypeParameterName" />
|
|
||||||
|
|
||||||
<!-- See: https://checkstyle.org/checks/naming/interfacetypeparametername.html#InterfaceTypeParameterName -->
|
|
||||||
<module name="InterfaceTypeParameterName" />
|
|
||||||
|
|
||||||
<!-- See: https://checkstyle.org/checks/naming/methodtypeparametername.html#MethodTypeParameterName -->
|
|
||||||
<module name="MethodTypeParameterName" />
|
|
||||||
|
|
||||||
<!-- See: https://checkstyle.org/checks/coding/defaultcomeslast.html#DefaultComesLast -->
|
<!-- See: https://checkstyle.org/checks/coding/defaultcomeslast.html#DefaultComesLast -->
|
||||||
<module name="DefaultComesLast" />
|
<module name="DefaultComesLast" />
|
||||||
|
|
||||||
|
@ -11,11 +11,6 @@ import lombok.Setter;
|
|||||||
* @author Braydon
|
* @author Braydon
|
||||||
*/
|
*/
|
||||||
public final class FeatherSettings {
|
public final class FeatherSettings {
|
||||||
/**
|
|
||||||
* The amount of threads to use for {@link FeatherThreads}.
|
|
||||||
*/
|
|
||||||
@Setter @Getter private static int threadCount = 4;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The {@link Gson} instance to use for serialization.
|
* The {@link Gson} instance to use for serialization.
|
||||||
*/
|
*/
|
||||||
|
@ -1,20 +0,0 @@
|
|||||||
package me.braydon.feather;
|
|
||||||
|
|
||||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
|
||||||
|
|
||||||
import java.util.concurrent.ExecutorService;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Feather thread pool. This is used by default
|
|
||||||
* when executing tasks in asynchronous pipelines.
|
|
||||||
*
|
|
||||||
* @author Braydon
|
|
||||||
*/
|
|
||||||
public final class FeatherThreads {
|
|
||||||
private static final AtomicInteger ID = new AtomicInteger(0); // The thread id
|
|
||||||
public static final ExecutorService THREAD_POOL = Executors.newFixedThreadPool(FeatherSettings.getThreadCount(), new ThreadFactoryBuilder()
|
|
||||||
.setNameFormat("Feather Thread #" + ID.incrementAndGet())
|
|
||||||
.build()); // The thread pool to execute on
|
|
||||||
}
|
|
@ -1,78 +0,0 @@
|
|||||||
package me.braydon.feather;
|
|
||||||
|
|
||||||
import lombok.NonNull;
|
|
||||||
import me.braydon.feather.annotation.Collection;
|
|
||||||
import me.braydon.feather.annotation.Field;
|
|
||||||
|
|
||||||
import java.io.Closeable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a database.
|
|
||||||
*
|
|
||||||
* @author Braydon
|
|
||||||
* @param <B> the bootstrap class of this database
|
|
||||||
* @param <C> the type of credentials this database uses
|
|
||||||
* @param <S> the type of sync pipeline for this database
|
|
||||||
* @param <A> the type of async pipeline for this database
|
|
||||||
*/
|
|
||||||
public interface IDatabase<B, C, S, A> extends Closeable {
|
|
||||||
/**
|
|
||||||
* Get the name of this database.
|
|
||||||
*
|
|
||||||
* @return the database name
|
|
||||||
*/
|
|
||||||
@NonNull String getName();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize a connection to this database.
|
|
||||||
*
|
|
||||||
* @param credentials the optional credentials to use
|
|
||||||
*/
|
|
||||||
void connect(C credentials);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if this database is connected.
|
|
||||||
*
|
|
||||||
* @return the database connection state
|
|
||||||
*/
|
|
||||||
boolean isConnected();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the bootstrap class
|
|
||||||
* instance for this database.
|
|
||||||
*
|
|
||||||
* @return the bootstrap class instance, null if none
|
|
||||||
* @see B for bootstrap class
|
|
||||||
*/
|
|
||||||
B getBootstrap();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the synchronized
|
|
||||||
* pipeline for this database.
|
|
||||||
*
|
|
||||||
* @return the synchronized pipeline
|
|
||||||
* @see S for synchronized pipeline
|
|
||||||
*/
|
|
||||||
@NonNull S sync();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the asynchronous
|
|
||||||
* pipeline for this database.
|
|
||||||
*
|
|
||||||
* @return the asynchronous pipeline
|
|
||||||
* @see A for asynchronous pipeline
|
|
||||||
*/
|
|
||||||
@NonNull A async();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write the given object to the database.
|
|
||||||
* <p>
|
|
||||||
* This object is an instance of a class
|
|
||||||
* annotated with {@link Collection}, and
|
|
||||||
* contains fields annotated with {@link Field}.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @param element the element to write
|
|
||||||
*/
|
|
||||||
void write(@NonNull Object element);
|
|
||||||
}
|
|
@ -1,10 +1,13 @@
|
|||||||
package me.braydon.feather.annotation;
|
package me.braydon.feather.annotation;
|
||||||
|
|
||||||
|
import me.braydon.feather.data.Document;
|
||||||
|
|
||||||
import java.lang.annotation.*;
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Classes tagged with this annotation
|
* Classes tagged with this annotation
|
||||||
* will be treated as a collection.
|
* will be treated as a collection that
|
||||||
|
* holds {@link Document}'s.
|
||||||
*
|
*
|
||||||
* @author Braydon
|
* @author Braydon
|
||||||
*/
|
*/
|
||||||
|
@ -3,9 +3,9 @@ package me.braydon.feather.annotation;
|
|||||||
import java.lang.annotation.*;
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fields tagged with this annotation will be treated
|
* {@link Field}'s tagged with this annotation will be
|
||||||
* as the primary identifying key for documents within
|
* treated as the primary identifying key for documents
|
||||||
* a {@link Collection}.
|
* within a {@link Collection}.
|
||||||
*
|
*
|
||||||
* @author Braydon
|
* @author Braydon
|
||||||
*/
|
*/
|
||||||
|
@ -1,8 +1,13 @@
|
|||||||
package me.braydon.feather.annotation;
|
package me.braydon.feather.annotation;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
|
||||||
import java.lang.annotation.*;
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* {@link Field}'s tagged with this annotation
|
||||||
|
* will have serialization handled by {@link Gson}.
|
||||||
|
*
|
||||||
* @author Braydon
|
* @author Braydon
|
||||||
*/
|
*/
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
29
src/main/java/me/braydon/feather/common/EntityUtils.java
Normal file
29
src/main/java/me/braydon/feather/common/EntityUtils.java
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
package me.braydon.feather.common;
|
||||||
|
|
||||||
|
import lombok.NonNull;
|
||||||
|
import lombok.experimental.UtilityClass;
|
||||||
|
import me.braydon.feather.annotation.Collection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Braydon
|
||||||
|
*/
|
||||||
|
@UtilityClass
|
||||||
|
public final class EntityUtils {
|
||||||
|
/**
|
||||||
|
* Ensure that the given entity is valid.
|
||||||
|
*
|
||||||
|
* @param entity the entity to validate
|
||||||
|
* @param allowEmptyCollections should empty collections be allowed?
|
||||||
|
*/
|
||||||
|
public static void ensureValid(@NonNull Object entity, boolean allowEmptyCollections) {
|
||||||
|
Class<?> clazz = entity.getClass(); // Get the element class
|
||||||
|
if (!clazz.isAnnotationPresent(Collection.class)) { // Missing annotation
|
||||||
|
throw new IllegalStateException("Element is missing @Collection annotation");
|
||||||
|
}
|
||||||
|
Collection annotation = clazz.getAnnotation(Collection.class); // Get the @Collection annotation
|
||||||
|
String collectionName = annotation.name(); // The name of the collection
|
||||||
|
if (collectionName.isEmpty() && !allowEmptyCollections) { // Missing collection name
|
||||||
|
throw new IllegalStateException("Missing collection name in @Collection for " + clazz.getSimpleName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -10,6 +10,8 @@ import lombok.Setter;
|
|||||||
* holds a pair of two values.
|
* holds a pair of two values.
|
||||||
*
|
*
|
||||||
* @author Braydon
|
* @author Braydon
|
||||||
|
* @param <L> the left value
|
||||||
|
* @param <R> the right value
|
||||||
*/
|
*/
|
||||||
@NoArgsConstructor @AllArgsConstructor @Setter @Getter
|
@NoArgsConstructor @AllArgsConstructor @Setter @Getter
|
||||||
public class Tuple<L, R> {
|
public class Tuple<L, R> {
|
||||||
|
@ -4,14 +4,18 @@ import lombok.Getter;
|
|||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
import me.braydon.feather.FeatherSettings;
|
import me.braydon.feather.FeatherSettings;
|
||||||
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.annotation.Serializable;
|
||||||
import me.braydon.feather.common.Tuple;
|
import me.braydon.feather.common.Tuple;
|
||||||
|
import me.braydon.feather.database.IDatabase;
|
||||||
|
|
||||||
import java.util.*;
|
import javax.annotation.concurrent.ThreadSafe;
|
||||||
|
import java.util.Collections;
|
||||||
|
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
|
||||||
@ -23,7 +27,7 @@ import java.util.*;
|
|||||||
* @author Braydon
|
* @author Braydon
|
||||||
* @param <V> the type of value this document holds
|
* @param <V> the type of value this document holds
|
||||||
*/
|
*/
|
||||||
@Getter @ToString
|
@ThreadSafe @Getter @ToString
|
||||||
public class Document<V> {
|
public class Document<V> {
|
||||||
/**
|
/**
|
||||||
* The key to use for the id field.
|
* The key to use for the id field.
|
||||||
@ -74,7 +78,7 @@ public class Document<V> {
|
|||||||
if (field.isAnnotationPresent(Serializable.class)) { // Serialize the field if @Serializable is present
|
if (field.isAnnotationPresent(Serializable.class)) { // Serialize the field if @Serializable is present
|
||||||
value = FeatherSettings.getGson().toJson(field.get(element));
|
value = FeatherSettings.getGson().toJson(field.get(element));
|
||||||
} else if (fieldType == UUID.class) { // Convert UUIDs into strings
|
} else if (fieldType == UUID.class) { // Convert UUIDs into strings
|
||||||
value = ((UUID) value).toString();
|
value = value.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
mappedData.put(key, new Tuple<>(field, (V) value)); // Store in our map
|
mappedData.put(key, new Tuple<>(field, (V) value)); // Store in our map
|
||||||
|
64
src/main/java/me/braydon/feather/database/IDatabase.java
Normal file
64
src/main/java/me/braydon/feather/database/IDatabase.java
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
package me.braydon.feather.database;
|
||||||
|
|
||||||
|
import lombok.NonNull;
|
||||||
|
import me.braydon.feather.repository.Repository;
|
||||||
|
|
||||||
|
import java.io.Closeable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a database.
|
||||||
|
*
|
||||||
|
* @author Braydon
|
||||||
|
* @param <B> the bootstrap class of this database
|
||||||
|
* @param <C> the type of credentials this database uses
|
||||||
|
* @param <R> the type of repository for this database
|
||||||
|
*/
|
||||||
|
public interface IDatabase<B, C, R extends Repository<?, ?, ?>> extends Closeable {
|
||||||
|
/**
|
||||||
|
* Get the name of this database.
|
||||||
|
*
|
||||||
|
* @return the database name
|
||||||
|
*/
|
||||||
|
@NonNull String getName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize a connection to this database.
|
||||||
|
*
|
||||||
|
* @param credentials the optional credentials to use
|
||||||
|
*/
|
||||||
|
void connect(C credentials);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if this database is connected.
|
||||||
|
*
|
||||||
|
* @return the database connection state
|
||||||
|
*/
|
||||||
|
boolean isConnected();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the latency to this database.
|
||||||
|
*
|
||||||
|
* @return the latency, -1 if not connected
|
||||||
|
*/
|
||||||
|
long getLatency();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the bootstrap class
|
||||||
|
* instance for this database.
|
||||||
|
*
|
||||||
|
* @return the bootstrap class instance, null if none
|
||||||
|
* @see B for bootstrap class
|
||||||
|
*/
|
||||||
|
B getBootstrap();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new repository
|
||||||
|
* using this database.
|
||||||
|
*
|
||||||
|
* @param <ID> the id type
|
||||||
|
* @param <E> the entity type
|
||||||
|
* @return the repository instance
|
||||||
|
* @see R for repository
|
||||||
|
*/
|
||||||
|
@NonNull <ID, E> R newRepository();
|
||||||
|
}
|
@ -0,0 +1,129 @@
|
|||||||
|
package me.braydon.feather.database.impl.mongodb;
|
||||||
|
|
||||||
|
import com.mongodb.BasicDBObject;
|
||||||
|
import com.mongodb.ConnectionString;
|
||||||
|
import com.mongodb.client.MongoClient;
|
||||||
|
import com.mongodb.client.MongoClients;
|
||||||
|
import com.mongodb.client.MongoDatabase;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NonNull;
|
||||||
|
import me.braydon.feather.database.IDatabase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link IDatabase} implementation for MongoDB.
|
||||||
|
*
|
||||||
|
* @author Braydon
|
||||||
|
* @see MongoClient for the bootstrap class
|
||||||
|
* @see ConnectionString for the credentials class
|
||||||
|
* @see MongoRepository for the repository class
|
||||||
|
* @see <a href="https://www.mongodb.com">MongoDB Official Site</a>
|
||||||
|
*/
|
||||||
|
public class MongoDB implements IDatabase<MongoClient, ConnectionString, MongoRepository<?, ?>> {
|
||||||
|
/**
|
||||||
|
* The current {@link MongoClient} instance.
|
||||||
|
*/
|
||||||
|
private MongoClient client;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link MongoDatabase} instance.
|
||||||
|
*/
|
||||||
|
@Getter private MongoDatabase database;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the name of this database.
|
||||||
|
*
|
||||||
|
* @return the database name
|
||||||
|
*/
|
||||||
|
@Override @NonNull
|
||||||
|
public String getName() {
|
||||||
|
return "MongoDB";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize a connection to this database.
|
||||||
|
*
|
||||||
|
* @param credentials the optional credentials to use
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void connect(ConnectionString credentials) {
|
||||||
|
if (credentials == null) { // We need valid credentials
|
||||||
|
throw new IllegalArgumentException("No credentials defined");
|
||||||
|
}
|
||||||
|
if (isConnected()) { // Already connected
|
||||||
|
throw new IllegalStateException("Already connected");
|
||||||
|
}
|
||||||
|
String databaseName = credentials.getDatabase(); // Get the database name
|
||||||
|
if (databaseName == null) {
|
||||||
|
throw new IllegalArgumentException("A database name is required");
|
||||||
|
}
|
||||||
|
if (client != null) { // We have a client, close it first
|
||||||
|
client.close();
|
||||||
|
}
|
||||||
|
client = MongoClients.create(credentials); // Create a new client
|
||||||
|
database = client.getDatabase(databaseName); // Get the database
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if this database is connected.
|
||||||
|
*
|
||||||
|
* @return the database connection state
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean isConnected() {
|
||||||
|
return client != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the latency to this database.
|
||||||
|
*
|
||||||
|
* @return the latency, -1 if not connected
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public long getLatency() {
|
||||||
|
if (!isConnected()) { // Not connected
|
||||||
|
return -1L;
|
||||||
|
}
|
||||||
|
// Return ping
|
||||||
|
long before = System.currentTimeMillis();
|
||||||
|
database.runCommand(new BasicDBObject("ping", "1"));
|
||||||
|
return System.currentTimeMillis() - before;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the bootstrap class
|
||||||
|
* instance for this database.
|
||||||
|
*
|
||||||
|
* @return the bootstrap class instance, null if none
|
||||||
|
* @see MongoClients for bootstrap class
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public MongoClient getBootstrap() {
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new repository
|
||||||
|
* using this database.
|
||||||
|
*
|
||||||
|
* @return the repository instance
|
||||||
|
* @see MongoRepository for repository
|
||||||
|
*/
|
||||||
|
@Override @NonNull
|
||||||
|
public <ID, E> MongoRepository<ID, E> newRepository() {
|
||||||
|
return new MongoRepository<>(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes this stream and releases any system resources associated
|
||||||
|
* with it. If the stream is already closed then invoking this
|
||||||
|
* method has no effect.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
if (client != null) {
|
||||||
|
client.close();
|
||||||
|
}
|
||||||
|
client = null;
|
||||||
|
database = null;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,160 @@
|
|||||||
|
package me.braydon.feather.database.impl.mongodb;
|
||||||
|
|
||||||
|
import com.mongodb.client.MongoCollection;
|
||||||
|
import com.mongodb.client.model.Filters;
|
||||||
|
import com.mongodb.client.model.Indexes;
|
||||||
|
import com.mongodb.client.model.UpdateOneModel;
|
||||||
|
import com.mongodb.client.model.UpdateOptions;
|
||||||
|
import lombok.NonNull;
|
||||||
|
import me.braydon.feather.annotation.Collection;
|
||||||
|
import me.braydon.feather.common.EntityUtils;
|
||||||
|
import me.braydon.feather.common.Tuple;
|
||||||
|
import me.braydon.feather.database.impl.mongodb.annotation.Index;
|
||||||
|
import me.braydon.feather.repository.Repository;
|
||||||
|
import org.bson.Document;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link MongoDB} {@link Repository} implementation.
|
||||||
|
*
|
||||||
|
* @author Braydon
|
||||||
|
* @param <ID> the identifier for type for entities
|
||||||
|
* @param <E> the entity type this repository stores
|
||||||
|
*/
|
||||||
|
public class MongoRepository<ID, E> extends Repository<MongoDB, ID, E> {
|
||||||
|
public MongoRepository(@NonNull MongoDB database) {
|
||||||
|
super(database);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the entity with the given id.
|
||||||
|
*
|
||||||
|
* @param id the entity id
|
||||||
|
* @return the entity with the id, null if none
|
||||||
|
* @see ID for id
|
||||||
|
* @see E for entity
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public E find(@NonNull ID id) {
|
||||||
|
String idString = id.toString(); // Stringify the ID
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the entity matching the given predicate.
|
||||||
|
*
|
||||||
|
* @param predicate the predicate to test
|
||||||
|
* @return the found entity
|
||||||
|
* @see E for entity
|
||||||
|
* @see Predicate for predicate
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public E findOne(@NonNull Predicate<E> predicate) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find all entities matching the given predicate.
|
||||||
|
*
|
||||||
|
* @param predicate the predicate to test
|
||||||
|
* @return the found entities
|
||||||
|
* @see E for entity
|
||||||
|
* @see Predicate for predicate
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<E> findAll(@NonNull Predicate<E> predicate) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all entities within this repository.
|
||||||
|
*
|
||||||
|
* @return the entities
|
||||||
|
* @see E for entity
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<E> findAll() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save the given entities.
|
||||||
|
*
|
||||||
|
* @param entities the entities to save
|
||||||
|
* @see E for entity
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void saveAll(@NonNull E... entities) {
|
||||||
|
Map<String, List<me.braydon.feather.data.Document<Object>>> toSave = new HashMap<>(); // The documents to save
|
||||||
|
|
||||||
|
// Iterate over the given entities and ensure they
|
||||||
|
// are all valid, and if they are, collect them so
|
||||||
|
// we can bulk save them later
|
||||||
|
for (E entity : entities) {
|
||||||
|
EntityUtils.ensureValid(entity, false); // Ensure our entity is valid
|
||||||
|
String collectionName = entity.getClass().getAnnotation(Collection.class).name(); // The name of the collection
|
||||||
|
|
||||||
|
// Add the document to our list of documents to save
|
||||||
|
List<me.braydon.feather.data.Document<Object>> documents = toSave.getOrDefault(collectionName, new ArrayList<>());
|
||||||
|
documents.add(new me.braydon.feather.data.Document<>(entity));
|
||||||
|
toSave.put(collectionName, documents);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterate over the documents we want to save, and create
|
||||||
|
// an update model for them, as well as update indexes.
|
||||||
|
for (Map.Entry<String, List<me.braydon.feather.data.Document<Object>>> entry : toSave.entrySet()) {
|
||||||
|
MongoCollection<Document> collection = getDatabase().getDatabase().getCollection(entry.getKey()); // The collection to save to
|
||||||
|
|
||||||
|
List<UpdateOneModel<Document>> updateModels = new ArrayList<>();
|
||||||
|
for (me.braydon.feather.data.Document<Object> document : entry.getValue()) {
|
||||||
|
// Add or update model to the list
|
||||||
|
updateModels.add(new UpdateOneModel<>(
|
||||||
|
Filters.eq(document.getIdKey(), document.getKey()),
|
||||||
|
new Document("$set", new Document(document.toMappedData())),
|
||||||
|
new UpdateOptions().upsert(true)
|
||||||
|
));
|
||||||
|
|
||||||
|
// Create indexes for @Index fields
|
||||||
|
for (Map.Entry<String, Tuple<Field, Object>> mappedEntry : document.getMappedData().entrySet()) {
|
||||||
|
java.lang.reflect.Field field = mappedEntry.getValue().getLeft();
|
||||||
|
if (field.isAnnotationPresent(Index.class)) {
|
||||||
|
collection.createIndex(Indexes.text(mappedEntry.getKey()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We have updates models present, bulk write them to the database
|
||||||
|
if (!updateModels.isEmpty()) {
|
||||||
|
collection.bulkWrite(updateModels);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the amount of stored entities.
|
||||||
|
*
|
||||||
|
* @return the amount of stored entities
|
||||||
|
* @see E for entity
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public long count() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Drop the given entity.
|
||||||
|
*
|
||||||
|
* @param entity the entity to drop
|
||||||
|
* @see E for entity
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void drop(@NonNull E entity) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
package me.braydon.feather.databases.mongodb.annotation;
|
package me.braydon.feather.database.impl.mongodb.annotation;
|
||||||
|
|
||||||
import me.braydon.feather.databases.mongodb.MongoDB;
|
import me.braydon.feather.database.impl.mongodb.MongoDB;
|
||||||
|
|
||||||
import java.lang.annotation.*;
|
import java.lang.annotation.*;
|
||||||
|
|
@ -1,15 +1,10 @@
|
|||||||
package me.braydon.feather.databases.redis;
|
package me.braydon.feather.database.impl.redis;
|
||||||
|
|
||||||
import io.lettuce.core.RedisClient;
|
import io.lettuce.core.RedisClient;
|
||||||
import io.lettuce.core.RedisURI;
|
import io.lettuce.core.RedisURI;
|
||||||
import io.lettuce.core.api.StatefulRedisConnection;
|
import io.lettuce.core.api.StatefulRedisConnection;
|
||||||
import io.lettuce.core.api.async.RedisAsyncCommands;
|
|
||||||
import io.lettuce.core.api.sync.RedisCommands;
|
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
import me.braydon.feather.IDatabase;
|
import me.braydon.feather.database.IDatabase;
|
||||||
import me.braydon.feather.annotation.Collection;
|
|
||||||
import me.braydon.feather.annotation.Field;
|
|
||||||
import me.braydon.feather.data.Document;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The {@link IDatabase} implementation for Redis.
|
* The {@link IDatabase} implementation for Redis.
|
||||||
@ -17,11 +12,10 @@ import me.braydon.feather.data.Document;
|
|||||||
* @author Braydon
|
* @author Braydon
|
||||||
* @see StatefulRedisConnection for the bootstrap class
|
* @see StatefulRedisConnection for the bootstrap class
|
||||||
* @see RedisURI for the credentials class
|
* @see RedisURI for the credentials class
|
||||||
* @see RedisCommands for the sync pipeline class
|
* @see RedisRepository for the repository class
|
||||||
* @see RedisAsyncCommands for the async pipeline class
|
|
||||||
* @see <a href="https://redis.io">Redis Official Site</a>
|
* @see <a href="https://redis.io">Redis Official Site</a>
|
||||||
*/
|
*/
|
||||||
public class Redis implements IDatabase<StatefulRedisConnection<String, String>, RedisURI, RedisCommands<String, String>, RedisAsyncCommands<String, String>> {
|
public class Redis implements IDatabase<StatefulRedisConnection<String, String>, RedisURI, RedisRepository<?, ?>> {
|
||||||
/**
|
/**
|
||||||
* The current {@link RedisClient} instance.
|
* The current {@link RedisClient} instance.
|
||||||
*/
|
*/
|
||||||
@ -75,6 +69,16 @@ public class Redis implements IDatabase<StatefulRedisConnection<String, String>,
|
|||||||
return client != null && (connection != null && connection.isOpen());
|
return client != null && (connection != null && connection.isOpen());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the latency to this database.
|
||||||
|
*
|
||||||
|
* @return the latency, -1 if not connected
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public long getLatency() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the bootstrap class
|
* Get the bootstrap class
|
||||||
* instance for this database.
|
* instance for this database.
|
||||||
@ -88,47 +92,25 @@ public class Redis implements IDatabase<StatefulRedisConnection<String, String>,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the synchronized
|
* Create a new repository
|
||||||
* pipeline for this database.
|
* using this database.
|
||||||
*
|
*
|
||||||
* @return the synchronized pipeline
|
* @return the repository instance
|
||||||
* @see RedisPipeline for synchronized pipeline
|
* @see RedisRepository for repository
|
||||||
*/
|
*/
|
||||||
@Override @NonNull
|
@Override @NonNull
|
||||||
public RedisCommands<String, String> sync() {
|
public <ID, E> RedisRepository<ID, E> newRepository() {
|
||||||
return connection.sync();
|
return new RedisRepository<>(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// @Override
|
||||||
* Get the asynchronous
|
// public void write(@NonNull Object element) {
|
||||||
* pipeline for this database.
|
// if (!element.getClass().isAnnotationPresent(Collection.class)) { // Missing annotation
|
||||||
*
|
// throw new IllegalStateException("Element is missing @Collection annotation");
|
||||||
* @return the asynchronous pipeline
|
// }
|
||||||
* @see RedisPipeline for asynchronous pipeline
|
// 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
|
||||||
@Override @NonNull
|
// }
|
||||||
public RedisAsyncCommands<String, String> async() {
|
|
||||||
return connection.async();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write the given object to the database.
|
|
||||||
* <p>
|
|
||||||
* This object is an instance of a class
|
|
||||||
* annotated with {@link Collection}, and
|
|
||||||
* contains fields annotated with {@link Field}.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @param element the element to write
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void write(@NonNull Object element) {
|
|
||||||
if (!element.getClass().isAnnotationPresent(Collection.class)) { // Missing annotation
|
|
||||||
throw new IllegalStateException("Element is missing @Collection annotation");
|
|
||||||
}
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Closes this stream and releases any system resources associated
|
* Closes this stream and releases any system resources associated
|
@ -0,0 +1,103 @@
|
|||||||
|
package me.braydon.feather.database.impl.redis;
|
||||||
|
|
||||||
|
import lombok.NonNull;
|
||||||
|
import me.braydon.feather.repository.Repository;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link Redis} {@link Repository} implementation.
|
||||||
|
*
|
||||||
|
* @author Braydon
|
||||||
|
* @param <ID> the identifier for type for entities
|
||||||
|
* @param <E> the entity type this repository stores
|
||||||
|
*/
|
||||||
|
public class RedisRepository<ID, E> extends Repository<Redis, ID, E> {
|
||||||
|
public RedisRepository(@NonNull Redis database) {
|
||||||
|
super(database);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the entity with the given id.
|
||||||
|
*
|
||||||
|
* @param id the entity id
|
||||||
|
* @return the entity with the id, null if none
|
||||||
|
* @see ID for id
|
||||||
|
* @see E for entity
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public E find(@NonNull ID id) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the entity matching the given predicate.
|
||||||
|
*
|
||||||
|
* @param predicate the predicate to test
|
||||||
|
* @return the found entity
|
||||||
|
* @see E for entity
|
||||||
|
* @see Predicate for predicate
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public E findOne(@NonNull Predicate<E> predicate) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find all entities matching the given predicate.
|
||||||
|
*
|
||||||
|
* @param predicate the predicate to test
|
||||||
|
* @return the found entities
|
||||||
|
* @see E for entity
|
||||||
|
* @see Predicate for predicate
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<E> findAll(@NonNull Predicate<E> predicate) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all entities within this repository.
|
||||||
|
*
|
||||||
|
* @return the entities
|
||||||
|
* @see E for entity
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<E> findAll() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save the given entities.
|
||||||
|
*
|
||||||
|
* @param entities the entities to save
|
||||||
|
* @see E for entity
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void saveAll(@NonNull E... entities) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the amount of stored entities.
|
||||||
|
*
|
||||||
|
* @return the amount of stored entities
|
||||||
|
* @see E for entity
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public long count() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Drop the given entity.
|
||||||
|
*
|
||||||
|
* @param entity the entity to drop
|
||||||
|
* @see E for entity
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void drop(@NonNull E entity) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
}
|
@ -1,51 +0,0 @@
|
|||||||
package me.braydon.feather.databases.mongodb;
|
|
||||||
|
|
||||||
import com.mongodb.BasicDBObject;
|
|
||||||
import lombok.AccessLevel;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.NonNull;
|
|
||||||
import me.braydon.feather.FeatherThreads;
|
|
||||||
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
|
||||||
import java.util.concurrent.Executor;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The pipeline for handling asynchronous {@link MongoDB} operations.
|
|
||||||
*
|
|
||||||
* @author Braydon
|
|
||||||
*/
|
|
||||||
@AllArgsConstructor(access = AccessLevel.PROTECTED)
|
|
||||||
public final class MongoAsyncPipeline {
|
|
||||||
/**
|
|
||||||
* The database to handle operations for.
|
|
||||||
*/
|
|
||||||
@NonNull private final MongoDB database;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the latency to the database.
|
|
||||||
*
|
|
||||||
* @return the latency
|
|
||||||
*/
|
|
||||||
public CompletableFuture<Long> getPing() {
|
|
||||||
return getPing(FeatherThreads.THREAD_POOL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the latency to the database.
|
|
||||||
*
|
|
||||||
* @param executor the thread executor to use
|
|
||||||
* @return the latency
|
|
||||||
* @see Executor for executor
|
|
||||||
*/
|
|
||||||
public CompletableFuture<Long> getPing(@NonNull Executor executor) {
|
|
||||||
return CompletableFuture.supplyAsync(() -> {
|
|
||||||
if (!database.isConnected()) { // Not connected
|
|
||||||
return -1L;
|
|
||||||
}
|
|
||||||
// Return ping
|
|
||||||
long before = System.currentTimeMillis();
|
|
||||||
database.getDatabase().runCommand(new BasicDBObject("ping", "1"));
|
|
||||||
return System.currentTimeMillis() - before;
|
|
||||||
}, executor);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,176 +0,0 @@
|
|||||||
package me.braydon.feather.databases.mongodb;
|
|
||||||
|
|
||||||
import com.mongodb.ConnectionString;
|
|
||||||
import com.mongodb.client.MongoClient;
|
|
||||||
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.
|
|
||||||
*
|
|
||||||
* @author Braydon
|
|
||||||
* @see MongoClient for the bootstrap class
|
|
||||||
* @see ConnectionString for the credentials class
|
|
||||||
* @see MongoSyncPipeline for the sync pipeline class
|
|
||||||
* @see MongoAsyncPipeline for the async pipeline class
|
|
||||||
* @see <a href="https://www.mongodb.com">MongoDB Official Site</a>
|
|
||||||
*/
|
|
||||||
public class MongoDB implements IDatabase<MongoClient, ConnectionString, MongoSyncPipeline, MongoAsyncPipeline> {
|
|
||||||
/**
|
|
||||||
* The current {@link MongoClient} instance.
|
|
||||||
*/
|
|
||||||
private MongoClient client;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The {@link MongoDatabase} instance.
|
|
||||||
*/
|
|
||||||
@Getter private MongoDatabase database;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the name of this database.
|
|
||||||
*
|
|
||||||
* @return the database name
|
|
||||||
*/
|
|
||||||
@Override @NonNull
|
|
||||||
public String getName() {
|
|
||||||
return "MongoDB";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize a connection to this database.
|
|
||||||
*
|
|
||||||
* @param credentials the optional credentials to use
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void connect(ConnectionString credentials) {
|
|
||||||
if (credentials == null) { // We need valid credentials
|
|
||||||
throw new IllegalArgumentException("No credentials defined");
|
|
||||||
}
|
|
||||||
if (isConnected()) { // Already connected
|
|
||||||
throw new IllegalStateException("Already connected");
|
|
||||||
}
|
|
||||||
String databaseName = credentials.getDatabase(); // Get the database name
|
|
||||||
if (databaseName == null) {
|
|
||||||
throw new IllegalArgumentException("A database name is required");
|
|
||||||
}
|
|
||||||
if (client != null) { // We have a client, close it first
|
|
||||||
client.close();
|
|
||||||
}
|
|
||||||
client = MongoClients.create(credentials); // Create a new client
|
|
||||||
database = client.getDatabase(databaseName); // Get the database
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if this database is connected.
|
|
||||||
*
|
|
||||||
* @return the database connection state
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean isConnected() {
|
|
||||||
return client != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the bootstrap class
|
|
||||||
* instance for this database.
|
|
||||||
*
|
|
||||||
* @return the bootstrap class instance, null if none
|
|
||||||
* @see MongoClients for bootstrap class
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public MongoClient getBootstrap() {
|
|
||||||
return client;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the synchronized
|
|
||||||
* pipeline for this database.
|
|
||||||
*
|
|
||||||
* @return the synchronized pipeline
|
|
||||||
* @see MongoSyncPipeline for synchronized pipeline
|
|
||||||
*/
|
|
||||||
@Override @NonNull
|
|
||||||
public MongoSyncPipeline sync() {
|
|
||||||
return new MongoSyncPipeline(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the asynchronous
|
|
||||||
* pipeline for this database.
|
|
||||||
*
|
|
||||||
* @return the asynchronous pipeline
|
|
||||||
* @see MongoAsyncPipeline for asynchronous pipeline
|
|
||||||
*/
|
|
||||||
@Override @NonNull
|
|
||||||
public MongoAsyncPipeline async() {
|
|
||||||
return new MongoAsyncPipeline(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write the given object to the database.
|
|
||||||
* <p>
|
|
||||||
* This object is an instance of a class
|
|
||||||
* annotated with {@link Collection}, and
|
|
||||||
* contains fields annotated with {@link Field}.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @param element the element to write
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void write(@NonNull Object element) {
|
|
||||||
Class<?> clazz = element.getClass(); // Get the element class
|
|
||||||
if (!clazz.isAnnotationPresent(Collection.class)) { // Missing annotation
|
|
||||||
throw new IllegalStateException("Element is missing @Collection annotation");
|
|
||||||
}
|
|
||||||
Collection annotation = clazz.getAnnotation(Collection.class); // Get the @Collection annotation
|
|
||||||
String collectionName = annotation.name(); // The name of the collection
|
|
||||||
if (collectionName.isEmpty()) { // Missing collection name
|
|
||||||
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); // 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.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()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Closes this stream and releases any system resources associated
|
|
||||||
* with it. If the stream is already closed then invoking this
|
|
||||||
* method has no effect.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void close() {
|
|
||||||
if (client != null) {
|
|
||||||
client.close();
|
|
||||||
}
|
|
||||||
client = null;
|
|
||||||
database = null;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,36 +0,0 @@
|
|||||||
package me.braydon.feather.databases.mongodb;
|
|
||||||
|
|
||||||
import com.mongodb.BasicDBObject;
|
|
||||||
import lombok.AccessLevel;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.NonNull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The pipeline for handling synchronous {@link MongoDB} operations.
|
|
||||||
*
|
|
||||||
* @author Braydon
|
|
||||||
*/
|
|
||||||
@AllArgsConstructor(access = AccessLevel.PROTECTED)
|
|
||||||
public final class MongoSyncPipeline {
|
|
||||||
/**
|
|
||||||
* The database to handle operations for.
|
|
||||||
*
|
|
||||||
* @see MongoDB for database
|
|
||||||
*/
|
|
||||||
@NonNull private final MongoDB database;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the latency to the database.
|
|
||||||
*
|
|
||||||
* @return the latency
|
|
||||||
*/
|
|
||||||
public long getPing() {
|
|
||||||
if (!database.isConnected()) { // Not connected
|
|
||||||
return -1L;
|
|
||||||
}
|
|
||||||
// Return ping
|
|
||||||
long before = System.currentTimeMillis();
|
|
||||||
database.getDatabase().runCommand(new BasicDBObject("ping", "1"));
|
|
||||||
return System.currentTimeMillis() - before;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,20 +0,0 @@
|
|||||||
package me.braydon.feather.databases.redis;
|
|
||||||
|
|
||||||
import lombok.AccessLevel;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.NonNull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The pipeline for handling {@link Redis} operations.
|
|
||||||
*
|
|
||||||
* @author Braydon
|
|
||||||
*/
|
|
||||||
@AllArgsConstructor(access = AccessLevel.PROTECTED)
|
|
||||||
public final class RedisPipeline {
|
|
||||||
/**
|
|
||||||
* The database to handle operations for.
|
|
||||||
*
|
|
||||||
* @see Redis for database
|
|
||||||
*/
|
|
||||||
@NonNull private final Redis database;
|
|
||||||
}
|
|
@ -4,16 +4,21 @@ import lombok.AccessLevel;
|
|||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
import me.braydon.feather.IDatabase;
|
import me.braydon.feather.database.IDatabase;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A repository belonging to a {@link IDatabase}.
|
* A repository belonging to a {@link IDatabase}.
|
||||||
*
|
*
|
||||||
* @author Braydon
|
* @author Braydon
|
||||||
* @param <D> the database
|
* @param <D> the database this repository uses
|
||||||
|
* @param <ID> the identifier for type for entities
|
||||||
|
* @param <E> the entity type this repository stores
|
||||||
*/
|
*/
|
||||||
@AllArgsConstructor @Getter(AccessLevel.PROTECTED)
|
@AllArgsConstructor @Getter(AccessLevel.PROTECTED)
|
||||||
public abstract class Repository<D extends IDatabase<?, ?, ?, ?>> {
|
public abstract class Repository<D extends IDatabase<?, ?, ?>, ID, E> {
|
||||||
/**
|
/**
|
||||||
* The database this repository belongs to.
|
* The database this repository belongs to.
|
||||||
*
|
*
|
||||||
@ -22,11 +27,74 @@ public abstract class Repository<D extends IDatabase<?, ?, ?, ?>> {
|
|||||||
@NonNull private final D database;
|
@NonNull private final D database;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save the given element to the database.
|
* Get the entity with the given id.
|
||||||
*
|
*
|
||||||
* @param element the element to save
|
* @param id the entity id
|
||||||
|
* @return the entity with the id, null if none
|
||||||
|
* @see ID for id
|
||||||
|
* @see E for entity
|
||||||
*/
|
*/
|
||||||
public final void save(@NonNull Object element) {
|
public abstract E find(@NonNull ID id);
|
||||||
database.write(element);
|
|
||||||
|
/**
|
||||||
|
* Find the entity matching the given predicate.
|
||||||
|
*
|
||||||
|
* @param predicate the predicate to test
|
||||||
|
* @return the found entity
|
||||||
|
* @see E for entity
|
||||||
|
* @see Predicate for predicate
|
||||||
|
*/
|
||||||
|
public abstract E findOne(@NonNull Predicate<E> predicate);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find all entities matching the given predicate.
|
||||||
|
*
|
||||||
|
* @param predicate the predicate to test
|
||||||
|
* @return the found entities
|
||||||
|
* @see E for entity
|
||||||
|
* @see Predicate for predicate
|
||||||
|
*/
|
||||||
|
public abstract List<E> findAll(@NonNull Predicate<E> predicate);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all entities within this repository.
|
||||||
|
*
|
||||||
|
* @return the entities
|
||||||
|
* @see E for entity
|
||||||
|
*/
|
||||||
|
public abstract List<E> findAll();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save the given entity to the database.
|
||||||
|
*
|
||||||
|
* @param entity the entity to save
|
||||||
|
* @see E for entity
|
||||||
|
*/
|
||||||
|
public void save(@NonNull E entity) {
|
||||||
|
saveAll(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save the given entities.
|
||||||
|
*
|
||||||
|
* @param entities the entities to save
|
||||||
|
* @see E for entity
|
||||||
|
*/
|
||||||
|
public abstract void saveAll(@NonNull E... entities);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the amount of stored entities.
|
||||||
|
*
|
||||||
|
* @return the amount of stored entities
|
||||||
|
* @see E for entity
|
||||||
|
*/
|
||||||
|
public abstract long count();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Drop the given entity.
|
||||||
|
*
|
||||||
|
* @param entity the entity to drop
|
||||||
|
* @see E for entity
|
||||||
|
*/
|
||||||
|
public abstract void drop(@NonNull E entity);
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user