Skip to content

Commit

Permalink
@AutoStaticConfig - auto-loading feature for YamlStaticConfig
Browse files Browse the repository at this point in the history
  • Loading branch information
Rubix327 committed Oct 28, 2022
1 parent dd5c031 commit 6994e96
Show file tree
Hide file tree
Showing 9 changed files with 204 additions and 51 deletions.
51 changes: 38 additions & 13 deletions src/main/java/org/mineacademy/fo/ChatUtil.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
package org.mineacademy.fo;

import java.awt.Color;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.bukkit.ChatColor;
import org.mineacademy.fo.MinecraftVersion.V;
import org.mineacademy.fo.model.Whiteblacklist;
import org.mineacademy.fo.plugin.SimplePlugin;
import org.mineacademy.fo.remain.CompChatColor;

import java.awt.*;
import java.text.Normalizer;
import java.util.ArrayList;
import java.util.Arrays;
Expand All @@ -9,15 +17,6 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.bukkit.ChatColor;
import org.mineacademy.fo.MinecraftVersion.V;
import org.mineacademy.fo.model.Whiteblacklist;
import org.mineacademy.fo.plugin.SimplePlugin;
import org.mineacademy.fo.remain.CompChatColor;

import lombok.AccessLevel;
import lombok.NoArgsConstructor;

/**
* Utility class for managing in-game chat.
*/
Expand Down Expand Up @@ -225,8 +224,7 @@ public static String capitalizeFirst(final String message) {
* capitalizeFully("") = ""
* capitalizeFully("i am FINE") = "I Am Fine"
* </pre>
*
* @param message the String to capitalize, may be null
* @return capitalized String, <code>null</code> if null String input
*/
public static String capitalizeFully(String str) {
Expand Down Expand Up @@ -262,7 +260,6 @@ private static String capitalizeFully(String str, char[] delimiters) {
* </pre>
*
* @author Apache Commons - WordUtils
* @param message the String to capitalize, may be null
* @return capitalized String, <code>null</code> if null String input
*/
public static String capitalize(String str) {
Expand Down Expand Up @@ -299,6 +296,34 @@ private static String capitalize(String str, char[] delimiters) {
return str;
}

/**
* Converts UPPER_UNDERSCORE string to Capital_Underscore
*/
public static String upperToCapitalUnderscore(String s){
char[] array = s.toLowerCase().toCharArray();
StringBuilder sb = new StringBuilder();
boolean capitalizeNext = false;
char next;

sb.append(Character.toUpperCase(array[0]));
for (int i = 1; i < array.length; i++){
if (array[i] == '_'){
capitalizeNext = true;
next = array[i];
} else {
if (capitalizeNext){
next = Character.toUpperCase(array[i]);
capitalizeNext = false;
}
else{
next = array[i];
}
}
sb.append(next);
}
return sb.toString();
}

private static boolean isDelimiter(char ch, char[] delimiters) {
if (delimiters == null)
return Character.isWhitespace(ch);
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/org/mineacademy/fo/annotation/AutoConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
import java.lang.annotation.Target;

/**
* This annotation automatically saves and loads fields between a file and a YamlConfig.<br><br>
* This annotation automatically saves and loads fields between a file and your custom
* class extending {@link org.mineacademy.fo.settings.YamlConfig}.<br><br>
* <b>On class</b>:
* <ul>
* <li>Saves and loads all non-static class fields</li>
Expand Down
46 changes: 46 additions & 0 deletions src/main/java/org/mineacademy/fo/annotation/AutoStaticConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package org.mineacademy.fo.annotation;

import com.google.common.base.CaseFormat;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* This annotation automatically saves and loads fields between a file and your custom
* class extending {@link org.mineacademy.fo.settings.YamlStaticConfig}.<br><br>
* <b>On class</b>:
* <ul>
* <li>Saves and loads all static class fields</li>
* <li>But skips fields that have disabled this feature by <i>@AutoStaticConfig(false)</i></li>
* </ul>
* When using on class, if you want to prevent one specific field from auto-loading and auto-saving,
* use <i>@AutoStaticConfig(false)</i> on that field.<br><br>
*
* This annotation only works if is set above class. But you can disable fields separately.<br><br>
*
* <b>About Format:</b><br>
* <ul>
* <li>By default, format of fields is Capital_Underscore which corresponds to Foundation naming convention.</li>
* <li>You can change format to your desired, but system fields (Version, Locale, etc.) will stay the same.</li>
* </ul>
*/
@Target({ElementType.TYPE, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoStaticConfig {

/**
* When false, automatic loading and saving does not work for class or field above which is set.
*/
boolean value() default true;

/**
* In what format should we convert your fields to the file.<br>
* Only usable if set on class. You can only set one format for one class.<br>
* System fields (Version, Locale, etc.) will stay the same regardless of this value.<br>
* Default: Capital_Underscore.
*/
CaseFormat[] format() default {};

}
Original file line number Diff line number Diff line change
Expand Up @@ -198,13 +198,16 @@ else if (name.matches("localization\\/messages\\_(.*)\\.yml"))
final List<Class<?>> delayedLoading = new ArrayList<>();

for (final Class<?> customSettings : staticCustom)
if (SimpleSettings.class.isAssignableFrom(customSettings))
if (SimpleSettings.class.isAssignableFrom(customSettings)) {
YamlStaticConfig.load((Class<? extends YamlStaticConfig>) customSettings);
else
}
else {
delayedLoading.add(customSettings);
}

for (final Class<?> delayedSettings : delayedLoading)
for (final Class<?> delayedSettings : delayedLoading) {
YamlStaticConfig.load((Class<? extends YamlStaticConfig>) delayedSettings);
}
}

/*
Expand Down
38 changes: 24 additions & 14 deletions src/main/java/org/mineacademy/fo/settings/FileConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -1191,7 +1191,6 @@ final void load(@NonNull File file) {
}

try {
this.onPreLoad();
this.loadFields();
this.onLoad();

Expand Down Expand Up @@ -1256,13 +1255,19 @@ protected void onPreLoad(){

/**
* Called automatically when the configuration has been loaded, used to load your
* fields in your class here if @AutoConfig is not used.
* fields in your class if @AutoConfig is not used.
* <br>
* You can throw {@link EventHandledException} here to indicate to your child class to interrupt loading
*/
protected void onLoad() {
}

/**
* Called automatically after {@link #onLoad()} regardless of configuration loading success.
*/
protected void onLoadFinish() {
}

/**
* Save the configuration to the file immediately (you need to call loadConfiguration(File) first)
*/
Expand Down Expand Up @@ -1304,11 +1309,13 @@ public final void save(@NonNull File file) {

final String data = this.saveToString();

try (Writer writer = new OutputStreamWriter(Files.newOutputStream(file.toPath()), StandardCharsets.UTF_8)) {
writer.write(data);
if (data != null){
try (Writer writer = new OutputStreamWriter(Files.newOutputStream(file.toPath()), StandardCharsets.UTF_8)) {
writer.write(data);

} catch (final Exception ex) {
Remain.sneaky(ex);
} catch (final Exception ex) {
Remain.sneaky(ex);
}
}

// Update file
Expand All @@ -1318,6 +1325,8 @@ public final void save(@NonNull File file) {
} catch (final Exception ex) {
Remain.sneaky(ex);
}

this.onSaveFinish();
}
}

Expand Down Expand Up @@ -1354,6 +1363,12 @@ protected void onSave() {
this.set(entry.getKey(), entry.getValue());
}

/**
* Called automatically after {@link #onSave()} (typically when configuration has been saved).
*/
protected void onSaveFinish(){
}

/**
* Get values from file and set them to fields annotated with @AutoConfig
*/
Expand Down Expand Up @@ -1455,7 +1470,7 @@ private List<Field> getFieldsToAutoSave() {
/**
* Get the deserialized object from the given path depending on its field class type.
*/
private Object getBasedOnClass(String path, Field field){
public Object getBasedOnClass(String path, Field field){
Class<?> fieldType = field.getType();

// ***
Expand Down Expand Up @@ -1533,7 +1548,7 @@ enum TypeMethod {
}

/**
* Get the name under which the value will be located in the file.
* Get the name under which the value will be saved in the file.
* Based on user-defined AutoConfig.format() and is lower_underscore by default.
*/
private String getFormattedFieldName(Field field) {
Expand All @@ -1555,19 +1570,14 @@ protected boolean canSaveFile() {

/**
* Implementation by specific configurations to generate file contents to save.
*
* @return
*/
@NonNull
abstract String saveToString();

/**
* Override to implement custom saving mechanism, used automatically in {@link #onSave()}
* you can return only the data you actually want to save here.
*
* <br>
* Returns null by default!
*
* @return
*/
public SerializedMap saveToMap() {
return null;
Expand Down
31 changes: 21 additions & 10 deletions src/main/java/org/mineacademy/fo/settings/SimpleLocalization.java
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
package org.mineacademy.fo.settings;

import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.mineacademy.fo.Common;
import org.mineacademy.fo.FileUtil;
import org.mineacademy.fo.Valid;
import org.mineacademy.fo.command.PermsCommand;
import org.mineacademy.fo.plugin.SimplePlugin;

/**
* A simple implementation of a basic localization file.
* We create the localization/messages_LOCALEPREFIX.yml file
* automatically and fill it with values from your localization/messages_LOCALEPREFIX.yml
* file placed within in your plugin's jar file.
* We create the localization/messages_LOCALE.yml file
* automatically and fill it with values from your localization/messages_LOCALE.yml
* file placed within in your plugin's jar file.<br>
* To change the folder and file prefix, override {@link #getFilePrefix()} method.
*/
@SuppressWarnings("unused")
public class SimpleLocalization extends YamlStaticConfig {
Expand All @@ -27,20 +30,28 @@ public class SimpleLocalization extends YamlStaticConfig {
// Loading
// --------------------------------------------------------------------

/**
* Override to change the file prefix. You can also use folders with forward slash (/)<br>
* Default: localization/messages_LOCALE.yml
*/
protected String getFilePrefix(){
return "localization/messages_";
}

/**
* Create and load the localization/messages_LOCALEPREFIX.yml file.
* <p>
* See {@link SimpleSettings#LOCALE_PREFIX} for the locale prefix.
* <p>
* The locale file is extracted from your plugins jar to the localization/ folder
* if it does not exists, or updated if it is out of date.
* if it does not exist, or updated if it is out of date.
*/
@Override
protected final void onLoad() throws Exception {
final String localePath = "localization/messages_" + SimpleSettings.LOCALE_PREFIX + ".yml";
final String localePath = getFilePrefix() + SimpleSettings.LOCALE_PREFIX + ".yml";
final Object content = FileUtil.getInternalFileContent(localePath);

Valid.checkNotNull(content, SimplePlugin.getNamed() + " does not support the localization: messages_" + SimpleSettings.LOCALE_PREFIX
Valid.checkNotNull(content, SimplePlugin.getNamed() + " does not support the localization: " + getFilePrefix() + SimpleSettings.LOCALE_PREFIX
+ ".yml (For custom locale, set the Locale to 'en' and edit your English file instead)");

this.loadConfiguration(localePath);
Expand Down Expand Up @@ -103,8 +114,8 @@ protected final boolean alwaysSaveOnLoad() {
public static final class Commands {

/**
* true = https://i.imgur.com/us88BCT.png
* false = https://i.imgur.com/N7jLu7v.png
* true = <a href="https://i.imgur.com/us88BCT.png">...</a>
* false = <a href="https://i.imgur.com/N7jLu7v.png">...</a>
*/
public static Boolean SIMPLE_HELP_DESIGN = false;

Expand Down Expand Up @@ -741,15 +752,15 @@ private static void init() {
*
* @return
*/
public static final Boolean isLocalizationCalled() {
public static Boolean isLocalizationCalled() {
return localizationClassCalled;
}

/**
* Reset the flag indicating that the class has been loaded,
* used in reloading.
*/
public static final void resetLocalizationCall() {
public static void resetLocalizationCall() {
localizationClassCalled = false;
}
}
9 changes: 4 additions & 5 deletions src/main/java/org/mineacademy/fo/settings/SimpleSettings.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
* A simple implementation of a typical main plugin settings
* where each key can be accessed in a static way from anywhere.
* <p>
* Typically we use this class for settings.yml main plugin config.
* Typically, we use this class for settings.yml main plugin config.
*/
// Use for settings.yml
@SuppressWarnings("unused")
Expand Down Expand Up @@ -175,15 +175,14 @@ protected int getConfigVersion() {
public static Boolean NOTIFY_UPDATES = true;

/**
* Should we warn about incompatibilities.
* Should we warn about incompatibilities?
* It is used in {@link org.mineacademy.fo.plugin.AutoRegisterScanner#autoRegister(Class, boolean)}.
* Please hide these warnings only on the last stage of your plugin development.
*/
public static Boolean HIDE_INCOMPATIBILITY_WARNINGS = false;

/**
* Should we warn about Nashorn not installed on the server.
* Is is used
* Should we warn about Nashorn not installed on the server?
*/
public static Boolean HIDE_NASHORN_WARNINGS = false;

Expand Down Expand Up @@ -262,7 +261,7 @@ private static void init() {
}

/**
* Upgrade some of the old and ancient settings from our premium plugins.
* Upgrade some old and ancient settings from our premium plugins.
*/
private static void upgradeOldSettings() {

Expand Down
Loading

0 comments on commit 6994e96

Please sign in to comment.