001package com.mrivanplays.annotationconfig.core.resolver.settings; 002 003import com.mrivanplays.annotationconfig.core.resolver.ConfigResolver; 004import java.util.HashMap; 005import java.util.Map; 006import java.util.Optional; 007 008/** 009 * Represents load settings. They are used upon annotated config load. 010 * 011 * @author MrIvanPlays 012 * @since 2.0.0 013 */ 014public final class LoadSettings { 015 016 /** 017 * Creates a new empty {@link LoadSettings.Builder} 018 * 019 * @return empty builder instance 020 */ 021 public static LoadSettings.Builder newBuilder() { 022 return newBuilder(false); 023 } 024 025 /** 026 * Creates a new {@link LoadSettings.Builder} 027 * 028 * @param fromDefaults whether to instantiate load settings from {@link LoadSettings#getDefault()} 029 * @return builder instance 030 */ 031 public static LoadSettings.Builder newBuilder(boolean fromDefaults) { 032 return new LoadSettings.Builder(fromDefaults); 033 } 034 035 /** 036 * Creates new empty load settings. If used unmodified on a {@link ConfigResolver}, the config 037 * resolver will fall back to the default settings (a.ka {@link LoadSettings#getDefault()}). 038 * 039 * @return empty load settings 040 */ 041 public static LoadSettings empty() { 042 return new LoadSettings(); 043 } 044 045 private static LoadSettings def; 046 047 /** 048 * Returns the default load settings. 049 * 050 * @return defaults 051 */ 052 public static LoadSettings getDefault() { 053 if (def == null) { 054 def = initializeDefaultSettings(); 055 } 056 return def; 057 } 058 059 private static LoadSettings initializeDefaultSettings() { 060 LoadSettings settings = new LoadSettings(); 061 settings.set(LoadSetting.GENERATE_NEW_OPTIONS, true); 062 settings.set(LoadSetting.NULL_READ_HANDLER, NullReadHandleOption.SET_NULL); 063 return settings; 064 } 065 066 private Map<String, Object> settings; 067 068 private LoadSettings() { 069 this.settings = new HashMap<>(); 070 } 071 072 private LoadSettings(Map<String, Object> settings) { 073 this.settings = settings; 074 } 075 076 /** 077 * Returns the value held for the specified {@link LoadSetting} {@code setting} 078 * 079 * @param setting the load setting you want the value for 080 * @param <T> value type 081 * @return load setting value optional, which can be empty 082 */ 083 public <T> Optional<T> get(LoadSetting<T> setting) { 084 Object val = settings.get(setting.getKey()); 085 if (val == null || !setting.getType().isAssignableFrom(val.getClass())) { 086 return Optional.empty(); 087 } 088 return Optional.of(setting.getType().cast(val)); 089 } 090 091 /** 092 * Binds the specified {@code value} to the specified {@link LoadSetting} {@code setting}. If the 093 * load setting already has a value, it gets replaced. 094 * 095 * @param setting the load setting you want the value to be bound to 096 * @param value the value you want bound 097 * @param <T> value type 098 */ 099 public <T> void set(LoadSetting<T> setting, T value) { 100 if (settings.containsKey(setting.getKey())) { 101 settings.replace(setting.getKey(), value); 102 } else { 103 settings.put(setting.getKey(), value); 104 } 105 } 106 107 /** 108 * Creates a copy of the current load settings 109 * 110 * @return copy 111 */ 112 public LoadSettings copy() { 113 return new LoadSettings(this.settings); 114 } 115 116 /** 117 * Represents a builder for {@link LoadSettings} 118 * 119 * @author MrIvanPlays 120 * @since 2.0.0 121 */ 122 public static final class Builder { 123 124 private final LoadSettings loadSettings; 125 126 public Builder(boolean fromDefaults) { 127 if (fromDefaults) { 128 loadSettings = LoadSettings.getDefault().copy(); 129 } else { 130 loadSettings = LoadSettings.empty(); 131 } 132 } 133 134 private Builder(Builder other) { 135 this.loadSettings = other.loadSettings; 136 } 137 138 /** 139 * Creates a copy of the current builder. 140 * 141 * @return copy 142 */ 143 public Builder copy() { 144 return new Builder(this); 145 } 146 147 /** 148 * Binds the specified {@code value} to the specified {@link LoadSetting} {@code setting}. 149 * 150 * @param setting the setting you want the value to be bound to 151 * @param value the value you want bound 152 * @param <T> value type 153 * @return this instance for chaining 154 */ 155 public <T> Builder withSetting(LoadSetting<T> setting, T value) { 156 loadSettings.set(setting, value); 157 return this; 158 } 159 160 /** 161 * Builds this builder into {@link LoadSettings} 162 * 163 * @return load settings 164 */ 165 public LoadSettings build() { 166 return loadSettings; 167 } 168 } 169}