001package com.mrivanplays.annotationconfig.toml;
002
003import com.moandjiezana.toml.Toml;
004import com.moandjiezana.toml.TomlWriter;
005import com.mrivanplays.annotationconfig.core.AnnotationType;
006import com.mrivanplays.annotationconfig.core.CustomAnnotationRegistry;
007import com.mrivanplays.annotationconfig.core.internal.AnnotatedConfigResolver;
008import com.mrivanplays.annotationconfig.core.internal.AnnotationHolder;
009import java.io.File;
010import java.io.IOException;
011import java.io.PrintWriter;
012import java.util.Collections;
013import java.util.List;
014import java.util.Map;
015
016/** Represents configuration, utilising TOML. */
017public final class TomlConfig {
018
019  private static CustomAnnotationRegistry annotationRegistry = new CustomAnnotationRegistry();
020
021  private static final TomlWriter DEFAULT_TOML_WRITER = new TomlWriter();
022
023  /**
024   * Returns the {@link CustomAnnotationRegistry} for this config.
025   *
026   * @return custom annotation registry
027   */
028  public static CustomAnnotationRegistry getAnnotationRegistry() {
029    return annotationRegistry;
030  }
031
032  /**
033   * Loads the config object from the file. If the file does not exist, it creates one.
034   *
035   * @param annotatedConfig annotated config
036   * @param file file
037   */
038  public static void load(Object annotatedConfig, File file) {
039    load(annotatedConfig, file, DEFAULT_TOML_WRITER);
040  }
041
042  /**
043   * Loads the config object from the file. If the file does not exist, it creates one.
044   *
045   * @param annotatedConfig annotated config
046   * @param file file
047   * @param tomlWriter toml writer
048   */
049  public static void load(Object annotatedConfig, File file, TomlWriter tomlWriter) {
050    List<Map.Entry<AnnotationHolder, List<AnnotationType>>> map =
051        AnnotatedConfigResolver.resolveAnnotations(annotatedConfig, annotationRegistry, true);
052    AnnotatedConfigResolver.ValueWriter valueWriter = new TomlValueWriter(tomlWriter);
053    if (!file.exists()) {
054      AnnotatedConfigResolver.dump(
055          annotatedConfig,
056          map,
057          file,
058          "# ",
059          valueWriter,
060          annotationRegistry,
061          TomlConfig.class,
062          true);
063    }
064
065    Toml toml = new Toml().read(file);
066    AnnotatedConfigResolver.setFields(
067        annotatedConfig,
068        toml.toMap(),
069        map,
070        annotationRegistry,
071        "# ",
072        valueWriter,
073        file,
074        false,
075        true,
076        TomlConfig.class);
077  }
078
079  private static final class TomlValueWriter implements AnnotatedConfigResolver.ValueWriter {
080
081    private TomlWriter tomlWriter;
082
083    TomlValueWriter(TomlWriter tomlWriter) {
084      this.tomlWriter = tomlWriter;
085    }
086
087    @Override
088    public void write(String key, Object value, PrintWriter writer) throws IOException {
089      tomlWriter.write(Collections.singletonMap(key, value), writer);
090      writer.append('\n');
091    }
092
093    @Override
094    public void writeCustom(Object value, PrintWriter writer, String annoName) throws IOException {
095      if (value instanceof Map) {
096        tomlWriter.write(value, writer);
097        writer.append('\n');
098        return;
099      }
100      if (value instanceof String && ((String) value).indexOf('=') != -1) {
101        String valueString = (String) value;
102        String[] arr = valueString.split("=");
103        tomlWriter.write(Collections.singletonMap(arr[0], arr[1]), writer);
104        writer.append('\n');
105        return;
106      }
107      throw new IllegalArgumentException(
108          "Invalid syntax for toml custom write: annotation '"
109              + annoName
110              + "'; written must be either a map or string in format key=value");
111    }
112  }
113}