Make configurations with ease
JavaDocs: https://jd.mrivanplays.com/annotationconfig/
WARNING: You may want to read CHANGELOG.md before seeing anything from this section.
Config example
import com.mrivanplays.annotationconfig.core.annotations.ConfigObject;
import com.mrivanplays.annotationconfig.core.annotations.Ignore;
import com.mrivanplays.annotationconfig.core.annotations.Key;
import com.mrivanplays.annotationconfig.core.annotations.Max;
import com.mrivanplays.annotationconfig.core.annotations.Min;
import com.mrivanplays.annotationconfig.core.annotations.comment.Comment;
import com.mrivanplays.annotationconfig.core.serialization.DataObject;
import com.mrivanplays.annotationconfig.core.serialization.FieldTypeSerializer;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@Comment("Generated by AnnotatedConfig v2.1.0")
@Comment("This is a config example for developers.")
public class ExampleAnnotatedConfig {
@Comment("This value can only be between 1 and 3 ( 1 and 3 included )")
@Min(minInt = 1)
@Max(maxInt = 3)
private int foo = 2;
@Comment("This string cannot be longer than 20 characters ( spaces are included )")
@Max(maxInt = 20)
private String bar = "This is some string";
@ConfigObject private MessagesSection messages = new MessagesSection();
@Comment("All configurable messages")
public static final class MessagesSection {
@Comment("The no permission message")
@Key("no-permission")
private String noPermission = "You don't have permission to perform this command";
@Comment("The no spamming message")
@Key("no-spamming")
private String noSpamming = "You can't spam this";
public String getNoPermission() {
return noPermission;
}
public String getNoSpamming() {
return noSpamming;
}
}
@Ignore private String importantClass = "com.mrivanplays.something.Important"; // this is ignored
@Comment("This is also going to be serialized as a config object,")
@Comment("but it is much more controllable rather than @ConfigObject")
private SomethingToSerialize serialize = new SomethingToSerialize("foo", 1, (byte) 0x2);
public static final class SomethingToSerialize {
private final String foo;
private final int bar;
private final byte baz;
public SomethingToSerialize(String foo, int bar, byte baz) {
this.foo = foo;
this.bar = bar;
this.baz = baz;
}
public String getFoo() {
return foo;
}
public int getBar() {
return bar;
}
public byte getBaz() {
return baz;
}
}
/**
* This should be registered before calling the dump method for this annotated config using the
* SerializerRegistry
*/
public static final class SomethingToSerializeSerializer
implements FieldTypeSerializer<SomethingToSerialize> {
@Override
public SomethingToSerialize deserialize(DataObject data, Field field) {
return new SomethingToSerialize(
data.get("foo").getAsString(), data.get("bar").getAsInt(), data.get("baz").getAsByte());
}
@Override
public DataObject serialize(SomethingToSerialize value, Field field) {
DataObject ret = new DataObject();
ret.put("foo", value.getFoo());
ret.put("bar", value.getBar());
ret.put("baz", value.getBaz());
return ret;
}
}
@Comment("This cannot have a negative value")
@Min(minDouble = 0)
@Key("barxtwo") // you can also apply @Key to regular fields, not just in config objects
private double baz = 0.2;
@Comment("AnnotatedConfig can also read & write lists")
@Key("foo-list")
private List<String> fooList = Arrays.asList("This is", "a lore", "as an example", "for list");
@Comment("Lists can be of all primitive types")
@Key("bar-list")
private List<Integer> barList = Arrays.asList(1, 2, 3, 4);
@Comment("Same for maps, but a map can only be Map<String, Object>")
@Comment("otherwise you will need another object")
@Key("foo-map")
private Map<String, Object> fooMap =
new LinkedHashMap<String, Object>() {
{
put("foo", 1);
put("bar", "This is a section value");
put("baz", 3);
}
};
@Comment("This doesn't have a serializer registered")
@Comment("so it gets serialized by the default serializer")
@Key("default-serializer-example")
private DefaultSerializationExample defaultSerExample =
new DefaultSerializationExample("bar", 1, 5.6);
public static final class DefaultSerializationExample {
private String foo;
private int bar;
private double baz;
public DefaultSerializationExample(String foo, int bar, double baz) {
this.foo = foo;
this.bar = bar;
this.baz = baz;
}
public String getFoo() {
return foo;
}
public int getBar() {
return bar;
}
public double getBaz() {
return baz;
}
}
@Comment("You can create sections like this too")
@Key("inside.section.foo")
private String fooInsideSection = "foo";
@ConfigObject
@Key("section-inside-section")
private SectionInsideSection insideSection = new SectionInsideSection();
@Comment("This is a section inside a section example")
public static class SectionInsideSection {
@Comment("Comments are supported here too!")
@Key("pp.baz")
private int baz = 69420;
@Comment("And here!")
@Key("pp.foo")
private double foo = 3.3;
public int getBaz() {
return baz;
}
public double getFoo() {
return foo;
}
}
// this is featured in the next example
public static class SectionObject {
private int aabb;
private String ccdd;
public SectionObject(int aabb, String ccdd) {
this.aabb = aabb;
this.ccdd = ccdd;
}
public int getAabb() {
return aabb;
}
public String getCcdd() {
return ccdd;
}
}
@Comment("This is a section object list")
private SectionObjectList<SectionObject> sectionObjectList =
SectionObjectList.newBuilderForType(SectionObject.class)
.defaultValue("asdfp", new SectionObject(1, "lorem"))
.defaultValue("pepepepepe", new SectionObject(2, "ipsum"))
.build();
public int getFoo() {
return foo;
}
public String getBar() {
return bar;
}
public MessagesSection getMessages() {
return messages;
}
public String getImportantClass() {
return importantClass;
}
public SomethingToSerialize getSerialize() {
return serialize;
}
public double getBaz() {
return baz;
}
public List<String> getFooList() {
return fooList;
}
public List<Integer> getBarList() {
return barList;
}
public Map<String, Object> getFooMap() {
return fooMap;
}
public DefaultSerializationExample getDefaultSerExample() {
return defaultSerExample;
}
public String getFooInsideSection() {
return fooInsideSection;
}
public SectionInsideSection getInsideSection() {
return insideSection;
}
public SectionObjectList<SectionObject> getSectionObjectList() {
return sectionObjectList;
}
}
Config example output (YAML)
Keep in mind in order to show you all of the features of AnnotatedConfig, everything has been stuffed in 1 class. Don't forget that in Java you can do multiple classes ;) . Line count doesn't matter.
# Generated by AnnotatedConfig v2.1.0
# This is a config example for developers.
# This cannot have a negative value
barxtwo: 0.2
# This is a section object list
sectionObjectList:
asdfp:
aabb: 1
ccdd: "lorem"
pepepepepe:
aabb: 2
ccdd: "ipsum"
# This is also going to be serialized as a config object,
# but it is much more controllable rather than @ConfigObject
serialize:
foo: "foo"
bar: 1
baz: 2
# This string cannot be longer than 20 characters ( spaces are included )
bar: "This is some string"
# Same for maps, but a map can only be Map<String, Object>
# otherwise you will need another object
foo-map:
foo: 1
bar: "This is a section value"
baz: 3
# This value can only be between 1 and 3 ( 1 and 3 included )
foo: 2
# AnnotatedConfig can also read & write lists
foo-list:
- "This is"
- "a lore"
- "as an example"
- "for list"
# All configurable messages
messages:
# The no spamming message
no-spamming: "You can't spam this"
# The no permission message
no-permission: "You don't have permission to perform this command"
# This doesn't have a serializer registered
# so it gets serialized by the default serializer
default-serializer-example:
foo: "bar"
bar: 1
baz: 5.6
# This is a section inside a section example
section-inside-section:
pp:
# Comments are supported here too!
baz: 69420
# And here!
foo: 3.3
# Lists can be of all primitive types
bar-list:
- 1
- 2
- 3
- 4
inside:
section:
# You can create sections like this too
foo: "foo"
Config dump/load
Keep in mind these are the simplest examples
Base code for all examples:
import com.mrivanplays.annotationconfig.utils.TypeToken;
File file = // ...
SerializerRegistry serializerRegistry = SerializerRegistry.INSTANCE;
serializerRegistry.registerSerializer(
ExampleAnnotatedConfig.SomethingToSerialize.class,
new ExampleAnnotatedConfig.SomethingToSerializeSerializer());
serializerRegistry.registerSerializer(
new TypeToken<SectionObjectList<SectionObject>>() {}.getType(),
new SectionObjectListSerializer<SectionObject>());
ExampleAnnotatedConfig annotatedConfig = new ExampleAnnotatedConfig();
YAML example:
YamlConfig.getConfigResolver().loadOrDump(anotatedConfig, file, /* loader settings */);
.conf/.properties example:
PropertyConfig.getConfigResolver().loadOrDump(annotatedConfig, file, /* loader settings */);
TOML example:
TomlConfig.getConfigResolver().loadOrDump(annotatedConfig, file, /* loader settings */);
Custom config type example:
// all values specified in the builder should be for the specific config type
ConfigResolver configResolver = ConfigResolver.newBuilder()
/* other options inside the builder */
.withCommentPrefix("# ") // comment prefix for the config type
.withValueWriter(() -> /* insert value writer here */)
.withValueReader(/* insert value reader here */)
.shouldReverseFields(true /* should we reverse fields */)
.build();
configResolver.loadOrDump(annotatedConfig, file, /* loader settings */);
Maven:
<build>
<plugins>
<plugin>
<version>3.7.0</version>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<compilerArgs>
<arg>-parameters</arg>
</compilerArgs>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.1.1</version>
<configuration>
<relocations>
<!-- Relocating is only necessary if you're shading for other library addition -->
<relocation>
<pattern>com.mrivanplays.annotationconfig</pattern>
<shadedPattern>[YOUR PLUGIN PACKAGE].annotationconfig
</shadedPattern> <!-- Replace this -->
</relocation>
</relocations>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>ivan</id>
<url>https://repo.mrivanplays.com/repository/ivan/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>com.mrivanplays</groupId>
<!-- Types: toml, yaml -->
<!-- If you want .conf/.properties, or custom implementation configuration, you can set the type to core -->
<artifactId>annotationconfig-(type)</artifactId> <!-- Replace type -->
<version>VERSION</version> <!-- Replace with latest version -->
<scope>compile</scope>
</dependency>
</dependencies>