Initial
This commit is contained in:
commit
e443249166
29 changed files with 2887 additions and 0 deletions
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
.idea
|
||||||
|
target
|
||||||
|
*/target
|
||||||
21
LICENSE.md
Normal file
21
LICENSE.md
Normal file
|
|
@ -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.
|
||||||
92
README.md
Normal file
92
README.md
Normal file
|
|
@ -0,0 +1,92 @@
|
||||||
|
### Add as maven dependency
|
||||||
|
```xml
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>zhdev-repo</id>
|
||||||
|
<url>https://repo.zhdev.org/maven</url>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
```
|
||||||
|
```xml
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.zhdev</groupId>
|
||||||
|
<artifactId>all</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example for reflection
|
||||||
|
#### Maven dependency
|
||||||
|
```xml
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.zhdev</groupId>
|
||||||
|
<artifactId>common</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
```
|
||||||
|
#### 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
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.zhdev</groupId>
|
||||||
|
<artifactId>io</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
```
|
||||||
|
#### 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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
32
all/pom.xml
Normal file
32
all/pom.xml
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
<project>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<artifactId>parent</artifactId>
|
||||||
|
<groupId>org.zhdev.varioutil</groupId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>all</artifactId>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>${project.groupId}</groupId>
|
||||||
|
<artifactId>common</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>${project.groupId}</groupId>
|
||||||
|
<artifactId>io</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>${project.groupId}</groupId>
|
||||||
|
<artifactId>bukkit</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
||||||
51
bukkit/pom.xml
Normal file
51
bukkit/pom.xml
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
<project>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<artifactId>parent</artifactId>
|
||||||
|
<groupId>org.zhdev.varioutil</groupId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>bukkit</artifactId>
|
||||||
|
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>spigot-repo</id>
|
||||||
|
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>${project.groupId}</groupId>
|
||||||
|
<artifactId>io</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>${project.groupId}</groupId>
|
||||||
|
<artifactId>common</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.spigotmc</groupId>
|
||||||
|
<artifactId>spigot-api</artifactId>
|
||||||
|
<version>1.20-R0.1-SNAPSHOT</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.spigotmc</groupId>
|
||||||
|
<artifactId>spigot</artifactId>
|
||||||
|
<version>1.20-R0.1-SNAPSHOT</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.spigotmc</groupId>
|
||||||
|
<artifactId>minecraft-server</artifactId>
|
||||||
|
<version>1.20-R0.1-SNAPSHOT</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
||||||
15
bukkit/src/main/java/org/zhdev/config/BukkitConfig.java
Normal file
15
bukkit/src/main/java/org/zhdev/config/BukkitConfig.java
Normal file
|
|
@ -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;
|
||||||
|
}
|
||||||
77
bukkit/src/main/java/org/zhdev/config/BukkitYamlConfig.java
Normal file
77
bukkit/src/main/java/org/zhdev/config/BukkitYamlConfig.java
Normal file
|
|
@ -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<String, Object> 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<String, Object> 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
11
common/pom.xml
Normal file
11
common/pom.xml
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
<project>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<artifactId>parent</artifactId>
|
||||||
|
<groupId>org.zhdev.varioutil</groupId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>common</artifactId>
|
||||||
|
</project>
|
||||||
198
common/src/main/java/org/zhdev/Version.java
Executable file
198
common/src/main/java/org/zhdev/Version.java
Executable file
|
|
@ -0,0 +1,198 @@
|
||||||
|
package org.zhdev;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public final class Version implements Comparable<Version> {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
83
common/src/main/java/org/zhdev/reflection/FieldSearcher.java
Executable file
83
common/src/main/java/org/zhdev/reflection/FieldSearcher.java
Executable file
|
|
@ -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> T get(Class<T> type) {
|
||||||
|
return type.cast(get());
|
||||||
|
}
|
||||||
|
}
|
||||||
103
common/src/main/java/org/zhdev/reflection/MethodSearcher.java
Executable file
103
common/src/main/java/org/zhdev/reflection/MethodSearcher.java
Executable file
|
|
@ -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> T invoke(Class<T> returnType) {
|
||||||
|
return returnType.cast(invoke());
|
||||||
|
}
|
||||||
|
}
|
||||||
66
common/src/main/java/org/zhdev/util/ArrayUtils.java
Normal file
66
common/src/main/java/org/zhdev/util/ArrayUtils.java
Normal file
|
|
@ -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> T get(T[] array, int index) {
|
||||||
|
return index < array.length ? array[index] : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> T get(T[] array, int index, T fallback) {
|
||||||
|
T t = get(array, index);
|
||||||
|
return t == null ? fallback : t;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> T get(T[] array, int index, Function<T[], T> fallbackFunction) {
|
||||||
|
T t = get(array, index);
|
||||||
|
return t == null ? fallbackFunction.apply(array) : t;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T, R> R[] map(T[] array, IntFunction<R[]> arrayConstructor, Function<T, R> 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 <T> String[] mapToString(T[] array, IntFunction<String[]> arrayConstructor) {
|
||||||
|
return map(array, arrayConstructor, String::valueOf);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> Byte[] mapToByte(T[] array, IntFunction<Byte[]> arrayConstructor) {
|
||||||
|
return map(array, arrayConstructor, NumberUtils::parseByte);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> Short[] mapToShort(T[] array, IntFunction<Short[]> arrayConstructor) {
|
||||||
|
return map(array, arrayConstructor, NumberUtils::parseShort);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> Integer[] mapToInteger(T[] array, IntFunction<Integer[]> arrayConstructor) {
|
||||||
|
return map(array, arrayConstructor, NumberUtils::parseInt);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> Long[] mapToLong(T[] array, IntFunction<Long[]> arrayConstructor) {
|
||||||
|
return map(array, arrayConstructor, NumberUtils::parseLong);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> Float[] mapToFloat(T[] array, IntFunction<Float[]> arrayConstructor) {
|
||||||
|
return map(array, arrayConstructor, NumberUtils::parseFloat);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> Double[] mapToDouble(T[] array, IntFunction<Double[]> arrayConstructor) {
|
||||||
|
return map(array, arrayConstructor, NumberUtils::parseDouble);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <C extends Collection<R>, T, R> C mapAndToCollection(T[] array, IntFunction<C> collectionConstructor, Function<T, R> function) {
|
||||||
|
C collection = collectionConstructor.apply(array.length);
|
||||||
|
for (T t : array) {
|
||||||
|
R r = function.apply(t);
|
||||||
|
collection.add(r);
|
||||||
|
}
|
||||||
|
return collection;
|
||||||
|
}
|
||||||
|
}
|
||||||
68
common/src/main/java/org/zhdev/util/CollectionUtils.java
Normal file
68
common/src/main/java/org/zhdev/util/CollectionUtils.java
Normal file
|
|
@ -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> T get(List<T> list, int index) {
|
||||||
|
return index < list.size() ? list.get(index) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> T get(List<T> list, int index, T fallback) {
|
||||||
|
T t = get(list, index);
|
||||||
|
return t == null ? fallback : t;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> T get(List<T> list, int index, Function<List<T>, T> fallbackFunction) {
|
||||||
|
T t = get(list, index);
|
||||||
|
return t == null ? fallbackFunction.apply(list) : t;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <C extends Collection<R>, T, R> C map(Collection<T> collection, IntFunction<C> collectionConstructor, Function<T, R> function) {
|
||||||
|
C mappedCollection = collectionConstructor.apply(collection.size());
|
||||||
|
for (T t : collection) {
|
||||||
|
mappedCollection.add(function.apply(t));
|
||||||
|
}
|
||||||
|
return mappedCollection;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <C extends Collection<String>, T> C mapToString(Collection<T> collection, IntFunction<C> collectionConstructor) {
|
||||||
|
return map(collection, collectionConstructor, String::valueOf);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <C extends Collection<Byte>, T> C mapToByte(Collection<T> collection, IntFunction<C> collectionConstructor) {
|
||||||
|
return map(collection, collectionConstructor, NumberUtils::parseByte);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <C extends Collection<Short>, T> C mapToShort(Collection<T> collection, IntFunction<C> collectionConstructor) {
|
||||||
|
return map(collection, collectionConstructor, NumberUtils::parseShort);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <C extends Collection<Integer>, T> C mapToInteger(Collection<T> collection, IntFunction<C> collectionConstructor) {
|
||||||
|
return map(collection, collectionConstructor, NumberUtils::parseInt);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <C extends Collection<Long>, T> C mapToLong(Collection<T> collection, IntFunction<C> collectionConstructor) {
|
||||||
|
return map(collection, collectionConstructor, NumberUtils::parseLong);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <C extends Collection<Float>, T> C mapToFloat(Collection<T> collection, IntFunction<C> collectionConstructor) {
|
||||||
|
return map(collection, collectionConstructor, NumberUtils::parseFloat);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <C extends Collection<Double>, T> C mapToDouble(Collection<T> collection, IntFunction<C> collectionConstructor) {
|
||||||
|
return map(collection, collectionConstructor, NumberUtils::parseDouble);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T, R> R[] mapAndToArray(Collection<T> collection, IntFunction<R[]> arrayConstructor, Function<T, R> function) {
|
||||||
|
R[] array = arrayConstructor.apply(collection.size());
|
||||||
|
int i = 0;
|
||||||
|
for (T t : collection) {
|
||||||
|
array[i] = function.apply(t);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
}
|
||||||
143
common/src/main/java/org/zhdev/util/DateTimeUtils.java
Executable file
143
common/src/main/java/org/zhdev/util/DateTimeUtils.java
Executable file
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
82
common/src/main/java/org/zhdev/util/EnumUtils.java
Executable file
82
common/src/main/java/org/zhdev/util/EnumUtils.java
Executable file
|
|
@ -0,0 +1,82 @@
|
||||||
|
package org.zhdev.util;
|
||||||
|
|
||||||
|
public class EnumUtils {
|
||||||
|
private static <T extends Enum<T>> T[] getValues(T eNum) {
|
||||||
|
return getValues(eNum.getDeclaringClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <T extends Enum<T>> T[] getValues(Class<T> clazz) {
|
||||||
|
return clazz.getEnumConstants();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <T extends Enum<T>> 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 extends Enum<T>> T indexOf(T[] values, int index) {
|
||||||
|
return indexOf(values, index, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T extends Enum<T>> T indexOf(Class<T> clazz, int index, boolean orLast, boolean orFirst) {
|
||||||
|
return indexOf(getValues(clazz), index, orLast, orFirst);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T extends Enum<T>> T indexOf(Class<T> clazz, int index) {
|
||||||
|
return indexOf(getValues(clazz), index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T extends Enum<T>> T indexOf(T eNum, int index, boolean orLast, boolean orFirst) {
|
||||||
|
return indexOf(getValues(eNum), index, orLast, orFirst);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T extends Enum<T>> T indexOf(T eNum, int index) {
|
||||||
|
return indexOf(getValues(eNum), index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T extends Enum<T>> T first(Class<T> clazz) {
|
||||||
|
return getValues(clazz)[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T extends Enum<T>> T last(Class<T> clazz) {
|
||||||
|
T[] values = getValues(clazz);
|
||||||
|
return values[values.length - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T extends Enum<T>> T first(T eNum) {
|
||||||
|
return getValues(eNum)[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T extends Enum<T>> T last(T eNum) {
|
||||||
|
T[] values = getValues(eNum);
|
||||||
|
return values[values.length - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T extends Enum<T>> 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 extends Enum<T>> 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 extends Enum<T>> T previous(T eNum) {
|
||||||
|
return previous(eNum, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T extends Enum<T>> T next(T eNum) {
|
||||||
|
return next(eNum, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
132
common/src/main/java/org/zhdev/util/NumberUtils.java
Executable file
132
common/src/main/java/org/zhdev/util/NumberUtils.java
Executable file
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
231
common/src/main/java/org/zhdev/util/ReflectionUtils.java
Executable file
231
common/src/main/java/org/zhdev/util/ReflectionUtils.java
Executable file
|
|
@ -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<Class<?>> consumer) {
|
||||||
|
for (Enumeration<JarEntry> 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<Class<?>> 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<JarEntry> consumer) {
|
||||||
|
for (Enumeration<JarEntry> 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<JarEntry> 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
67
common/src/main/java/org/zhdev/util/ResourceUtils.java
Executable file
67
common/src/main/java/org/zhdev/util/ResourceUtils.java
Executable file
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
269
common/src/main/java/org/zhdev/util/StringUtils.java
Executable file
269
common/src/main/java/org/zhdev/util/StringUtils.java
Executable file
|
|
@ -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<String> elements) {
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
Iterator<String> 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<String> elements) {
|
||||||
|
return join(beginIndex, -1, delimiter, lastDelimiter, elements);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String join(String delimiter, String lastDelimiter, Iterable<String> elements) {
|
||||||
|
return join(0, delimiter, lastDelimiter, elements);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String join(int beginIndex, int lastIndex, String delimiter, Iterable<String> elements) {
|
||||||
|
return join(beginIndex, lastIndex, delimiter, delimiter, elements);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String join(int beginIndex, String delimiter, Iterable<String> elements) {
|
||||||
|
return join(beginIndex, delimiter, delimiter, elements);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String join(String delimiter, Iterable<String> 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]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <blockquote>For example,
|
||||||
|
* <pre>{@code
|
||||||
|
* StringUtils.replaceKeyValue("Hi, %username%! This is %what%",
|
||||||
|
* "%username%", "human",
|
||||||
|
* "%what%", "Java program")
|
||||||
|
* }</pre></blockquote>
|
||||||
|
*/
|
||||||
|
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<String> 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<String> 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
20
io/pom.xml
Normal file
20
io/pom.xml
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
<project>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<artifactId>parent</artifactId>
|
||||||
|
<groupId>org.zhdev.varioutil</groupId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>io</artifactId>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.yaml</groupId>
|
||||||
|
<artifactId>snakeyaml</artifactId>
|
||||||
|
<version>2.0</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
||||||
41
io/src/main/java/org/zhdev/config/Config.java
Normal file
41
io/src/main/java/org/zhdev/config/Config.java
Normal file
|
|
@ -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;
|
||||||
|
}
|
||||||
18
io/src/main/java/org/zhdev/config/ConfigException.java
Normal file
18
io/src/main/java/org/zhdev/config/ConfigException.java
Normal file
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
123
io/src/main/java/org/zhdev/config/ConfigSection.java
Normal file
123
io/src/main/java/org/zhdev/config/ConfigSection.java
Normal file
|
|
@ -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> {
|
||||||
|
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<String, Object> toMap();
|
||||||
|
|
||||||
|
<T> T get(String key);
|
||||||
|
|
||||||
|
<T> T get(String key, T fallback);
|
||||||
|
|
||||||
|
<T> T get(String key, Function<String, T> fallback);
|
||||||
|
|
||||||
|
<T> T getOrSet(String key, T fallback, String... blockComments);
|
||||||
|
|
||||||
|
<T> T getOrSet(String key, Function<String, T> 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<String, Byte> fallback);
|
||||||
|
|
||||||
|
Byte getOrSetByte(String key, Byte fallback, String... blockComments);
|
||||||
|
|
||||||
|
Byte getOrSetByte(String key, Function<String, Byte> fallback, String... blockComments);
|
||||||
|
|
||||||
|
Short getShort(String key);
|
||||||
|
|
||||||
|
Short getShort(String key, Short fallback);
|
||||||
|
|
||||||
|
Short getShort(String key, Function<String, Short> fallback);
|
||||||
|
|
||||||
|
Short getOrSetShort(String key, Short fallback, String... blockComments);
|
||||||
|
|
||||||
|
Short getOrSetShort(String key, Function<String, Short> fallback, String... blockComments);
|
||||||
|
|
||||||
|
Integer getInteger(String key);
|
||||||
|
|
||||||
|
Integer getInteger(String key, Integer fallback);
|
||||||
|
|
||||||
|
Integer getInteger(String key, Function<String, Integer> fallback);
|
||||||
|
|
||||||
|
Integer getOrSetInteger(String key, Integer fallback, String... blockComments);
|
||||||
|
|
||||||
|
Integer getOrSetInteger(String key, Function<String, Integer> fallback, String... blockComments);
|
||||||
|
|
||||||
|
Long getLong(String key);
|
||||||
|
|
||||||
|
Long getLong(String key, Long fallback);
|
||||||
|
|
||||||
|
Long getLong(String key, Function<String, Long> fallback);
|
||||||
|
|
||||||
|
Long getOrSetLong(String key, Long fallback, String... blockComments);
|
||||||
|
|
||||||
|
Long getOrSetLong(String key, Function<String, Long> fallback, String... blockComments);
|
||||||
|
|
||||||
|
Float getFloat(String key);
|
||||||
|
|
||||||
|
Float getFloat(String key, Float fallback);
|
||||||
|
|
||||||
|
Float getFloat(String key, Function<String, Float> fallback);
|
||||||
|
|
||||||
|
Float getOrSetFloat(String key, Float fallback, String... blockComments);
|
||||||
|
|
||||||
|
Float getOrSetFloat(String key, Function<String, Float> fallback, String... blockComments);
|
||||||
|
|
||||||
|
Double getDouble(String key);
|
||||||
|
|
||||||
|
Double getDouble(String key, Double fallback);
|
||||||
|
|
||||||
|
Double getDouble(String key, Function<String, Double> fallback);
|
||||||
|
|
||||||
|
Double getOrSetDouble(String key, Double fallback, String... blockComments);
|
||||||
|
|
||||||
|
Double getOrSetDouble(String key, Function<String, Double> fallback, String... blockComments);
|
||||||
|
|
||||||
|
String getString(String key);
|
||||||
|
|
||||||
|
String getString(String key, String fallback);
|
||||||
|
|
||||||
|
String getString(String key, Function<String, String> fallback);
|
||||||
|
|
||||||
|
String getOrSetString(String key, String fallback, String... blockComments);
|
||||||
|
|
||||||
|
String getOrSetString(String key, Function<String, String> fallback, String... blockComments);
|
||||||
|
|
||||||
|
List<?> getList(String key);
|
||||||
|
|
||||||
|
List<?> getList(String key, List<?> fallback);
|
||||||
|
|
||||||
|
List<?> getList(String key, Function<String, List<?>> fallback);
|
||||||
|
|
||||||
|
List<?> getOrSetList(String key, List<?> fallback, String... blockComments);
|
||||||
|
|
||||||
|
List<?> getOrSetList(String key, Function<String, List<?>> fallback, String... blockComments);
|
||||||
|
|
||||||
|
<T> T set(String key, T object, String... blockComments);
|
||||||
|
|
||||||
|
<T> T set(String key, T object);
|
||||||
|
|
||||||
|
<T> T remove(String key);
|
||||||
|
|
||||||
|
void clear();
|
||||||
|
}
|
||||||
19
io/src/main/java/org/zhdev/config/ConfigSectionNode.java
Normal file
19
io/src/main/java/org/zhdev/config/ConfigSectionNode.java
Normal file
|
|
@ -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() {
|
||||||
|
}
|
||||||
|
}
|
||||||
469
io/src/main/java/org/zhdev/config/MapConfigSection.java
Normal file
469
io/src/main/java/org/zhdev/config/MapConfigSection.java
Normal file
|
|
@ -0,0 +1,469 @@
|
||||||
|
package org.zhdev.config;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
public class MapConfigSection implements ConfigSection {
|
||||||
|
protected final LinkedHashMap<String, ConfigSectionNode> map;
|
||||||
|
|
||||||
|
protected MapConfigSection(LinkedHashMap<String, ConfigSectionNode> 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<String, Object> toMap() {
|
||||||
|
Map<String, Object> map = new LinkedHashMap<>(this.map.size());
|
||||||
|
for (Map.Entry<String, ConfigSectionNode> 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> T get(String key) {
|
||||||
|
ConfigSectionNode node = map.get(key);
|
||||||
|
return node == null ? null : (T) node.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public <T> T get(String key, T fallback) {
|
||||||
|
ConfigSectionNode node = map.get(key);
|
||||||
|
return node == null ? fallback : (T) node.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> T get(String key, Function<String, T> fallback) {
|
||||||
|
T object = get(key);
|
||||||
|
return object == null ? fallback.apply(key) : object;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> 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> T getOrSet(String key, Function<String, T> 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<String, Byte> 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<String, Byte> 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<String, Short> 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<String, Short> 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<String, Integer> 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<String, Integer> 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<String, Long> 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<String, Long> 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<String, Float> 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<String, Float> 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<String, Double> 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<String, Double> 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<String, String> 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<String, String> 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<String, List<?>> 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<String, List<?>> 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> 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> 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> T remove(String key) {
|
||||||
|
return (T) map.remove(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear() {
|
||||||
|
map.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<String> iterator() {
|
||||||
|
return map.keySet().iterator();
|
||||||
|
}
|
||||||
|
}
|
||||||
258
io/src/main/java/org/zhdev/config/YamlConfig.java
Normal file
258
io/src/main/java/org/zhdev/config/YamlConfig.java
Normal file
|
|
@ -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<CommentLine> 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<CommentLine> createCommentLines(String[] comments, CommentType commentType) {
|
||||||
|
List<CommentLine> 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<NodeTuple> tuples = new ArrayList<>();
|
||||||
|
for (Map.Entry<String, ConfigSectionNode> 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
16
io/src/main/java/org/zhdev/config/YamlConfigConstructor.java
Normal file
16
io/src/main/java/org/zhdev/config/YamlConfigConstructor.java
Normal file
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
10
io/src/main/java/org/zhdev/config/YamlConfigRepresenter.java
Normal file
10
io/src/main/java/org/zhdev/config/YamlConfigRepresenter.java
Normal file
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
169
pom.xml
Normal file
169
pom.xml
Normal file
|
|
@ -0,0 +1,169 @@
|
||||||
|
<project>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>org.zhdev.varioutil</groupId>
|
||||||
|
<artifactId>parent</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
<packaging>pom</packaging>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<modules>
|
||||||
|
<module>common</module>
|
||||||
|
<module>io</module>
|
||||||
|
<module>bukkit</module>
|
||||||
|
<module>all</module>
|
||||||
|
</modules>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<defaultGoal>install</defaultGoal>
|
||||||
|
<resources>
|
||||||
|
<resource>
|
||||||
|
<directory>src\main\resources</directory>
|
||||||
|
<filtering>true</filtering>
|
||||||
|
</resource>
|
||||||
|
<resource>
|
||||||
|
<directory>pattern</directory>
|
||||||
|
<filtering>false</filtering>
|
||||||
|
</resource>
|
||||||
|
</resources>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>3.10.1</version>
|
||||||
|
<configuration>
|
||||||
|
<source>8</source>
|
||||||
|
<target>8</target>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-shade-plugin</artifactId>
|
||||||
|
<version>3.4.1</version>
|
||||||
|
<configuration>
|
||||||
|
<filters>
|
||||||
|
<filter>
|
||||||
|
<artifact>*:*</artifact>
|
||||||
|
<excludes>
|
||||||
|
<exclude>META-INF/**</exclude>
|
||||||
|
</excludes>
|
||||||
|
</filter>
|
||||||
|
</filters>
|
||||||
|
<shadedArtifactAttached>true</shadedArtifactAttached>
|
||||||
|
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||||
|
<minimizeJar>true</minimizeJar>
|
||||||
|
</configuration>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>shade</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
|
<version>3.2.2</version>
|
||||||
|
<configuration>
|
||||||
|
<archive>
|
||||||
|
<addMavenDescriptor>false</addMavenDescriptor>
|
||||||
|
<manifest>
|
||||||
|
<addClasspath>false</addClasspath>
|
||||||
|
<addDefaultEntries>false</addDefaultEntries>
|
||||||
|
<addDefaultImplementationEntries>false</addDefaultImplementationEntries>
|
||||||
|
</manifest>
|
||||||
|
<manifestEntries/>
|
||||||
|
</archive>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
<profiles>
|
||||||
|
<profile>
|
||||||
|
<id>deploy</id>
|
||||||
|
<build>
|
||||||
|
<defaultGoal>clean install deploy</defaultGoal>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-deploy-plugin</artifactId>
|
||||||
|
<version>2.7</version>
|
||||||
|
<configuration>
|
||||||
|
<altDeploymentRepository>local::default::file:${user.home}/repo/maven/</altDeploymentRepository>
|
||||||
|
</configuration>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>deploy</id>
|
||||||
|
<goals>
|
||||||
|
<goal>deploy</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</profile>
|
||||||
|
<profile>
|
||||||
|
<id>javadoc</id>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-javadoc-plugin</artifactId>
|
||||||
|
<version>3.4.1</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>attach-javadocs</id>
|
||||||
|
<goals>
|
||||||
|
<goal>jar</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
<configuration>
|
||||||
|
<additionalOptions>
|
||||||
|
<option>-Xdoclint:none</option>
|
||||||
|
</additionalOptions>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</profile>
|
||||||
|
<profile>
|
||||||
|
<id>source</id>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-source-plugin</artifactId>
|
||||||
|
<version>3.2.1</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>attach-sources</id>
|
||||||
|
<phase>verify</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>jar-no-fork</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</profile>
|
||||||
|
</profiles>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jetbrains</groupId>
|
||||||
|
<artifactId>annotations-java5</artifactId>
|
||||||
|
<version>24.0.1</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
||||||
Loading…
Add table
Add a link
Reference in a new issue