diff --git a/core/src/main/java/cc/carm/lib/configuration/source/ConfigurationFactory.java b/core/src/main/java/cc/carm/lib/configuration/source/ConfigurationFactory.java index 85d466e..41adb62 100644 --- a/core/src/main/java/cc/carm/lib/configuration/source/ConfigurationFactory.java +++ b/core/src/main/java/cc/carm/lib/configuration/source/ConfigurationFactory.java @@ -20,6 +20,13 @@ import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Supplier; +/** + * ConfigurationFactory, used to create configuration holder. + * + * @param The {@link ConfigureSource} type + * @param The {@link ConfigurationHolder} type. + * @param Self builder, for further implement support. + */ public abstract class ConfigurationFactory< SOURCE extends ConfigureSource, HOLDER extends ConfigurationHolder, @@ -139,18 +146,39 @@ public abstract class ConfigurationFactory< return self(); } + /** + * Supply the base path generator for this configuration holder + * + * @param generator {@link PathGenerator} + * @return this + */ public SELF pathGenerator(PathGenerator generator) { return initializer(loader -> { loader.pathGenerator(generator); }); } + /** + * Register a new annotation for metadata to the configuration loader + * + * @param annotation The {@link Annotation} + * @param metadata The {@link ConfigurationMetadata} type + * @param extractor The {@link Function} to extract the metadata from the annotation + * @param The metadata type + * @param The annotation type + * @return this + */ public SELF metaAnnotation(@NotNull Class annotation, @NotNull ConfigurationMetadata metadata, @NotNull Function extractor) { return initializer(loader -> loader.registerAnnotation(annotation, metadata, extractor)); } + /** + * Build the configuration holder. + * + * @return The configuration holder + */ public abstract @NotNull HOLDER build(); } diff --git a/core/src/main/java/cc/carm/lib/configuration/source/loader/PathGenerator.java b/core/src/main/java/cc/carm/lib/configuration/source/loader/PathGenerator.java index df9701e..665f43a 100644 --- a/core/src/main/java/cc/carm/lib/configuration/source/loader/PathGenerator.java +++ b/core/src/main/java/cc/carm/lib/configuration/source/loader/PathGenerator.java @@ -9,6 +9,12 @@ import org.jetbrains.annotations.Nullable; import java.lang.reflect.Field; import java.util.function.UnaryOperator; +/** + * Path generator for configuration. + *

+ * Path generator is a utility class that helps to generate the path of the configuration. + * It can be used to generate the path of the field or class. + */ public class PathGenerator { public static PathGenerator of() { diff --git a/core/src/main/java/cc/carm/lib/configuration/source/section/ConfigureSection.java b/core/src/main/java/cc/carm/lib/configuration/source/section/ConfigureSection.java index b1de0a1..00955a9 100644 --- a/core/src/main/java/cc/carm/lib/configuration/source/section/ConfigureSection.java +++ b/core/src/main/java/cc/carm/lib/configuration/source/section/ConfigureSection.java @@ -11,56 +11,199 @@ import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Stream; +/** + * Represents a section of a configuration. + * + * @author Carm + * @since 4.0.0 + */ public interface ConfigureSection { + /** + * Gets the parent section of this section. + *

+ * For root sections, this will return null. + * + * @return Parent section, or null if this is a root section. + */ + @Contract(pure = true) @Nullable ConfigureSection parent(); + /** + * Gets a set containing all keys in this section. + *

+ * If deep is set to true, then this will contain all the keys within any + * child {@link ConfigureSection}s (and their children paths). + *

+ * If deep is set to false, then this will contain only the keys of any + * direct children, and not their own children. + * + * @param deep Whether to get a deep list. + * @return Set of keys contained within this Section. + */ @NotNull @UnmodifiableView default Set getKeys(boolean deep) { return getValues(deep).keySet(); } + /** + * Gets a set containing all values in this section. + *

+ * If deep is set to true, then this will contain all the keys within any + * child {@link ConfigureSection}s (and their children paths). + *

+ * If deep is set to false, then this will contain only the keys of any + * direct children, and not their own children. + * + * @param deep Whether to get a deep list. + * @return Map of data values contained within this Section. + */ @NotNull @UnmodifiableView Map getValues(boolean deep); + /** + * Sets the value at the given path. + *

+ * Null values will be kept, if you want to remove a value use {@link #remove(String)} + * Path separator depends on holder's + * {@link cc.carm.lib.configuration.source.option.StandardOptions#PATH_SEPARATOR} + * + * @param path The path to set the value at. + * @param value The value to set. + */ void set(@NotNull String path, @Nullable Object value); + /** + * Removes the value at the given path. + *

+ * Path separator depends on holder's + * {@link cc.carm.lib.configuration.source.option.StandardOptions#PATH_SEPARATOR} + * + * @param path The path to remove the value at. + */ + void remove(@NotNull String path); + + /** + * Check if the value of given path is present. + *

+ * Path separator depends on holder's + * {@link cc.carm.lib.configuration.source.option.StandardOptions#PATH_SEPARATOR} + * + * @param path The path to check. + * @return True if the value is present, false otherwise. + */ boolean contains(@NotNull String path); + /** + * Predicate the value of given path is specific type. + * + * @param path The path to check. + * @param typeClass The type's class + * @param The type to check. + * @return True if the value is present and is the correct type, false otherwise. + */ default boolean isType(@NotNull String path, @NotNull Class typeClass) { return typeClass.isInstance(get(path)); } + /** + * Predicate the value of given path is a {@link List}. + * + * @param path The path to check. + * @return True if the value is present and is a list, false otherwise. + */ default boolean isList(@NotNull String path) { return isType(path, List.class); } + /** + * Get the value as a {@link List} from the specified path. + * + * @param path The path to get the {@link List}. + * @return The list if the path exists and is a list, otherwise null. + */ @Nullable List getList(@NotNull String path); + /** + * Predicate the value of given path is a {@link ConfigureSection}. + * + * @param path The path to check. + * @return True if the value is present and is a section, false otherwise. + */ default boolean isSection(@NotNull String path) { return isType(path, ConfigureSection.class); } + /** + * Get the value as a {@link ConfigureSection} from the specified path. + * + * @param path The path to get the section. + * @return The section if the path exists and is a section, otherwise null. + */ @Nullable ConfigureSection getSection(@NotNull String path); + /** + * Get the origin value of the path. + * + * @param path The path to get the value from. + * @return The value at the path, or null if not found. + */ @Nullable Object get(@NotNull String path); - default @Nullable T get(@NotNull String path, @NotNull Class clazz) { - return get(path, null, clazz); + /** + * Get the value of the path for specific type, + * if the path does not exist, return null. + * + * @param path The path to get the value from. + * @param type The type class of the value + * @param The type of the value + * @return The value at the path, or the default value if not found. + */ + default @Nullable T get(@NotNull String path, @NotNull Class type) { + return get(path, null, type); } - default @Nullable T get(@NotNull String path, @NotNull DataFunction parser) { + /** + * Get the value of the path using a parser function, + * if the path does not exist, return NULL. + * + * @param path The path to get the value from. + * @param parser The function to parse the value + * @param The type of the value + * @return The value at the path, or null if not found. + */ + default @Nullable T get(@NotNull String path, @NotNull DataFunction<@Nullable Object, T> parser) { return get(path, null, parser); } + /** + * Get the value of the path for specific type, + * if the path does not exist, return the default value. + * + * @param path The path to get the value from. + * @param defaults The default value to return if the path does not exist. + * @param clazz The type class of the value + * @param The type of the value + * @return The value at the path, or the default value if not found. + */ @Contract("_,!null,_->!null") - default @Nullable T get(@NotNull String path, @Nullable T defaultValue, @NotNull Class clazz) { - return get(path, defaultValue, DataFunction.castObject(clazz)); + default @Nullable T get(@NotNull String path, @Nullable T defaults, @NotNull Class clazz) { + return get(path, defaults, DataFunction.castObject(clazz)); } + /** + * Get the value of the path using a parser function, + * if the path does not exist, return the default value. + * + * @param path The path to get the value from. + * @param defaultValue The default value to return if the path does not exist. + * @param parser The function to parse the value + * @param The type of the value + * @return The value at the path, or the default value if not found. + */ @Contract("_,!null,_->!null") default @Nullable T get(@NotNull String path, @Nullable T defaultValue, @NotNull DataFunction parser) { @@ -75,125 +218,290 @@ public interface ConfigureSection { return defaultValue; } - + /** + * Predicate the value of given path is a {@link Boolean}. + * + * @param path The path to check. + * @return True if the value is present and is a boolean, false otherwise. + */ default boolean isBoolean(@NotNull String path) { return isType(path, Boolean.class); } + /** + * Get the value as a {@link Boolean} from the specified path. + * + * @param path The path to get the boolean. + * @return The boolean if the path exists and is a boolean, otherwise false. + */ default boolean getBoolean(@NotNull String path) { return getBoolean(path, false); } + /** + * Get the value as a {@link Boolean} from the specified path. + * + * @param path The path to get the boolean. + * @param def The default value to return if the path does not exist. + * @return The boolean if the path exists and is a boolean, otherwise the default value. + */ @Contract("_, !null -> !null") default @Nullable Boolean getBoolean(@NotNull String path, @Nullable Boolean def) { return get(path, def, DataFunction.booleanValue()); } + /** + * Predicate the value of given path is a {@link Byte}. + * + * @param path The path to check. + * @return True if the value is present and is a byte, false otherwise. + */ default @Nullable Boolean isByte(@NotNull String path) { return isType(path, Byte.class); } + /** + * Get the value as a {@link Byte} from the specified path. + * + * @param path The path to get the byte. + * @return The byte if the path exists and is a byte, otherwise 0. + */ default @Nullable Byte getByte(@NotNull String path) { return getByte(path, (byte) 0); } + /** + * Get the value as a {@link Byte} from the specified path. + * + * @param path The path to get the byte. + * @param def The default value to return if the path does not exist. + * @return The byte if the path exists and is a byte, otherwise the default value. + */ @Contract("_, !null -> !null") default @Nullable Byte getByte(@NotNull String path, @Nullable Byte def) { return get(path, def, DataFunction.byteValue()); } + /** + * Predicate the value of given path is a {@link Short}. + * + * @param path The path to check. + * @return True if the value is present and is a short, false otherwise. + */ default boolean isShort(@NotNull String path) { return isType(path, Short.class); } + /** + * Get the value as a {@link Short} from the specified path. + * + * @param path The path to get the short. + * @return The short if the path exists and is a short, otherwise 0. + */ default @Nullable Short getShort(@NotNull String path) { return getShort(path, (short) 0); } + /** + * Get the value as a {@link Short} from the specified path. + * + * @param path The path to get the short. + * @param def The default value to return if the path does not exist. + * @return The short if the path exists and is a short, otherwise the default value. + */ @Contract("_, !null -> !null") default @Nullable Short getShort(@NotNull String path, @Nullable Short def) { return get(path, def, DataFunction.shortValue()); } - + /** + * Predicate the value of given path is a {@link Integer}. + * + * @param path The path to check. + * @return True if the value is present and is a int, false otherwise. + */ default boolean isInt(@NotNull String path) { return isType(path, Integer.class); } + /** + * Get the value as a {@link Integer} from the specified path. + * + * @param path The path to get the int. + * @return The int if the path exists and is a int, otherwise 0. + */ default @Nullable Integer getInt(@NotNull String path) { return getInt(path, 0); } + /** + * Get the value as a {@link Integer} from the specified path. + * + * @param path The path to get the int. + * @param def The default value to return if the path does not exist. + * @return The int if the path exists and is a int, otherwise the default value. + */ @Contract("_, !null -> !null") default @Nullable Integer getInt(@NotNull String path, @Nullable Integer def) { return get(path, def, DataFunction.intValue()); } + /** + * Predicate the value of given path is a {@link Long}.F + * + * @param path The path to check. + * @return True if the value is present and is a long, false otherwise. + */ default boolean isLong(@NotNull String path) { return isType(path, Long.class); } + /** + * Get the value as a {@link Long} from the specified path. + * + * @param path The path to get the long. + * @return The long if the path exists and is a long, otherwise 0. + */ default @Nullable Long getLong(@NotNull String path) { return getLong(path, 0L); } + /** + * Get the value as a {@link Long} from the specified path. + * + * @param path The path to get the long. + * @param def The default value to return if the path does not exist. + * @return The long if the path exists and is a long, otherwise the default value. + */ @Contract("_, !null -> !null") default @Nullable Long getLong(@NotNull String path, @Nullable Long def) { return get(path, def, DataFunction.longValue()); } - + /** + * Predicate the value of given path is a {@link Float}. + * + * @param path The path to check. + * @return True if the value is present and is a float, false otherwise. + */ default boolean isFloat(@NotNull String path) { return isType(path, Float.class); } + /** + * Get the value as a {@link Float} from the specified path. + * + * @param path The path to get the float. + * @return The float if the path exists and is a float, otherwise 0. + */ default @Nullable Float getFloat(@NotNull String path) { return getFloat(path, 0.0F); } + /** + * Get the value as a {@link Float} from the specified path. + * + * @param path The path to get the float. + * @param def The default value to return if the path does not exist. + * @return The float if the path exists and is a float, otherwise the default value. + */ @Contract("_, !null -> !null") default @Nullable Float getFloat(@NotNull String path, @Nullable Float def) { return get(path, def, DataFunction.floatValue()); } - + /** + * Predicate the value of given path is a {@link Double}. + * + * @param path The path to check. + * @return True if the value is present and is a double, false otherwise. + */ default boolean isDouble(@NotNull String path) { return isType(path, Double.class); } + /** + * Get the value as a {@link Double} from the specified path. + * + * @param path The path to get the double. + * @return The double if the path exists and is a double, otherwise 0. + */ default @Nullable Double getDouble(@NotNull String path) { return getDouble(path, 0.0D); } + /** + * Get the value as a {@link Double} from the specified path. + * + * @param path The path to get the double. + * @param def The default value to return if the path does not exist. + * @return The double if the path exists and is a double, otherwise the default value. + */ @Contract("_, !null -> !null") default @Nullable Double getDouble(@NotNull String path, @Nullable Double def) { return get(path, def, DataFunction.doubleValue()); } - + /** + * Predicate the value of given path is a {@link Character}. + * + * @param path The path to check. + * @return True if the value is present and is a char, false otherwise. + */ default boolean isChar(@NotNull String path) { return isType(path, Boolean.class); } + /** + * Get the value as a {@link Character} from the specified path. + * + * @param path The path to get the char. + * @return The char if the path exists and is a char, otherwise null. + */ default @Nullable Character getChar(@NotNull String path) { return getChar(path, null); } + /** + * Get the value as a {@link Character} from the specified path. + * + * @param path The path to get the char. + * @param def The default value to return if the path does not exist. + * @return The char if the path exists and is a char, otherwise the default value. + */ @Contract("_, !null -> !null") default @Nullable Character getChar(@NotNull String path, @Nullable Character def) { return get(path, def, Character.class); } - + /** + * Predicate the value of given path is a {@link String}. + * + * @param path The path to check. + * @return True if the value is present and is a string, false otherwise. + */ default boolean isString(@NotNull String path) { return isType(path, String.class); } + /** + * Get the value as a {@link String} from the specified path. + * + * @param path The path to get the string. + * @return The string if the path exists and is a string, otherwise null. + */ default @Nullable String getString(@NotNull String path) { return getString(path, null); } + /** + * Get the value as a {@link String} from the specified path. + * + * @param path The path to get the string. + * @param def The default value to return if the path does not exist. + * @return The string if the path exists and is a string, otherwise the default value. + */ @Contract("_, !null -> !null") default @Nullable String getString(@NotNull String path, @Nullable String def) { return get(path, def, String.class); @@ -291,17 +599,41 @@ public interface ConfigureSection { return getList(path, DataFunction.castObject(Character.class)); } + /** + * Get the specific type of collection from the section. + * + * @param path The path to get the collection from + * @param constructor The constructor of the collection + * @param parser The function to parse the values + * @param The type of the values + * @param The type of the collection + * @return The collection of values + */ default > @NotNull C getCollection(@NotNull String path, @NotNull Supplier constructor, @NotNull DataFunction parser) { return parseCollection(getList(path), constructor, parser); } + /** + * Get the specific type of steam from the section. + * + * @param path The path to get the stream from + * @return The stream of values + */ default @NotNull Stream stream(@NotNull String path) { List values = getList(path); return values == null ? Stream.empty() : values.stream(); } + /** + * Get the specific type of steam from the section. + * + * @param path The path to get the stream from + * @param parser The function to parse the values + * @param The type of the values + * @return The stream of values + */ default @NotNull Stream stream(@NotNull String path, @NotNull Function parser) { return stream(path).map(parser); } diff --git a/core/src/main/java/cc/carm/lib/configuration/source/section/ConfigureSource.java b/core/src/main/java/cc/carm/lib/configuration/source/section/ConfigureSource.java index 6edf142..7322bc1 100644 --- a/core/src/main/java/cc/carm/lib/configuration/source/section/ConfigureSource.java +++ b/core/src/main/java/cc/carm/lib/configuration/source/section/ConfigureSource.java @@ -10,6 +10,14 @@ import org.jetbrains.annotations.Nullable; import java.util.List; import java.util.Map; +/** + * ConfigureSource represents the source of configuration, + * which can be a file, a database, or any other source. + * + * @param

The type of the root section. + * @param The original configuration object. + * @param The type of the source itself, for further implement support. + */ public abstract class ConfigureSource< SECTION extends ConfigureSection, ORIGINAL, SELF extends ConfigureSource> diff --git a/features/commentable/src/main/java/cc/carm/lib/configuration/annotation/InlineComments.java b/features/commentable/src/main/java/cc/carm/lib/configuration/annotation/InlineComments.java index a162961..f76089d 100644 --- a/features/commentable/src/main/java/cc/carm/lib/configuration/annotation/InlineComments.java +++ b/features/commentable/src/main/java/cc/carm/lib/configuration/annotation/InlineComments.java @@ -9,7 +9,12 @@ import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) public @interface InlineComments { - + /** + * Multiple inline comments support. + * + * @return inline comment contents. + * @see InlineComment + */ InlineComment[] value(); } diff --git a/features/section/src/main/java/cc/carm/lib/configuration/source/section/MemorySection.java b/features/section/src/main/java/cc/carm/lib/configuration/source/section/MemorySection.java index 10ba244..b29fb4f 100644 --- a/features/section/src/main/java/cc/carm/lib/configuration/source/section/MemorySection.java +++ b/features/section/src/main/java/cc/carm/lib/configuration/source/section/MemorySection.java @@ -88,6 +88,16 @@ public class MemorySection implements ConfigureSection { } } + @Override + public void remove(@NotNull String path) { + MemorySection section = getSectionFor(path); + if (section != this) { + section.remove(childPath(path)); + } else { + this.data.remove(path); + } + } + @Override public boolean contains(@NotNull String path) { return get(path) != null;