GithubHelp home page GithubHelp logo

annotationconfig's Introduction

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>

annotationconfig's People

Contributors

dependabot[bot] avatar mrivanplays avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

Forkers

adabugra

annotationconfig's Issues

Manual load/dump

Allow user to manually load or dump object data instead of using loadOrDump

Maven dependency for yaml module has a misstype

Hi, I was trying to add a maven dependency for the yaml module, but maven didn't want to resolve the dependency for some reason.

After some investigation, I noticed, that the actual dependency artifactId is called annotationconfg-yaml instead of annotationconfig-yaml (missing 'i' in "config")
Would be nice to fix :D

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.