commit e443249166b634be47443d04545acf95c187b86f Author: rozhur Date: Sun Jul 16 20:06:05 2023 +0500 Initial diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..20992d4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.idea +target +*/target diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..d56bd28 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 rozhur + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..672e414 --- /dev/null +++ b/README.md @@ -0,0 +1,92 @@ +### Add as maven dependency +```xml + + + zhdev-repo + https://repo.zhdev.org/maven + + +``` +```xml + + + org.zhdev + all + 1.0-SNAPSHOT + + +``` + +### Example for reflection +#### Maven dependency +```xml + + + org.zhdev + common + 1.0-SNAPSHOT + + +``` +#### Code +```java +import java.lang.reflect.Field; + +import org.bukkit.Bukkit; + +public class BukkitFields { + public static final Field METHOD__CraftServer__getServer; + + static { + METHOD__CraftServer__getServer = ReflectionUtils.methodSearcher() + .of(Bukkit.getServer()) + .methodOf("getServer") + .returns(CLASS__DedicatedServer) + .search(); + } +} +``` + +### Example for yaml +#### Maven dependency +```xml + + + org.zhdev + io + 1.0-SNAPSHOT + + +``` +#### Code + +```java +import org.zhdev.config.Config; +import org.zhdev.config.YamlConfig; + +import java.util.List; + +public class Main { + public static void main(String[] args) { + Config config = new YamlConfig(); + + config.load(); // load from ./config.yml file by default + config.load("test.yml"); // load from ./test.yml by 1st argument + + // set value to "Hello world!" of 'test' key and set block comment from 3rd argument + config.set("test", "Hello world!", "It's hello world comment!"); + + config.save(); // save as ./config.yml by default + config.save("test.yml"); // save as ./test.yml by 1st argument + + Config anotherConfig = new YamlConfig("another.yml"); // create with default name "another.yml" + config.load(); // load from ./another.yml by default + + // get value "test" as integer or "5" if it is null + Integer value = config.getInteger("test", 5); + + // get value "foo->bar->testlist" as list + List list = config.getSection("foo", "bar").getList("testlist"); + } +} +``` diff --git a/all/pom.xml b/all/pom.xml new file mode 100644 index 0000000..0cf0933 --- /dev/null +++ b/all/pom.xml @@ -0,0 +1,32 @@ + + 4.0.0 + + + parent + org.zhdev.varioutil + 1.0-SNAPSHOT + + + all + + + + ${project.groupId} + common + ${project.version} + compile + + + ${project.groupId} + io + ${project.version} + compile + + + ${project.groupId} + bukkit + ${project.version} + compile + + + \ No newline at end of file diff --git a/bukkit/pom.xml b/bukkit/pom.xml new file mode 100644 index 0000000..dcc97e7 --- /dev/null +++ b/bukkit/pom.xml @@ -0,0 +1,51 @@ + + 4.0.0 + + + parent + org.zhdev.varioutil + 1.0-SNAPSHOT + + + bukkit + + + + spigot-repo + https://hub.spigotmc.org/nexus/content/repositories/snapshots/ + + + + + + ${project.groupId} + io + ${project.version} + compile + + + ${project.groupId} + common + ${project.version} + compile + + + org.spigotmc + spigot-api + 1.20-R0.1-SNAPSHOT + provided + + + org.spigotmc + spigot + 1.20-R0.1-SNAPSHOT + provided + + + org.spigotmc + minecraft-server + 1.20-R0.1-SNAPSHOT + provided + + + \ No newline at end of file diff --git a/bukkit/src/main/java/org/zhdev/config/BukkitConfig.java b/bukkit/src/main/java/org/zhdev/config/BukkitConfig.java new file mode 100644 index 0000000..16b8f5b --- /dev/null +++ b/bukkit/src/main/java/org/zhdev/config/BukkitConfig.java @@ -0,0 +1,15 @@ +package org.zhdev.config; + +import org.bukkit.plugin.Plugin; + +import java.io.File; + +public interface BukkitConfig extends Config { + File load(Plugin plugin, String path) throws ConfigException; + + File load(Plugin plugin) throws ConfigException; + + File saveIfEmpty(Plugin plugin, String path) throws ConfigException; + + File saveIfEmpty(Plugin plugin) throws ConfigException; +} diff --git a/bukkit/src/main/java/org/zhdev/config/BukkitYamlConfig.java b/bukkit/src/main/java/org/zhdev/config/BukkitYamlConfig.java new file mode 100644 index 0000000..65c9548 --- /dev/null +++ b/bukkit/src/main/java/org/zhdev/config/BukkitYamlConfig.java @@ -0,0 +1,77 @@ +package org.zhdev.config; + +import org.bukkit.configuration.serialization.ConfigurationSerializable; +import org.bukkit.configuration.serialization.ConfigurationSerialization; +import org.bukkit.plugin.Plugin; +import org.yaml.snakeyaml.nodes.Node; +import org.zhdev.util.ResourceUtils; + +import java.io.File; +import java.io.InputStream; +import java.util.LinkedHashMap; +import java.util.Map; + +public class BukkitYamlConfig extends YamlConfig implements BukkitConfig { + public BukkitYamlConfig(String key) { + super(key); + } + + public BukkitYamlConfig() {} + + @Override + protected Object constructHandle(Node keyNode, Node valueNode, String key, Object value) { + if (value instanceof Map) { + Map raw = (Map) valueNode; + if (raw.containsKey(ConfigurationSerialization.SERIALIZED_TYPE_KEY)) { + Map map = new LinkedHashMap<>(raw.size()); + for (Map.Entry entry : raw.entrySet()) { + map.put(String.valueOf(entry.getKey()), entry.getValue()); + } + return ConfigurationSerialization.deserializeObject(map); + } + } + return super.constructHandle(keyNode, valueNode, key, value); + } + + @Override + protected Node representHandle(String key, Object value) { + if (value instanceof ConfigurationSerializable) { + ConfigurationSerializable serializable = (ConfigurationSerializable) value; + Map values = new LinkedHashMap<>(); + values.put(ConfigurationSerialization.SERIALIZED_TYPE_KEY, ConfigurationSerialization.getAlias(serializable.getClass())); + values.putAll(serializable.serialize()); + return REPRESENTER.represent(values); + } + return super.representHandle(key, value); + } + + @Override + public File load(Plugin plugin, String path) throws ConfigException { + ClassLoader classLoader = plugin.getClass().getClassLoader(); + InputStream stream = ResourceUtils.getResource(path, classLoader); + if (stream != null) { + load(stream); + } + + File file = load(plugin.getDataFolder().getPath() + File.separatorChar + path); + if (file.length() == 0) { + ResourceUtils.saveResource(path, file, classLoader); + } + return load(plugin.getDataFolder().getPath() + File.separatorChar + path); + } + + @Override + public File load(Plugin plugin) throws ConfigException { + return load(plugin, key); + } + + @Override + public File saveIfEmpty(Plugin plugin, String path) throws ConfigException { + return saveIfEmpty(plugin.getDataFolder().getPath() + File.separatorChar + path); + } + + @Override + public File saveIfEmpty(Plugin plugin) throws ConfigException { + return saveIfEmpty(plugin, key); + } +} diff --git a/common/pom.xml b/common/pom.xml new file mode 100644 index 0000000..d09b582 --- /dev/null +++ b/common/pom.xml @@ -0,0 +1,11 @@ + + 4.0.0 + + + parent + org.zhdev.varioutil + 1.0-SNAPSHOT + + + common + \ No newline at end of file diff --git a/common/src/main/java/org/zhdev/Version.java b/common/src/main/java/org/zhdev/Version.java new file mode 100755 index 0000000..9109268 --- /dev/null +++ b/common/src/main/java/org/zhdev/Version.java @@ -0,0 +1,198 @@ +package org.zhdev; + +import org.jetbrains.annotations.NotNull; + +public final class Version implements Comparable { + private final int major; + private final int minor; + private final int patch; + private final State state; + private final String string; + + public Version(int major, int minor, int patch, @NotNull State state) { + this.major = major; + this.minor = minor; + this.patch = patch; + this.state = state; + this.string = major + "." + minor + (patch > 0 ? "." + patch : "") + (state != State.RELEASE ? '-' + state.name() : ""); + } + + public int getMajor() { + return major; + } + + public int getMinor() { + return minor; + } + + public int getPatch() { + return patch; + } + + public State getState() { + return state; + } + + public int compareTo(int major, int minor, int patch, State state) { + int result = this.major - major; + if (result == 0) { + result = this.minor - minor; + if (result == 0) { + result = this.patch - patch; + if (result == 0) { + result = this.state.compareTo(state); + } + } + } + return result; + } + + @Override + public int compareTo(Version version) { + return compareTo(version.major, version.minor, version.patch, version.state); + } + + public int compareTo(int major, int minor, int patch) { + int result = this.major - major; + if (result == 0) { + result = this.minor - minor; + if (result == 0) { + result = this.patch - patch; + } + } + return result; + } + + public int compareTo(int major, int minor) { + int result = this.major - major; + if (result == 0) { + result = this.minor - minor; + } + return result; + } + + public boolean equals(int major, int minor, int patch, State state) { + return major == this.major && minor == this.minor && patch == this.patch && this.state == state; + } + + public boolean equals(int major, int minor, int patch) { + return major == this.major && minor == this.minor && patch == this.patch; + } + + public boolean equals(int major, int minor) { + return major == this.major && minor == this.minor; + } + + public boolean lessThan(Version version) { + return compareTo(version) < 0; + } + + public boolean lessThan(int major, int minor, int patch, State state) { + return compareTo(major, minor, patch, state) < 0; + } + + public boolean lessThan(int major, int minor, int patch) { + return compareTo(major, minor, patch) < 0; + } + + public boolean lessThan(int major, int minor) { + return compareTo(major, minor) < 0; + } + + public boolean moreThan(Version version) { + return compareTo(version) > 0; + } + + public boolean moreThan(int major, int minor, int patch, State state) { + return compareTo(major, minor, patch, state) > 0; + } + + public boolean moreThan(int major, int minor, int patch) { + return compareTo(major, minor, patch) > 0; + } + + public boolean moreThan(int major, int minor) { + return compareTo(major, minor) > 0; + } + + public boolean moreOrEqual(Version version) { + return compareTo(version) >= 0; + } + + public boolean moreOrEqual(int major, int minor, int patch, State state) { + return compareTo(major, minor, patch, state) >= 0; + } + + public boolean moreOrEqual(int major, int minor, int patch) { + return compareTo(major, minor, patch) >= 0; + } + + public boolean moreOrEqual(int major, int minor) { + return compareTo(major, minor) >= 0; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Version version = (Version) o; + + if (major != version.major) return false; + if (minor != version.minor) return false; + if (patch != version.patch) return false; + return state == version.state; + } + + @Override + public int hashCode() { + int result = major; + result = 31 * result + minor; + result = 31 * result + patch; + result = 31 * result + (state != null ? state.hashCode() : 0); + return result; + } + + @Override + public String toString() { + return string; + } + + public static Version fromString(String string) { + String[] semver = string.split("\\.", 3); + if (semver.length < 2) { + throw new IllegalArgumentException("Incorrect semver (" + string + ")"); + } + + int major = Integer.parseInt(semver[0]); + int minor; + + String[] split; + int patch; + if (semver.length < 3) { + split = semver[1].split("-|\\s", 2); + minor = Integer.parseInt(split[0]); + patch = 0; + } else { + split = semver[2].split("-|\\s", 2); + minor = Integer.parseInt(semver[1]); + patch = Integer.parseInt(split[0]); + } + + State state; + if (split.length > 1) { + state = State.valueOf(split[1].toUpperCase()); + } else { + state = State.RELEASE; + } + + return new Version(major, minor, patch, state); + } + + public enum State { + SNAPSHOT, + ALPHA, + BETA, + RELEASE + } +} diff --git a/common/src/main/java/org/zhdev/reflection/FieldSearcher.java b/common/src/main/java/org/zhdev/reflection/FieldSearcher.java new file mode 100755 index 0000000..7bd1a37 --- /dev/null +++ b/common/src/main/java/org/zhdev/reflection/FieldSearcher.java @@ -0,0 +1,83 @@ +package org.zhdev.reflection; + +import org.zhdev.util.ReflectionUtils; + +import java.lang.reflect.Field; + +public class FieldSearcher { + private Class type; + private Object instance; + private Class fieldType; + private String[] fieldNames; + + public FieldSearcher typeOf(String typeName) { + this.type = ReflectionUtils.getType(typeName); + return this; + } + + public FieldSearcher typeOf(String packageName, String typeName) { + this.type = ReflectionUtils.getType(packageName, typeName); + return this; + } + + public FieldSearcher typeOf(String... typeNames) { + this.type = ReflectionUtils.searchType(typeNames); + return this; + } + + public FieldSearcher typeOf(String packageName, String... typeNames) { + this.type = ReflectionUtils.searchType(new String[] { packageName }, typeNames); + return this; + } + + public FieldSearcher type(Class type) { + this.type = type; + return this; + } + + public FieldSearcher instance(Object instance) { + this.instance = instance; + return this; + } + + public FieldSearcher of(Object instance) { + this.type = instance.getClass(); + this.instance = instance; + return this; + } + + public FieldSearcher fieldType(Class fieldType) { + this.fieldType = fieldType; + return this; + } + + public FieldSearcher fieldTypeOf(String... fieldTypeNames) { + this.fieldType = ReflectionUtils.searchType(fieldTypeNames); + return this; + } + + public FieldSearcher fieldOf(String... fieldNames) { + this.fieldNames = fieldNames; + return this; + } + + public Field search() { + if (type == null) { + throw new IllegalStateException("Class not defined"); + } + + if (fieldNames == null || fieldNames.length == 0) { + throw new IllegalStateException("Field names not specified"); + } + + return ReflectionUtils.searchField(type, fieldType, fieldNames); + } + + public Object get() { + return ReflectionUtils.getFieldValue(search(), instance); + } + + public T get(Class type) { + return type.cast(get()); + } +} diff --git a/common/src/main/java/org/zhdev/reflection/MethodSearcher.java b/common/src/main/java/org/zhdev/reflection/MethodSearcher.java new file mode 100755 index 0000000..da144a4 --- /dev/null +++ b/common/src/main/java/org/zhdev/reflection/MethodSearcher.java @@ -0,0 +1,103 @@ +package org.zhdev.reflection; + +import org.zhdev.util.ReflectionUtils; + +import java.lang.reflect.Method; + +public class MethodSearcher { + private Class type; + private Object instance; + private Class returnType; + private String[] methodNames; + private Class[] parameterTypes; + private Object[] args; + + public MethodSearcher typeOf(String typeName) { + this.type = ReflectionUtils.getType(typeName); + return this; + } + + public MethodSearcher typeOf(String packageName, String typeName) { + this.type = ReflectionUtils.getType(packageName, typeName); + return this; + } + + public MethodSearcher typeOf(String... typeNames) { + this.type = ReflectionUtils.searchType(typeNames); + return this; + } + + public MethodSearcher typeOf(String packageName, String... typeNames) { + this.type = ReflectionUtils.searchType(new String[] { packageName }, typeNames); + return this; + } + + public MethodSearcher type(Class clazz) { + this.type = clazz; + return this; + } + + public MethodSearcher instance(Object instance) { + this.instance = instance; + return this; + } + + public MethodSearcher of(Object instance) { + this.type = instance.getClass(); + this.instance = instance; + return this; + } + + public MethodSearcher returns(Class returnType) { + this.returnType = returnType; + return this; + } + + public MethodSearcher returnsOf(String... returnTypeNames) { + this.returnType = ReflectionUtils.searchType(returnTypeNames); + return this; + } + + public MethodSearcher methodOf(String... methodNames) { + this.methodNames = methodNames; + return this; + } + + public MethodSearcher parameters(Class... parameterTypes) { + this.parameterTypes = parameterTypes; + return this; + } + + public MethodSearcher args(Object... args) { + this.args = args; + return this; + } + + public Method search() { + if (type == null) { + throw new IllegalStateException("Class not defined"); + } + + if (methodNames == null) { + methodNames = new String[0]; + } + + if (parameterTypes == null) { + parameterTypes = new Class[0]; + } + + if (args == null) { + args = new Object[0]; + } + + return ReflectionUtils.searchMethod(type, returnType, methodNames, parameterTypes); + } + + public Object invoke() { + return ReflectionUtils.invokeMethod(instance, search(), args); + } + + public T invoke(Class returnType) { + return returnType.cast(invoke()); + } +} diff --git a/common/src/main/java/org/zhdev/util/ArrayUtils.java b/common/src/main/java/org/zhdev/util/ArrayUtils.java new file mode 100644 index 0000000..4feabea --- /dev/null +++ b/common/src/main/java/org/zhdev/util/ArrayUtils.java @@ -0,0 +1,66 @@ +package org.zhdev.util; + +import java.util.Collection; +import java.util.function.Function; +import java.util.function.IntFunction; + +public class ArrayUtils { + public static T get(T[] array, int index) { + return index < array.length ? array[index] : null; + } + + public static T get(T[] array, int index, T fallback) { + T t = get(array, index); + return t == null ? fallback : t; + } + + public static T get(T[] array, int index, Function fallbackFunction) { + T t = get(array, index); + return t == null ? fallbackFunction.apply(array) : t; + } + + public static R[] map(T[] array, IntFunction arrayConstructor, Function function) { + R[] mappedArray = arrayConstructor.apply(array.length); + for (int i = 0; i < array.length; i ++) { + mappedArray[i] = function.apply(array[i]); + } + return mappedArray; + } + + public static String[] mapToString(T[] array, IntFunction arrayConstructor) { + return map(array, arrayConstructor, String::valueOf); + } + + public static Byte[] mapToByte(T[] array, IntFunction arrayConstructor) { + return map(array, arrayConstructor, NumberUtils::parseByte); + } + + public static Short[] mapToShort(T[] array, IntFunction arrayConstructor) { + return map(array, arrayConstructor, NumberUtils::parseShort); + } + + public static Integer[] mapToInteger(T[] array, IntFunction arrayConstructor) { + return map(array, arrayConstructor, NumberUtils::parseInt); + } + + public static Long[] mapToLong(T[] array, IntFunction arrayConstructor) { + return map(array, arrayConstructor, NumberUtils::parseLong); + } + + public static Float[] mapToFloat(T[] array, IntFunction arrayConstructor) { + return map(array, arrayConstructor, NumberUtils::parseFloat); + } + + public static Double[] mapToDouble(T[] array, IntFunction arrayConstructor) { + return map(array, arrayConstructor, NumberUtils::parseDouble); + } + + public static , T, R> C mapAndToCollection(T[] array, IntFunction collectionConstructor, Function function) { + C collection = collectionConstructor.apply(array.length); + for (T t : array) { + R r = function.apply(t); + collection.add(r); + } + return collection; + } +} diff --git a/common/src/main/java/org/zhdev/util/CollectionUtils.java b/common/src/main/java/org/zhdev/util/CollectionUtils.java new file mode 100644 index 0000000..2a05dac --- /dev/null +++ b/common/src/main/java/org/zhdev/util/CollectionUtils.java @@ -0,0 +1,68 @@ +package org.zhdev.util; + +import java.util.Collection; +import java.util.List; +import java.util.function.Function; +import java.util.function.IntFunction; + +public class CollectionUtils { + public static T get(List list, int index) { + return index < list.size() ? list.get(index) : null; + } + + public static T get(List list, int index, T fallback) { + T t = get(list, index); + return t == null ? fallback : t; + } + + public static T get(List list, int index, Function, T> fallbackFunction) { + T t = get(list, index); + return t == null ? fallbackFunction.apply(list) : t; + } + + public static , T, R> C map(Collection collection, IntFunction collectionConstructor, Function function) { + C mappedCollection = collectionConstructor.apply(collection.size()); + for (T t : collection) { + mappedCollection.add(function.apply(t)); + } + return mappedCollection; + } + + public static , T> C mapToString(Collection collection, IntFunction collectionConstructor) { + return map(collection, collectionConstructor, String::valueOf); + } + + public static , T> C mapToByte(Collection collection, IntFunction collectionConstructor) { + return map(collection, collectionConstructor, NumberUtils::parseByte); + } + + public static , T> C mapToShort(Collection collection, IntFunction collectionConstructor) { + return map(collection, collectionConstructor, NumberUtils::parseShort); + } + + public static , T> C mapToInteger(Collection collection, IntFunction collectionConstructor) { + return map(collection, collectionConstructor, NumberUtils::parseInt); + } + + public static , T> C mapToLong(Collection collection, IntFunction collectionConstructor) { + return map(collection, collectionConstructor, NumberUtils::parseLong); + } + + public static , T> C mapToFloat(Collection collection, IntFunction collectionConstructor) { + return map(collection, collectionConstructor, NumberUtils::parseFloat); + } + + public static , T> C mapToDouble(Collection collection, IntFunction collectionConstructor) { + return map(collection, collectionConstructor, NumberUtils::parseDouble); + } + + public static R[] mapAndToArray(Collection collection, IntFunction arrayConstructor, Function function) { + R[] array = arrayConstructor.apply(collection.size()); + int i = 0; + for (T t : collection) { + array[i] = function.apply(t); + i++; + } + return array; + } +} diff --git a/common/src/main/java/org/zhdev/util/DateTimeUtils.java b/common/src/main/java/org/zhdev/util/DateTimeUtils.java new file mode 100755 index 0000000..35778d8 --- /dev/null +++ b/common/src/main/java/org/zhdev/util/DateTimeUtils.java @@ -0,0 +1,143 @@ +package org.zhdev.util; + +import java.time.*; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; +import java.util.Locale; +import java.util.concurrent.TimeUnit; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class DateTimeUtils { + public static final long ONE_MINUTE = TimeUnit.MINUTES.toMillis(1); + public static final long ONE_HOUR = TimeUnit.HOURS.toMillis(1); + public static final long FOUR_HOURS = ONE_HOUR * 5; + public static final long ONE_DAY = TimeUnit.DAYS.toMillis(1); + public static final long TWO_DAYS = ONE_DAY * 2; + public static final long WEEK = ONE_DAY * 7; + + public static final String[] DATE_PATTERNS = {"d/M/yyyy", "d MMMM yyyy", "d/M/yy", "d MMM yyyy", "yyyy MMM d", "yyyy MMMM d", "yyyy/M/d", "yyyy-M-d", "d M yyyy", "d.M.yyyy", "yyyy.m.d"}; + public static final String[] DATETIME_PATTERNS = {"d/M/yyyy-H:mm", "d MMMM yyyy H:mm", "d/M/yy H:mm", "d MMM yyyy H:mm", "yyyy MMM d H:mm", "yyyy MMMM d H:mm", "yyyy/M/d-H:mm", "yyyy-M-d-H:mm", "d M yyyy H:mm", "d.M.yyyy H:mm", "yyyy.m.d H:mm"}; + + public static int getAge(LocalDate birthDate) { + return Period.between(birthDate, LocalDate.now()).getYears(); + } + + public static int getAge(long millis) { + return getAge(Instant.ofEpochMilli(millis).atZone(ZoneId.systemDefault()).toLocalDate()); + } + + public static LocalDate getLocalDate(String input, Locale locale, String... patterns) { + for (String pattern : patterns) { + try { + DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern, locale); + return LocalDate.parse(input, formatter); + } catch (DateTimeParseException ignored) {} + } + throw new IllegalArgumentException("Invalid date input: " + input); + } + + public static LocalDate getLocalDate(String input, String... patterns) { + return getLocalDate(input, Locale.getDefault(), patterns); + } + + + public static LocalDateTime getLocalDateTime(String input, Locale locale, String... patterns) { + for (String pattern : patterns) { + try { + DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern, locale); + return LocalDateTime.parse(input, formatter); + } catch (DateTimeParseException ignored) {} + } + throw new IllegalArgumentException("Invalid date input: " + input); + } + + public static LocalDateTime getLocalDateTime(String input, String... patterns) { + return getLocalDateTime(input, Locale.getDefault(), patterns); + } + + public static long toMillis(String str, TimeUnit unit) { + long total = 0; + Matcher m = Pattern.compile("([0-9]+)(?i)(ms|[a-z])?").matcher(str); + while (m.find()) { + int num = Integer.parseInt(m.group(1)); + String type = String.valueOf(m.group(2)); + if (type.equalsIgnoreCase("ms")) { + total += num; + } else { + switch (type.charAt(0)) { + case 't': case 'T': { + total += (num / 20.0) * 1000L; + break; + } + case 's': case 'S': { + total += TimeUnit.SECONDS.toMillis(num); + break; + } + case 'm': { + total += TimeUnit.MINUTES.toMillis(num); + break; + } + case 'h': case 'H': { + total += TimeUnit.HOURS.toMillis(num); + break; + } + case 'd': case 'D': { + total += TimeUnit.DAYS.toMillis(num); + break; + } + case 'w': case 'W': { + total += TimeUnit.DAYS.toMillis(num) * 7; + break; + } + case 'M': { + total += TimeUnit.DAYS.toMillis(num) * 31; + break; + } + case 'y': case 'Y': { + total += TimeUnit.DAYS.toMillis(num) * 365; + break; + } + default: { + if (unit == null) { + break; + } + switch (unit) { + case MILLISECONDS: total += num; + break; + case MINUTES: total += TimeUnit.MINUTES.toMillis(num); + break; + case HOURS: total += TimeUnit.HOURS.toMillis(num); + break; + case DAYS: total += TimeUnit.DAYS.toMillis(num); + break; + default: total += TimeUnit.SECONDS.toMillis(num); + break; + } + break; + } + } + } + } + return total; + } + + public static long toMillis(String str) { + return toMillis(str, TimeUnit.SECONDS); + } + + public static int toTicks(String str, TimeUnit unit) { + return (int) (toMillis(str, unit) / 1000.0 * 20); + } + + public static int toTicks(String str) { + return toTicks(str, TimeUnit.SECONDS); + } + + public static ZonedDateTime getZonedDateTime(ZoneId zoneId, long millis) { + if (ZoneId.systemDefault().equals(zoneId)) { + return ZonedDateTime.ofInstant(Instant.ofEpochMilli(millis), zoneId); + } + return LocalDateTime.ofInstant(Instant.ofEpochMilli(millis), zoneId).atZone(ZoneId.systemDefault()); + } +} diff --git a/common/src/main/java/org/zhdev/util/EnumUtils.java b/common/src/main/java/org/zhdev/util/EnumUtils.java new file mode 100755 index 0000000..680a07e --- /dev/null +++ b/common/src/main/java/org/zhdev/util/EnumUtils.java @@ -0,0 +1,82 @@ +package org.zhdev.util; + +public class EnumUtils { + private static > T[] getValues(T eNum) { + return getValues(eNum.getDeclaringClass()); + } + + private static > T[] getValues(Class clazz) { + return clazz.getEnumConstants(); + } + + private static > T indexOf(T[] values, int index, boolean orLast, boolean orFirst) { + if (index < 0) { + return orLast ? values[values.length - 1] : values[0]; + } + + int max = values.length - 1; + if (index > max) { + return orFirst ? values[0] : values[max]; + } + + return values[index]; + } + + private static > T indexOf(T[] values, int index) { + return indexOf(values, index, false, false); + } + + public static > T indexOf(Class clazz, int index, boolean orLast, boolean orFirst) { + return indexOf(getValues(clazz), index, orLast, orFirst); + } + + public static > T indexOf(Class clazz, int index) { + return indexOf(getValues(clazz), index); + } + + public static > T indexOf(T eNum, int index, boolean orLast, boolean orFirst) { + return indexOf(getValues(eNum), index, orLast, orFirst); + } + + public static > T indexOf(T eNum, int index) { + return indexOf(getValues(eNum), index); + } + + public static > T first(Class clazz) { + return getValues(clazz)[0]; + } + + public static > T last(Class clazz) { + T[] values = getValues(clazz); + return values[values.length - 1]; + } + + public static > T first(T eNum) { + return getValues(eNum)[0]; + } + + public static > T last(T eNum) { + T[] values = getValues(eNum); + return values[values.length - 1]; + } + + public static > T previous(T eNum, boolean orLast) { + int previous = eNum.ordinal() - 1; + return previous < 0 ? orLast ? last(eNum) : getValues(eNum)[0] : getValues(eNum)[previous]; + } + + public static > T next(T eNum, boolean orFirst) { + T[] values = getValues(eNum); + int max = values.length - 1; + int next = eNum.ordinal() + 1; + return next > max ? (orFirst ? values[0] : values[max]) : values[next]; + } + + public static > T previous(T eNum) { + return previous(eNum, false); + } + + public static > T next(T eNum) { + return next(eNum, false); + } +} diff --git a/common/src/main/java/org/zhdev/util/NumberUtils.java b/common/src/main/java/org/zhdev/util/NumberUtils.java new file mode 100755 index 0000000..aef2c0f --- /dev/null +++ b/common/src/main/java/org/zhdev/util/NumberUtils.java @@ -0,0 +1,132 @@ +package org.zhdev.util; + +public class NumberUtils { + public static boolean isDigit(String input) { + for (int i = 0; i < input.length(); i++){ + if (!Character.isDigit(input.charAt(i))) { + return false; + } + } + return true; + } + + public static byte parseByte(String str, byte def) { + try { + return Byte.parseByte(str); + } catch (NumberFormatException e) { + return def; + } + } + + public static short parseShort(String str, short def) { + try { + return Short.parseShort(str); + } catch (NumberFormatException e) { + return def; + } + } + + public static int parseInt(String str, int def) { + try { + return Integer.parseInt(str); + } catch (NumberFormatException e) { + return def; + } + } + + public static long parseLong(String str, long def) { + try { + return Long.parseLong(str); + } catch (NumberFormatException e) { + return def; + } + } + + public static double parseFloat(String str, float def) { + try { + return Float.parseFloat(str); + } catch (NumberFormatException e) { + return def; + } + } + + public static double parseDouble(String str, double def) { + try { + return Double.parseDouble(str); + } catch (NumberFormatException e) { + return def; + } + } + + public static Byte parseByte(Object obj, Byte def) { + try { + return Byte.parseByte(String.valueOf(obj)); + } catch (NumberFormatException e) { + return def; + } + } + + public static Byte parseByte(Object obj) { + return parseByte(obj, null); + } + + public static Short parseShort(Object obj, Short def) { + try { + return Short.parseShort(String.valueOf(obj)); + } catch (NumberFormatException e) { + return def; + } + } + + public static Short parseShort(Object obj) { + return parseShort(obj, null); + } + + public static Integer parseInt(Object obj, Integer def) { + try { + return Integer.parseInt(String.valueOf(obj)); + } catch (NumberFormatException e) { + return def; + } + } + + public static Integer parseInt(Object obj) { + return parseInt(obj, null); + } + + public static Long parseLong(Object obj, Long def) { + try { + return Long.parseLong(String.valueOf(obj)); + } catch (NumberFormatException e) { + return def; + } + } + + public static Long parseLong(Object obj) { + return parseLong(obj, null); + } + + public static Float parseFloat(Object obj, Float def) { + try { + return Float.parseFloat(String.valueOf(obj)); + } catch (NumberFormatException e) { + return def; + } + } + + public static Float parseFloat(Object obj) { + return parseFloat(obj, null); + } + + public static Double parseDouble(Object obj, Double def) { + try { + return Double.parseDouble(String.valueOf(obj)); + } catch (NumberFormatException e) { + return def; + } + } + + public static Double parseDouble(Object obj) { + return parseDouble(obj, null); + } +} diff --git a/common/src/main/java/org/zhdev/util/ReflectionUtils.java b/common/src/main/java/org/zhdev/util/ReflectionUtils.java new file mode 100755 index 0000000..115139f --- /dev/null +++ b/common/src/main/java/org/zhdev/util/ReflectionUtils.java @@ -0,0 +1,231 @@ +package org.zhdev.util; + +import org.zhdev.reflection.FieldSearcher; +import org.zhdev.reflection.MethodSearcher; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.Enumeration; +import java.util.function.Consumer; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; + +public class ReflectionUtils { + private static Method getMethod0(Class type, String methodName, Class... args) throws NoSuchMethodException { + Method method = type.getDeclaredMethod(methodName, args); + method.setAccessible(true); + return method; + } + + private static Field getField0(Class type, String fieldName) throws NoSuchFieldException { + Field field = type.getDeclaredField(fieldName); + field.setAccessible(true); + return field; + } + + private static boolean compareParameters(Class[] required, Class... parameters) { + if (required.length != parameters.length) { + return false; + } + + for (int i = 0; i < required.length; i++) { + if (!parameters[i].isAssignableFrom(required[i])) { + return false; + } + } + + return true; + } + + private static Method checkMethodType(Method method, Class requiredType) throws IllegalStateException { + if (requiredType == null || requiredType.isAssignableFrom(method.getReturnType())) return method; + throw new IllegalStateException(requiredType + " is not assignable from type of " + method); + } + + private static Field checkFieldType(Field field, Class requiredType) throws IllegalStateException { + if (requiredType == null || requiredType.isAssignableFrom(field.getType())) return field; + throw new IllegalStateException(requiredType + " is not assignable from type of " + field); + } + + public static Class getType(String typeName) throws NoClassDefFoundError { + try { + return Class.forName(typeName); + } catch (ClassNotFoundException e) { + throw new NoClassDefFoundError(typeName); + } + } + + public static Class searchType(String... typeNames) throws NoClassDefFoundError { + for (String typeName : typeNames) { + try { + return Class.forName(typeName); + } catch (ClassNotFoundException ignored) {} + } + + throw new NoClassDefFoundError(String.join(", ", typeNames)); + } + + public static Class getType(String packageName, String typeSimpleName) throws NoClassDefFoundError { + String typeName = packageName + '.' + typeSimpleName; + try { + return Class.forName(typeName); + } catch (ClassNotFoundException e) { + throw new NoClassDefFoundError(typeName); + } + } + + public static Class searchType(String[] packageNames, String... typeNames) throws NoClassDefFoundError { + for (String packageName : packageNames) { + for (String typeName : typeNames) { + try { + return Class.forName(packageName + '.' + typeName); + } catch (ClassNotFoundException ignored) {} + } + } + + throw new NoClassDefFoundError(String.join(", ", typeNames) + " in " + String.join(", ", packageNames)); + } + + public static Method getMethod(Class type, String methodName, Class... parameterTypes) throws NoSuchMethodError { + try { + return getMethod0(type, methodName, parameterTypes); + } catch (NoSuchMethodException e) { + throw new NoSuchMethodError(e.getMessage()); + } + } + + public static Method searchMethod(Class type, Class returnType, String[] methodNames, Class... parameterTypes) throws NoSuchMethodError { + IllegalStateException exception = null; + for (String methodName : methodNames) { + try { + return checkMethodType(getMethod0(type, methodName, parameterTypes), returnType); + } catch (IllegalStateException e) { + exception = e; + } catch (NoSuchMethodException ignored) { } + } + + if (parameterTypes.length > 0) { + for (Method m : type.getDeclaredMethods()) { + if (compareParameters(parameterTypes, m.getParameterTypes())) { + return checkMethodType(m, returnType); + } + } + } + + if (exception != null) { + throw exception; + } + + throw new NoSuchMethodError(String.join(", ", methodNames) + " in " + type); + } + + public static Object invokeMethod(Object instance, Method method, Object... args) throws IllegalStateException { + try { + return method.invoke(instance, args); + } catch (ReflectiveOperationException e) { + throw new IllegalStateException(e.getMessage()); + } + } + + public static Field getField(Class type, String fieldName) throws NoSuchFieldError { + try { + return getField0(type, fieldName); + } catch (NoSuchFieldException e) { + throw new NoSuchFieldError(fieldName); + } + } + + public static Field searchField(Class type, Class fieldType, String... fieldNames) throws NoSuchFieldError { + IllegalStateException exception = null; + for (String fieldName : fieldNames) { + try { + return checkFieldType(getField0(type, fieldName), fieldType); + } catch (IllegalStateException e) { + exception = e; + } catch (NoSuchFieldException ignored) {} + } + + if (exception != null) { + throw exception; + } + + throw new NoSuchFieldError(String.join(", ", fieldNames) + " in " + type); + } + + public static Object getFieldValue(Field field, Object instance) throws IllegalStateException { + try { + return field.get(instance); + } catch (IllegalAccessException e) { + throw new IllegalStateException(e.getMessage()); + } + } + + public static void setFieldValue(Field field, Object instance, Object value) throws IllegalStateException { + try { + field.set(instance, value); + } catch (IllegalAccessException e) { + throw new IllegalStateException(e.getMessage()); + } + } + + public static void forEachClass(ClassLoader loader, JarFile jarFile, String packageName, Consumer> consumer) { + for (Enumeration entry = jarFile.entries(); entry.hasMoreElements(); ) { + JarEntry jarEntry = entry.nextElement(); + String name = jarEntry.getName(); + if (!name.endsWith(".class")) { + continue; + } + + String link = name.substring(0, name.length() - 6).replace("/", "."); + + int index = link.lastIndexOf('.'); + String packagePath = index == -1 ? "" : link.substring(0, index); + + if (packagePath.equals(packageName)) { + try { + consumer.accept(loader.loadClass(link)); + } catch (ClassNotFoundException ignored) {} + } + } + } + + public static void forEachClass(ClassLoader loader, File file, String packageName, Consumer> consumer) { + try (JarFile jarFile = new JarFile(file)) { + forEachClass(loader, jarFile, packageName, consumer); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + + public static void forEachJarEntry(JarFile jarFile, String packageName, Consumer consumer) { + for (Enumeration entry = jarFile.entries(); entry.hasMoreElements(); ) { + JarEntry jarEntry = entry.nextElement(); + + String name = jarEntry.getName(); + int index = name.lastIndexOf('/'); + String packagePath = index == -1 ? name : name.substring(0, index); + + if (packagePath.equals(packageName)) { + consumer.accept(jarEntry); + } + } + } + + public static void forEachJarEntry(File file, String packageName, Consumer consumer) { + try (JarFile jarFile = new JarFile(file)) { + forEachJarEntry(jarFile, packageName, consumer); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + + public static MethodSearcher methodSearcher() { + return new MethodSearcher(); + } + + public static FieldSearcher fieldSearcher() { + return new FieldSearcher(); + } +} diff --git a/common/src/main/java/org/zhdev/util/ResourceUtils.java b/common/src/main/java/org/zhdev/util/ResourceUtils.java new file mode 100755 index 0000000..f3f36a8 --- /dev/null +++ b/common/src/main/java/org/zhdev/util/ResourceUtils.java @@ -0,0 +1,67 @@ +package org.zhdev.util; + +import java.io.*; +import java.net.URL; +import java.net.URLConnection; +import java.nio.file.Files; + +public class ResourceUtils { + public static InputStream getResource(String path, ClassLoader loader) { + try { + URL url = loader.getResource(path); + if (url == null) { + return null; + } + + URLConnection connection = url.openConnection(); + connection.setUseCaches(false); + return connection.getInputStream(); + } catch (IOException e) { + return null; + } + } + + public static InputStream getResource(String path) { + return getResource(path, ResourceUtils.class.getClassLoader()); + } + + public static boolean saveResource(String resourcePath, File outFile, ClassLoader loader) throws IllegalStateException { + if (resourcePath == null || resourcePath.equals("")) { + return false; + } + + resourcePath = resourcePath.replace('\\', '/'); + InputStream in = getResource(resourcePath, loader); + if (in == null) { + return false; + } + + File parent = outFile.getParentFile(); + if (parent != null && !parent.exists()) { + parent.mkdirs(); + } + + try { + if (!outFile.exists() || outFile.length() == 0) { + OutputStream stream = Files.newOutputStream(outFile.toPath()); + byte[] buf = new byte[1024]; + int len; + while ((len = in.read(buf)) > 0) { + stream.write(buf, 0, len); + } + stream.close(); + in.close(); + return true; + } + } catch (IOException e) { + throw new IllegalStateException("Could not save resource " + resourcePath + " to " + outFile, e); + } + + return false; + } + + + public static boolean saveResource(String resourcePath, File outFile) throws IllegalStateException { + return saveResource(resourcePath, outFile); + } +} diff --git a/common/src/main/java/org/zhdev/util/StringUtils.java b/common/src/main/java/org/zhdev/util/StringUtils.java new file mode 100755 index 0000000..7f9df2e --- /dev/null +++ b/common/src/main/java/org/zhdev/util/StringUtils.java @@ -0,0 +1,269 @@ +package org.zhdev.util; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +public class StringUtils { + public static String join(int beginIndex, int lastIndex, String delimiter, String lastDelimiter, String... elements) { + StringBuilder builder = new StringBuilder(); + for (; beginIndex < elements.length; beginIndex++) { + if (beginIndex == lastIndex) { + builder.append(lastDelimiter); + } else { + builder.append(delimiter); + } + builder.append(elements[beginIndex]); + } + return builder.toString(); + } + + public static String join(int beginIndex, String delimiter, String lastDelimiter, String... elements) { + return join(beginIndex, elements.length - 1, delimiter, lastDelimiter, elements); + } + + public static String join(String delimiter, String lastDelimiter, String... elements) { + return join(0, delimiter, lastDelimiter, elements); + } + + public static String join(int beginIndex, int lastIndex, String delimiter, String... elements) { + return join(beginIndex, lastIndex, delimiter, delimiter, elements); + } + + public static String join(int beginIndex, String delimiter, String... elements) { + return join(beginIndex, delimiter, delimiter, elements); + } + + public static String join(String delimiter, String... elements) { + return join(delimiter, delimiter, elements); + } + + public static String join(int beginIndex, int lastIndex, String delimiter, String lastDelimiter, Iterable elements) { + StringBuilder builder = new StringBuilder(); + Iterator iterator = elements.iterator(); + int i = 0; + while (iterator.hasNext()) { + if (i < beginIndex) { + continue; + } + String element = iterator.next(); + if (builder.length() > 0) { + if (iterator.hasNext()) { + builder.append(delimiter); + } else { + builder.append(lastDelimiter); + } + } + builder.append(element); + i++; + if (i == lastIndex) { + break; + } + } + return builder.toString(); + } + + public static String join(int beginIndex, String delimiter, String lastDelimiter, Iterable elements) { + return join(beginIndex, -1, delimiter, lastDelimiter, elements); + } + + public static String join(String delimiter, String lastDelimiter, Iterable elements) { + return join(0, delimiter, lastDelimiter, elements); + } + + public static String join(int beginIndex, int lastIndex, String delimiter, Iterable elements) { + return join(beginIndex, lastIndex, delimiter, delimiter, elements); + } + + public static String join(int beginIndex, String delimiter, Iterable elements) { + return join(beginIndex, delimiter, delimiter, elements); + } + + public static String join(String delimiter, Iterable elements) { + return join(delimiter, delimiter, elements); + } + + public static void replaceKeyValue(StringBuilder builder, Object... args) { + Object replacement = null; + for (int i = 0; i < args.length; i++) { + if (i % 2 == 0) { + replacement = args[i]; + } else { + replace(builder, String.valueOf(replacement), args[i]); + } + } + } + + /** + *
For example, + *
{@code
+     *     StringUtils.replaceKeyValue("Hi, %username%! This is %what%",
+     *                                 "%username%", "human",
+     *                                 "%what%", "Java program")
+     * }
+ */ + public static String replaceKeyValue(String str, Object... args) { + if (args.length == 0) { + return str; + } + StringBuilder builder = new StringBuilder(str); + replaceKeyValue(builder, args); + return builder.toString(); + } + + public static void replace(StringBuilder builder, String replacement, Object value) { + int index = builder.indexOf(replacement); + if (index == -1) { + return; + } + + String result = String.valueOf(value); + + do { + builder.replace(index, index + replacement.length(), result); + + index = builder.indexOf(replacement, index + result.length()); + } while (index != -1); + } + + public static String escape(String str, String escape, char... chars) { + StringBuilder builder = new StringBuilder(str); + + for (char c : chars) { + replace(builder, String.valueOf(c), escape + c); + } + + return builder.toString(); + } + + public static String escape(String str, char... chars) { + return escape(str, "\\", chars); + } + + public static String unescape(String str, String escape, char... chars) { + StringBuilder builder = new StringBuilder(str); + + for (char c : chars) { + replace(builder, escape + c, c); + } + + return builder.toString(); + } + + public static String unescape(String str, char... chars) { + return unescape(str, "\\", chars); + } + + public static void format(StringBuilder builder, Object... args) { + for (int i = 0; i < args.length; i++) { + String replacement = "{" + i + "}"; + Object arg = args[i]; + replace(builder, replacement, String.valueOf(arg)); + } + } + + public static String format(String str, Object... args) { + if (args.length == 0) { + return str; + } + StringBuilder builder = new StringBuilder(str); + format(builder, args); + return builder.toString(); + } + + public static String[] splitByDelimiter(String line, char delimiter, int limit, char escape, char open, char close) { + StringBuilder builder = new StringBuilder(); + List list = new ArrayList<>(); + + boolean quote = false; + Character previous = null; + for (int i = 0; i < line.length(); i++) { + if (list.size() == limit) { + break; + } + + char c = line.charAt(i); + builder.append(c); + if (!quote && c == open || c == close) { + if (previous == null || previous != escape) { + builder.setLength(builder.length() - 1); + quote = !quote; + } else { + builder.setLength(builder.length() - 2); + builder.append(c); + } + } else if (!quote && c == delimiter) { + builder.setLength(builder.length() - 1); + list.add(builder.toString()); + builder.setLength(0); + } + + previous = c; + } + + list.add(builder.toString()); + + return list.toArray(new String[0]); + } + + public static String[] splitByDelimiter(String line, char delimiter, int limit, char escape, char quotation) { + return splitByDelimiter(line, delimiter, limit, escape, quotation, quotation); + } + + public static String[] splitByDelimiter(String line, char delimiter, int limit, char escape) { + return splitByDelimiter(line, delimiter, limit, escape, '"'); + } + + public static String[] splitByDelimiter(String line, char delimiter, int limit) { + return splitByDelimiter(line, delimiter, limit, '\\'); + } + + public static String[] splitByDelimiter(String line, char delimiter) { + return splitByDelimiter(line, delimiter, -2); + } + + public static String[] splitByLength(String str, Character ignore, int length, int limit) { + StringBuilder builder = new StringBuilder(); + List list = new ArrayList<>(); + + int lastStrIndex = str.length() - 1; + boolean flag = false; + for (int i = 0; i < str.length(); i++) { + if (limit > 0 && list.size() == limit) { + break; + } + if (flag) { + builder.append(ignore); + flag = false; + } + + char c = str.charAt(i); + if (ignore == null || c != ignore) { + builder.append(c); + } else { + flag = true; + } + + if (i == lastStrIndex || (i + 1) % length == 0) { + list.add(builder.toString()); + builder.setLength(0); + } + } + + return list.toArray(new String[0]); + } + + public static String[] splitByLength(String str, char ignore, int length) { + return splitByLength(str, ignore, length, -1); + } + + public static String[] splitByLength(String str, int length) { + return splitByLength(str, null, length, -1); + } + + public static String upperFirstCase(String str) { + char[] chars = str.toCharArray(); + chars[0] = Character.toUpperCase(chars[0]); + return new String(chars); + } +} diff --git a/io/pom.xml b/io/pom.xml new file mode 100644 index 0000000..80ba09b --- /dev/null +++ b/io/pom.xml @@ -0,0 +1,20 @@ + + 4.0.0 + + + parent + org.zhdev.varioutil + 1.0-SNAPSHOT + + + io + + + + org.yaml + snakeyaml + 2.0 + compile + + + \ No newline at end of file diff --git a/io/src/main/java/org/zhdev/config/Config.java b/io/src/main/java/org/zhdev/config/Config.java new file mode 100644 index 0000000..c6671e8 --- /dev/null +++ b/io/src/main/java/org/zhdev/config/Config.java @@ -0,0 +1,41 @@ +package org.zhdev.config; + +import java.io.*; + +public interface Config extends ConfigSection { + String DEFAULT_KEY = "config.yml"; + + String getKey(); + + String[] getHeaderComments(); + + String[] getEndComments(); + + void setHeaderComments(String... headerComments); + + void setEndComments(String... endComments); + + void load(Reader reader); + + void load(InputStream stream) throws IOException, ConfigException; + + void load(File file) throws IOException, ConfigException; + + File load(String path) throws ConfigException; + + File load() throws ConfigException; + + void save(Writer writer); + + void save(OutputStream stream) throws IOException, ConfigException; + + void save(File file) throws IOException, ConfigException; + + File save(String path) throws ConfigException; + + File save() throws ConfigException; + + File saveIfEmpty(String path) throws ConfigException; + + File saveIfEmpty() throws ConfigException; +} diff --git a/io/src/main/java/org/zhdev/config/ConfigException.java b/io/src/main/java/org/zhdev/config/ConfigException.java new file mode 100644 index 0000000..8bb0e2c --- /dev/null +++ b/io/src/main/java/org/zhdev/config/ConfigException.java @@ -0,0 +1,18 @@ +package org.zhdev.config; + +public class ConfigException extends RuntimeException { + public ConfigException() { + } + + public ConfigException(Throwable cause) { + super(cause); + } + + public ConfigException(String s) { + super(s); + } + + public ConfigException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/io/src/main/java/org/zhdev/config/ConfigSection.java b/io/src/main/java/org/zhdev/config/ConfigSection.java new file mode 100644 index 0000000..722f83b --- /dev/null +++ b/io/src/main/java/org/zhdev/config/ConfigSection.java @@ -0,0 +1,123 @@ +package org.zhdev.config; + +import java.util.List; +import java.util.Map; +import java.util.function.Function; + +public interface ConfigSection extends Iterable { + String[] getBlockComments(String key); + + String[] getInlineComments(String key); + + void setBlockComments(String key, String... blockComments); + + void setInlineComments(String key, String... inlineComments); + + void removeBlockComments(String key); + + void removeInlineComments(String key); + + Map toMap(); + + T get(String key); + + T get(String key, T fallback); + + T get(String key, Function fallback); + + T getOrSet(String key, T fallback, String... blockComments); + + T getOrSet(String key, Function fallback, String... blockComments); + + ConfigSection getSection(String key, String... names); + + ConfigSection getOrCreateSection(String key, String... names); + + Byte getByte(String key); + + Byte getByte(String key, Byte fallback); + + Byte getByte(String key, Function fallback); + + Byte getOrSetByte(String key, Byte fallback, String... blockComments); + + Byte getOrSetByte(String key, Function fallback, String... blockComments); + + Short getShort(String key); + + Short getShort(String key, Short fallback); + + Short getShort(String key, Function fallback); + + Short getOrSetShort(String key, Short fallback, String... blockComments); + + Short getOrSetShort(String key, Function fallback, String... blockComments); + + Integer getInteger(String key); + + Integer getInteger(String key, Integer fallback); + + Integer getInteger(String key, Function fallback); + + Integer getOrSetInteger(String key, Integer fallback, String... blockComments); + + Integer getOrSetInteger(String key, Function fallback, String... blockComments); + + Long getLong(String key); + + Long getLong(String key, Long fallback); + + Long getLong(String key, Function fallback); + + Long getOrSetLong(String key, Long fallback, String... blockComments); + + Long getOrSetLong(String key, Function fallback, String... blockComments); + + Float getFloat(String key); + + Float getFloat(String key, Float fallback); + + Float getFloat(String key, Function fallback); + + Float getOrSetFloat(String key, Float fallback, String... blockComments); + + Float getOrSetFloat(String key, Function fallback, String... blockComments); + + Double getDouble(String key); + + Double getDouble(String key, Double fallback); + + Double getDouble(String key, Function fallback); + + Double getOrSetDouble(String key, Double fallback, String... blockComments); + + Double getOrSetDouble(String key, Function fallback, String... blockComments); + + String getString(String key); + + String getString(String key, String fallback); + + String getString(String key, Function fallback); + + String getOrSetString(String key, String fallback, String... blockComments); + + String getOrSetString(String key, Function fallback, String... blockComments); + + List getList(String key); + + List getList(String key, List fallback); + + List getList(String key, Function> fallback); + + List getOrSetList(String key, List fallback, String... blockComments); + + List getOrSetList(String key, Function> fallback, String... blockComments); + + T set(String key, T object, String... blockComments); + + T set(String key, T object); + + T remove(String key); + + void clear(); +} diff --git a/io/src/main/java/org/zhdev/config/ConfigSectionNode.java b/io/src/main/java/org/zhdev/config/ConfigSectionNode.java new file mode 100644 index 0000000..d02dc64 --- /dev/null +++ b/io/src/main/java/org/zhdev/config/ConfigSectionNode.java @@ -0,0 +1,19 @@ +package org.zhdev.config; + +class ConfigSectionNode { + Object value; + String[] blockComments; + String[] inlineComments; + + ConfigSectionNode(Object value, String[] blockComments) { + this.value = value; + this.blockComments = blockComments; + } + + ConfigSectionNode(Object value) { + this.value = value; + } + + ConfigSectionNode() { + } +} diff --git a/io/src/main/java/org/zhdev/config/MapConfigSection.java b/io/src/main/java/org/zhdev/config/MapConfigSection.java new file mode 100644 index 0000000..96c3851 --- /dev/null +++ b/io/src/main/java/org/zhdev/config/MapConfigSection.java @@ -0,0 +1,469 @@ +package org.zhdev.config; + +import java.util.*; +import java.util.function.Function; + +public class MapConfigSection implements ConfigSection { + protected final LinkedHashMap map; + + protected MapConfigSection(LinkedHashMap map) {; + this.map = map; + } + + protected MapConfigSection() { + this(new LinkedHashMap<>()); + } + + public String[] getBlockComments(String key) { + ConfigSectionNode node = map.get(key); + return node == null ? null : node.blockComments; + } + + public String[] getInlineComments(String key) { + ConfigSectionNode node = map.get(key); + return node == null ? null : node.inlineComments; + } + + public void setBlockComments(String key, String... blockComments) { + ConfigSectionNode node = map.get(key); + if (node == null) { + node = new ConfigSectionNode(); + map.put(key, node); + } + node.blockComments = blockComments; + } + + public void setInlineComments(String key, String... inlineComments) { + ConfigSectionNode node = map.get(key); + if (node == null) { + node = new ConfigSectionNode(); + map.put(key, node); + } + node.inlineComments = inlineComments; + } + + public void removeBlockComments(String key) { + ConfigSectionNode node = map.get(key); + if (node != null) { + node.blockComments = null; + } + } + + public void removeInlineComments(String key) { + ConfigSectionNode node = map.get(key); + if (node != null) { + node.inlineComments = null; + } + } + + @Override + public Map toMap() { + Map map = new LinkedHashMap<>(this.map.size()); + for (Map.Entry entry : this.map.entrySet()) { + Object obj = entry.getValue().value; + if (obj instanceof MapConfigSection) { + obj = ((MapConfigSection) obj).toMap(); + } + map.put(entry.getKey(), obj); + } + return map; + } + + @SuppressWarnings("unchecked") + public T get(String key) { + ConfigSectionNode node = map.get(key); + return node == null ? null : (T) node.value; + } + + @SuppressWarnings("unchecked") + public T get(String key, T fallback) { + ConfigSectionNode node = map.get(key); + return node == null ? fallback : (T) node.value; + } + + public T get(String key, Function fallback) { + T object = get(key); + return object == null ? fallback.apply(key) : object; + } + + public T getOrSet(String key, T fallback, String... blockComments) { + T object = get(key); + if (object == null) { + map.put(key, new ConfigSectionNode(fallback, blockComments)); + return fallback; + } + return object; + } + + public T getOrSet(String key, Function fallback, String... blockComments) { + T object = get(key); + if (object == null) { + object = fallback.apply(key); + map.put(key, new ConfigSectionNode(object, blockComments)); + } + return object; + } + + public MapConfigSection getSection(String key, String... names) { + Object object = get(key); + if (object instanceof MapConfigSection) { + MapConfigSection section = (MapConfigSection) object; + for (String n : names) { + section = section.getSection(n); + if (section == null) return null; + } + return section; + } + return null; + } + + public MapConfigSection getOrCreateSection(String key, String... names) { + MapConfigSection section; + Object object = get(key); + if (object instanceof MapConfigSection) { + section = (MapConfigSection) object; + } else { + section = new MapConfigSection(); + map.put(key, new ConfigSectionNode(section)); + } + for (String n : names) section = section.getOrCreateSection(n); + return section; + } + + public Byte getByte(String key) { + Object object = get(key); + if (object instanceof Byte) { + return (Byte) object; + } else if (object instanceof Number) { + Number number = (Number) object; + return number.byteValue(); + } + return null; + } + + public Byte getByte(String key, Byte fallback) { + Byte object = getByte(key); + return object == null ? fallback : object; + } + + public Byte getByte(String key, Function fallback) { + Byte object = getByte(key); + return object == null ? fallback.apply(key) : object; + } + + public Byte getOrSetByte(String key, Byte fallback, String... blockComments) { + Byte object = getByte(key); + if (object == null) { + map.put(key, new ConfigSectionNode(fallback, blockComments)); + return fallback; + } + return object; + } + + public Byte getOrSetByte(String key, Function fallback, String... blockComments) { + Byte object = getByte(key); + if (object == null) { + object = fallback.apply(key); + map.put(key, new ConfigSectionNode(object, blockComments)); + } + return object; + } + + public Short getShort(String key) { + Object object = get(key); + if (object instanceof Short) { + return (Short) object; + } else if (object instanceof Number) { + Number number = (Number) object; + return number.shortValue(); + } + return null; + } + + public Short getShort(String key, Short fallback) { + Short object = getShort(key); + return object == null ? fallback : object; + } + + public Short getShort(String key, Function fallback) { + Short object = getShort(key); + return object == null ? fallback.apply(key) : object; + } + + public Short getOrSetShort(String key, Short fallback, String... blockComments) { + Short object = getShort(key); + if (object == null) { + map.put(key, new ConfigSectionNode(fallback, blockComments)); + return fallback; + } + return object; + } + + public Short getOrSetShort(String key, Function fallback, String... blockComments) { + Short object = getShort(key); + if (object == null) { + object = fallback.apply(key); + map.put(key, new ConfigSectionNode(object, blockComments)); + } + return object; + } + + public Integer getInteger(String key) { + Object object = get(key); + if (object instanceof Integer) { + return (Integer) object; + } else if (object instanceof Number) { + Number number = (Number) object; + return number.intValue(); + } + return null; + } + + public Integer getInteger(String key, Integer fallback) { + Integer object = getInteger(key); + return object == null ? fallback : object; + } + + public Integer getInteger(String key, Function fallback) { + Integer object = getInteger(key); + return object == null ? fallback.apply(key) : object; + } + + public Integer getOrSetInteger(String key, Integer fallback, String... blockComments) { + Integer object = getInteger(key); + if (object == null) { + map.put(key, new ConfigSectionNode(fallback, blockComments)); + return fallback; + } + return object; + } + + public Integer getOrSetInteger(String key, Function fallback, String... blockComments) { + Integer object = getInteger(key); + if (object == null) { + object = fallback.apply(key); + map.put(key, new ConfigSectionNode(object, blockComments)); + } + return object; + } + + public Long getLong(String key) { + Object object = get(key); + if (object instanceof Long) { + return (Long) object; + } else if (object instanceof Number) { + Number number = (Number) object; + return number.longValue(); + } + return null; + } + + public Long getLong(String key, Long fallback) { + Long object = getLong(key); + return object == null ? fallback : object; + } + + public Long getLong(String key, Function fallback) { + Long object = getLong(key); + return object == null ? fallback.apply(key) : object; + } + + public Long getOrSetLong(String key, Long fallback, String... blockComments) { + Long object = getLong(key); + if (object == null) { + map.put(key, new ConfigSectionNode(fallback, blockComments)); + return fallback; + } + return object; + } + + public Long getOrSetLong(String key, Function fallback, String... blockComments) { + Long object = getLong(key); + if (object == null) { + object = fallback.apply(key); + map.put(key, new ConfigSectionNode(object, blockComments)); + } + return object; + } + + public Float getFloat(String key) { + Object object = get(key); + if (object instanceof Float) { + return (Float) object; + } else if (object instanceof Number) { + Number number = (Number) object; + return number.floatValue(); + } + return null; + } + + public Float getFloat(String key, Float fallback) { + Float object = getFloat(key); + return object == null ? fallback : object; + } + + public Float getFloat(String key, Function fallback) { + Float object = getFloat(key); + return object == null ? fallback.apply(key) : object; + } + + public Float getOrSetFloat(String key, Float fallback, String... blockComments) { + Float object = getFloat(key); + if (object == null) { + map.put(key, new ConfigSectionNode(fallback, blockComments)); + return fallback; + } + return object; + } + + public Float getOrSetFloat(String key, Function fallback, String... blockComments) { + Float object = getFloat(key); + if (object == null) { + object = fallback.apply(key); + map.put(key, new ConfigSectionNode(object, blockComments)); + } + return object; + } + + public Double getDouble(String key) { + Object object = get(key); + if (object instanceof Double) { + return (Double) object; + } else if (object instanceof Number) { + Number number = (Number) object; + return number.doubleValue(); + } + return null; + } + + public Double getDouble(String key, Double fallback) { + Double object = getDouble(key); + return object == null ? fallback : object; + } + + public Double getDouble(String key, Function fallback) { + Double object = getDouble(key); + return object == null ? fallback.apply(key) : object; + } + + public Double getOrSetDouble(String key, Double fallback, String... blockComments) { + Double object = getDouble(key); + if (object == null) { + map.put(key, new ConfigSectionNode(fallback, blockComments)); + return fallback; + } + return object; + } + + public Double getOrSetDouble(String key, Function fallback, String... blockComments) { + Double object = getDouble(key); + if (object == null) { + object = fallback.apply(key); + map.put(key, new ConfigSectionNode(object, blockComments)); + } + return object; + } + + public String getString(String key) { + Object object = get(key); + return object == null ? null : object.toString(); + } + + public String getString(String key, String fallback) { + String object = getString(key); + return object == null ? fallback : object; + } + + public String getString(String key, Function fallback) { + String object = getString(key); + return object == null ? fallback.apply(key) : object; + } + + public String getOrSetString(String key, String fallback, String... blockComments) { + String object = getString(key); + if (object == null) { + map.put(key, new ConfigSectionNode(fallback, blockComments)); + return fallback; + } + return object; + } + + public String getOrSetString(String key, Function fallback, String... blockComments) { + String object = getString(key); + if (object == null) { + object = fallback.apply(key); + map.put(key, new ConfigSectionNode(object, blockComments)); + } + return object; + } + + public List getList(String key) { + Object object = get(key); + return object instanceof List ? (List) object : null; + } + + public List getList(String key, List fallback) { + List object = getList(key); + return object == null ? fallback : object; + } + + public List getList(String key, Function> fallback) { + List object = getList(key); + return object == null ? fallback.apply(key) : object; + } + + public List getOrSetList(String key, List fallback, String... blockComments) { + List object = getList(key); + if (object == null) { + map.put(key, new ConfigSectionNode(fallback, blockComments)); + return fallback; + } + return object; + } + + public List getOrSetList(String key, Function> fallback, String... blockComments) { + List object = getList(key); + if (object == null) { + object = fallback.apply(key); + map.put(key, new ConfigSectionNode(fallback, blockComments)); + } + return object; + } + + @SuppressWarnings("unchecked") + public T set(String key, T value, String... blockComments) { + ConfigSectionNode node = map.get(key); + if (node == null) { + return (T) map.put(key, new ConfigSectionNode(value, blockComments)); + } + Object oldValue = node.value; + node.value = value; + node.blockComments = blockComments; + return (T) oldValue; + } + + @SuppressWarnings("unchecked") + public T set(String key, T value) { + ConfigSectionNode node = map.get(key); + if (node == null) { + return (T) map.put(key, new ConfigSectionNode(value)); + } + Object oldValue = node.value; + node.value = value; + return (T) oldValue; + } + + @SuppressWarnings("unchecked") + public T remove(String key) { + return (T) map.remove(key); + } + + public void clear() { + map.clear(); + } + + @Override + public Iterator iterator() { + return map.keySet().iterator(); + } +} diff --git a/io/src/main/java/org/zhdev/config/YamlConfig.java b/io/src/main/java/org/zhdev/config/YamlConfig.java new file mode 100644 index 0000000..cd523ef --- /dev/null +++ b/io/src/main/java/org/zhdev/config/YamlConfig.java @@ -0,0 +1,258 @@ +package org.zhdev.config; + +import org.yaml.snakeyaml.DumperOptions; +import org.yaml.snakeyaml.LoaderOptions; +import org.yaml.snakeyaml.Yaml; +import org.yaml.snakeyaml.comments.CommentLine; +import org.yaml.snakeyaml.comments.CommentType; +import org.yaml.snakeyaml.nodes.*; +import org.yaml.snakeyaml.parser.ParserException; + +import java.io.*; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class YamlConfig extends MapConfigSection implements Config { + protected static final YamlConfigConstructor CONSTRUCTOR; + protected static final YamlConfigRepresenter REPRESENTER; + protected static final Yaml YAML; + + protected final String key; + + protected String[] headerComments; + protected String[] endComments; + + public YamlConfig(String key) { + super(null); + this.key = key; + } + + public YamlConfig() { + this(DEFAULT_KEY); + } + + @Override + public String getKey() { + return key; + } + + @Override + public String[] getHeaderComments() { + return headerComments; + } + + @Override + public String[] getEndComments() { + return endComments; + } + + @Override + public void setHeaderComments(String... headerComments) { + this.headerComments = headerComments; + } + + @Override + public void setEndComments(String... endComments) { + this.endComments = endComments; + } + + private String[] createComments(List lines) { + String[] comments = new String[lines.size()]; + for (int i = 0; i < lines.size(); i++) { + CommentLine line = lines.get(i); + comments[i] = line.getValue().trim(); + } + return comments; + } + + protected Object constructHandle(Node keyNode, Node valueNode, String key, Object value) { + if (valueNode instanceof MappingNode) { + MapConfigSection childSection = new MapConfigSection(); + nodesToSections(childSection, (MappingNode) valueNode); + value = childSection; + } + + return value; + } + + private void nodesToSections(MapConfigSection section, MappingNode node) { + for (NodeTuple tuple : node.getValue()) { + Node keyNode = tuple.getKeyNode(); + Node valueNode = tuple.getValueNode(); + String key = String.valueOf(CONSTRUCTOR.constructObject(keyNode)); + Object value = constructHandle(keyNode, valueNode, key, CONSTRUCTOR.constructObject(valueNode)); + + ConfigSectionNode sectionNode = new ConfigSectionNode(value); + if (keyNode.getBlockComments() != null && keyNode.getBlockComments().size() > 0) { + sectionNode.blockComments = createComments(keyNode.getBlockComments()); + } + + if (keyNode.getInLineComments() != null && keyNode.getInLineComments().size() > 0) { + sectionNode.inlineComments = createComments((valueNode instanceof MappingNode || valueNode instanceof SequenceNode ? keyNode : valueNode).getInLineComments()); + } + + section.map.put(key, sectionNode); + } + } + + @Override + public void load(Reader reader) throws ConfigException { + try { + MappingNode node = (MappingNode) YAML.compose(reader); + if (node == null) return; + if (node.getBlockComments() != null && node.getBlockComments().size() > 0) { + headerComments = createComments(node.getBlockComments()); + } + if (node.getEndComments() != null && node.getEndComments().size() > 0) { + endComments = createComments(node.getEndComments()); + } + nodesToSections(this, node); + } catch (ParserException e) { + throw new ConfigException(e); + } + } + + @Override + public void load(InputStream stream) { + load(new InputStreamReader(stream, StandardCharsets.UTF_8)); + } + + @Override + public void load(File file) throws IOException, ConfigException { + load(Files.newInputStream(file.toPath())); + } + + @Override + public File load(String path) throws ConfigException { + File file = new File(path); + try { + if (file.exists()) load(file); + } catch (IOException e) { + throw new ConfigException(e); + } + return file; + } + + @Override + public File load() throws ConfigException { + return load(key); + } + + private List createCommentLines(String[] comments, CommentType commentType) { + List lines = new ArrayList<>(comments.length); + for (String comment : comments) { + lines.add(new CommentLine(null, null, comment.isEmpty() ? comment : " " + comment, commentType)); + } + return lines; + } + + protected Node representHandle(String key, Object value) { + Node valueNode; + if (value instanceof MapConfigSection) { + valueNode = sectionsToNodes((MapConfigSection) value); + } else { + valueNode = REPRESENTER.represent(value); + } + return valueNode; + } + + private MappingNode sectionsToNodes(MapConfigSection section) { + List tuples = new ArrayList<>(); + for (Map.Entry entry : section.map.entrySet()) { + String key = entry.getKey(); + ConfigSectionNode sectionNode = entry.getValue(); + Object value = sectionNode.value; + + Node keyNode = REPRESENTER.represent(key); + Node valueNode = representHandle(key, value); + + keyNode.setBlockComments(sectionNode.blockComments == null ? null : createCommentLines(sectionNode.blockComments, CommentType.BLOCK)); + + (valueNode instanceof MappingNode || valueNode instanceof SequenceNode ? keyNode : valueNode).setInLineComments(sectionNode.inlineComments == null ? null : createCommentLines(sectionNode.inlineComments, CommentType.IN_LINE)); + tuples.add(new NodeTuple(keyNode, valueNode)); + } + + return new MappingNode(Tag.MAP, tuples, DumperOptions.FlowStyle.BLOCK); + } + + @Override + public void save(Writer writer) { + MappingNode node = sectionsToNodes(this); + node.setBlockComments(headerComments == null ? null : createCommentLines(headerComments, CommentType.BLOCK)); + node.setEndComments(endComments == null ? null : createCommentLines(endComments, CommentType.BLOCK)); + YAML.serialize(node, writer); + } + + @Override + public void save(OutputStream stream) { + save(new OutputStreamWriter(stream, StandardCharsets.UTF_8)); + } + + @Override + public void save(File file) throws IOException { + save(Files.newOutputStream(file.toPath())); + } + + @Override + public File save(String path) throws ConfigException { + File file = new File(path); + if (!file.exists()) { + File parent = file.getParentFile(); + if (parent != null) parent.mkdirs(); + try { + file.createNewFile(); + save(file); + } catch (IOException e) { + throw new ConfigException(e); + } + } + return file; + } + + @Override + public File save() throws ConfigException { + return save(key); + } + + @Override + public File saveIfEmpty(String path) throws ConfigException { + File file = new File(path); + if (file.length() == 0) { + File parent = file.getParentFile(); + if (parent != null) parent.mkdirs(); + try { + file.createNewFile(); + save(file); + } catch (IOException e) { + throw new ConfigException(e); + } + } + return file; + } + + @Override + public File saveIfEmpty() throws ConfigException { + return saveIfEmpty(key); + } + + static { + LoaderOptions loaderOptions = new LoaderOptions(); + loaderOptions.setProcessComments(true); + + DumperOptions dumperOptions = new DumperOptions(); + dumperOptions.setProcessComments(true); + dumperOptions.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); + dumperOptions.setDefaultScalarStyle(DumperOptions.ScalarStyle.PLAIN); + + YamlConfigRepresenter representer = new YamlConfigRepresenter(dumperOptions); + representer.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); + representer.setDefaultScalarStyle(DumperOptions.ScalarStyle.PLAIN); + + REPRESENTER = representer; + + YAML = new Yaml(CONSTRUCTOR = new YamlConfigConstructor(loaderOptions), representer, dumperOptions, loaderOptions); + } +} diff --git a/io/src/main/java/org/zhdev/config/YamlConfigConstructor.java b/io/src/main/java/org/zhdev/config/YamlConfigConstructor.java new file mode 100644 index 0000000..f3eb654 --- /dev/null +++ b/io/src/main/java/org/zhdev/config/YamlConfigConstructor.java @@ -0,0 +1,16 @@ +package org.zhdev.config; + +import org.yaml.snakeyaml.LoaderOptions; +import org.yaml.snakeyaml.constructor.SafeConstructor; +import org.yaml.snakeyaml.nodes.Node; + +public class YamlConfigConstructor extends SafeConstructor { + public YamlConfigConstructor(LoaderOptions loaderOptions) { + super(loaderOptions); + } + + @Override + protected Object constructObject(Node node) { + return super.constructObject(node); + } +} diff --git a/io/src/main/java/org/zhdev/config/YamlConfigRepresenter.java b/io/src/main/java/org/zhdev/config/YamlConfigRepresenter.java new file mode 100644 index 0000000..dbbd2d2 --- /dev/null +++ b/io/src/main/java/org/zhdev/config/YamlConfigRepresenter.java @@ -0,0 +1,10 @@ +package org.zhdev.config; + +import org.yaml.snakeyaml.DumperOptions; +import org.yaml.snakeyaml.representer.Representer; + +public class YamlConfigRepresenter extends Representer { + public YamlConfigRepresenter(DumperOptions options) { + super(options); + } +} diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..303b2cb --- /dev/null +++ b/pom.xml @@ -0,0 +1,169 @@ + + 4.0.0 + + org.zhdev.varioutil + parent + 1.0-SNAPSHOT + pom + + + UTF-8 + UTF-8 + + + + common + io + bukkit + all + + + + install + + + src\main\resources + true + + + pattern + false + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.10.1 + + 8 + 8 + + + + org.apache.maven.plugins + maven-shade-plugin + 3.4.1 + + + + *:* + + META-INF/** + + + + true + false + true + + + + package + + shade + + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.2.2 + + + false + + false + false + false + + + + + + + + + + + deploy + + clean install deploy + + + org.apache.maven.plugins + maven-deploy-plugin + 2.7 + + local::default::file:${user.home}/repo/maven/ + + + + deploy + + deploy + + + + + + + + + javadoc + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.4.1 + + + attach-javadocs + + jar + + + + + + + + + + + + + + source + + + + org.apache.maven.plugins + maven-source-plugin + 3.2.1 + + + attach-sources + verify + + jar-no-fork + + + + + + + + + + + + org.jetbrains + annotations-java5 + 24.0.1 + provided + + + \ No newline at end of file