Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

100 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

license issues api version support

AnnotationConfig

Make configurations with ease

JavaDocs: https://jd.mrivanplays.com/annotationconfig/

Examples

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 */);

Installation

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>

About

Make configurations with ease

Resources

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors

Languages