001package com.mrivanplays.annotationconfig.core;
002
003import com.mrivanplays.annotationconfig.core.internal.AnnotatedConfigResolver;
004import com.mrivanplays.annotationconfig.core.internal.AnnotationHolder;
005import java.io.File;
006import java.io.FileReader;
007import java.io.IOException;
008import java.io.PrintWriter;
009import java.io.Reader;
010import java.util.HashMap;
011import java.util.List;
012import java.util.Map;
013import java.util.Properties;
014
015/** Represents configuration, utilising .conf/.properties configuration type. */
016public final class PropertyConfig {
017
018  private static CustomAnnotationRegistry annotationRegistry = new CustomAnnotationRegistry();
019
020  private static final AnnotatedConfigResolver.ValueWriter VALUE_WRITER = new PropertyValueWriter();
021
022  /**
023   * Returns the {@link CustomAnnotationRegistry} for this config.
024   *
025   * @return custom annotation registry
026   */
027  public static CustomAnnotationRegistry getAnnotationRegistry() {
028    return annotationRegistry;
029  }
030
031  /**
032   * Loads the config object from the file. If the file does not exist, it creates one.
033   *
034   * @param annotatedConfig annotated config
035   * @param file file
036   */
037  public static void load(Object annotatedConfig, File file) {
038    List<Map.Entry<AnnotationHolder, List<AnnotationType>>> map =
039        AnnotatedConfigResolver.resolveAnnotations(annotatedConfig, annotationRegistry, false);
040    if (!file.exists()) {
041      AnnotatedConfigResolver.dump(
042          annotatedConfig,
043          map,
044          file,
045          "# ",
046          VALUE_WRITER,
047          annotationRegistry,
048          PropertyConfig.class,
049          false);
050    }
051    Properties properties = new Properties();
052    try (Reader reader = new FileReader(file)) {
053      properties.load(reader);
054    } catch (IOException e) {
055      throw new RuntimeException(e);
056    }
057    Map<String, Object> toMap = new HashMap<>();
058    for (Object key : properties.keySet()) {
059      toMap.put(String.valueOf(key), properties.get(key));
060    }
061    AnnotatedConfigResolver.setFields(
062        annotatedConfig,
063        toMap,
064        map,
065        annotationRegistry,
066        "# ",
067        VALUE_WRITER,
068        file,
069        true,
070        false,
071        PropertyConfig.class);
072  }
073
074  private static final class PropertyValueWriter implements AnnotatedConfigResolver.ValueWriter {
075
076    @Override
077    public void write(String key, Object value, PrintWriter writer) {
078      if (value instanceof Map<?, ?>) {
079        for (Map.Entry<?, ?> entry : ((Map<?, ?>) value).entrySet()) {
080          if (entry.getKey() instanceof String) {
081            write(key, entry.getValue(), writer);
082          }
083        }
084      }
085      writer.println(key + "=" + value.toString());
086      writer.append('\n');
087    }
088
089    @Override
090    public void writeCustom(Object value, PrintWriter writer, String annoName) {
091      if (!(value instanceof String)
092          && !(value instanceof Character)
093          && !(value instanceof char[])) {
094        throw new IllegalArgumentException(
095            "Cannot write other than String, char and char[] for .properties/.conf config: annotation '"
096                + annoName
097                + "'");
098      }
099      writer.write(String.valueOf(value));
100    }
101  }
102}