Added FieldFilter

If your configuration has a lot of fields and you want to exclude some
of these fields without making them final, static or transient, you can
configure your properties object to use additional FieldFilters.

A FieldFilter filters the fields of a configuration class by a specified
criterion. For example, if you only want to include fields whose names
don't start with 'ignore', you would add the following filter:

YamlProperties properties = YamlProperties.builder()
                .addFilter(field -> !field.getName().startsWith("ignore"))
                // ...
                .build();
dev v2.1.0
Exlll 6 years ago
parent b8caedc86d
commit 58b81f3314

@ -1,5 +1,5 @@
name: ConfigLib
author: Exlll
version: 2.0.3
version: 2.1.0
main: de.exlll.configlib.ConfigLib

@ -1,5 +1,5 @@
name: ConfigLib
author: Exlll
version: 2.0.3
version: 2.1.0
main: de.exlll.configlib.ConfigLib

@ -1,10 +1,13 @@
package de.exlll.configlib;
import de.exlll.configlib.filter.FieldFilter;
import de.exlll.configlib.filter.FieldFilters;
import de.exlll.configlib.format.FieldNameFormatter;
import de.exlll.configlib.format.FieldNameFormatters;
import java.io.IOException;
import java.util.*;
import java.util.Map;
import java.util.Objects;
/**
* Parent class of all configurations.
@ -103,6 +106,7 @@ public abstract class Configuration<C extends Configuration<C>> {
*/
protected static class Properties {
private final FieldNameFormatter formatter;
private final FieldFilter filter;
/**
* Constructs a new {@code Properties} object.
@ -112,6 +116,7 @@ public abstract class Configuration<C extends Configuration<C>> {
*/
protected Properties(Builder<?> builder) {
this.formatter = builder.formatter;
this.filter = builder.filter;
}
static Builder<?> builder() {
@ -132,6 +137,15 @@ public abstract class Configuration<C extends Configuration<C>> {
return formatter;
}
/**
* Returns the {@code FieldFilter} of a configuration
*
* @return {@code FieldFilter} of a configuration
*/
public final FieldFilter getFilter() {
return filter;
}
/**
* Builder classes are used for constructing {@code Properties}.
*
@ -139,6 +153,7 @@ public abstract class Configuration<C extends Configuration<C>> {
*/
protected static abstract class Builder<B extends Builder<B>> {
private FieldNameFormatter formatter = FieldNameFormatters.IDENTITY;
private FieldFilter filter = FieldFilters.DEFAULT;
protected Builder() {}
@ -154,13 +169,30 @@ public abstract class Configuration<C extends Configuration<C>> {
*
* @param formatter formatter for configuration
* @return this {@code Builder}
* @throws NullPointerException if {@code formatter ist null}
* @throws NullPointerException if {@code formatter} is null
*/
public final B setFormatter(FieldNameFormatter formatter) {
this.formatter = Objects.requireNonNull(formatter);
return getThis();
}
/**
* Composes the given {@link FieldFilter} with the
* {@code FieldFilters.DEFAULT} instance and any other
* previously added filters.
* <p>
* The added filter is not evaluated for a field if the field has
* already been filtered or by some other {@code FieldFilter}.
*
* @param filter field filter that is added
* @return this {@code Builder}
* @throws NullPointerException if {@code filter} is null
*/
public final B addFilter(FieldFilter filter) {
this.filter = this.filter.and(filter);
return getThis();
}
/**
* Builds a new {@code Properties} instance using the values set.
*

@ -1,18 +1,14 @@
package de.exlll.configlib;
import de.exlll.configlib.Converter.ConversionInfo;
import de.exlll.configlib.filter.FieldFilter;
import de.exlll.configlib.format.FieldNameFormatter;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;
import static de.exlll.configlib.Validator.*;
import static java.util.stream.Collectors.toList;
enum FieldMapper {
;
@ -21,7 +17,8 @@ enum FieldMapper {
Object inst, Configuration.Properties props
) {
Map<String, Object> map = new LinkedHashMap<>();
for (Field field : FieldFilter.filterFields(inst.getClass())) {
FieldFilter filter = props.getFilter();
for (Field field : filter.filterDeclaredFieldsOf(inst.getClass())) {
Object val = toConvertibleObject(field, inst, props);
FieldNameFormatter fnf = props.getFormatter();
String fn = fnf.fromFieldName(field.getName());
@ -45,7 +42,8 @@ enum FieldMapper {
Object inst, Map<String, Object> instMap,
Configuration.Properties props
) {
for (Field field : FieldFilter.filterFields(inst.getClass())) {
FieldFilter filter = props.getFilter();
for (Field field : filter.filterDeclaredFieldsOf(inst.getClass())) {
FieldNameFormatter fnf = props.getFormatter();
String fn = fnf.fromFieldName(field.getName());
Object mapValue = instMap.get(fn);
@ -79,27 +77,4 @@ enum FieldMapper {
Object val = Reflect.getValue(field, instance);
checkNotNull(val, field.getName());
}
enum FieldFilter implements Predicate<Field> {
DEFAULT;
static List<Field> filterFields(Class<?> cls) {
Field[] fields = cls.getDeclaredFields();
return Arrays.stream(fields)
.filter(DEFAULT)
.collect(toList());
}
@Override
public boolean test(Field field) {
if (field.isSynthetic()) {
return false;
}
int mods = field.getModifiers();
return !(Modifier.isFinal(mods) ||
Modifier.isStatic(mods) ||
Modifier.isTransient(mods));
}
}
}

@ -266,9 +266,9 @@ final class Validator {
}
}
static void checkConverterHasNoArgsConstructor(Class<?> convClass, String fn) {
if (!Reflect.hasNoArgConstructor(convClass)) {
String msg = "Converter '" + convClass.getSimpleName() + "' used " +
static void checkConverterHasNoArgsConstructor(Class<?> converterClass, String fn) {
if (!Reflect.hasNoArgConstructor(converterClass)) {
String msg = "Converter '" + converterClass.getSimpleName() + "' used " +
"on field '" + fn + "' doesn't have a no-args constructor.";
throw new ConfigurationException(msg);
}
@ -284,14 +284,6 @@ final class Validator {
}
}
static boolean isTypeMap(Map<?, ?> map) {
return map.entrySet().stream().allMatch(entry -> {
Class<?> keyCls = entry.getKey().getClass();
Class<?> valCls = entry.getValue().getClass();
return (String.class == keyCls) && Reflect.isSimpleType(valCls);
});
}
static void checkFieldTypeAssignableFrom(Class<?> type, ConversionInfo info) {
Class<?> fieldType = info.getFieldType();
if (!fieldType.isAssignableFrom(type)) {

@ -0,0 +1,26 @@
package de.exlll.configlib.filter;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.function.Predicate;
import static java.util.stream.Collectors.toList;
@FunctionalInterface
public interface FieldFilter extends Predicate<Field> {
@Override
default FieldFilter and(Predicate<? super Field> other) {
Objects.requireNonNull(other);
return (t) -> test(t) && other.test(t);
}
default List<? extends Field> filterDeclaredFieldsOf(Class<?> cls) {
Field[] fields = cls.getDeclaredFields();
return Arrays.stream(fields)
.filter(this)
.collect(toList());
}
}

@ -0,0 +1,20 @@
package de.exlll.configlib.filter;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public enum FieldFilters implements FieldFilter {
DEFAULT {
@Override
public boolean test(Field field) {
if (field.isSynthetic()) {
return false;
}
int mods = field.getModifiers();
return !(Modifier.isFinal(mods) ||
Modifier.isStatic(mods) ||
Modifier.isTransient(mods));
}
}
}

@ -3,8 +3,6 @@ package de.exlll.configlib;
import de.exlll.configlib.configs.mem.InSharedMemoryConfiguration;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
@ -14,7 +12,7 @@ class ConfigurationTest {
}
@Test
void configExecutesPreSaveHook() throws IOException {
void configExecutesPreSaveHook() {
class A extends TestHook {
int i = 0;
@ -31,7 +29,7 @@ class ConfigurationTest {
}
@Test
void configExecutesPostLoadHook() throws IOException {
void configExecutesPostLoadHook() {
class A extends TestHook {
int i = 0;

@ -4,7 +4,6 @@ import de.exlll.configlib.annotation.ConfigurationElement;
import java.util.Map;
import static de.exlll.configlib.Configuration.Properties;
import static de.exlll.configlib.configs.yaml.YamlConfiguration.YamlProperties.DEFAULT;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
@ -43,14 +42,6 @@ public class FieldMapperHelpers {
assertThat(ex.getMessage(), is(msg));
}
public static void assertItmCfgExceptionMessage(
Object o, Properties props, String msg
) {
ConfigurationException ex = assertItmThrowsCfgException(o, props);
assertThat(ex.getMessage(), is(msg));
}
public static void assertIfmCfgExceptionMessage(
Object o, Map<String, Object> map, String msg
) {
@ -58,13 +49,6 @@ public class FieldMapperHelpers {
assertThat(ex.getMessage(), is(msg));
}
public static void assertIfmCfgExceptionMessage(
Object o, Map<String, Object> map, Properties props, String msg
) {
ConfigurationException ex = assertIfmThrowsCfgException(o, map, props);
assertThat(ex.getMessage(), is(msg));
}
public static ConfigurationException assertItmThrowsCfgException(Object o) {
return assertThrows(
ConfigurationException.class,
@ -72,15 +56,6 @@ public class FieldMapperHelpers {
);
}
public static ConfigurationException assertItmThrowsCfgException(
Object o, Configuration.Properties props
) {
return assertThrows(
ConfigurationException.class,
() -> instanceToMap(o, props)
);
}
public static ConfigurationException assertIfmThrowsCfgException(
Object o, Map<String, Object> map
) {
@ -90,31 +65,23 @@ public class FieldMapperHelpers {
);
}
public static ConfigurationException assertIfmThrowsCfgException(
Object o, Map<String, Object> map, Configuration.Properties props
) {
return assertThrows(
ConfigurationException.class,
() -> instanceFromMap(o, map, props)
);
}
public static Map<String, Object> instanceToMap(Object o) {
return instanceToMap(o, DEFAULT);
}
public static Map<String, Object> instanceToMap(
Object o, Configuration.Properties props) {
Object o, Configuration.Properties props
) {
return FieldMapper.instanceToMap(o, props);
}
public static <T> T instanceFromMap(T o, Map<String, Object> map) {
FieldMapper.instanceFromMap(o, map, DEFAULT);
return o;
return instanceFromMap(o, map, DEFAULT);
}
public static <T> T instanceFromMap(
T o, Map<String, Object> map, Configuration.Properties props) {
T o, Map<String, Object> map, Configuration.Properties props
) {
FieldMapper.instanceFromMap(o, map, props);
return o;
}

@ -1,7 +1,6 @@
package de.exlll.configlib;
import de.exlll.configlib.Converter.ConversionInfo;
import de.exlll.configlib.FieldMapper.FieldFilter;
import de.exlll.configlib.annotation.ElementType;
import de.exlll.configlib.annotation.NoConvert;
import de.exlll.configlib.classes.TestClass;
@ -12,13 +11,11 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.function.Predicate;
import static de.exlll.configlib.Converters.ENUM_CONVERTER;
import static de.exlll.configlib.Converters.SIMPLE_TYPE_CONVERTER;
@ -32,9 +29,6 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
@SuppressWarnings({"unused", "ThrowableNotThrown"})
class FieldMapperTest {
private static final Class<ClassWithFinalStaticTransientField> CWFSTF =
ClassWithFinalStaticTransientField.class;
private static final Predicate<Field> filter = FieldFilter.DEFAULT;
private static final TestClass t = TestClass.TEST_VALUES;
private static final Configuration.Properties DEFAULT =
Configuration.Properties.builder().build();
@ -374,45 +368,6 @@ class FieldMapperTest {
assertThat(instanceToMap(new Object()), instanceOf(LinkedHashMap.class));
}
@Test
void filteredFieldsFiltersFields() throws NoSuchFieldException {
List<Field> fields = FieldFilter.filterFields(CWFSTF);
assertThat(fields.size(), is(0));
class A {
private int i;
private final int j = 0;
private transient int k;
}
fields = FieldFilter.filterFields(A.class);
assertThat(fields.size(), is(1));
assertThat(fields.get(0), is(A.class.getDeclaredField("i")));
}
@Test
void defaultFilterFiltersSyntheticFields() {
for (Field field : ClassWithSyntheticField.class.getDeclaredFields()) {
assertThat(field.isSynthetic(), is(true));
assertThat(filter.test(field), is(false));
}
}
@Test
void defaultFilterFiltersFinalStaticTransientFields()
throws NoSuchFieldException {
Field field = CWFSTF.getDeclaredField("i");
assertThat(Modifier.isFinal(field.getModifiers()), is(true));
assertThat(filter.test(field), is(false));
field = CWFSTF.getDeclaredField("j");
assertThat(Modifier.isStatic(field.getModifiers()), is(true));
assertThat(filter.test(field), is(false));
field = CWFSTF.getDeclaredField("k");
assertThat(Modifier.isTransient(field.getModifiers()), is(true));
assertThat(filter.test(field), is(false));
}
private static Converter<Object, Object> converter = SIMPLE_TYPE_CONVERTER;
private static ConversionInfo newInfo(String fieldName, Object o) {
@ -479,8 +434,8 @@ class FieldMapperTest {
for (String cls : classes) {
for (Number number : numbers) {
ConversionInfo info = newInfo(cls);
Object conv = converter.convertFrom(number, info);
assertThat(conv, instanceOf(info.getFieldType()));
Object converted = converter.convertFrom(number, info);
assertThat(converted, instanceOf(info.getFieldType()));
}
}
}
@ -521,11 +476,30 @@ class FieldMapperTest {
assertThat(a.ex, sameInstance(cls));
}
private static final class ClassWithFinalStaticTransientField {
private final int i = 0;
private static int j;
private transient int k;
@Test
void fieldMapperUsesFiltersAdded() {
class A {
private int a = 1;
private int b = 2;
private int c = 3;
private transient int d = 4;
private final int e = 5;
}
Configuration.Properties props = Configuration.Properties.builder()
.addFilter(field -> !field.getName().equals("a"))
.addFilter(field -> !field.getName().equals("c"))
.build();
Map<String, Object> map = instanceToMap(new A(), props);
assertThat(map.size(), is(1));
assertThat(map, is(mapOf("b", 2)));
map = mapOf("a", -1, "b", -2, "c", -3, "d", -4, "e", -5);
A a = instanceFromMap(new A(), map, props);
assertThat(a.a, is(1));
assertThat(a.b, is(-2));
assertThat(a.c, is(3));
assertThat(a.d, is(4));
assertThat(a.e, is(5));
}
private final class ClassWithSyntheticField {}
}

@ -1,6 +1,5 @@
package de.exlll.configlib;
import de.exlll.configlib.FieldMapperHelpers.*;
import de.exlll.configlib.annotation.ConfigurationElement;
import de.exlll.configlib.annotation.ElementType;
import de.exlll.configlib.classes.TestSubClass;

@ -0,0 +1,7 @@
package de.exlll.configlib.classes;
public final class ClassWithFinalStaticTransientField {
private final int i = 0;
private static int j;
private transient int k;
}

@ -99,34 +99,6 @@ public final class TestSubClass {
return string;
}
public List<String> getList() {
return list;
}
public Set<String> getSet() {
return set;
}
public Map<String, Integer> getMap() {
return map;
}
public TestSubSubClass getTestSubSubClass() {
return testSubSubClass;
}
public List<TestSubSubClass> getSubClassList() {
return subClassList;
}
public Set<TestSubSubClass> getSubClassSet() {
return subClassSet;
}
public Map<String, TestSubSubClass> getSubClassMap() {
return subClassMap;
}
@Override
public String toString() {
return "TestSubClass{" +

@ -46,26 +46,6 @@ public final class TestSubSubClass {
return asMap;
}
public int getPrimInt() {
return primInt;
}
public String getString() {
return string;
}
public List<String> getList() {
return list;
}
public Set<String> getSet() {
return set;
}
public Map<String, Integer> getMap() {
return map;
}
@Override
public String toString() {
return "TestSubSubClass{" +

@ -40,7 +40,7 @@ class YamlConfigurationTest {
}
@Test
void loadAndSaveExecutesPostLoadHook() throws IOException {
void loadAndSaveExecutesPostLoadHook() {
class A extends YamlConfiguration {
int i = 0;
@ -58,7 +58,7 @@ class YamlConfigurationTest {
}
@Test
void loadAndSaveSavesConfiguration() throws IOException {
void loadAndSaveSavesConfiguration() {
YamlConfiguration configuration = new TestClass(
configPath, TestClass.TEST_VALUES
);
@ -71,7 +71,7 @@ class YamlConfigurationTest {
}
@Test
void loadAndSaveLoadsConfiguration() throws IOException {
void loadAndSaveLoadsConfiguration() {
new TestClass(configPath, TestClass.TEST_VALUES).save();
YamlConfiguration configuration = new TestClass(configPath);
@ -81,7 +81,7 @@ class YamlConfigurationTest {
}
@Test
void loadLoadsConfig() throws IOException {
void loadLoadsConfig() {
setupConfigPath();
Configuration configuration = new TestClass(configPath);
assertThat(configuration, is(not(TestClass.TEST_VALUES)));
@ -89,7 +89,7 @@ class YamlConfigurationTest {
assertThat(configuration, is((TestClass.TEST_VALUES)));
}
private void setupConfigPath() throws IOException {
private void setupConfigPath() {
Configuration configuration = new TestClass(
configPath, TestClass.TEST_VALUES
);
@ -97,14 +97,14 @@ class YamlConfigurationTest {
}
@Test
void loadThrowsExceptionIfTypesDontMatch() throws IOException {
void loadThrowsExceptionIfTypesDoNotMatch() {
Configuration configuration = new TestClass(configPath);
configuration.save();
assertThrows(IllegalArgumentException.class, configuration::load);
}
@Test
void saveCreatesConfig() throws IOException {
void saveCreatesConfig() {
assertThat(Files.exists(testPath), is(false));
Configuration configuration = new TestClass(testPath);
configuration.save();

@ -0,0 +1,58 @@
package de.exlll.configlib.filter;
import de.exlll.configlib.classes.ClassWithFinalStaticTransientField;
import org.junit.jupiter.api.Test;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.List;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
class FieldFilterTest {
private static final FieldFilter filter = FieldFilters.DEFAULT;
private static final Class<ClassWithFinalStaticTransientField> CWFSTF =
ClassWithFinalStaticTransientField.class;
@Test
void filteredFieldsFiltersFields() throws NoSuchFieldException {
List<? extends Field> fields = filter.filterDeclaredFieldsOf(CWFSTF);
assertThat(fields.size(), is(0));
class A {
private int i;
private final int j = 0;
private transient int k;
}
fields = filter.filterDeclaredFieldsOf(A.class);
assertThat(fields.size(), is(1));
assertThat(fields.get(0), is(A.class.getDeclaredField("i")));
}
@Test
void defaultFilterFiltersSyntheticFields() {
for (Field field : ClassWithSyntheticField.class.getDeclaredFields()) {
assertThat(field.isSynthetic(), is(true));
assertThat(filter.test(field), is(false));
}
}
@Test
void defaultFilterFiltersFinalStaticTransientFields()
throws NoSuchFieldException {
Field field = CWFSTF.getDeclaredField("i");
assertThat(Modifier.isFinal(field.getModifiers()), is(true));
assertThat(filter.test(field), is(false));
field = CWFSTF.getDeclaredField("j");
assertThat(Modifier.isStatic(field.getModifiers()), is(true));
assertThat(filter.test(field), is(false));
field = CWFSTF.getDeclaredField("k");
assertThat(Modifier.isTransient(field.getModifiers()), is(true));
assertThat(filter.test(field), is(false));
}
private final class ClassWithSyntheticField {}
}

@ -46,6 +46,14 @@ public final class CollectionFactory {
return map;
}
public static <K, V> Map<K, V> mapOf(
K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5
) {
Map<K, V> map = mapOf(k1, v1, k2, v2, k3, v3, k4, v4);
map.put(k5, v5);
return map;
}
public static <K, V> Map.Entry<K, V> mapEntry(K k, V v) {
return new MapEntry<>(k, v);
}

@ -325,6 +325,24 @@ YamlProperties properties = YamlProperties.builder()
Note: Changing the configuration style may break adding comments using the `@Comment` annotation.
##### Adding field filters
If your configuration has a lot of fields and you want to exclude some of these fields without
making them final, static or transient, you can configure your properties object to use additional
`FieldFilter`s. A `FieldFilter` filters the fields of a configuration class by a specified criterion.
For example, if you only want to include fields whose names don't start with _ignore_, you would add
the following filter:
```java
YamlProperties properties = YamlProperties.builder()
.addFilter(field -> !field.getName().startsWith("ignore"))
// ...
.build();
```
Note: A filter is not evaluated for a field if the field has already been filtered or by some
other `FieldFilter`.
#### Adding custom converters
Any field can be converted using a custom converter. This can be useful if you don't like the default
conversion mechanism or if you have classes that cannot be annotated as `ConfigurationElement`s
@ -447,14 +465,14 @@ public final class DatabasePlugin extends JavaPlugin {
<dependency>
<groupId>de.exlll</groupId>
<artifactId>configlib-bukkit</artifactId>
<version>2.0.3</version>
<version>2.1.0</version>
</dependency>
<!-- for Bungee plugins -->
<dependency>
<groupId>de.exlll</groupId>
<artifactId>configlib-bungee</artifactId>
<version>2.0.3</version>
<version>2.1.0</version>
</dependency>
```
#### Gradle
@ -466,9 +484,9 @@ repositories {
}
dependencies {
// for Bukkit plugins
compile group: 'de.exlll', name: 'configlib-bukkit', version: '2.0.3'
compile group: 'de.exlll', name: 'configlib-bukkit', version: '2.1.0'
// for Bungee plugins
compile group: 'de.exlll', name: 'configlib-bungee', version: '2.0.3'
compile group: 'de.exlll', name: 'configlib-bungee', version: '2.1.0'
}
```

@ -1,6 +1,6 @@
allprojects {
group 'de.exlll'
version '2.0.3'
version '2.1.0'
}
subprojects {
apply plugin: 'java'

@ -1,5 +1,3 @@
## Tutorial
This tutorial is intended to show most of the features of this library, so let's say that
we want to create the following configuration file for some kind of game:
@ -220,9 +218,8 @@ public final class GameConfig extends BukkitYamlConfiguration {
}
```
`ConfigurationElement`s must have a no-args constructor which is to create
instances of a given element. If the no-args constructor is a valid constructor
for your program, it must initialize the fields to some non-`null` value.
`ConfigurationElement`s must have a no-args constructor which is used to create
instances of a given element.
#### 7. Add `usersByName`
@ -298,7 +295,7 @@ public final class GameConfig extends BukkitYamlConfiguration {
The `arenaHeight` can simply be represented by an `int` field. The `arenaCenter`
is of type `Location`. We could again use the `@NoConvert` annotation but this
would result in a different representation. Instead, we are going to implement our
`Converter`.
own `Converter`.
First we have to create a class that implements `Converter<Location, String>`:
@ -351,8 +348,8 @@ public final class GameConfig extends BukkitYamlConfiguration {
Before we can use our new configuration, we have to instantiate it by passing
a `Path` and a `BukkitYamlProperties` object to its constructor. In this case
the `BukkitYamlProperties` is used to change the formatting and to append
additional text to the created configuration file.
the `BukkitYamlProperties` is used to change the formatting of field names,
to append text to the configuration file and to add an additional field filter.
```java
public final class GamePlugin extends JavaPlugin {
@ -362,12 +359,12 @@ public final class GamePlugin extends JavaPlugin {
Path configPath = new File(getDataFolder(), "config.yml").toPath();
BukkitYamlProperties properties = BukkitYamlProperties.builder()
.addFilter(field -> !field.getName().startsWith("ignore"))
.setFormatter(FieldNameFormatters.LOWER_UNDERSCORE)
.setAppendedComments(Arrays.asList(
"", "Remember to play fair!"
))
.build();
GameConfig config = new GameConfig(configPath, properties);
config.loadAndSave();
}
@ -403,6 +400,7 @@ public final class GamePlugin extends JavaPlugin {
Path configPath = new File(getDataFolder(), "config.yml").toPath();
BukkitYamlProperties properties = BukkitYamlProperties.builder()
.addFilter(field -> !field.getName().startsWith("ignore"))
.setFormatter(FieldNameFormatters.LOWER_UNDERSCORE)
.setAppendedComments(Arrays.asList(
"", "Remember to play fair!"
@ -442,6 +440,8 @@ final class GameConfig extends BukkitYamlConfiguration {
private Location arenaCenter = new Location(
Bukkit.getWorld("world"), 0, 128, 0
);
private String ignoreMe = "1";
private String ignoreMeToo = "2";
public GameConfig(Path path, BukkitYamlProperties properties) {
super(path, properties);
@ -503,6 +503,14 @@ final class User {
this.credentials = new Credentials(username, password);
this.email = email;
}
public Credentials getCredentials() {
return credentials;
}
public String getEmail() {
return email;
}
}
@ConfigurationElement
@ -517,5 +525,13 @@ final class Credentials {
this.username = username;
this.password = password;
}
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
}
```
Loading…
Cancel
Save