Initial project

This commit is contained in:
Timi
2025-07-19 14:39:55 +08:00
parent db30b3c9b7
commit 2f607878cb
39 changed files with 2043 additions and 94 deletions

128
.gitignore vendored
View File

@ -1,98 +1,38 @@
# ---> JetBrains
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# AWS User-specific
.idea/**/aws.xml
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/artifacts
# .idea/compiler.xml
# .idea/jarRepositories.xml
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# SonarLint plugin
.idea/sonarlint/
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
# ---> Maven
target/ target/
pom.xml.tag !.mvn/wrapper/maven-wrapper.jar
pom.xml.releaseBackup !**/src/main/**/target/
pom.xml.versionsBackup !**/src/test/**/target/
pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
.mvn/timing.properties
# https://github.com/takari/maven-wrapper#usage-without-binary-jar
.mvn/wrapper/maven-wrapper.jar
# Eclipse m2e generated files ### IntelliJ IDEA ###
# Eclipse Core .idea/modules.xml
.project .idea/jarRepositories.xml
# JDT-specific (Eclipse Java Development Tools) .idea/compiler.xml
.idea/libraries/
*.iws
*.iml
*.ipr
### Eclipse ###
.apt_generated
.classpath .classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/
### Mac OS ###
.DS_Store

4
.idea/.gitignore generated vendored Normal file
View File

@ -0,0 +1,4 @@
# Default ignored files
/shelf/
/workspace.xml
/CopilotChatHistory.xml

7
.idea/encodings.xml generated Normal file
View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
</component>
</project>

14
.idea/misc.xml generated Normal file
View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MavenProjectsManager">
<option name="originalFiles">
<list>
<option value="$PROJECT_DIR$/pom.xml" />
</list>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" project-jdk-name="21" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

124
.idea/uiDesigner.xml generated Normal file
View File

@ -0,0 +1,124 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Palette2">
<group name="Swing">
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
</item>
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
</item>
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.svg" removable="false" auto-create-binding="false" can-attach-label="true">
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
</item>
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
<initial-values>
<property name="text" value="Button" />
</initial-values>
</item>
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="RadioButton" />
</initial-values>
</item>
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="CheckBox" />
</initial-values>
</item>
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
<initial-values>
<property name="text" value="Label" />
</initial-values>
</item>
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
</item>
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
</item>
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
<preferred-size width="-1" height="20" />
</default-constraints>
</item>
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
</item>
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
</item>
</group>
</component>
</project>

6
.idea/vcs.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

42
pom.xml Normal file
View File

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.imyeyu.java</groupId>
<artifactId>timi-java</artifactId>
<version>0.0.1</version>
<packaging>jar</packaging>
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.test.skip>true</maven.test.skip>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
<configuration>
<source>21</source>
<target>21</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.10.3</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,86 @@
package com.imyeyu.java;
import java.util.Collection;
import java.util.Map;
/**
*
* @author 夜雨
* @since 2021-02-13 11:39
*/
public interface TimiJava {
/**
* 通用判空
* <pre>
* TimiJava.isEmpty(null) = true;
* TimiJava.isEmpty("") = true;
* TimiJava.isEmpty(" ") = true;
* TimiJava.isEmpty((StringBuilder) "") = true;
* TimiJava.isEmpty((StringBuilder) " ") = true;
* TimiJava.isEmpty((StringBuffer) "") = true;
* TimiJava.isEmpty((StringBuffer) " ") = true;
* TimiJava.isEmpty([]) = true;
* TimiJava.isEmpty(list.size == 0) = true;
* TimiJava.isEmpty(set.size == 0) = true;
* TimiJava.isEmpty(map.size == 0) = true;
*
* otherwise = false;
* </pre>
*
* @param object 对象
* @return true 为空
*/
static boolean isEmpty(Object object) {
if (object == null) {
return true;
}
if (object instanceof CharSequence charSequence) {
if (charSequence instanceof String string) {
return string.isEmpty() || string.trim().isEmpty();
} else {
return charSequence.toString().trim().isEmpty();
}
}
if (object.getClass().isArray()) {
return ((Object[]) object).length == 0;
}
if (object instanceof Collection<?> list) {
return list.isEmpty();
}
if (object instanceof Map<?, ?> map) {
return map.isEmpty();
}
return false;
}
/**
* {@link #isEmpty(Object)} 取反
*
* @param object 判定对象
* @return true 为非空
*/
static boolean isNotEmpty(Object object) {
return !isEmpty(object);
}
@SafeVarargs
static <T> T firstNotNull(T... objects) {
for (int i = 0; i < objects.length; i++) {
if (objects[i] != null) {
return objects[i];
}
}
return null;
}
@SafeVarargs
static <T> T firstNotEmpty(T... objects) {
for (int i = 0; i < objects.length; i++) {
if (TimiJava.isNotEmpty(objects[i])) {
return objects[i];
}
}
return null;
}
}

View File

@ -0,0 +1,20 @@
package com.imyeyu.java.bean;
/**
* 通用执行接口
*
* @author 夜雨
* @since 2022-02-09 20:06
*/
public interface Callback {
/** 执行程序 */
void handler() throws RuntimeException;
static void handle(Callback callback) {
if (callback == null) {
return;
}
callback.handler();
}
}

View File

@ -0,0 +1,32 @@
package com.imyeyu.java.bean;
/**
* 通用回调接口
*
* @author 夜雨
* @since 2021-11-09 20:53
*
* @param <T> 执行程序入参泛型
*/
public interface CallbackArg<T> {
/**
* 执行程序
*
* @param t 入参
* @throws RuntimeException 运行时异常
*/
void handler(T t) throws RuntimeException;
/**
* 非空时执行回调
*
* @param callbackArg 回调
*/
static <T> void handle(T t, CallbackArg<T> callbackArg) {
if (callbackArg == null) {
return;
}
callbackArg.handler(t);
}
}

View File

@ -0,0 +1,34 @@
package com.imyeyu.java.bean;
/**
* 通用可返回回调接口
*
* @author 夜雨
* @since 2022-05-26 14:24
*
* @param <T> 执行程序入参泛型
* @param <R> 执行程序返回泛型
*/
public interface CallbackArgReturn<T, R> {
/**
* 执行程序
*
* @param t 入参
* @return 执行返回
* @throws RuntimeException 运行时异常
*/
R handler(T t) throws RuntimeException;
/**
* 非空时执行回调
*
* @param callbackArgReturn 回调
*/
static <T, R> R handle(T t, CallbackArgReturn<T, R> callbackArgReturn) {
if (callbackArgReturn == null) {
return null;
}
return callbackArgReturn.handler(t);
}
}

View File

@ -0,0 +1,32 @@
package com.imyeyu.java.bean;
/**
* 通用执行回调接口
*
* @author 夜雨
* @since 2022-02-09 19:59
*
* @param <R> 执行返回泛型
*/
public interface CallbackReturn<R> {
/**s
* 执行程序
*
* @return 执行返回
* @throws RuntimeException 运行时异常
*/
R handler() throws RuntimeException;
/**
* 非空时执行回调
*
* @param callbackReturn 回调
*/
static <R> R handle(CallbackReturn<R> callbackReturn) {
if (callbackReturn == null) {
return null;
}
return callbackReturn.handler();
}
}

View File

@ -0,0 +1,47 @@
package com.imyeyu.java.bean;
/**
* 多语言
*
* @author 夜雨
* @since 2022-02-23 11:25
*/
public enum Language {
/** 英语 */
en_US("English"),
/** 简中 */
zh_CN("简体中文"),
/** 繁中 */
zh_TW("繁体中文"),
/** 日语 */
ja_JP("日本語"),
/** 韩语 */
ko_KR("한국인"),
/** 俄语 */
ru_RU("русский"),
/** 德语 */
de_DE("Deutsch");
/** 名称 */
final String name;
Language(String name) {
this.name = name;
}
/**
* 获取语言名称
*
* @return 语言名称
*/
public String getName() {
return name;
}
}

View File

@ -0,0 +1,18 @@
package com.imyeyu.java.bean;
/**
* @author 夜雨
* @since 2024-04-03 11:27
*/
public interface LanguageMapping {
void add(String key, String value);
boolean has(String key);
String text(String key);
String text(String key, String def);
String textArgs(String key, Object... args);
}

View File

@ -0,0 +1,20 @@
package com.imyeyu.java.bean;
/**
* @author 夜雨
* @since 2024-04-01 10:28
*/
public interface LanguageMsgMapping<T> {
T msg(String msg);
T msgKey(String msgKey);
void setMsg(String msg);
String getMsg();
void setMsgKey(String msgKey);
String getMsgKey();
}

View File

@ -0,0 +1,2 @@
/** 通用 Java Bean通用接口 */
package com.imyeyu.java.bean;

View File

@ -0,0 +1,135 @@
package com.imyeyu.java.bean.timi;
/**
* 通用代码(基于 HTTP 代码扩展)
*
* @author 夜雨
* @since 2021-05-21 14:32
*/
public enum TimiCode {
// ---------- 200 正常 ----------
/** 执行成功 */
SUCCESS(20000),
/** 执行成功,忽略请求 */
IGNORE (20001),
// ---------- 400 参数异常 ----------
/** 缺少参数 */
ARG_MISS(40000),
/** 不合法的参数 */
ARG_BAD(40001),
/** 过期的参数 */
ARG_EXPIRED(40002),
// ---------- 401 权限异常 ----------
/** 无权限 */
PERMISSION_MISS(40100),
/** 无权限 */
PERMISSION_ERROR (40101),
/** 非法请求 */
REQUEST_BAD(40102),
// ---------- 403 数据异常 ----------
/** 数据已存在 */
DATA_EXIST (40301),
// ---------- 404 资源异常 ----------
/** 无数据 */
RESULT_NULL(40400),
/** 返回数据异常 */
RESULT_BAD (40401),
/** 禁用的数据 */
RESULT_BAN (40402),
/** 上游服务器连接超时 */
RESULT_TIMEOUT (40403),
// ---------- 500 致命异常 ----------
/** 服务异常 */
ERROR(50000),
/** 服务异常 */
ERROR_NOT_SUPPORT(50001),
/** 服务异常 */
ERROR_NPE_VARIABLE(50002),
/** 服务关闭 */
ERROR_SERVICE_OFF(50003),
/** 服务繁忙 */
ERROR_SERVICE_BUSY(50300);
final Integer value;
TimiCode(Integer value) {
this.value = value;
}
/**
* 转为通用异常
*
* @return 异常
*/
public TimiException toException() {
return toException(toString());
}
/**
* 转为通用异常
*
* @param msg 异常消息
* @return 异常
*/
public TimiException toException(String msg) {
return new TimiException(this, msg);
}
/**
* 转为通用返回对象
*
* @return 返回对象
*/
public TimiResponse<?> toResponse() {
return new TimiResponse<>(this).msg(toString());
}
/**
* 获取代码
*
* @return 代码
*/
public Integer getValue() {
return value;
}
/**
* 根据代码返回对象
*
* @param code 代码
* @return 对象
*/
public static TimiCode fromCode(int code) {
TimiCode[] codes = values();
for (int i = 0; i < codes.length; i++) {
if (codes[i].getValue() == code) {
return codes[i];
}
}
return null;
}
}

View File

@ -0,0 +1,77 @@
package com.imyeyu.java.bean.timi;
import com.imyeyu.java.bean.LanguageMsgMapping;
/**
* 致命错误
*
* @author 夜雨
* @since 2023-04-27 15:55
*/
public class TimiError extends AssertionError implements LanguageMsgMapping<TimiError> {
/** 代码 */
protected final TimiCode code;
protected String msgKey;
/** @param code 代码 */
public TimiError(TimiCode code) {
this.code = code;
}
/**
* 构造器
*
* @param code 代码
* @param msg 消息
*/
public TimiError(TimiCode code, String msg) {
super(msg);
this.code = code;
}
/**
* 获取代码
*
* @return 代码
*/
public TimiCode getCode() {
return code;
}
public TimiResponse<?> toResponse() {
return new TimiResponse<>(code).msg(getMessage()).msgKey(msgKey);
}
@Override
public TimiError msg(String msg) {
throw new UnsupportedOperationException("unsupported to change message");
}
@Override
public TimiError msgKey(String msgKey) {
setMsgKey(msgKey);
return this;
}
@Override
public void setMsg(String msg) {
throw new UnsupportedOperationException("unsupported to change message");
}
@Override
public String getMsg() {
return getMessage();
}
@Override
public void setMsgKey(String msgKey) {
this.msgKey = msgKey;
}
@Override
public String getMsgKey() {
return msgKey;
}
}

View File

@ -0,0 +1,133 @@
package com.imyeyu.java.bean.timi;
import com.imyeyu.java.TimiJava;
import com.imyeyu.java.bean.CallbackReturn;
import com.imyeyu.java.bean.LanguageMsgMapping;
/**
* 通用运行时异常,附加通用代码
*
* @author 夜雨
* @since 2021-05-20 15:18
*/
public class TimiException extends RuntimeException implements LanguageMsgMapping<TimiException> {
/** 代码 */
protected final TimiCode code;
protected String msgKey;
/** @param code 代码 */
public TimiException(TimiCode code) {
this.code = code;
}
/**
* 构造器
*
* @param code 代码
* @param msg 消息
*/
public TimiException(TimiCode code, String msg) {
super(msg);
this.code = code;
}
/**
* 构造器
*
* @param code 代码
* @param msg 消息
*/
public TimiException(TimiCode code, String msg, Throwable e) {
super(msg, e);
this.code = code;
}
/**
* 获取代码
*
* @return 代码
*/
public TimiCode getCode() {
return code;
}
public TimiResponse<?> toResponse() {
return new TimiResponse<>(code).msg(getMessage()).msgKey(msgKey);
}
@Override
public TimiException msg(String msg) {
throw new UnsupportedOperationException("unsupported to change message");
}
@Override
public TimiException msgKey(String msgKey) {
setMsgKey(msgKey);
return this;
}
@Override
public void setMsg(String msg) {
throw new UnsupportedOperationException("unsupported to change message");
}
@Override
public String getMsg() {
return getMessage();
}
@Override
public void setMsgKey(String msgKey) {
this.msgKey = msgKey;
}
@Override
public String getMsgKey() {
return msgKey;
}
public static <T> T required(T t, String message) {
if (TimiJava.isEmpty(t)) {
throw new TimiException(TimiCode.ARG_MISS, message);
}
return t;
}
public static <T> void requiredNull(T t, String message) throws TimiException {
if (t != null) {
throw new TimiException(TimiCode.ERROR, message);
}
}
public static void requiredTrue(boolean bool, String message) throws TimiException {
if (bool) {
return;
}
throw new TimiException(TimiCode.ERROR, message);
}
public static void requiredFalse(boolean bool, String message) throws TimiException {
if (!bool) {
return;
}
throw new TimiException(TimiCode.ERROR, message);
}
public static void requiredTrue(CallbackReturn<Boolean> callback, String message) throws TimiException {
TimiException.required(callback, "not found callback");
if (callback.handler()) {
return;
}
throw new TimiException(TimiCode.ERROR, message);
}
public static void requiredFalse(CallbackReturn<Boolean> callback, String message) throws TimiException {
TimiException.required(callback, "not found callback");
if (!callback.handler()) {
return;
}
throw new TimiException(TimiCode.ERROR, message);
}
}

View File

@ -0,0 +1,168 @@
package com.imyeyu.java.bean.timi;
import com.imyeyu.java.bean.LanguageMsgMapping;
import java.io.Serializable;
/**
* 通用接口返回对象
*
* @author 夜雨
* @since 2021-07-01 20:18
*/
public class TimiResponse<T> implements Serializable, LanguageMsgMapping<TimiResponse<T>> {
/** 代码 */
protected Integer code;
/** 消息 */
protected String msg;
protected String msgKey;
/** 数据体 */
protected T data;
/** 默认构造器 */
public TimiResponse() {
}
/**
* 构造器
*
* @param code 代码
*/
public TimiResponse(TimiCode code) {
this(code, null);
}
/**
* 构造器
*
* @param code 代码
* @param data 数据体
*/
public TimiResponse(TimiCode code, T data) {
this(code, data, null);
}
/**
* 构造器
*
* @param code 代码
* @param data 数据体
* @param msg 消息
*/
public TimiResponse(TimiCode code, T data, String msg) {
this.code = code.getValue();
this.data = data;
this.msg = msg;
}
/** @return true 为成功code 为 20000 段 */
public boolean isSuccess() {
return code != null && code <= 30000;
}
/** @return true 为失败isSuccess 取反 */
public boolean isFail() {
return !isSuccess();
}
/**
* 转为通用异常
*
* @return 异常
*/
public TimiException toException() {
TimiCode code = TimiCode.fromCode(this.code);
if (code == null) {
throw new NullPointerException("unknow timi code: " + this.code);
}
return code.toException(msg);
}
/**
* 获取代码
*
* @return 代码
*/
public Integer getCode() {
return code;
}
/**
* 设置代码
*
* @param code 代码
*/
public void setCode(Integer code) {
this.code = code;
}
/**
* 获取数据体
*
* @return 数据体
*/
public T getData() {
return data;
}
/**
* 设置数据体
*
* @param data 数据体
*/
public void setData(T data) {
this.data = data;
}
/**
* 追加消息(避免和泛型字符串冲突)
*
* @param msg 消息
* @return 本对象
*/
@Override
public TimiResponse<T> msg(String msg) {
this.msg = msg;
return this;
}
/**
* 获取消息
*
* @return 消息
*/
@Override
public String getMsg() {
return msg;
}
/**
* 设置消息
*
* @param msg 消息
*/
@Override
public void setMsg(String msg) {
this.msg = msg;
}
@Override
public TimiResponse<T> msgKey(String msgKey) {
this.msgKey = msgKey;
return this;
}
@Override
public String getMsgKey() {
return msgKey;
}
@Override
public void setMsgKey(String msgKey) {
this.msgKey = msgKey;
}
}

View File

@ -0,0 +1,2 @@
/** 个人常用的通用类 */
package com.imyeyu.java.bean.timi;

View File

@ -0,0 +1,18 @@
package com.imyeyu.java.obs;
import java.util.List;
/**
* @author 夜雨
* @since 2024-09-01 15:15
*/
public interface ChangeListener<T> {
void handler(T from, T to);
static <T> void notifyListener(List<ChangeListener<T>> listenerList, T from, T to) {
for (int i = 0; i < listenerList.size(); i++) {
listenerList.get(i).handler(from, to);
}
}
}

View File

@ -0,0 +1,29 @@
package com.imyeyu.java.obs;
import java.util.List;
/**
* @author 夜雨
* @since 2024-09-01 15:59
*/
public interface CollectionChangeListener<E> {
/**
* @author 夜雨
* @since 2024-09-01 19:47
*/
enum ChangeType {
ADD,
REMOVE
}
void handler(ChangeType type, E e) throws RuntimeException;
static <E> void notifyListener(List<CollectionChangeListener<E>> listenerList, ChangeType type, E element) {
for (int i = 0; i < listenerList.size(); i++) {
listenerList.get(i).handler(type, element);
}
}
}

View File

@ -0,0 +1,34 @@
package com.imyeyu.java.obs;
import java.util.List;
/**
* @author 夜雨
* @since 2024-09-01 18:01
*/
public interface MapChangeListener<K, V> {
/**
*
*
* @author 夜雨
* @since 2024-09-01 23:51
*/
enum ChangeType {
ADD,
UPDATE,
REMOVE
}
void handler(ChangeType type, K key, V value);
@SuppressWarnings("unchecked")
static <K, V> void notifyListener(List<MapChangeListener<K, V>> listenerList, ChangeType type, Object key, V value) {
for (int i = 0; i < listenerList.size(); i++) {
listenerList.get(i).handler(type, (K) key, value);
}
}
}

View File

@ -0,0 +1,16 @@
package com.imyeyu.java.obs;
/**
* @author 夜雨
* @since 2024-09-01 15:07
*/
public interface Observable<T> {
T get();
void set(T value);
void addListener(ChangeListener<T> changeListener);
void removeListener(ChangeListener<T> changeListener);
}

View File

@ -0,0 +1,16 @@
package com.imyeyu.java.obs;
/**
* @author 夜雨
* @since 2024-09-01 18:43
*/
public class ObservableBoolean extends ObservableObject<Boolean> {
public ObservableBoolean() {
super();
}
public ObservableBoolean(Boolean value) {
super(value);
}
}

View File

@ -0,0 +1,16 @@
package com.imyeyu.java.obs;
/**
* @author 夜雨
* @since 2024-09-01 18:43
*/
public class ObservableDouble extends ObservableObject<Double> {
public ObservableDouble() {
super();
}
public ObservableDouble(Number value) {
super(value.doubleValue());
}
}

View File

@ -0,0 +1,16 @@
package com.imyeyu.java.obs;
/**
* @author 夜雨
* @since 2024-09-01 18:43
*/
public class ObservableFloat extends ObservableObject<Float> {
public ObservableFloat() {
super();
}
public ObservableFloat(Float value) {
super(value);
}
}

View File

@ -0,0 +1,15 @@
package com.imyeyu.java.obs;
/**
* @author 夜雨
* @since 2024-09-01 15:06
*/
public class ObservableInteger extends ObservableObject<Integer> {
public ObservableInteger() {
}
public ObservableInteger(Integer value) {
super(value);
}
}

View File

@ -0,0 +1,114 @@
package com.imyeyu.java.obs;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.function.Predicate;
/**
* @author 夜雨
* @since 2024-09-01 17:51
*/
public class ObservableList<E> extends ArrayList<E> {
private final List<CollectionChangeListener<E>> changeListenerList = new ArrayList<>();
public ObservableList() {
}
public ObservableList(Collection<? extends E> c) {
super(c);
}
public void addChangeListener(CollectionChangeListener<E> listener) {
changeListenerList.add(listener);
}
public void removeChangeListener(CollectionChangeListener<E> listener) {
changeListenerList.add(listener);
}
@Override
public boolean add(E e) {
boolean result = super.add(e);
if (result) {
CollectionChangeListener.notifyListener(changeListenerList, CollectionChangeListener.ChangeType.ADD, e);
}
return result;
}
@Override
public void add(int index, E element) {
super.add(index, element);
CollectionChangeListener.notifyListener(changeListenerList, CollectionChangeListener.ChangeType.ADD, element);
}
@Override
public boolean addAll(Collection<? extends E> c) {
boolean result = super.addAll(c);
if (result) {
for (E e : c) {
CollectionChangeListener.notifyListener(changeListenerList, CollectionChangeListener.ChangeType.ADD, e);
}
}
return result;
}
@Override
public boolean addAll(int index, Collection<? extends E> c) {
boolean result = super.addAll(index, c);
if (result) {
for (E e : c) {
CollectionChangeListener.notifyListener(changeListenerList, CollectionChangeListener.ChangeType.ADD, e);
}
}
return result;
}
@Override
public E remove(int index) {
E removed = super.remove(index);
if (removed != null) {
CollectionChangeListener.notifyListener(changeListenerList, CollectionChangeListener.ChangeType.REMOVE, removed);
}
return removed;
}
@Override
public boolean remove(Object o) {
return remove(indexOf(o)) != null;
}
@SuppressWarnings("unchecked")
@Override
public boolean removeAll(Collection<?> c) {
boolean result = super.removeAll(c);
if (result) {
for (Object e : c) {
CollectionChangeListener.notifyListener(changeListenerList, CollectionChangeListener.ChangeType.REMOVE, (E) e);
}
}
return result;
}
@Override
public boolean removeIf(Predicate<? super E> filter) {
boolean removed = false;
Iterator<E> iterator = iterator();
while (iterator.hasNext()) {
E e = iterator.next();
if (filter.test(e)) {
iterator.remove(); // 此方法会触发 notifyListener
removed = true;
}
}
return removed;
}
@Override
public ObservableList<E> subList(int fromIndex, int toIndex) {
List<E> subList = super.subList(fromIndex, toIndex);
return new ObservableList<>(subList);
}
}

View File

@ -0,0 +1,16 @@
package com.imyeyu.java.obs;
/**
* @author 夜雨
* @since 2024-09-01 18:43
*/
public class ObservableLong extends ObservableObject<Long> {
public ObservableLong() {
super();
}
public ObservableLong(Long value) {
super(value);
}
}

View File

@ -0,0 +1,60 @@
package com.imyeyu.java.obs;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author 夜雨
* @since 2024-09-01 18:32
*/
public class ObservableMap<K, V> extends HashMap<K, V> {
private final List<MapChangeListener<K, V>> changeListenerList = new ArrayList<>();
public void addChangeListener(MapChangeListener<K, V> listener) {
changeListenerList.add(listener);
}
public void removeChangeListener(MapChangeListener<K, V> listener) {
changeListenerList.add(listener);
}
@Override
public V put(K key, V value) {
V v = super.put(key, value);
if (v == null) {
MapChangeListener.notifyListener(changeListenerList, MapChangeListener.ChangeType.ADD, key, value);
} else if (!v.equals(value)) {
MapChangeListener.notifyListener(changeListenerList, MapChangeListener.ChangeType.UPDATE, key, value);
}
return v;
}
@Override
public void putAll(Map<? extends K, ? extends V> m) {
for (Map.Entry<? extends K, ? extends V> item : m.entrySet()) {
put(item.getKey(), item.getValue());
}
}
@Override
public V remove(Object key) {
V removed = super.remove(key);
if (removed != null) {
MapChangeListener.notifyListener(changeListenerList, MapChangeListener.ChangeType.REMOVE, key, removed);
}
return removed;
}
@SuppressWarnings("unchecked")
@Override
public boolean remove(Object key, Object value) {
boolean result = super.remove(key, value);
if (result) {
MapChangeListener.notifyListener(changeListenerList, MapChangeListener.ChangeType.REMOVE, key, (V) value);
}
return result;
}
}

View File

@ -0,0 +1,47 @@
package com.imyeyu.java.obs;
import java.util.ArrayList;
import java.util.List;
/**
* @author 夜雨
* @since 2024-09-01 15:22
*/
public abstract class ObservableObject<T> implements Observable<T> {
private final List<ChangeListener<T>> changeListenerList = new ArrayList<>();
private T value;
public ObservableObject() {
}
public ObservableObject(T value) {
this.value = value;
}
@Override
public final T get() {
return value;
}
@Override
public final void set(T toValue) {
final T from = this.value;
this.value = toValue;
boolean isChanged = !from.equals(toValue);
if (isChanged) {
ChangeListener.notifyListener(changeListenerList, from, toValue);
}
}
@Override
public void addListener(ChangeListener<T> changeListener) {
changeListenerList.add(changeListener);
}
@Override
public void removeListener(ChangeListener<T> changeListener) {
changeListenerList.remove(changeListener);
}
}

View File

@ -0,0 +1,81 @@
package com.imyeyu.java.obs;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.function.Predicate;
/**
* @author 夜雨
* @since 2024-09-01 18:29
*/
public class ObservableSet<E> extends HashSet<E> {
private final List<CollectionChangeListener<E>> changeListenerList = new ArrayList<>();
public void addChangeListener(CollectionChangeListener<E> listener) {
changeListenerList.add(listener);
}
public void removeChangeListener(CollectionChangeListener<E> listener) {
changeListenerList.add(listener);
}
@Override
public boolean add(E e) {
boolean result = super.add(e);
if (result) {
CollectionChangeListener.notifyListener(changeListenerList, CollectionChangeListener.ChangeType.ADD, e);
}
return result;
}
@Override
public boolean addAll(Collection<? extends E> c) {
boolean result = super.addAll(c);
if (result) {
for (E e : c) {
CollectionChangeListener.notifyListener(changeListenerList, CollectionChangeListener.ChangeType.ADD, e);
}
}
return result;
}
@SuppressWarnings("unchecked")
@Override
public boolean remove(Object o) {
boolean removed = super.remove(o);
if (removed) {
CollectionChangeListener.notifyListener(changeListenerList, CollectionChangeListener.ChangeType.REMOVE, (E) o);
}
return removed;
}
@SuppressWarnings("unchecked")
@Override
public boolean removeAll(Collection<?> c) {
boolean result = super.removeAll(c);
if (result) {
for (Object e : c) {
CollectionChangeListener.notifyListener(changeListenerList, CollectionChangeListener.ChangeType.REMOVE, (E) e);
}
}
return result;
}
@Override
public boolean removeIf(Predicate<? super E> filter) {
boolean removed = false;
Iterator<E> iterator = iterator();
while (iterator.hasNext()) {
E e = iterator.next();
if (filter.test(e)) {
iterator.remove(); // 此方法会触发 notifyListener
removed = true;
}
}
return removed;
}
}

View File

@ -0,0 +1,29 @@
package com.imyeyu.java.obs;
/**
* @author 夜雨
* @since 2024-09-01 18:43
*/
public class ObservableString extends ObservableObject<String> {
public ObservableString() {
super();
}
public ObservableString(String value) {
super(value);
}
public boolean isEmpty() {
return get().isEmpty() || get().trim().isEmpty();
}
public boolean isNotEmpty() {
return !isEmpty();
}
@Override
public String toString() {
return get();
}
}

View File

@ -0,0 +1,266 @@
package com.imyeyu.java.ref;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* 反射相关
*
* @author 夜雨
* @since 2023-05-04 15:05
*/
public class Ref {
/**
* 获取类字段列表
*
* @param clazz 类
* @return 字段列表
*/
public static List<Field> listFields(Class<?> clazz) {
return List.of(clazz.getDeclaredFields());
}
/**
* 获取类字段列表(包括父类)
*
* @param clazz 类
* @return 字段列表
*/
public static List<Field> listAllFields(Class<?> clazz) {
List<Field> result = new ArrayList<>();
while (clazz != null && clazz != Object.class) {
Collections.addAll(result, clazz.getDeclaredFields());
clazz = clazz.getSuperclass();
}
return result;
}
/**
*
* @param keyName
* @return
*/
public static String getFieldName(String keyName) {
String[] splits = {"-", "_", " "};
StringBuilder full = new StringBuilder(keyName.substring(0, 1).toUpperCase() + keyName.substring(1));
for (int i = 0; i < splits.length; i++) {
if (keyName.contains(splits[i])) {
// 存在分隔符
full.setLength(0);
String[] word = keyName.split(splits[i]);
for (int j = 0; j < word.length; j++) {
full.append(word[j].substring(0, 1).toUpperCase()).append(word[j].substring(1));
}
break;
}
}
return String.valueOf(full.charAt(0)).toLowerCase() + full.substring(1);
}
/**
* 反射获取对象字段,包括父级类,直至 {@link Object},如果都不存在则返回 null
*
* @param clazz 类
* @param fieldName 字段名
* @return 字段
*/
public static Field getField(Class<?> clazz, String fieldName) {
do {
try {
Field field = clazz.getDeclaredField(fieldName);
field.setAccessible(true);
return field;
} catch (NoSuchFieldException e) {
clazz = clazz.getSuperclass();
}
} while (clazz != Object.class);
throw new NullPointerException(String.format("not found field: %s in %s", fieldName, clazz));
}
/**
* 反射获取对象字段值,包括父级类,直至 {@link Object}
*
* @param object 对象
* @param fieldName 字段名
* @param toClass 返回类
* @param <T> 返回类型
* @return 字段值
* @throws IllegalAccessException 反射访问失败
* @throws NullPointerException 向上反射直至 {@link Object} 也找不到该字段
*/
public static <T> T getFieldValue(Object object, String fieldName, Class<? extends T> toClass) throws IllegalAccessException, NullPointerException {
return getFieldValue(object, getField(object.getClass(), fieldName), toClass);
}
/**
* 反射获取对象字段值
*
* @param object 对象
* @param field 字段
* @param toClass 返回类
* @param <T> 返回类型
* @return 字段值
* @throws IllegalAccessException 反射访问失败
* @throws NullPointerException 向上反射直至 {@link Object} 也找不到该字段
*/
public static <T> T getFieldValue(Object object, Field field, Class<? extends T> toClass) throws IllegalAccessException, NullPointerException {
if (field == null) {
throw new NullPointerException("field can not be null");
}
field.setAccessible(true);
return toClass.cast(field.get(object));
}
/**
* 反射获取类字段
*
* @param objectClass 类
* @param fieldName 字段名
* @return 字段
*/
public static Field getClassField(Class<?> objectClass, String fieldName) {
try {
Field field = objectClass.getDeclaredField(fieldName);
field.setAccessible(true);
return field;
} catch (NoSuchFieldException e) {
return null;
}
}
/**
* 反射获取指定类字段值
*
* @param object 对象
* @param objectClass 类
* @param fieldName 字段名
* @param toClass 值类型
* @param <T> 值类型
* @return 字段值
* @throws IllegalAccessException 反射访问失败
* @throws NoSuchFieldException 字段不存在
*/
public static <T> T getClassFieldValue(Object object, Class<?> objectClass, String fieldName, Class<T> toClass) throws IllegalAccessException, NoSuchFieldException {
Field field = getClassField(objectClass, fieldName);
if (field == null) {
throw new NoSuchFieldException("not found " + fieldName + " field in " + objectClass.getSimpleName());
}
field.setAccessible(true);
return toClass.cast(field.get(object));
}
/**
* 反射设置对象字段值,包括父级类,直至 {@link Object}
*
* @param object 对象
* @param fieldName 字段名
* @param value 字段值
* @throws IllegalAccessException 反射访问失败
* @throws NoSuchFieldException 向上反射直至 {@link Object} 也找不到该字段
*/
public static void setFieldValue(Object object, String fieldName, Object value) throws IllegalAccessException, NoSuchFieldException {
Field field = getField(object.getClass(), fieldName);
if (field == null) {
throw new NoSuchFieldException("not found " + fieldName + " field in " + object.getClass().getSimpleName());
}
setFieldValue(object, field, value);
}
public static void setFieldValue(Object object, Field field, Object value) throws IllegalAccessException {
field.setAccessible(true);
field.set(object, value);
}
/**
* 反射设置对象字段值
*
* @param object 对象
* @param objectClass 类
* @param fieldName 字段名
* @param value 字段值
* @throws IllegalAccessException 反射访问失败
* @throws NullPointerException 字段不存在
*/
public static void setClassFieldValue(Object object, Class<?> objectClass, String fieldName, Object value) throws IllegalAccessException, NullPointerException {
Field field = getClassField(objectClass, fieldName);
if (field == null) {
throw new NullPointerException("not found " + fieldName + " field in " + objectClass.getSimpleName() + " class");
}
field.setAccessible(true);
field.set(object, value);
}
/**
* 反射查找方法,包括父级类,直至 {@link Object},如果都不存在则返回 null
*
* @param clazz 类
* @param methodName 方法名
* @param parameterTypes 可选参
* @return 方法对象
*/
public static Method getMethod(Class<?> clazz, String methodName, Class<?>... parameterTypes) {
if (clazz == null) {
throw new NullPointerException("class can not be null");
}
do {
try {
Method method = clazz.getDeclaredMethod(methodName, parameterTypes);
method.setAccessible(true);
return method;
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
}
} while (clazz != Object.class);
return null;
}
/**
* 字符串转枚举
*
* @param clazz 枚举类
* @param string 字符串
* @param <T> 泛型
* @return 泛型
*/
public static <T extends Enum<?>> T toType(Class<T> clazz, String string) {
if (string == null) {
return null;
}
T[] ts = clazz.getEnumConstants();
if (ts == null) {
throw new IllegalArgumentException(clazz.getName() + " is not an enum type");
}
for (int i = 0; i < ts.length; i++) {
if (ts[i].name().equalsIgnoreCase(string)) {
return ts[i];
}
}
return null;
}
/**
*
*
* @param owner
* @param keyName
* @return
*/
public static RefField field(Class<?> owner, String keyName) {
return new RefField(owner, keyName);
}
/**
*
* @param type
* @return
* @param <T>
* @throws Exception
*/
public static <T> T newInstance(Class<T> type) throws Exception {
return type.getDeclaredConstructor().newInstance();
}
}

View File

@ -0,0 +1,77 @@
package com.imyeyu.java.ref;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
*
*
* @author 夜雨
* @since 2024-04-26 15:46
*/
public class RefField {
private Class<?> type;
private Field field;
private Method setter;
private Method getter;
RefField(Class<?> owner, String keyName) {
String fieldName = Ref.getFieldName(keyName);
String fieldNameUpper = String.valueOf(fieldName.charAt(0)).toUpperCase() + fieldName.substring(1);
field = Ref.getField(owner, fieldName);
type = field.getType();
String setterName;
String getterName;
if (boolean.class.equals(field.getType()) || Boolean.class.equals(field.getType())) {
if (fieldName.startsWith("is")) {
setterName = "set" + fieldName.substring(2);
getterName = fieldName;
} else {
setterName = "set" + fieldNameUpper;
getterName = "is" + fieldNameUpper;
}
} else {
setterName = "set" + fieldNameUpper;
getterName = "get" + fieldNameUpper;
}
setter = Ref.getMethod(owner, setterName, field.getType());
getter = Ref.getMethod(owner, getterName);
}
public Class<?> getType() {
return type;
}
public void setType(Class<?> type) {
this.type = type;
}
public Field getField() {
return field;
}
public void setField(Field field) {
this.field = field;
}
public Method getSetter() {
return setter;
}
public void setSetter(Method setter) {
this.setter = setter;
}
public Method getGetter() {
return getter;
}
public void setGetter(Method getter) {
this.getter = getter;
}
}

View File

@ -0,0 +1,60 @@
package test;
import com.imyeyu.java.obs.ObservableList;
import com.imyeyu.java.obs.ObservableMap;
import com.imyeyu.java.obs.ObservableString;
import org.junit.jupiter.api.Test;
import java.util.List;
/**
* @author 夜雨
* @since 2024-09-01 23:26
*/
public class TestObs {
@Test
public void testString() {
ObservableString obsString = new ObservableString("test1");
System.out.println("init value = " + obsString);
obsString.addListener((from, to) -> System.out.printf("from %s to %s%n", from, to));
obsString.set("test2");
System.out.println("now value = " + obsString);
assert obsString.get().equals("test2");
}
@Test
public void testList() {
ObservableList<String> list = new ObservableList<>();
list.addChangeListener((type, string) -> System.out.printf("%s element %s to list%n", type, string));
list.add("test1");
list.add("test2");
list.add("test3");
list.add("test4");
list.add("test5");
list.addAll(List.of("test7", "test8"));
list.add(0, "test0");
System.out.println(list);
list.remove("test2");
list.remove(0);
list.removeAll(List.of("test3", "test4"));
list.removeIf(item -> item.equals("test1")); // 移除 0, 1, 2, 3, 4
System.out.println(list);
}
@Test
public void testMap() {
ObservableMap<String, String> map = new ObservableMap<>();
map.addChangeListener((type, key, value) -> System.out.printf("%s element %s:%s to map%n", type, key, value));
map.put("t1", "test1");
map.put("t1", "test1update"); // test1 更新
map.put("t2", "test2");
map.put("t2", "test2"); // test2 不更新
map.put("t3", "test3");
map.put("t4", "test4");
map.put("t5", "test5");
map.remove("t1");
map.remove("t2", "test2");
System.out.println(map);
}
}

View File

@ -0,0 +1,96 @@
package test;
import com.imyeyu.java.ref.Ref;
import com.imyeyu.java.ref.RefField;
import org.junit.jupiter.api.Test;
/**
* @author 夜雨
* @since 2024-04-26 11:05
*/
public class TestRef {
private boolean isBoy;
private boolean boy;
private String fieldName;
@Test
public void test() {
String t1 = Ref.getFieldName("is-boy");
assert t1.equals("isBoy");
String t2 = Ref.getFieldName("is_boy");
assert t2.equals("isBoy");
String t3 = Ref.getFieldName("is boy");
assert t3.equals("isBoy");
String t4 = Ref.getFieldName("isBoy");
assert t4.equals("isBoy");
String t5 = Ref.getFieldName("boy");
assert t5.equals("boy");
String t6 = Ref.getFieldName("fieldName");
assert t6.equals("fieldName");
String t7 = Ref.getFieldName("field name");
assert t7.equals("fieldName");
String t8 = Ref.getFieldName("field-Name");
assert t8.equals("fieldName");
String t9 = Ref.getFieldName("field_Name");
assert t9.equals("fieldName");
}
@Test
public void refBooleanField() {
RefField refField = Ref.field(TestRef.class, "is-boy");
assert refField.getSetter() != null && refField.getSetter().getName().equals("setBoy");
assert refField.getGetter() != null && refField.getGetter().getName().equals("isBoy");
}
@Test
public void refBoolean2Field() {
RefField refField = Ref.field(TestRef.class, "boy");
assert refField.getSetter() != null && refField.getSetter().getName().equals("setBoy");
assert refField.getGetter() != null && refField.getGetter().getName().equals("isBoy");
}
@Test
public void refStringField() {
RefField refField = Ref.field(TestRef.class, "fieldName");
assert refField.getSetter() != null && refField.getSetter().getName().equals("setFieldName");
assert refField.getGetter() != null && refField.getGetter().getName().equals("getFieldName");
}
@Test
public void refString2Field() {
RefField refField = Ref.field(TestRef.class, "field-name");
assert refField.getSetter() != null && refField.getSetter().getName().equals("setFieldName");
assert refField.getGetter() != null && refField.getGetter().getName().equals("getFieldName");
}
@Test
public void refString3Field() {
RefField refField = Ref.field(TestRef.class, "field_name");
assert refField.getSetter() != null && refField.getSetter().getName().equals("setFieldName");
assert refField.getGetter() != null && refField.getGetter().getName().equals("getFieldName");
}
@Test
public void refString4Field() {
RefField refField = Ref.field(TestRef.class, "field name");
assert refField.getSetter() != null && refField.getSetter().getName().equals("setFieldName");
assert refField.getGetter() != null && refField.getGetter().getName().equals("getFieldName");
}
public boolean isBoy() {
return isBoy;
}
public void setBoy(boolean boy) {
isBoy = boy;
}
public String getFieldName() {
return fieldName;
}
public void setFieldName(String fieldName) {
this.fieldName = fieldName;
}
}