001package com.mrivanplays.annotationconfig.yaml; 002 003import com.mrivanplays.annotationconfig.core.AnnotationType; 004import com.mrivanplays.annotationconfig.core.CustomAnnotationRegistry; 005import com.mrivanplays.annotationconfig.core.internal.AnnotatedConfigResolver; 006import com.mrivanplays.annotationconfig.core.internal.AnnotationHolder; 007import java.io.File; 008import java.io.FileReader; 009import java.io.IOException; 010import java.io.PrintWriter; 011import java.io.Reader; 012import java.util.LinkedHashMap; 013import java.util.List; 014import java.util.Map; 015import org.yaml.snakeyaml.Yaml; 016 017/** Represents configuration, utilising YAML */ 018public final class YamlConfig { 019 020 private static CustomAnnotationRegistry annotationRegistry = new CustomAnnotationRegistry(); 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 private static final Yaml YAML = new Yaml(); 032 private static final AnnotatedConfigResolver.ValueWriter VALUE_WRITER = new YamlValueWriter(); 033 034 /** 035 * Loads the config object from the file. If the file does not exist, it creates one. 036 * 037 * @param annotatedConfig annotated config 038 * @param file file 039 */ 040 public static void load(Object annotatedConfig, File file) { 041 List<Map.Entry<AnnotationHolder, List<AnnotationType>>> map = 042 AnnotatedConfigResolver.resolveAnnotations(annotatedConfig, annotationRegistry, true); 043 if (!file.exists()) { 044 AnnotatedConfigResolver.dump( 045 annotatedConfig, 046 map, 047 file, 048 "# ", 049 VALUE_WRITER, 050 annotationRegistry, 051 YamlConfig.class, 052 true); 053 } 054 055 try (Reader reader = new FileReader(file)) { 056 Map<String, Object> values = YAML.loadAs(reader, LinkedHashMap.class); 057 if (values == null) { 058 return; 059 } 060 AnnotatedConfigResolver.setFields( 061 annotatedConfig, 062 values, 063 map, 064 annotationRegistry, 065 "# ", 066 VALUE_WRITER, 067 file, 068 true, 069 true, 070 YamlConfig.class); 071 } catch (IOException e) { 072 throw new RuntimeException(e); 073 } 074 } 075 076 private static final class YamlValueWriter implements AnnotatedConfigResolver.ValueWriter { 077 078 @Override 079 public void write(String key, Object value, PrintWriter writer) { 080 write(key, value, writer, 2); 081 } 082 083 private void write(String key, Object value, PrintWriter writer, int childIndents) { 084 StringBuilder intentPrefixBuilder = new StringBuilder(); 085 for (int i = 0; i < childIndents; i++) { 086 intentPrefixBuilder.append(" "); 087 } 088 String intentPrefix = intentPrefixBuilder.toString(); 089 if (value instanceof Map<?, ?>) { 090 writer.println(key + ":"); 091 for (Map.Entry<String, Object> entry : ((Map<String, Object>) value).entrySet()) { 092 String mapKey = entry.getKey(); 093 Object v = entry.getValue(); 094 if (v instanceof List<?>) { 095 for (Object b : (List<?>) v) { 096 writer.println(intentPrefix + " - " + b); 097 } 098 } else if (v instanceof Map<?, ?>) { 099 write(mapKey, v, writer, childIndents + 2); 100 } else { 101 writer.println(intentPrefix + mapKey + ": " + v); 102 } 103 } 104 } else if (value instanceof List<?>) { 105 writer.println(key + ":"); 106 for (Object b : (List<?>) value) { 107 writer.println(intentPrefix + "- " + b); 108 } 109 } else { 110 writer.println(key + ": " + value); 111 } 112 writer.append('\n'); 113 } 114 115 @Override 116 public void writeCustom(Object value, PrintWriter writer, String annoName) { 117 if (!(value instanceof String) 118 && !(value instanceof Character) 119 && !(value instanceof char[])) { 120 throw new IllegalArgumentException( 121 "Cannot write other than String, char and char[] for yaml config: annotation '" 122 + annoName 123 + "'"); 124 } 125 writer.write(String.valueOf(value)); 126 } 127 } 128}