Added builder, DataTracker and KeyValue #16

Manually merged
quentinlegot merged 40 commits from dev into master 2023-06-13 22:15:40 +02:00
13 changed files with 251 additions and 12 deletions
Showing only changes of commit c66067da8c - Show all commits

View File

@ -0,0 +1,8 @@
package fr.altarik.toolbox.core.builder;
public class EmptyCollectionException extends NullPointerException {
public EmptyCollectionException(String message) {
super(message);
}
}

View File

@ -0,0 +1,11 @@
package fr.altarik.toolbox.core.builder;
public interface IBuilder<T> {
/**
* Build the builders parameters into T object
* @return The created objects thanks to given parameters
* @throws Exception if any error occur during creation of the built object
*/
T build() throws Exception;
}

View File

@ -0,0 +1,24 @@
package fr.altarik.toolbox.core.builder;
/**
* Builder parameter, for more flexibility
* @param <T> the parameter type
* @see OptionalParamBuilder
* @see RequiredParamBuilder
* @see RequiredCollectionParameterBuilder
*/
public interface IParamBuilder<T> {
/**
* Get the given object, may return {@link NullPointerException} depending on the policy of implemented class
* @return the parameter given by {@link IParamBuilder#set(Object)}
* @throws NullPointerException may throw this error depending on the policy of implemented class
*/
T get() throws NullPointerException;
/**
* Change/insert the value of the parameter
* @param parameter the given parameter
*/
void set(T parameter);
}

View File

@ -0,0 +1,24 @@
package fr.altarik.toolbox.core.builder;
/**
* Doesn't throw a {@link NullPointerException} when using {@link IParamBuilder#get()} in any case
* @param <T> the returned type
* @see IParamBuilder
*/
public class OptionalParamBuilder<T> implements IParamBuilder<T> {
private T parameter;
public OptionalParamBuilder(T param) {
this.parameter = param;
}
@Override
public T get() throws NullPointerException {
return parameter;
}
@Override
public void set(T parameter) {
this.parameter = parameter;
}
}

View File

@ -0,0 +1,52 @@
package fr.altarik.toolbox.core.builder;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
import java.util.Objects;
/**
* Mostly same as {@link RequiredParamBuilder} but for list
* @param <E> The type contained in the collection
* @param <T> The returned type
*/
public class RequiredCollectionParameterBuilder<E, T extends Collection<E>> implements IParamBuilder<T> {
private final T collection;
private final boolean canBeEmpty;
public RequiredCollectionParameterBuilder(@NotNull T collection, boolean canBeEmpty) {
this.collection = Objects.requireNonNull(collection);
this.canBeEmpty = canBeEmpty;
}
/**
* <p>Return the list, if not empty</p>
* <p>If empty, return the collection if {@code canBeEmpty} if true, otherwise throw a {@link NullPointerException}</p>
* @return the collection
* @throws NullPointerException if collection is empty and {@code canBeEmpty} is false
*/
@Override
public T get() throws NullPointerException {
if(canBeEmpty) {
return collection;
} else if(!collection.isEmpty()) {
return collection;
} else {
throw new EmptyCollectionException("Collection cannot be empty");
}
}
@Override
public void set(T parameter) {
throw new UnsupportedOperationException("Use `add` in place of `set` for RequiredCollectionParameterBuilder");
}
/**
* Add an element to the collection
* @param element element to add to the list
*/
public void add(E element) {
collection.add(element);
}
}

View File

@ -0,0 +1,30 @@
package fr.altarik.toolbox.core.builder;
import java.util.Objects;
/**
* Throw a {@link NullPointerException} when using {@link IParamBuilder#get()} if the parameter doesn't have been initialized
* @param <T> the returned type
*/
public class RequiredParamBuilder<T> implements IParamBuilder<T> {
private T parameter;
public RequiredParamBuilder(T parameter) {
this.parameter = parameter;
}
public RequiredParamBuilder() {
this(null);
}
@Override
public T get() {
return Objects.requireNonNull(parameter);
}
@Override
public void set(T parameter) {
this.parameter = parameter;
}
}

View File

@ -0,0 +1,38 @@
import fr.altarik.toolbox.core.builder.IBuilder;
import fr.altarik.toolbox.core.builder.RequiredCollectionParameterBuilder;
import fr.altarik.toolbox.core.builder.RequiredParamBuilder;
import java.util.ArrayList;
import java.util.List;
public class BuilderImpl implements IBuilder<BuilderResult> {
private final RequiredCollectionParameterBuilder<String, List<String>> collection;
private final RequiredParamBuilder<Integer> numberOfSentences;
private BuilderImpl(boolean canBeEmpty) {
this.collection = new RequiredCollectionParameterBuilder<>(new ArrayList<>(), canBeEmpty);
this.numberOfSentences = new RequiredParamBuilder<>();
}
public BuilderImpl addSentence(String sentence) {
collection.add(sentence);
return this;
}
public BuilderImpl numberOfSentence(int i) {
this.numberOfSentences.set(i);
return this;
}
public static BuilderImpl builder(boolean canBeEmpty) {
return new BuilderImpl(canBeEmpty);
}
@Override
public BuilderResult build() throws Exception {
return new BuilderResult(collection.get(), numberOfSentences.get());
}
}

View File

@ -0,0 +1,5 @@
import java.util.List;
public record BuilderResult(List<String> sentences, int numberOfSentences) {
}

View File

@ -0,0 +1,32 @@
import fr.altarik.toolbox.core.builder.EmptyCollectionException;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.util.Arrays;
public class BuilderTest {
@Test
void builderTest() throws Exception {
BuilderImpl builder = BuilderImpl.builder(true);
builder.addSentence("First sentence");
builder.addSentence("Second sentence");
builder.numberOfSentence(2);
BuilderResult res = builder.build();
Assertions.assertEquals(Arrays.asList("First sentence", "Second sentence"), res.sentences());
Assertions.assertEquals(res.numberOfSentences(), 2);
BuilderImpl builder1 = BuilderImpl.builder(false);
builder1.numberOfSentence(3);
Assertions.assertThrowsExactly(EmptyCollectionException.class, builder1::build);
BuilderImpl builder2 = BuilderImpl.builder(true);
builder2.numberOfSentence(3);
Assertions.assertDoesNotThrow(builder2::build);
BuilderImpl builder3 = BuilderImpl.builder(true);
Assertions.assertThrowsExactly(NullPointerException.class, builder3::build);
}
}

View File

@ -1,6 +1,7 @@
dependencies {
implementation 'org.postgresql:postgresql:42.5.0'
testImplementation 'com.google.code.gson:gson:2.10'
implementation project(':Core')
}
test {

View File

@ -1,5 +1,8 @@
package fr.altarik.toolbox.database.keyvalue;
import fr.altarik.toolbox.core.builder.IBuilder;
import fr.altarik.toolbox.core.builder.RequiredCollectionParameterBuilder;
import fr.altarik.toolbox.core.builder.RequiredParamBuilder;
import fr.altarik.toolbox.database.SqlConnection;
import net.minecraft.util.Pair;
import org.jetbrains.annotations.NotNull;
@ -11,20 +14,30 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
public class KeyValueBuilder {
public class KeyValueBuilder implements IBuilder<KeyValueConnection> {
private final String tableName;
private final List<AdditionalColumn> additionalColumns;
private final SqlConnection connection;
private final RequiredParamBuilder<String> tableName;
private final RequiredCollectionParameterBuilder<AdditionalColumn, List<AdditionalColumn>> additionalColumns;
private final RequiredParamBuilder<SqlConnection> connection;
private KeyValueBuilder(SqlConnection connection, String tableName) {
this.connection = connection;
this.tableName = tableName;
this.additionalColumns = new ArrayList<>();
private KeyValueBuilder() {
this.tableName = new RequiredParamBuilder<>();
this.connection = new RequiredParamBuilder<>();
this.additionalColumns = new RequiredCollectionParameterBuilder<>(new ArrayList<>(), true);
}
public static KeyValueBuilder builder(@NotNull SqlConnection connection, @NotNull String tableName) {
return new KeyValueBuilder(connection, tableName);
public static KeyValueBuilder builder() {
return new KeyValueBuilder();
}
public KeyValueBuilder setConnection(@NotNull SqlConnection connection) {
this.connection.set(connection);
return this;
}
public KeyValueBuilder setTableName(@NotNull String tableName) {
this.tableName.set(tableName);
return this;
}
public KeyValueBuilder addColumn(AdditionalColumn additionalColumn) {
@ -33,7 +46,7 @@ public class KeyValueBuilder {
}
public KeyValueConnection build() throws SQLException {
return new KeyValueConnection(connection, tableName, additionalColumns);
return new KeyValueConnection(connection.get(), tableName.get(), additionalColumns.get());
}
public record AdditionalColumn(@NotNull String columnName, @NotNull JDBCType type, boolean notNull, @Nullable AdditionalColumnReference reference) {

View File

@ -30,6 +30,7 @@ class ConnectionTest {
try(PreparedStatement statement = connection.getConnection().prepareStatement("CREATE TABLE IF NOT EXISTS toolbox(id SERIAL, PRIMARY KEY (id));")) {
statement.executeUpdate();
}
connection.close();
});
}

View File

@ -10,4 +10,4 @@ pluginManagement {
}
rootProject.name = 'Toolbox'
include(':Tasks', ':Database', ':Pagination')
include(':Tasks', ':Database', ':Pagination', ':Core')