Move new configuration packages and add test for PropertyMap

This commit is contained in:
ljacqu
2016-01-05 21:59:08 +01:00
parent cb07b3df3d
commit 204a564a9a
17 changed files with 114 additions and 61 deletions
@@ -0,0 +1,17 @@
package fr.xephi.authme.settings.domain;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Comment for properties which are also included in the YAML file upon saving.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Comment {
String[] value() default "";
}
@@ -0,0 +1,104 @@
package fr.xephi.authme.settings.domain;
import org.bukkit.configuration.file.YamlConfiguration;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
/**
* Properties (i.e. a <i>setting</i> that is read from the config.yml file).
*/
public class Property<T> {
private final PropertyType<T> type;
private final String path;
private final T defaultValue;
private Property(PropertyType<T> type, String path, T defaultValue) {
Objects.requireNonNull(defaultValue);
this.type = type;
this.path = path;
this.defaultValue = defaultValue;
}
public static <T> Property<T> newProperty(PropertyType<T> type, String path, T defaultValue) {
return new Property<>(type, path, defaultValue);
}
@SafeVarargs
public static <U> Property<List<U>> newProperty(PropertyType<List<U>> type, String path, U... defaultValues) {
return new Property<>(type, path, Arrays.asList(defaultValues));
}
public static <E extends Enum<E>> Property<E> newProperty(Class<E> clazz, String path, E defaultValue) {
return new Property<>(new PropertyType.EnumProperty<>(clazz), path, defaultValue);
}
// -----
// Overloaded convenience methods for specific types
// -----
public static Property<Boolean> newProperty(String path, boolean defaultValue) {
return new Property<>(PropertyType.BOOLEAN, path, defaultValue);
}
public static Property<Integer> newProperty(String path, int defaultValue) {
return new Property<>(PropertyType.INTEGER, path, defaultValue);
}
public static Property<String> newProperty(String path, String defaultValue) {
return new Property<>(PropertyType.STRING, path, defaultValue);
}
// -----
// Hooks to the PropertyType methods
// -----
/**
* Get the property value from the given configuration.
*
* @param configuration The configuration to read the value from
* @return The value, or default if not present
*/
public T getFromFile(YamlConfiguration configuration) {
return type.getFromFile(this, configuration);
}
/**
* Format the property value as YAML.
*
* @param configuration The configuration to read the value from
* @return The property value as YAML
*/
public List<String> formatValueAsYaml(YamlConfiguration configuration) {
return type.asYaml(this, configuration);
}
// -----
// Trivial getters
// -----
/**
* Return the default value of the property.
*
* @return The default value
*/
public T getDefaultValue() {
return defaultValue;
}
/**
* Return the property path (i.e. the node at which this property is located in the YAML file).
*
* @return The path
*/
public String getPath() {
return path;
}
@Override
public String toString() {
return "Property '" + path + "'";
}
}
@@ -0,0 +1,182 @@
package fr.xephi.authme.settings.domain;
import org.bukkit.configuration.file.YamlConfiguration;
import java.util.ArrayList;
import java.util.List;
import static java.util.Arrays.asList;
/**
* Handles a certain property type and provides type-specific functionality.
*
* @param <T> The value of the property
* @see Property
*/
public abstract class PropertyType<T> {
public static final PropertyType<Boolean> BOOLEAN = new BooleanProperty();
public static final PropertyType<Double> DOUBLE = new DoubleProperty();
public static final PropertyType<Integer> INTEGER = new IntegerProperty();
public static final PropertyType<String> STRING = new StringProperty();
public static final PropertyType<List<String>> STRING_LIST = new StringListProperty();
/**
* Get the property's value from the given YAML configuration.
*
* @param property The property to retrieve
* @param configuration The YAML configuration to read from
* @return The read value, or the default value if absent
*/
public abstract T getFromFile(Property<T> property, YamlConfiguration configuration);
/**
* Return the property's value (or its default) as YAML.
*
* @param property The property to transform
* @param configuration The YAML configuration to read from
* @return The read value or its default in YAML format
*/
public List<String> asYaml(Property<T> property, YamlConfiguration configuration) {
return asYaml(getFromFile(property, configuration));
}
/**
* Transform the given value to YAML.
*
* @param value The value to transform
* @return The value as YAML
*/
protected abstract List<String> asYaml(T value);
/**
* Boolean property.
*/
private static final class BooleanProperty extends PropertyType<Boolean> {
@Override
public Boolean getFromFile(Property<Boolean> property, YamlConfiguration configuration) {
return configuration.getBoolean(property.getPath(), property.getDefaultValue());
}
@Override
protected List<String> asYaml(Boolean value) {
return asList(value ? "true" : "false");
}
}
/**
* Double property.
*/
private static final class DoubleProperty extends PropertyType<Double> {
@Override
public Double getFromFile(Property<Double> property, YamlConfiguration configuration) {
return configuration.getDouble(property.getPath(), property.getDefaultValue());
}
@Override
protected List<String> asYaml(Double value) {
return asList(String.valueOf(value));
}
}
/**
* Integer property.
*/
private static final class IntegerProperty extends PropertyType<Integer> {
@Override
public Integer getFromFile(Property<Integer> property, YamlConfiguration configuration) {
return configuration.getInt(property.getPath(), property.getDefaultValue());
}
@Override
protected List<String> asYaml(Integer value) {
return asList(String.valueOf(value));
}
}
/**
* String property.
*/
private static final class StringProperty extends PropertyType<String> {
@Override
public String getFromFile(Property<String> property, YamlConfiguration configuration) {
return configuration.getString(property.getPath(), property.getDefaultValue());
}
@Override
protected List<String> asYaml(String value) {
return asList(toYamlLiteral(value));
}
public static String toYamlLiteral(String str) {
// TODO: Need to handle new lines properly
return "'" + str.replace("'", "''") + "'";
}
}
/**
* String list property.
*/
private static final class StringListProperty extends PropertyType<List<String>> {
@Override
public List<String> getFromFile(Property<List<String>> property, YamlConfiguration configuration) {
if (!configuration.isList(property.getPath())) {
return property.getDefaultValue();
}
return configuration.getStringList(property.getPath());
}
@Override
protected List<String> asYaml(List<String> value) {
if (value.isEmpty()) {
return asList("[]");
}
List<String> resultLines = new ArrayList<>();
resultLines.add(""); // add
for (String entry : value) {
// TODO: StringProperty#toYamlLiteral will return List<String>...
resultLines.add(" - " + StringProperty.toYamlLiteral(entry));
}
return resultLines;
}
}
/**
* Enum property.
* @param <E> The enum class
*/
static final class EnumProperty<E extends Enum<E>> extends PropertyType<E> {
private Class<E> clazz;
public EnumProperty(Class<E> clazz) {
this.clazz = clazz;
}
@Override
public E getFromFile(Property<E> property, YamlConfiguration configuration) {
String textValue = configuration.getString(property.getPath());
if (textValue == null) {
return property.getDefaultValue();
}
E mappedValue = mapToEnum(textValue);
return mappedValue != null ? mappedValue : property.getDefaultValue();
}
@Override
protected List<String> asYaml(E value) {
return asList("'" + value + "'");
}
private E mapToEnum(String value) {
for (E entry : clazz.getEnumConstants()) {
if (entry.name().equalsIgnoreCase(value)) {
return entry;
}
}
return null;
}
}
}
@@ -0,0 +1,7 @@
package fr.xephi.authme.settings.domain;
/**
* Marker for classes that define {@link Property} fields.
*/
public interface SettingsClass {
}